-         

Ergebnis 1 bis 7 von 7

Thema: Fehlersuche Impulse zählen und auswerten

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    27.01.2004
    Beiträge
    9

    Fehlersuche Impulse zählen und auswerten

    Anzeige

    Hi,
    ich habe das Gefühl ich sehe wieder den Wald vor lauter Bäumen nicht. Ich hab nun schon mehrmals über den Code geschaut, mehrere Pausen gemacht...aber ich blicks nicht.
    Aber wozu gibts eine nette Community

    Ich habe eine Nibobee welche zwei Antriebsmotoren hat und an jedem einen Odometrysensor, welcher über Interrupts eine Variable hoch bzw. runter zählt.
    Dies wollte ich nun ausnutzen um beide Motoren mit der selben Drezahl drehen zu lassen. Sprich gleich viele Impulse pro bestimmter Zeit. Hier 10 Impulse pro 100ms (14 Impluse pro 100ms entsprechen ca. 100% PWM).

    Um die 100ms zu erreichen habe ich einen Timer, der jede ms "time_odo" incrementiert. Wenn dieser >=100 (falls die 100 verpasst) werden die Impulse vom rechten und linken Sensor eingelesen und mit der Vorgabe abgeglichen und dann das Motor-PWM incrementiert oder decrementiert. Zur Kontrolle noch ein paar LEDs ansteuern, timer_odo wieder auf 0 und fertig.

    Leider habe ich aber nun da Problem das, dass rechte Rad sich langsamer dreht als das Linke und ich nicht verstehe warum.
    Leider habe ich auch noch kein Display / UART und kann mir somit die Werte nicht rausgeben. (Ist aber bestellt)

    Code:
    #include <avr/io.h>
    #include <stdint.h>
    #include <avr/interrupt.h>
    #include <nibobee/motpwm.h>
    #include <nibobee/odometry.h>
    #include <nibobee/sens.h>
    #include <nibobee/delay.h>
    #include <nibobee/iodefs.h>
    
    // Prototypen 
    void LED_init(void);
    void LED_set(int8_t led0, int8_t led1, int8_t led2, int8_t led3);
    void Timer0_init(void);
    
    // globale Variable
    volatile uint16_t time_odo = 0;
    
    /*************
    	   Main
    **************/
    
    int main(void)
    {
    	// IO's init
    	sens_init();
    	Timer0_init();
    	LED_init();
    	odometry_init();
    	motpwm_init();
    
    	// Variable
    	int8_t odo_tick_l = 10;	// 14Ticks in 100ms => 90% PWM 
    	int8_t odo_tick_r = 10;
    	int16_t odo_left = 0;
    	int16_t odo_right = 0;
    	int16_t speed_l = 0;
    	int16_t speed_r = 0;
    
    	// Interrupts aktivieren
    	sei();
    
    	delay(500);
    	odometry_reset();
    
    	while(1)
    	{
    
    			if(time_odo >=100)						// Alle 100ms
    			{			
    				cli();		// Odo-Sensoren einlesen, damit right nicht weiterzählt => Interrupts aus
    				odo_left = odometry_getLeft(1);  // Linker Sensor in "odo_left" und dann reset des Senors
    				odo_right = odometry_getRight(1);  // Rechter Sensor in "odo_right" und dann reset des Senors
    				sei();		// Interrupts wieder an
    					
    				// Left
    				if(odo_left < odo_tick_l)
    				{
    					speed_l +=5;
    					LED_set(0,1,2,2);	
    				}
    				else if(odo_left > odo_tick_l)
    				{
    					speed_l -=5;
    					LED_set(1,0,2,2);
    				}
    				else LED_set(1,1,2,2);
    	
    				// Right
    				if(odo_right < odo_tick_r)
    				{
    					speed_r +=5;
    					LED_set(2,2,1,0);
    				}
    				else if(odo_right > odo_tick_r)
    				{
    					speed_r -=5;
    					LED_set(2,2,0,1);
    				}
    				else LED_set(2,2,1,1);
    
    				time_odo =0;
    			}
    
    			// Motoren mit PWM-Werten füttern
    			motpwm_setLeft(speed_l);
    			motpwm_setRight(speed_r);
    	}
    	return 0;
    }
    
    /*************
    	Funktionen
    *************/
    
    // *** LED ***
    void LED_init(void)
    {
    	DDRB |= (1<<PB0) | (1<<PB1) | (1<<PB2) | (1<<PB3);
    }
    
    void LED_set(int8_t led0, int8_t led1, int8_t led2, int8_t led3)
    {
    // Hier steht die LED ansteuerung, wird aber nicht gebraucht zum Code verstehen
    }
    
    // *** Timer0 ***
    void Timer0_init(void)
    {
    	TCCR0 =  (1<<WGM01);						// Timer im CTC-Modus
    	TCCR0 |= (1<<CS00) | (1<<CS01);	// Prescaler auf 64
    	OCR0 = 234;											// um ca. 1ms zu erreichen
    	TIMSK |= (1<<OCIE0);						// Interrupt "TIMER0_COMP_vect" aktivieren
    }
    
    /*************
    	Interrupts
    *************/
    
    ISR (TIMER0_COMP_vect)
    {
    	time_odo++;
    }
    Ich hoffe ihr könnt einen Fehler entdecken...Ich seh das Problem leider nicht.

    greez

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

    So auf den ersten Blick:

    Code:
                // Left
                if(odo_left < odo_tick_l)
                {
                   if(speed_l < 1019) speed_l +=5; // Maxwert 1023?
                   LED_set(0,1,2,2);
                }
                else if(odo_left > odo_tick_l)
                {
                   if(speed_l > 4)speed_l -=5; // eher unwahrscheinlich
                   LED_set(1,0,2,2);
                }
                else LED_set(1,1,2,2);
    (Ungetestet)

    Können die Motoren innerhalb 1ms die Drehzahl anpassen?

    Gute Kommentare, deshalb großes Lob von mir :)

    Gruß

    mic

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

  3. #3
    Neuer Benutzer Öfters hier
    Registriert seit
    27.01.2004
    Beiträge
    9
    Hi,
    danke für deine Antwort. Da du im Code nach Fehlern gesucht hast gehe ich davon aus, das mein Ansatz nicht ganz falsch sein kann.

    Wiso kommst du auf 1ms zum anpassen der Drezahl? Durch "if(time_odo >=100)" rufe ich nur alle 100ms den Abgleich auf. Oder?
    Wenn ich es richtig seh, hast du in dem Code nur Begrenzugen zugefügt. Diese werden aber nie erreicht (habe ich schon mal mit den Leds anzeigen lassen). Zudem werden diese in der Funktion "motpwm_setXXX()" auch noch überprüft.

    gruß

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

    Wieso kommst du auf 1ms
    Weil ich nach dem Ausrechnen der Timerfrequenz (1001,6Hz) die 100 vergessen hatte. Sorry.

    das mein Ansatz nicht ganz falsch sein kann
    Mein Ansatz war ein anderer, ich habe den zeitlichen Abstand zwischen zwei Löchern gemessen:

    http://www.roboternetz.de/phpBB2/zei...=482547#482547

    Keine Ahnung, welcher Ansatz besser ist und zum Ziel führt. Ich habe an dieser Stelle abgebrochen...

    Gruß

    mic

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

  5. #5
    Neuer Benutzer Öfters hier
    Registriert seit
    27.01.2004
    Beiträge
    9
    Hi,
    ich habe nun meine UART gebaut und habe festgestellt, dass beide Odometry-Sensoren die gleichen Werte bringen, aber die PWM-Werte um ca. 1/4 auseinanderliegen. Deshalb die Rechtskurven. Wenn ich die PWM von Hand einstell, damit er geradeaus fährt sind es aber weit weniger.

    Ich habe die Räder auch schon langsamer von Hand gedreht, aber die Sensoren erfassen alle Übergänge (immer 20 Pulse pro Umdrehung).

    Kann es noch was damit zu tun haben, dass der INT0 (linkes Rad) eine höhere Prio als der INT1 (rechts Rad) hat?

    Hier mal ein kurzer Auszug der erfassten Daten:
    Code:
    odo_L  odo_R  PWM_L PWM_R
    10	10	710	530
    10	11	710	525
    10	10	710	525
    10	12	710	520
    10	11	710	515
    10	12	710	510
    11	11	705	505
    10	10	705	505
    10	10	705	505
    10	10	705	505
    10	10	705	505
    10	12	705	500
    10	7	705	505
    10	10	705	505
    10	8	705	510
    10	12	705	505
    10	10	705	505
    10	11	705	500
    10	11	705	495
    10	9	705	500
    10	11	705	495
    10	12	705	490
    Irgendwo muss doch ein Fehler sein...

    gruß

  6. #6
    Neuer Benutzer Öfters hier
    Registriert seit
    27.01.2004
    Beiträge
    9
    Hat sich erledigt. War ein Hardwaredefekt.
    Hab den OP der die Sensoren auswertet mal getauscht und schon funktionierts...
    Ich liebe Bauteile die ESD-Schäden oder ähnliches haben.

    gruß

  7. #7
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    Ob der Sencor an Int0 oder int1 hängt sollte nicht wesentlich sein, es sein denn der µC wäre völlig überlastet. Das wird hier aber nicht der Fall sein.

    Der rechte Motor scheint nicht ganz so stabil zu sein. Die Schwankungen sind auch nicht symetrisch um den Sollwert und dadruch kommt im Mittel mehr als 10 für den Odometiresensor raus. Das Problem sind die Wert außerhalb von 9 -11: auch wenn der Sensor z.B. 13 zurückgiebt, wird der PWM Wert nur um 5 reduziert, genauso als hätte man 11 gehabt.

    Der unterschiedliche PWM Wert könnte z.B. durch die andere Drehrichting des Motors entstehen, oder durch Unterschiede in der Reibung im Getreibe. Das sollte aber ein gute Regelung kompensieren können.

    Eine Lösung wäre ein besserer Regelungsalgorithmus. Es kommt darauf an, dass auch die Summe der bisher zurückgelegten Schritte stimmt, nicht nur die momentane Geschwindigkeit. Eine einfache Idee wäre eine direkte Proportionalregelung: also statt der Schritte um +-5 den PWM wert um z.B. 3 * (odo_soll - odo_ist) zu verändern. Damit werden im PWM wert die Abweichungen aufaddiert und die Fehler können sich nicht unbegrenzt aufsummieren. Der kleinere Faktor von z.B. 3 eventuell für eine bessere Stbilität.

Berechtigungen

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