-         

Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 16

Thema: Mein erster Hexapod

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    18.09.2012
    Beiträge
    7

    Mein erster Hexapod

    Anzeige

    Hallo,

    bin jetzt ganz neu hier und schon eine ganze Weile einen Hexapod am bauen.
    Anfangs hat auch alles funktioniert. Ich steuer ihn mit einem AtMega16 und habe 18 Servomotoren angeschlossen. Jedoch gab es irgendwann Probleme mit den Signalen. Ich habe jedes Signal mal mit nem Osziloskop geprüft und jedesmal an genau der selben Stelle eines Servos zuckt das Signal wild hin und her und auch die Servos zucken dann.
    Ich benutze für die seitlichen Gelenke und die unteren Beingelenke Modelcraft RS-2 und für die oberen Beingelenke towerpro MG 995. Einzeln mit einem Servotester funktionieren alle einwandfrei.
    Ich habe das Programm für die Servosteuerung von einem Beispiel welches ich im Internet gefunden habe, abgeleitet, aber auch kommerzielle Servosteuersoftware ausprobiert. Überall tritt der selbe Fehler auf. Das kommerzielle Programm hies webbotlib.
    Zudem läuft der Mega16 mit einem 16MHz Quarz.
    Nun weiß ich nicht woran das liegt. Ist es irgendein Überlauf, der genau an der Stelle entsteht und das ganze asynchron laufen lässt? Ein Programmfehler? Ein möglicher Hardwarefehler?
    Als Datei noch der Schaltplan des Roboters.
    Das Problem ist leider dringend, da meine Bachelorarbeit davon abhängt.
    Vielen Dank schonmal und ich hoffe ich habe nichts vergessen zu erwähnen.

    Das Programm:

    Code:
    /*
        Eine 8-kanalige PWM mit intelligentem Lösungsansatz
     
        ATmega16 @ 16 MHz
     
    */
     
     
    #define BAUD 56000UL
    #define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)
    
    
    // Defines an den Controller und die Anwendung anpassen
     
    #define F_CPU         16000000L           // Systemtakt in Hz
    #define F_PWM         500L               // PWM-Frequenz in Hz
    #define PWM_PRESCALER 8                  // Vorteiler für den Timer
    #define PWM_STEPS     256                // PWM-Schritte pro Zyklus(1..256)
    #define PWM_PORT      PORTD             // Port für PWM
    #define PWM_DDR       DDRD               // Datenrichtungsregister für PWM
    #define PWM_PORT_2    PORTC             // Port für PWM
    #define PWM_DDR_2     DDRC               // Datenrichtungsregister für PWM
    #define PWM_PORT_3    PORTA             // Port für PWM
    #define PWM_DDR_3    DDRA               // Datenrichtungsregister für PWM
    #define PWM_CHANNELS  20               // Anzahl der PWM-Kanäle
     
    // ab hier nichts ändern, wird alles berechnet
     
    #define T_PWM (F_CPU/(PWM_PRESCALER*F_PWM*PWM_STEPS)) // Systemtakte pro PWM-Takt
    //#define T_PWM 1   //TEST
     
    #if ((T_PWM*PWM_PRESCALER)<(111+5))
        #error T_PWM zu klein, F_CPU muss vergrössert werden oder F_PWM oder PWM_STEPS verkleinert werden
    #endif
     
    #if ((T_PWM*PWM_STEPS)>65535)
        #error Periodendauer der PWM zu gross! F_PWM oder PWM_PRESCALER erhöhen.   
    #endif
    // includes
     
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <util/delay.h>
    #include <stdlib.h>
    #include <string.h>
    #include <stdint.h>
     
    // globale Variablen
     
    uint32_t pwm_timing[PWM_CHANNELS+1];          // Zeitdifferenzen der PWM Werte
    uint32_t pwm_timing_tmp[PWM_CHANNELS+1];      
     
    uint32_t  pwm_mask[PWM_CHANNELS+1];            // Bitmaske für PWM Bits, welche gelöscht werden sollen
    uint32_t  pwm_mask_tmp[PWM_CHANNELS+1];        // ändern uint16_t oder uint32_t für mehr Kanäle
     
    uint8_t  pwm_setting[PWM_CHANNELS];           // Einstellungen für die einzelnen PWM-Kanäle
    uint8_t  pwm_setting_tmp[PWM_CHANNELS+1];     // Einstellungen der PWM Werte, sortiert
                                                  // ändern auf uint16_t für mehr als 8 Bit Auflösung  
     
    volatile uint8_t pwm_cnt_max=1;               // Zählergrenze, Initialisierung mit 1 ist wichtig!
    volatile uint8_t pwm_sync;                    // Update jetzt möglich
     
     
    char s[4];
    char buffer[10];
    volatile uint8_t uart_str_count=0;
    volatile uint8_t servo=0;
    volatile uint8_t uart_str_complete = 0;
    
    // Pointer für wechselseitigen Datenzugriff
     
    uint32_t *isr_ptr_time  = pwm_timing;
    uint32_t *main_ptr_time = pwm_timing_tmp;
     
    uint32_t *isr_ptr_mask  = pwm_mask;              // Bitmasken fuer PWM-Kanäle
    uint32_t *main_ptr_mask = pwm_mask_tmp;          // ändern uint16_t oder uint32_t für mehr Kanäle
     
    // Zeiger austauschen
    // das muss in einem Unterprogramm erfolgen,
    // um eine Zwischenspeicherung durch den Compiler zu verhindern
    
    void geradeausGehen(uint8_t * pos,uint8_t tempo);
    void aufAb(uint8_t *pos,uint8_t tempo);
    
    void tausche_zeiger(void) {
        uint32_t *tmp_ptr16;
        uint32_t *tmp_ptr8;                          // ändern uint16_t oder uint32_t für mehr Kanäle
     
        tmp_ptr16 = isr_ptr_time;
        isr_ptr_time = main_ptr_time;
        main_ptr_time = tmp_ptr16;
        tmp_ptr8 = isr_ptr_mask;
        isr_ptr_mask = main_ptr_mask;
        main_ptr_mask = tmp_ptr8;
    }
     
    // PWM Update, berechnet aus den PWM Einstellungen
    // die neuen Werte für die Interruptroutine
     
    void pwm_update(void) {
        
        uint8_t i, j, k;
        uint32_t m1, m2, tmp_mask;                   // ändern uint16_t oder uint32_t für mehr Kanäle    
        uint8_t min, tmp_set;                       // ändern auf uint16_t für mehr als 8 Bit Auflösung
     
        // PWM Maske für Start berechnen
        // gleichzeitig die Bitmasken generieren und PWM Werte kopieren
     
        m1 = 1;
        m2 = 0;
        for(i=1; i<=(PWM_CHANNELS); i++) {
            main_ptr_mask[i]=~m1;                       // Maske zum Löschen der PWM Ausgänge
            pwm_setting_tmp[i] = pwm_setting[i-1];
            if (pwm_setting_tmp[i]!=0) m2 |= m1;        // Maske zum setzen der IOs am PWM Start
            m1 <<= 1;
        }
        main_ptr_mask[0]=m2;                            // PWM Start Daten 
     
        // PWM settings sortieren; Einfügesortieren
     
        for(i=1; i<=PWM_CHANNELS; i++) {
            min=PWM_STEPS-1;
            k=i;
            for(j=i; j<=PWM_CHANNELS; j++) {
                if (pwm_setting_tmp[j]<min) {
                    k=j;                                // Index und PWM-setting merken
                    min = pwm_setting_tmp[j];
                }
            }
            if (k!=i) {
                // ermitteltes Minimum mit aktueller Sortiertstelle tauschen
                tmp_set = pwm_setting_tmp[k];
                pwm_setting_tmp[k] = pwm_setting_tmp[i];
                pwm_setting_tmp[i] = tmp_set;
                tmp_mask = main_ptr_mask[k];
                main_ptr_mask[k] = main_ptr_mask[i];
                main_ptr_mask[i] = tmp_mask;
            }
        }
     
        // Gleiche PWM-Werte vereinigen, ebenso den PWM-Wert 0 löschen falls vorhanden
     
        k=PWM_CHANNELS;             // PWM_CHANNELS Datensätze
        i=1;                        // Startindex
     
        while(k>i) {
            while ( ((pwm_setting_tmp[i]==pwm_setting_tmp[i+1]) || (pwm_setting_tmp[i]==0))  && (k>i) ) {
     
                // aufeinanderfolgende Werte sind gleich und können vereinigt werden
                // oder PWM Wert ist Null
                if (pwm_setting_tmp[i]!=0)
                    main_ptr_mask[i+1] &= main_ptr_mask[i];        // Masken vereinigen
     
                // Datensatz entfernen,
                // Nachfolger alle eine Stufe hochschieben
                for(j=i; j<k; j++) {
                    pwm_setting_tmp[j] = pwm_setting_tmp[j+1];
                    main_ptr_mask[j] = main_ptr_mask[j+1];
                }
                k--;
            }
            i++;
        }
        
        // letzten Datensatz extra behandeln
        // Vergleich mit dem Nachfolger nicht möglich, nur löschen
        // gilt nur im Sonderfall, wenn alle Kanäle 0 sind
        if (pwm_setting_tmp[i]==0) k--;
     
        // Zeitdifferenzen berechnen
        
        if (k==0) { // Sonderfall, wenn alle Kanäle 0 sind
            main_ptr_time[0]=(uint16_t)T_PWM*PWM_STEPS/2;
            main_ptr_time[1]=(uint16_t)T_PWM*PWM_STEPS/2;
            k=1;
        }
        else {
            i=k;
            main_ptr_time[i]=(uint16_t)T_PWM*(PWM_STEPS-pwm_setting_tmp[i]);
            tmp_set=pwm_setting_tmp[i];
            i--;
            for (; i>0; i--) {
                main_ptr_time[i]=(uint16_t)T_PWM*(tmp_set-pwm_setting_tmp[i]);
                tmp_set=pwm_setting_tmp[i];
            }
            main_ptr_time[0]=1000+(uint16_t)T_PWM*tmp_set;
        }
     
        // auf Sync warten
     
        pwm_sync=0;             // Sync wird im Interrupt gesetzt
        while(pwm_sync==0);
     
        // Zeiger tauschen
        cli();
        tausche_zeiger();
        pwm_cnt_max = k;
        sei();
    }
     
    // Timer 1 Output COMPARE A Interrupt
     
    ISR(TIMER1_COMPA_vect) {
        static uint32_t pwm_cnt;                     // ändern auf uint16_t für mehr als 8 Bit Auflösung
        uint32_t tmp;                                // ändern uint16_t oder uint32_t für mehr Kanäle
     
        OCR1A += isr_ptr_time[pwm_cnt];
        tmp    = isr_ptr_mask[pwm_cnt];
        
        if (pwm_cnt == 0) {
            PWM_PORT = tmp;                         // Ports setzen zu Begin der PWM
    		PWM_PORT_2 = tmp>>8;   					// zusätzliche PWM-Ports hier setzen
    		PWM_PORT_3 = tmp>>16;
            pwm_cnt++;
        }
        else {
            PWM_PORT &= tmp;                        // Ports löschen
    		PWM_PORT_2 &= tmp>>8;                                       // zusätzliche PWM-Ports hier setzen
            PWM_PORT_3 &= tmp>>16;
    		if (pwm_cnt == pwm_cnt_max) {
               
    			OCR1A+=36000;
    			pwm_sync = 1;                       // Update jetzt möglich
                pwm_cnt  = 0;
    			
            }
            else pwm_cnt++;
        }
    }
    
    
    void uart_init(void)   
    {
       UBRRH = UBRR_VAL>>8;
       UBRRL = UBRR_VAL;
       /* evtl. verkuerzt falls Register aufeinanderfolgen (vgl. Datenblatt)
          UBRR = UBRR_VALUE;
       */
    
     UCSRB = (1 << RXEN) | (1 << TXEN) |(1<<RXCIE);
     UCSRC = (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0);
    
    }
    
    void adc_init(void){
    
    	ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1);
    	ADMUX=0 | (0<<REFS1) | (1<<REFS0);
    
    }
    
    int uart_putc(unsigned char c)
    {
        while (!(UCSRA & (1<<UDRE)))  /* warten bis Senden moeglich */
        {
        }                             
     
        UDR = c;                      /* sende Zeichen */
        return 0;
    }
    
    uint8_t uart_getc(void)
    {
        while (!(UCSRA & (1<<RXC)))   // warten bis Zeichen verfuegbar
            ;
        return UDR;                   // Zeichen aus UDR an Aufrufer zurueckgeben
    }
    
    void uart_puts (char *st)
    {
        while (*st)
        {   /* so lange *s != '\0' also ungleich dem "String-Endezeichen(Terminator)" */
            uart_putc(*st);
            st++;
        }
    	//uart_putc(' ');
    }
    
    
    int main(void) {
     
     
    	//uart_init();
    	//adc_init();
        // PWM Port einstellen
        
        PWM_DDR = 0xFF;         // Port als Ausgang
        // zusätzliche PWM-Ports hier setzen
    	PWM_DDR_2=0xFF;
    	PWM_DDR_3=0xFF;
        
        // Timer 1 OCRA1, als variablen Timer nutzen
     
        TCCR1B = 2;             // Timer läuft mit Prescaler 8
        TIMSK |= (1<<OCIE1A);   // Interrupt freischalten
     
        sei();                  // Interrupts global einschalten
     
     
    /******************************************************************/
    // nur zum testen, in der Anwendung entfernen
    
    // Test values
    volatile uint8_t tmp;
    // Bein 1
    // 2 mitte bein 80 -200		links 
    // 3 mitte fuß 50 -130  	links
    // 4 hinten gelenk 70 - 120	links
    // Bein 2
    // 5 hinten fuß 50 -130		links
    // 6 hinten bein 200 -80	links
    // 7 mitte gelenk 70 -120	links
    // Bein 3
    // 8 vorne bein 80 -200		links
    // 9 vorne fuß 50 -130		links
    // 10 vorne gelenk 70 - 120	links
    // Bein 4
    // 11
    // 12
    // 13
    // Bein 5
    // 14
    // 15
    // 16
    // Bein 6
    // 17
    // 18
    // 19
    //                      0    1    /2   3    4 /  5   6    7 / 8   9  10  /11  12 13 /14  15 16 /17 18  19
    const uint8_t t1[20]={100, 100,  30, 80, 140, 90, 30, 120,30,  90,120,230,180,120,230,180,120,180,230,130};
    const uint8_t t2[20]={60, 60, 120, 100, 140, 120, 110, 120,110,120,120,110,170,120,120,160,100,150,120,120};
    const uint8_t t3[8]={27, 40, 3, 17, 3, 99, 3, 0};
    const uint8_t t4[8]={0, 0, 0, 0, 0, 0, 0, 0};
    const uint8_t t5[8]={9, 1, 1, 1, 1, 1, 1, 1};
    const uint8_t t6[8]={33, 33, 33, 33, 33, 33, 33, 33};
    const uint8_t t7[8]={0, 0, 0, 0, 0, 0, 0, 88};
     
     
    // Messung der Interruptdauer
        tmp =1;
        tmp =2;
        tmp =3;
     
    // Debug 
     
      memcpy(pwm_setting, t2, 20);
        pwm_update();
     
        
    
    /******************************************************************/
    	/*
    	uint8_t tmp1[10];
    	memcpy(tmp1,t1,10);
        while(1){
    	tmp1[6]-=1;
    	tmp1[4]-=1;
    	if(tmp1[6]<=80) tmp1[6]=130;
    	if(tmp1[4]<=70) tmp1[4]=120;
    	 memcpy(pwm_setting, tmp1, 10);
        pwm_update();
    	_delay_ms(50);
    	};
    	*/
    	uint8_t pos[20];
    	memcpy(pos,t2,20);
    	
    	//startPos();
    	
    	while(1)
    	{
    	//
    	aufAb(pos,20);
    	//geradeausGehen(pos,20);
    	}
    	
    	
    	while(1){
    	
    	
    	
    	}
        return 0;
    }
    
    ISR(USART_RXC_vect)
    
      {
      uart_putc(UDR);
     if (servo==1)servoSteuer();
     else{
     unsigned char nextChar;
    
      // Daten aus dem Puffer lesen
      nextChar = UDR;
    
     if (nextChar=='s'){
     servo=1;
     
     }else{
    
      	if( uart_str_complete == 0 ) {
        // Daten werden erst in uart_string geschrieben, wenn nicht String-Ende/max Zeichenlänge erreicht ist/string gerade verarbeitet wird
        if( nextChar != '\n' &&
            nextChar != '\r' &&
            uart_str_count < 9 ) {
          buffer[uart_str_count] = nextChar;
          uart_str_count++;
        }
        else {
          buffer[uart_str_count] = '\0'; 
          uart_str_count=0;
    	  uart_str_complete=1;
    	  
             }
      }
      }
      }
    }
    
    void servoSteuer(void){
    	
    	static uint8_t servo_count;
    	uint8_t nextChar;
    	
      // Daten aus dem Puffer lesen
      nextChar = UDR;
      uart_putc(nextChar);
    	
    	if(nextChar !='s'){
    	 if(
           nextChar != '\r'){
    			
    		
    			
    			memcpy(pwm_setting[3],nextChar,8);
    			servo_count++;
    						
    		
    		}else{
    		servo_count=0;
    		servo=0;
    		uart_puts("finish");
    		pwm_update();
    	  }
    	  
    	}
    }
    
    void geradeausGehen(uint8_t* pos,uint8_t tempo)
    {
    	
    	
    	pos[8]=120;
    	pos[6]=120;
    	pos[14]=120;
    
    		
    	pos[2]=140;
    	pos[18]=100;
    	pos[11]=100;
    	
    	
    	memcpy(pwm_setting, pos, 20);
    		pwm_update();
    		_delay_ms(1000);
    		
    	while(pos[10] <= 140){
    		pos[4]++;
    		pos[7]--;
    		pos[10]++;
    		
    		pos[19]--;
    		pos[16]++;
    		pos[13]++;
    		if((pos[10]-80)%4==0 && (pos[10]-80)<=35){
    			pos[5]--;
    			pos[9]--;
    			pos[15]++;
    			}
    		else if((pos[10]-80)%4==0)
    		{
    			pos[5]++;
    			pos[9]++;
    			pos[15]--;
    			}
    		memcpy(pwm_setting, pos, 20);
    		pwm_update();
    		_delay_ms(tempo);
    		}
    		
    	
    			
    		//Beine
    		pos[2]=120;
    		pos[18]=120;
    		pos[11]=120;
    		
    		//Füße
    		pos[9]=100;
    		pos[5]=100;
    		pos[15]=180;
    		memcpy(pwm_setting, pos, 20);
    		pwm_update();
    		_delay_ms(1000);
    		
    		pos[8]=140;
    		pos[6]=140;
    		pos[14]=100;
    		
    		//Füße
    		pos[17]=170;
    		pos[12]=190;
    		pos[3]=80;
    		memcpy(pwm_setting, pos, 20);
    		pwm_update();
    		_delay_ms(1000);	
    		
    		while(pos[16] >= 80){
    		pos[4]--;
    		pos[7]++;
    		pos[10]--;
    		
    		pos[19]++;
    		pos[16]--;
    		pos[13]--;
    		if((pos[16]-50)%4==0 && (pos[16]-50)<=75){
    			pos[17]--;
    			pos[12]--;
    			pos[3]++;
    			}
    		else if((pos[16]-50)%4==0)
    		{
    			pos[17]++;
    			pos[12]++;
    			pos[3]--;
    			}
    		memcpy(pwm_setting, pos, 20);
    		pwm_update();
    		_delay_ms(tempo);
    		}
    		
    }
    
    void startPos(void){
    	//                      0    1   /2   3    4 /5   6    7 / 8   9  10  /11  12 13 /14  15   16/  17  18  19
    	uint8_t startPos[20]={60, 60, 150, 100, 140, 120,140, 120,140,120,120,80,170,120,90,150,100,150,90,120};
    	memcpy(pwm_setting, startPos, 20);
    	pwm_update();
    	_delay_ms(1000);
    	for(int i=0; i<15;i++){
    	
    	startPos[2]-=2;
    	startPos[6]-=2;
    	startPos[8]-=2;
    	startPos[9]--;
    	startPos[5]--;
    	startPos[3]--;
    	startPos[18]+=2;
    	startPos[11]+=2;
    	startPos[14]+=2;
    	startPos[17]++;
    	startPos[12]++;
    	startPos[15]++;
    	memcpy(pwm_setting, startPos, 20);
    	pwm_update();
    	_delay_ms(50);
    	
    	}
    	const uint8_t endStartPos[20]={100, 100,30, 80, 140, 90, 30, 120,30,90,120,230,180,120,230,180,120,180,230,130};
    	
    	//aufAb(endStartPos,50);
    
    
    }
    
    void aufAb(uint8_t *pos,uint8_t tempo){
    
    	uint8_t i=0;
    	
    	while (i<80){
    	i++;
    	pos[8]--;
    	pos[6]--;
    	pos[2]--;
    	pos[18]++;
    	pos[11]++;
    	pos[14]++;
    	
    	pos[9]++;
    	pos[5]++;
    	pos[3]++;
    	pos[17]--;
    	pos[12]--;
    	pos[15]--;
    	
    	memcpy(pwm_setting, pos, 20);
    		pwm_update();
    		_delay_ms(tempo);
    	}
    	
    		while (i>0){
    	i--;
    	pos[8]++;
    	pos[6]++;
    	pos[2]++;
    	pos[18]--;
    	pos[11]--;
    	pos[14]--;
    	
    	pos[9]--;
    	pos[5]--;
    	pos[3]--;
    	pos[17]++;
    	pos[12]++;
    	pos[15]++;
    	
    	memcpy(pwm_setting, pos, 20);
    		pwm_update();
    		_delay_ms(tempo);
    	}
    
    }
    Miniaturansichten angehängter Grafiken Miniaturansichten angehängter Grafiken RobotPlatine.jpg  

  2. #2
    RN-Premium User Roboter Genie Avatar von 5Volt-Junkie
    Registriert seit
    06.03.2008
    Alter
    30
    Beiträge
    946
    Hi und willkommen im Forum!

    Womit versorgust Du deine Servos? Hast Du schon versucht einzelne Servos anzusteuern? Es könnte an Stromverbrauch (spitzen) liegen. Es ist empfehlenswert noch ein paar Kondensatoren in die Versorgungsleitungen der Servos einzubauen.

    Hast Du die Signale auch ohne Servos gemessen? Tritt dieser Fehler dann immer noch auf?

  3. #3
    Benutzer Stammmitglied
    Registriert seit
    06.09.2012
    Beiträge
    30
    Servo Controller dazwischen hängen, der sich ausschliesslich um die Servos kümmert?

  4. #4
    Neuer Benutzer Öfters hier
    Registriert seit
    18.09.2012
    Beiträge
    7
    Hallo,

    danke schonmal für die Antworten.
    Also ich habe die Servos anfangs mit nem Schaltnetzteil und nem dicken Kondensator dazwischen beschaltet.
    Zurzeit läuft die Stromversorgung über eine umgebautes PC Netzteil. Da sollte die Spannung ja sauber sein. Wenn alles funktioniert, habe ich schon Akkus, die ja alles mitmachen sollten. Ich habe testweise schonmal kleine Kondensatoren zwischen Servos und Versorgung geschaltet, aber ohne Unterschied.
    So ein Servocontroller ist teuer und ich habe auch nicht allzuviel Geld zur Verfügung. Ich dachte halt, dass das Programm und der AtMega16 das hinbekommen würden. Auf jedenfall bekommen die das rechnerisch hin.
    Ohne Last habe ich die Signale auch schon geprüft, da war auch kein Unterschied. Ich habe schon den AtMega ausgetauscht, den Quarz ausgetauscht, die Servos ausgetauscht, alles ohne Veränderung. Meine Schlussfolgerung war, dass das Programm entweder nicht funktioniert oder ich zu blöd bin ne ordentliche Platine zu entwerfen und zu ätzen.
    Ich dachte anfangs auch, dass es an den Spitzen liegt, wenn alle Servos arbeiten, da ich dann schon so auf 4A max komme. Aber das PC Netzteil macht das ja locker mit (theoretisch).

  5. #5
    Erfahrener Benutzer Roboter Genie Avatar von HeXPloreR
    Registriert seit
    08.07.2008
    Ort
    24558
    Alter
    39
    Beiträge
    1.356
    Ich denke auch es sind Belastungsspitzen. Du hast Externe Versorgung für die Servos, woher kommt die?
    Ich würde vorschlagen Du trennst vorerst die Versorgungsspannung µC und Servos - falls noch nicht oder nicht korrekt. Weiter sind Stützkondensatoren in den Versorgungsleitungen, und auch zum µC eine Gute Idee.
    Du besorgst Dir einen LiPo Akku mit mindestens 2000mAh 11,1V (10C) dazu eine kleine Schaltung mit dem 7805 der dir 5V liefert.
    Der 7805 den du verbaut hast welche Leistung kann der vertragen 1A oder 2A? -oder mehr? Wird der besonders warm?

    Wenn ich mal wüßte was beim BrownOut detection konkret passiert?

    Wenn es anfangs lief, was hast Du verändert das es nun nicht mehr richtig läuft?

    Als allerersten versuch das nochmal einzu grenzen würde ich alles Servos abnehmen, und nur das bein welches am meisten mit dem Fehler auffällt dran lassen, dann ganz normal das Programm laufen lassen und wenn da dann immer noch etwas hackt und zuckt ist der Fehler höchstwahrscheinlich im Programm, da Du ja sagst deine Leistung sollte eigentlich für 18 Servos ausreichen, dann sollte es kein Problem bei 2-3 Servos mit der Versorgung geben und wenn der Fehler immer noch auftritt müsste er ja aus dem programm kommen. Probier das vielleicht seperat mit allen Beinen durch.
    Geändert von HeXPloreR (18.09.2012 um 18:30 Uhr)
    "Es ist schwierig, jemanden dazu zu bringen, etwas zu verstehen, wenn er sein Gehalt dafür bekommt, dass er es nicht versteht" [Upton Sinclair] gez-boykott

  6. #6
    Moderator Robotik Einstein Avatar von HannoHupmann
    Registriert seit
    19.11.2005
    Ort
    München
    Alter
    34
    Beiträge
    4.528
    Blog-Einträge
    1
    Wenn schon ein Osizi da ist dann mess mal die Spannung nach und kuck ob nicht dort ein ungewollter Spanungseinbruch ist. So wie du das Beschreibst und die Kollegen das schon richtig erkannt habe, lässt es eher auf einen Fehler in der Stromversorgung schliessen.

  7. #7
    Neuer Benutzer Öfters hier
    Registriert seit
    18.09.2012
    Beiträge
    7
    Argh
    also zu allererst:
    @HeXPloreR:

    ich habe nen Schaltplan hochgeladen, sowie gesagt, dass die Servos von einem PC Netzteil oder auch schon mit Akku bestromt werden.
    Weiter habe ich auch erwähnt, dass ich schon Kondensatoren zwischengeschaltet habe und dies keinen Unterschied ergeben hat.
    Was meinst du jetzt mit der Brown Out Detection?
    Meines Erachtens habe ich auch nichts geändert. Ich habe die Platine genommen, sie von dem Prototyp Hexapod auf meinen neuen gesetzt, der etwas größer und stabiler gebaut war und bessere Servos hat, habe die angeschlossen und seitdem Problem.
    Die Platine habe ich seitdem paarmal neu geätzt und auch verbessert(meines Erachtens). Die einzigen Änderungen waren jedoch dickere Leiterbahnen und eine LED ^^
    Ich habe schon alle Servos einzeln getest, einzelne Beine, nur eine Seite: das Ergebnis ist immer dasselbe. Es ruckelt.
    Wenn ich jedoch ein Programm schreibe, was einen Servo auf einer Position halten soll und nicht mehr macht mit derselben Stromversorgung, dann funktioniert das. Bzw. es hat vor einigen Wochen mal funktioniert. Ich werde es nachher nochmal ausprobieren.
    Meine Vermutung ist ja auch das Programm. Jedoch weiß ich leider nicht wo. Und wie gesagt, ich habe auch schon die "webbotlib" ausprobiert, die dafür geschrieben wurde und genau derselbe Fehler ist aufgetreten. Aber auf eine Lösung bin ich bisher noch nicht gekommen, deswegen frage ich ja hier nach einer Idee. Ich wüsste nicht wie ich eine saubere Versorgungsspannung als mit einem Akku hinbekommen soll.

    @ HannoHupmann

    Wo ist denn der Fehler dann in der Stromversorgung?
    Der Fehler tritt, wie schon oben beschrieben, immer an derselben Stelle auf wenn die Beine von oben nach unten gehen ungefähr mittig.
    Wieso sollte genau da die Spannung weg brechen? Die Last ist doch von unten nach oben stärker dachte ich.
    Ich habe auch schon im Akkubetrieb versucht die Servos zu steuern und bei einem Akku kann die Spannung doch ansich nicht weg brechen?

    Also ich weiß nicht, ob ich mich jetzt mehr mit einem Programmfehler auseinandersetzen muss oder doch das Problem an der Hardware liegt.bzw. Stromversorgung liegt oder ob sogar der Takt vom AtMega einfach falsch ist oder sonstwas.

  8. #8
    Moderator Robotik Visionär Avatar von radbruch
    Registriert seit
    27.12.2006
    Ort
    Stuttgart
    Alter
    54
    Beiträge
    5.782
    Blog-Einträge
    8
    Hallo

    Mein Code für 18 Servos mit einem 16MHz Mega16:
    http://www.roboternetz.de/community/...l=1#post524912

    Die Ansteuerung ist auf die zwei CompareMatch-ISR des Timer1 aufgeteilt. Die Impulse für die Servos werden jeweils nacheinander ausgegeben, dadurch werden die Anlaufströme gleichmässiger verteilt. Der Bereich der Impulslängen für meine Servos (ES05) war von ca. 200 bis ca. 500 (mit Reserve). 500 entspricht 2ms, 5000 dauert 20ms und ist die Startwiederholzeit von der während eines Zykluses die einzelnen Impulslängen abgezogen werden. Mit Impulslänge=0 wird das betreffende Servo nicht angesteuert.

    Zusätzliche Funktionen: 1/50-Sekunde Pause mit sleep() die mit den Servoimpulsen synchronisiert ist, gepufferter USART-Empfang per Interrupt und senden von Char, String und Integer (38400Baud), SPI-Ansteuerung und Terminalansteuerung für "Beine" mit drei Servos:

    ax,wert - Steuert das xte Servo im Strang A mit dem Wert wert an (x von 1 bis 9, wert von 200 bis 500)
    bx,wert - Steuert das xte Servo im Strang B mit dem Wert wert an
    cx,wert1,wert2,wert3 - Gibt an Bein x die Werte wert1, wert2 und wert3 an die Servos 1,2 und 3 aus.

    (Der letzte Wert in c() legt eine Wartezeit zwischen den Änderungen für einzelnen Servos in 1/50sek fest.)

    Das ist als Inspiration gedacht, denn auch bei der Servoansteuerung führen viele Wege zum Ziel.

    Gruß

    mic
    Geändert von radbruch (18.09.2012 um 19:30 Uhr)

    Atmel’s products are not intended, authorized, or warranted for use
    as components in applications intended to support or sustain life!

  9. #9
    Erfahrener Benutzer Roboter Genie Avatar von HeXPloreR
    Registriert seit
    08.07.2008
    Ort
    24558
    Alter
    39
    Beiträge
    1.356
    hmm, im programm fällt so auf den ersten blick nur auf das Du 20 PWM channels angibst, kann es möglich sein dass das bei 18 Servos zwei zuviel sind? Ist ein Servo vielleicht doppelt angesteuert?-ausversehen?
    ...benötigst Du diese momentan für etwas, sonst kannst Du sie vielleicht kurzfristig auf 18 ändern. Möglicher wird dadurch tatsächlich ein (timer)Überlauf irgendwo produziert. Oder dadurch Servopositionen bzw (PWM-frequenz) an den falschen Ports ausgegeben?

    Wie meinst Du dass das ein Akku nicht einbrechen kann?
    Ein normaler Akku kann gegebenfalls nicht so schnell auf die wechselnde Last der Servos reagieren, dadurch bricht die Spannung kurzfristig ein (die Kapazität kann nicht schnell genug abgegeben werden, ohne das der Akku schaden nimmt), das zucken entsteht. Stützkondensatoren können soetwas anfanglich kompensieren. Abhilfe schafft aber wohl nur ein Akku, getrennt von der Versorgungsspannung des µC, mit den überragenden Eigenschaften eines LiPo's genug Kapazität schnell zur Verfügung zu stellen.
    "Es ist schwierig, jemanden dazu zu bringen, etwas zu verstehen, wenn er sein Gehalt dafür bekommt, dass er es nicht versteht" [Upton Sinclair] gez-boykott

  10. #10
    RN-Premium User Roboter Genie Avatar von 5Volt-Junkie
    Registriert seit
    06.03.2008
    Alter
    30
    Beiträge
    946
    Alternative wäre mit einem einfachen Programm alle Servos anzusteuern. Ohne Berechnung etc. Sollten sie sich weiterhin komisch verhalten, würde ich die SW fast ausschließen.

    BTW: die Leiterbahnen sind aber ziemlich dünn ausgelegt

Seite 1 von 2 12 LetzteLetzte

Ähnliche Themen

  1. Erster Hexapod (5VJ)
    Von 5Volt-Junkie im Forum Vorstellung+Bilder+Ideen zu geplanten eigenen Projekten/Bots
    Antworten: 109
    Letzter Beitrag: 31.07.2012, 22:02
  2. Erster Hexapod
    Von High Light im Forum Vorstellung+Bilder+Ideen zu geplanten eigenen Projekten/Bots
    Antworten: 106
    Letzter Beitrag: 29.06.2012, 08:41
  3. Erster Hexapod
    Von Wergenter im Forum Allgemeines zum Thema Roboter / Modellbau
    Antworten: 2
    Letzter Beitrag: 25.03.2012, 18:19
  4. Mein erster Hexapod
    Von vitja09 im Forum Vorstellungen+Bilder von fertigen Projekten/Bots
    Antworten: 11
    Letzter Beitrag: 12.11.2010, 07:10
  5. Mein Hexapod Projekt
    Von klucky im Forum Vorstellungen+Bilder von fertigen Projekten/Bots
    Antworten: 32
    Letzter Beitrag: 15.02.2005, 11:13

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •