Hallo liebe AVR-Freunde,
eigentlich gibt es nicht wirklich ein Problem, aber als Perfektionist möchte man annähernd - insbesondere in ISR-Routinen - eine möglichst effiziente Lösung haben.
Für die Steuerung eines Servos habe ich einen OVF Timer auf einem ATmega328 eingerichtet, programmiert in C.
Die Daten:
- Periode 20 msecs = 50 Hz
- Impulsbreite 1,5 msec = Mittelstellung
- Impulsbreite 0,6 msec - 2,5 msec für 180 Grad Drehung (vermutlich etwas unüblich, aber mein Billigservo will es so)
Das läuft so auch zu meiner vollsten Zufriedenheit, der Oszi zeigt diese Werte mit erstaunlicher Stabilität
Das jeweilige HIGH/LOW-Signal für die Impulsbreite liesse sich am entsprechenden Pin wahrscheinlich mit einem CompareA/B automatisch setzen, ich habe es aber aus diversen Gründen manuell gemacht und aus der Arduino-IDE vorläufig "digitalWrite" dafür verwendet.
Diesen wollte ich nun mit "PORTD |= (1<<PD5)" bzw. "PORTD &= ~(1<<PD5)" einfach und effizient ersetzen. Erstaunlicherweise wird dann der Timer langsamer. ich musste den Feinabgleich an TCNT2 um ca. 20 vermindern (prescale=1, 10usec Auflösung) und die Impulse (An-/Abstiegszeit) werden recht schlampig. Die Frequenz von 50 Hz schwankt um bis zu +-8%.
Ein Blick in den Sourcecode von Arduinos "digitalWrite" zeigt einigen Aufwand, u.a. werden auch Ints kurz abgeschaltet - damit läufts wie gesagt auch sehr sauber.
Ich habe testweise vor/nach den PORTD-Bitmanipulationen CLI und SEI probiert - vielleicht etwas stabiler, aber nicht wesentlich wahrscheinlich nur Einbildung.
Prinzipiell würde die Servosteuerung so auch noch funktionieren - aber wenn man mal die Stabilität mit "digitalWrite" gesehen hat, fragt man sich:
Warum soviel Aufwand, um lediglich ein sauberes High/Low zu setzen?
Gruß,
Manfred
P.S.: Einem falsch gesetzten fuse Bit werde ich ja hoffentlich nicht schon wieder zum Opfer gefallen sein.
eigentlich gibt es nicht wirklich ein Problem, aber als Perfektionist möchte man annähernd - insbesondere in ISR-Routinen - eine möglichst effiziente Lösung haben.
Für die Steuerung eines Servos habe ich einen OVF Timer auf einem ATmega328 eingerichtet, programmiert in C.
Die Daten:
- Periode 20 msecs = 50 Hz
- Impulsbreite 1,5 msec = Mittelstellung
- Impulsbreite 0,6 msec - 2,5 msec für 180 Grad Drehung (vermutlich etwas unüblich, aber mein Billigservo will es so)
Das läuft so auch zu meiner vollsten Zufriedenheit, der Oszi zeigt diese Werte mit erstaunlicher Stabilität
Das jeweilige HIGH/LOW-Signal für die Impulsbreite liesse sich am entsprechenden Pin wahrscheinlich mit einem CompareA/B automatisch setzen, ich habe es aber aus diversen Gründen manuell gemacht und aus der Arduino-IDE vorläufig "digitalWrite" dafür verwendet.
Diesen wollte ich nun mit "PORTD |= (1<<PD5)" bzw. "PORTD &= ~(1<<PD5)" einfach und effizient ersetzen. Erstaunlicherweise wird dann der Timer langsamer. ich musste den Feinabgleich an TCNT2 um ca. 20 vermindern (prescale=1, 10usec Auflösung) und die Impulse (An-/Abstiegszeit) werden recht schlampig. Die Frequenz von 50 Hz schwankt um bis zu +-8%.
Ein Blick in den Sourcecode von Arduinos "digitalWrite" zeigt einigen Aufwand, u.a. werden auch Ints kurz abgeschaltet - damit läufts wie gesagt auch sehr sauber.
Ich habe testweise vor/nach den PORTD-Bitmanipulationen CLI und SEI probiert - vielleicht etwas stabiler, aber nicht wesentlich wahrscheinlich nur Einbildung.
Prinzipiell würde die Servosteuerung so auch noch funktionieren - aber wenn man mal die Stabilität mit "digitalWrite" gesehen hat, fragt man sich:
Warum soviel Aufwand, um lediglich ein sauberes High/Low zu setzen?
Gruß,
Manfred
P.S.: Einem falsch gesetzten fuse Bit werde ich ja hoffentlich nicht schon wieder zum Opfer gefallen sein.