-
        

Ergebnis 1 bis 8 von 8

Thema: Servo PWM Steuerung

  1. #1

    Servo PWM Steuerung

    Anzeige

    Hi,
    ich hab folgendes Problem, ich habe an den OC2 Port meines Atmel32 die PWM für einen Servo gelegt, der die Lenkung von etwas übernehmen soll.

    Ich hab schon ein bisschen herumprobiert, allersdings hab ich es bisher nur so hinbekommen, das 3 PWM Einheiten meinen Kompletten lenkeinschlag darstellen (wohlgemerkt für rechts, gerade aus und links)

    kann mir jemand einen Tipp geben, welcher Prescaler, welcher PWM Typ etc. man für Servos benutzt?

    danke im Vorraus

    gruss

  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

    Willkommen im RN-Forum.

    Hardware-PWM scheint mir zur Ansteuerung für Servos nicht gut geeignet. Das Impulse-Pause-Verhältniss der Servos ist wohl zu groß, ich habe das aber noch nicht versucht.

    Gute Erfahrungen habe ich mit einfachen Softwareansteuerungen mittels Timerinterrupt gemacht. Recht übersichtlich und, je nach Kontrollertakt, auch für mehrere Servos geeignet. Das Prinzip wird im RN-Wiki beschrieben: http://www.roboternetz.de/wissen/ind...os#Ansteuerung

    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
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    11.12.2007
    Ort
    weit weg von nahe Bonn
    Alter
    33
    Beiträge
    2.378
    Atmega8, Timer 1, WGM 14

    8000000Hz / 64(PS) / 1000(Fast PWM, Top = ICR1)

    macht 8ms von 0 - 1000 gezählt,

    ich übersteuere meine Servos ein wenig und meine stellwerte sind links = 200, mitte = 300, rechts = 400 für alternativ OCR1A bzw. OCR1B

    in der compare match ISR schalte ich das DDRB für die PINs B1 und B2 nur alle 4 interrupts auf ausgang, so bekomm ich ausreichend pause zwischen 2 impulsen

    EDIT: hardware benutze ich nur wenn ich der meinung bin, dass meine Servos ungenau laufen oder sie anfangen zu ruckeln um den fehler einzugrenzen

  4. #4
    Hi,
    danke für die Antworten, ich habe jetzt versucht das mit Interrupt umzusetzen. Alle 10 µs wird ein Interrupt ausgelöst bei dem eine 'TimerVariable' hochgezählt wird. Mit einer Funktion frage ich diese Variable ab und mache über zwei Vergleichswerte (Periodendauer und Highzeit) die PWM zu steuern:

    Theoretisch sollte die PWM den Port 1,5 ms anschalten und 20,5 ms aus sein.
    Praktisch ist das Verhältniss von high und low aber 50 %.

    Ich hab schon einiges an den Werten geändert, es hat sich allerdings nichts getan. Ich seh im moment den Wald vor lauter Bäumen nicht Habt ihr eine idee?

    Code:
    void init()
    {
    	//--- Timer 2 initialisieren ---
    	TCCR2=0x01; 	// Teiler 1/1
    	TCCR2|=0x28; 	// Modus: Zählen bis Vergleichswert
    	OCR2=80; 	// Vergleichswert speichern
    	TIMSK=0x80; 	// Interrupt bei Vergleichswert A
    	//--- Interrupts erlauben ---
    	sei();
    	sbi(DDRC,3);   // PortC3 auf Ausgang
    }
    //--------------------------------------------------------------------
    // TIMER2_COMP_vect - Timer2 Interrupt bei Vergleichswert A
    // aktuelle Einstellung:  100000 Hz  10 µs
    //--------------------------------------------------------------------
    volatile int timer01=0; //Timer zählvariable
    int spwm=50;  // PWM-Wert
    bool x = false;
    
    ISR(TIMER2_COMP_vect)
    {
    		timer01++;
    }
    
    void servo (int timer01)
    {
     	if (timer01<=2200) //2200 * 10 µs = Periodendauer
     	 {
    	 	if (timer01<=(spwm+100))
    	 	{ 
    	 		if (x == false) 
    	 		{
    	 			sbi(PORTC,3);
    	 			x = true;
    	 		}
    	 	 }
    	 	if (timer01>(spwm+100))
    	 	{ 
    	 		if (x == true) 
    	 		{
    	 			cbi(PORTC,3);
    	 			x = false;
    	 		}
    		 }
    	  }
    	 else {timer01=0; //Nachdem die Periode vorbei ist, wird der
                                       //Timerzähler wieder auf null gesetzt
    	       } 	  
    	
    }
    
    main()
    {
    	init();
    	while (true)
    	{
    	
    	servo(timer01);	
    		
    		
    	} 
    }
    vielen danke

    gruß Tobias

  5. #5
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    Ein interrupt alle 10 µs ist schon ziehmlich an der Grenze, da reicht eventuell die Rechenzeit schon nicht mehr aus, bei weniger als 6 MHz Takt.
    Nur um etwas hochzuzählen brauchts auch noch keine ISR, das kann der Timer auch gleich in Hardware.

    Besser wäre es da schon je Servo Kanal nur einen Interrupt auszulösen wenn der Puls zu ende gehen soll. Wenn mehr Kanäle gbraucht werden, dann die pulse nacheinander erzeugen, nicht gleichzeitig.

  6. #6
    Hi,

    also mir arbeiten mit 8 Mhz, daher sollte die von dir angesprchene Problematik ja kein Problem darstellen?

    Ich verstehe einfach nur nicht, warum der µC nicht das macht, was ich brauche.
    Es muss doch irgendein Fehler im Code sein oder?
    Die Logik stimmt doch soweit ?

    gruß

  7. #7
    Benutzer Stammmitglied
    Registriert seit
    20.01.2005
    Ort
    Weimar
    Alter
    34
    Beiträge
    33
    Ich hing bis letzte Woche auch noch daran das ich mit meinem Mega168 Servos mittels PWM steuern wollte. Als Randbedingung stellte ich mir erstmal NUR den 8bit Timer2 zu benutzen doch das wollte partou nicht gehen da das Verhältnis von High zu low ja ungefähr 1/10 entspricht und und per interrupt der ausgelöst wird wenn ein bestimmter Highwert erreicht wurde um den selbigen Timer für die Low Time zu konfigurieren und zu reseten wollte auch nicht so recht funktionieren.

    Naja entnervt bin ich dann zum Soft PWM umgesprungen ,das Programmieren hat keine 10 min gedauert und es lief... Leider ist diese Art der Ansteuerung recht "Schmutzig" den in den Schleifen kann der Mega ja nun nichtsmehr machen...

    Ach ja ich weis ja nicht wo die Highpegel Zeiten herkommen jedoch hab ich durch Oszi Messungen mit einem MG995 Servo ermittelt das die Mittenstellung hier bei 1,5ms high ist und jeweils für links und rechts 1ms also gesamtbereich von 0,5-2,5 ms als low bin ich inmittlerweile bei 12ms angekommen.
    Edit: hab mal ein Bild der ermittelten pwm zeiten erstellt



    Falls wer was zu der Servoansteuerung mittels 8bit timer sagen kann währe ich sehr erfreut , vielleicht habe ich ja etwas übersehen :O

    MFG Hellsing

  8. #8
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    Die Logic in dem Programm oben sieht auf den ersten Blick OK aus. Allerdings wird der Puls durch aktives Warten ausgegeben. Für eine spätere Anwendung ist das ziehmlich unpraktisch.
    Ein kleines Problem ist noch im Code: der zugriff auf Timer01 im Hauptprogramm ist nicht Atomar. das heißt es ist nicht sicher das high und low Byte immer zusammengehören, wenn mittendrin ein Interrupt auftritt. Das kann gelegentliche Fehler verursachen.
    Ist denn sicher das der Controller wirklich mit 8 MHz läuft und nicht den internen 1 MHz.

    Bei 8 MHz sind 10 µs gerade man 80 Zyklen. Allein das sichern der Register für die ISR kann schon so um die 30 Zyklen brauchen.

Berechtigungen

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