https://www.mikrocontroller.net/api.php?action=feedcontributions&user=Dl4aas&feedformat=atomMikrocontroller.net - Benutzerbeiträge [de]2024-03-28T14:35:22ZBenutzerbeiträgeMediaWiki 1.38.5https://www.mikrocontroller.net/index.php?title=AVR-Tutorial:_Servo&diff=55563AVR-Tutorial: Servo2011-03-05T22:26:37Z<p>Dl4aas: /* Das Servo-Impulstelegram */</p>
<hr />
<div>Die Seite ist noch im entstehen und bis sie einigermassen vollständig ist, noch kein Teil des Tutorials<br />
<br />
= Allgemeines über Servos =<br />
<br />
= Stromversorung =<br />
Werden Servos an einem µC betrieben, so ist es am Besten, sie aus einer eigenen Stromquelle (Akku) zu betreiben. Manche Servos erzeugen kleine Störungen auf der Versorungsspannung, die einen µC durchaus zum Abstürzen bringen können. Muss man Servos gemeinsam mit einem µC von derselben Stromquelle betreiben, so sollte man sich gleich darauf einrichten, diesen Störimpulsen mit Kondensatoren zu Leibe rücken zu müssen. Unter Umständen ist hier auch eine Mischung als kleinen schnellen Kondensatoren (100nF) und etwas größeren, aber dafür auch langsameren Kondensatoren (einige µF) notwendig.<br />
<br />
Die eindeutig beste Option ist es aber, die Servos strommässig vom µC zu entkoppeln und ihnen ihre eigene Stromquelle zu geben. Servos sind nicht besonders heikel. Auch im Modellbau müssen sie mit unterschiedlichen Spannungen zurechtkommen, bedingt durch die dort übliche Versorung aus Akkus, die im Laufe der Betriebszeit des Modells natürlich durch die Entladung ihre Voltzahl immer weiter reduzieren. Im Modellbau werden Akkus mit 4 oder 5 Zellen verwendet, sodass Servos mit Spannungen von ca. 4V bis hinauf zu ca. 6V zurecht kommen müssen, wobei randvolle Akkus diese 6V schon auch mal überschreiten können. Bei sinkenden Spannungslage verlieren Servos naturgemäß etwas an Kraft bzw. werden in ihrer Stellgeschwindigkeit unter Umständen langsamer.<br />
<br />
Die Servos werden dann nur mit ihrer Masseleitung und natürlich mit ihrer Impulsleitung mit dem µC verbunden.<br />
= Das Servo-Impulstelegram =<br />
Das Signal, das an den Servo geschickt wird, hat eine Länge von ungefähr 20ms. Diese 20ms sind nicht besonders kritisch und sind ein Überbleibsel von der Technik mit der mehrere Kanäle über die Funkstrecke einer Fernsteuerung übertragen werden. Für das Servo wichtig ist die Impulsdauer in der ersten Phase eines Servosignals. Nominell ist dieser Impuls zwischen 1ms und 2ms lang. Wobei das jeweils die Endstellungen des Servos sind, an denen es noch nicht mechanisch begrenzt wird. Eine Pulslänge von 1.5ms wäre dann Servomittelstellung. Für die Positionsauswertung des Servos haben die 20ms Wiederholdauer keine besondere Bedeutung, sieht man einmal davon ab, dass ein Servo bei kürzeren Zeiten entsprechend öfter Positionsimpulse bekommt und daher auch öfter die Position gegebenenfalls korrigiert, was möglicherweise in einem etwas höheren Stromverbrauch resultiert.<br />
<br />
Umgekehrt lässt sich definitiv Strom sparen, indem die Pulse ganz ausgesetzt werden: Der Servo bleibt in der Position, in der er sich gerade befindet - korrigiert sich aber auch nicht mehr. Kommen die Impulse selten, also z.B. alle 50ms, läuft der Servo langsamer in seine Zielposition (praktische Erfahrungen, vermutlich nirgends spezifiziert). Dieses Verhalten lässt sich nutzen, um die manchmal unerwünschten ruckartigen Bewegungen eines Servos abzumildern.<br />
<br />
[[Bild:Servo.gif|framed|center| Servo Impulsdiagramm]]<br />
<br />
Den meisten Servos macht es nichts aus, wenn die Länge des Servoprotokolls anstelle von 20ms auf zb 10ms verkürzt wird. Bei der Generierung des Servosignals muss man daher den 20ms keine besondere Beachtung schenken. Eine kleine Pause nach dem eigentlichen Positionssignal reicht in den meisten Fällen aus und es spielt keine allzugroße Rolle, wie lange diese Pause tatsächlich ist. Generiert man das Imulsdiagramm zb. mit einem Timer, so orientiert man sich daher daran, dass man den 1.0 - 2.0ms Puls gut generieren kann und nicht an den 20ms.<br />
<br />
Reale Servos haben allerdings in den Endstellungen noch Reserven, so dass man bei vielen Servos auch Pulslängen von 0.9 bis 2.1 oder sogar noch kleinere/größere Werte benutzen kann. Allerdings sollte man hier etwas Vorsicht walten lassen. Wenn das Servo unbelastet in einer der Endstellungen deutlich zu 'knurren' anfängt, dann hat man es übertrieben. Das Servo ist an seinen mechanischen Endanschlag gefahren worden und auf Dauer wird das der Motor bzw. das Getriebe nicht aushalten.<br />
<br />
= Programmierung =<br />
== einfache Servoansteuerung mittels Warteschleifen ==<br />
<br />
Im folgenden Programm wurden einfache Warteschleifen auf die im Tutorial übliche Taktfrequen von 4Mhz angepasst, so dass sich die typischen Servo-Pulsdauern ergeben. Ein am Port B, beliebiger Pin angeschlossenes Servo dreht damit ständig vor und zurück. Die Servoposition kann durch laden eines Wertes im Bereich 1 bis ca 160 in das Register r18 und anschliessendem Aufruf von servoPuls in einen Puls für ein Servo umgewandelt werden.<br />
<br />
<avrasm><br />
.include "m8def.inc"<br />
<br />
.equ XTAL = 4000000<br />
<br />
rjmp init<br />
<br />
init:<br />
ldi r16, HIGH(RAMEND) ; Stackpointer initialisieren<br />
out SPH, r16<br />
ldi r16, LOW(RAMEND)<br />
out SPL, r16<br />
<br />
ldi r16, 0xFF<br />
out DDRD, r16<br />
<br />
loop: ldi r18, 0<br />
<br />
loop1: inc r18<br />
cpi r18, 160<br />
breq loop2<br />
<br />
rcall servoPuls<br />
<br />
rjmp loop1<br />
<br />
loop2: dec r18<br />
cpi r18, 0<br />
breq loop1<br />
<br />
rcall servoPuls<br />
<br />
rjmp loop2<br />
<br />
servoPuls:<br />
push r18<br />
ldi r16, 0xFF ; Ausgabepin auf 1<br />
out PORTD, r16<br />
<br />
rcall wait_puls ; die Wartezeit abwarten<br />
<br />
ldi r16, 0x00 ; Ausgabepin wieder auf 0<br />
out PORTD, r16<br />
<br />
rcall wait_pause ; und die Pause hinten nach abwarten<br />
pop r18<br />
ret<br />
;<br />
wait_pause:<br />
ldi r19, 15<br />
w_paus_1: rcall wait_1ms<br />
dec r19<br />
brne w_paus_1<br />
ret<br />
;<br />
wait_1ms: ldi r18, 10 ; 1 Millisekunde warten<br />
w_loop2: ldi r17, 132 ; Es muessen bei 4 Mhz 4000 Zyklen verbraten werden<br />
w_loop1: dec r17 ; die innerste Schleife umfasst 3 Takte und wird 132<br />
brne w_loop1 ; mal abgearbeitet: 132 * 3 = 396 Takte<br />
dec r18 ; dazu noch 4 Takte für die äussere Schleife = 400<br />
brne w_loop2 ; 10 Wiederholungen: 4000 Takte<br />
ret ; der ret ist nicht eingerechnet<br />
;<br />
; r18 muss mit der Anzahl der Widerholungen belegt werden<br />
; vernünftige Werte laufen von 1 bis ca 160<br />
wait_puls:<br />
w_loop4: ldi r17, 10 ; die variable Zeit abwarten<br />
w_loop3: dec r17<br />
brne w_loop3<br />
dec r18<br />
brne w_loop4<br />
<br />
rcall wait_1ms ; und noch 1 Millisekunde drauflegen<br />
ret<br />
</avrasm><br />
<br />
Wie meistens gilt auch hier: Warteschleifen sind in der Programmierung nicht erwünscht. Der Prozessor kann in diesen Warteschleifen nichts anderes machen. Etwas ausgeklügeltere Programme, bei denen mehrere Dinge gleichzeitig gemacht werden sollen, sind damit nicht vernünftig realisierbar.<br />
Daher sollte die Methode mittels Warteschleifen nur dann benutzt werden, wenn dies nicht benötigt wird, wie zb einem simplen Servotester, bei dem man die Servoposition zb durch Auslesen eines Potis mit dem ADC festlegt.<br />
<br />
Ausserdem ist die Berechnung der Warteschleifen auf eine bestimmte Taktfrequenz unangenehm und fehleranfällig :-)<br />
<br />
== einfache Servoansteuerung mittels Timer ==<br />
<br />
=== Ansteuerung mit dem 16-Bit Timer 1 ===<br />
<br />
=== Ansteuerung mit dem 8-Bit Timer 2 ===<br />
<br />
Mit einem 8 Bit Timer ist es gar nicht so einfach, sowohl die Zeiten für den Servopuls als auch die für die Pause danach unter einen Hut zu bringen. Abhilfe schafft ein Trick.<br />
<br />
Der Timer wird so eingestellt, dass sich der Servopuls gut erzeugen lässt. Dazu wird der Timer in den CTC Modus gestellt und das zugehörige Vergleichsregister so eingestellt, dass sich die entsprechenden Interrupts zeitlich so ergeben, wie es für einen Puls benötigt wird. In einem Aufruf des Interrupts wird der Ausgangspin für das Servo auf 1 gestellt, im nächsten wird er wieder auf 0 gestellt. Die kleine Pause bis zum nächsten Servoimpuls wird so erzeugt, dass eine gewisse Anzahl an Interrupt Aufrufen einfach nichts gemacht wird. Ähnlich wie bei einer PWM wird also auch hier wieder ein Zähler installiert, der die Anzahl der Interrupt Aufrufe mitzählt und immer wieder auf 0 zurückgestellt wird.<br />
<br />
Die eigentliche Servoposition steht im Register OCR2. Rein rechnerisch beträgt ihr Wertebereich:<br />
<br />
1ms 4000000 / 64 / 1000 OCR2 = 62.5<br />
<br />
2ms 4000000 / 64 / 500 OCR2 = 125<br />
<br />
mit einer Mittelstellung von ( 62.5 + 125 ) / 2 = 93.75<br />
<br />
<avrasm><br />
.include "m16def.inc"<br />
<br />
.equ XTAL = 4000000<br />
<br />
rjmp init<br />
<br />
.org OC2addr<br />
rjmp Compare_vect<br />
<br />
init: <br />
ldi r16, HIGH(RAMEND) ; Stackpointer initialisieren<br />
out SPH, r16<br />
ldi r16, LOW(RAMEND)<br />
out SPL, r16<br />
<br />
ldi r16, 0x80<br />
out DDRB, r16 ; Servo Ausgangspin -> Output<br />
<br />
ldi r17, 0 ; Software-Zähler<br />
<br />
ldi r16, 120<br />
out OCR2, r16 ; OCR0 ist der Servowert<br />
<br />
ldi r16, 1<<OCIE2<br />
out TIMSK, r16<br />
<br />
ldi r16, (1<<WGM21) | (1<<CS22) ; CTC, Prescaler: 64<br />
out TCCR2, r16<br />
<br />
sei<br />
<br />
main:<br />
rjmp main<br />
<br />
Compare_vect:<br />
in r18, SREG<br />
inc r17<br />
cpi r17, 1<br />
breq PulsOn<br />
cpi r17, 2<br />
breq PulsOff<br />
cpi r17, 10<br />
brne return<br />
ldi r17, 0<br />
return: out SREG, r18<br />
reti<br />
<br />
PulsOn: sbi PORTB, 0<br />
rjmp return<br />
<br />
PulsOff: cbi PORTB, 0<br />
rjmp return<br />
</avrasm><br />
<br />
== Ansteuerung mehrerer Servos mittels Timer ==<br />
<br />
----<br />
<br />
{{Navigation_zurückhochvor|<br />
zurücktext=7-Segment-Anzeige|<br />
zurücklink=AVR-Tutorial: 7-Segment-Anzeige|<br />
hochtext=Inhaltsverzeichnis|<br />
hochlink=AVR-Tutorial|<br />
vortext=Watchdog|<br />
vorlink=AVR-Tutorial: Watchdog}}<br />
<br />
[[Category:AVR-Tutorial]]<br />
[[Category:Servos]]</div>Dl4aashttps://www.mikrocontroller.net/index.php?title=Benutzer:Dl4aas&diff=55562Benutzer:Dl4aas2011-03-05T22:17:45Z<p>Dl4aas: </p>
<hr />
<div>Der Benutzername ist mein Amateurfunk-Rufzeichen - und die meisten Basteleien hängen mit diesem Hobby zusammen.<br />
<br />
Die Hauptaktivitäten drehen sich derzeit um Wetterballons mit Amateurfunk-Nutzlasten, dazu findet sich einiges [http://www.ballonprojekt.de hier].</div>Dl4aashttps://www.mikrocontroller.net/index.php?title=Benutzer:Dl4aas&diff=55561Benutzer:Dl4aas2011-03-05T22:17:11Z<p>Dl4aas: Die Seite wurde neu angelegt: „Der Benutzername ist mein Amateurfunk-Rufzeichen - und die meisten Basteleien hängen mit diesem Hobby zusammen. Die Hauptaktivitäten drehen sich derzeit um Wet…“</p>
<hr />
<div>Der Benutzername ist mein Amateurfunk-Rufzeichen - und die meisten Basteleien hängen mit diesem Hobby zusammen.<br />
<br />
Die Hauptaktivitäten drehen sich derzeit um Wetterballons mit Amateurfunk-Nutzlasten, dazu findet sich einiges [[http://www.ballonprojekt.de hier]].</div>Dl4aashttps://www.mikrocontroller.net/index.php?title=AVR-Tutorial:_Servo&diff=55560AVR-Tutorial: Servo2011-03-05T22:13:17Z<p>Dl4aas: /* allgemeines über Servos */</p>
<hr />
<div>Die Seite ist noch im entstehen und bis sie einigermassen vollständig ist, noch kein Teil des Tutorials<br />
<br />
= Allgemeines über Servos =<br />
<br />
= Stromversorung =<br />
Werden Servos an einem µC betrieben, so ist es am Besten, sie aus einer eigenen Stromquelle (Akku) zu betreiben. Manche Servos erzeugen kleine Störungen auf der Versorungsspannung, die einen µC durchaus zum Abstürzen bringen können. Muss man Servos gemeinsam mit einem µC von derselben Stromquelle betreiben, so sollte man sich gleich darauf einrichten, diesen Störimpulsen mit Kondensatoren zu Leibe rücken zu müssen. Unter Umständen ist hier auch eine Mischung als kleinen schnellen Kondensatoren (100nF) und etwas größeren, aber dafür auch langsameren Kondensatoren (einige µF) notwendig.<br />
<br />
Die eindeutig beste Option ist es aber, die Servos strommässig vom µC zu entkoppeln und ihnen ihre eigene Stromquelle zu geben. Servos sind nicht besonders heikel. Auch im Modellbau müssen sie mit unterschiedlichen Spannungen zurechtkommen, bedingt durch die dort übliche Versorung aus Akkus, die im Laufe der Betriebszeit des Modells natürlich durch die Entladung ihre Voltzahl immer weiter reduzieren. Im Modellbau werden Akkus mit 4 oder 5 Zellen verwendet, sodass Servos mit Spannungen von ca. 4V bis hinauf zu ca. 6V zurecht kommen müssen, wobei randvolle Akkus diese 6V schon auch mal überschreiten können. Bei sinkenden Spannungslage verlieren Servos naturgemäß etwas an Kraft bzw. werden in ihrer Stellgeschwindigkeit unter Umständen langsamer.<br />
<br />
Die Servos werden dann nur mit ihrer Masseleitung und natürlich mit ihrer Impulsleitung mit dem µC verbunden.<br />
= Das Servo-Impulstelegram =<br />
Das Signal, das an den Servo geschickt wird, hat eine Länge von ungefähr 20ms. Diese 20ms sind nicht besonders kritisch und sind ein Überbleibsel von der Technik mit der mehrere Kanäle über die Funkstrecke einer Fernsteuerung übertragen werden. Für das Servo wichtig ist die Impulsdauer in der ersten Phase eines Servosignals. Nominell ist dieser Impuls zwischen 1ms und 2ms lang. Wobei das jeweils die Endstellungen des Servos sind, an denen es noch nicht mechanisch begrenzt wird. Eine Pulslänge von 1.5ms wäre dann Servomittelstellung. Für die Positionsauswertung des Servos haben die 20ms Wiederholdauer keine besondere Bedeutung, sieht man einmal davon ab, dass ein Servo bei kürzeren Zeiten entsprechend öfter Positionsimpulse bekommt und daher auch öfter die Position gegebenenfalls korrigiert, was möglicherweise in einem etwas höheren Stromverbrauch resultiert.<br />
<br />
[[Bild:Servo.gif|framed|center| Servo Impulsdiagramm]]<br />
<br />
Den meisten Servos macht es nichts aus, wenn die Länge des Servoprotokolls anstelle von 20ms auf zb 10ms verkürzt wird. Bei der Generierung des Servosignals muss man daher den 20ms keine besondere Beachtung schenken. Eine kleine Pause nach dem eigentlichen Positionssignal reicht in den meisten Fällen aus und es spielt keine allzugroße Rolle, wie lange diese Pause tatsächlich ist. Generiert man das Imulsdiagramm zb. mit einem Timer, so orientiert man sich daher daran, dass man den 1.0 - 2.0ms Puls gut generieren kann und nicht an den 20ms.<br />
<br />
Reale Servos haben allerdings in den Endstellungen noch Reserven, so dass man bei vielen Servos auch Pulslängen von 0.9 bis 2.1 oder sogar noch kleinere/größere Werte benutzen kann. Allerdings sollte man hier etwas Vorsicht walten lassen. Wenn das Servo unbelastet in einer der Endstellungen deutlich zu 'knurren' anfängt, dann hat man es übertrieben. Das Servo ist an seinen mechanischen Endanschlag gefahren worden und auf Dauer wird das der Motor bzw. das Getriebe nicht aushalten.<br />
= Programmierung =<br />
== einfache Servoansteuerung mittels Warteschleifen ==<br />
<br />
Im folgenden Programm wurden einfache Warteschleifen auf die im Tutorial übliche Taktfrequen von 4Mhz angepasst, so dass sich die typischen Servo-Pulsdauern ergeben. Ein am Port B, beliebiger Pin angeschlossenes Servo dreht damit ständig vor und zurück. Die Servoposition kann durch laden eines Wertes im Bereich 1 bis ca 160 in das Register r18 und anschliessendem Aufruf von servoPuls in einen Puls für ein Servo umgewandelt werden.<br />
<br />
<avrasm><br />
.include "m8def.inc"<br />
<br />
.equ XTAL = 4000000<br />
<br />
rjmp init<br />
<br />
init:<br />
ldi r16, HIGH(RAMEND) ; Stackpointer initialisieren<br />
out SPH, r16<br />
ldi r16, LOW(RAMEND)<br />
out SPL, r16<br />
<br />
ldi r16, 0xFF<br />
out DDRD, r16<br />
<br />
loop: ldi r18, 0<br />
<br />
loop1: inc r18<br />
cpi r18, 160<br />
breq loop2<br />
<br />
rcall servoPuls<br />
<br />
rjmp loop1<br />
<br />
loop2: dec r18<br />
cpi r18, 0<br />
breq loop1<br />
<br />
rcall servoPuls<br />
<br />
rjmp loop2<br />
<br />
servoPuls:<br />
push r18<br />
ldi r16, 0xFF ; Ausgabepin auf 1<br />
out PORTD, r16<br />
<br />
rcall wait_puls ; die Wartezeit abwarten<br />
<br />
ldi r16, 0x00 ; Ausgabepin wieder auf 0<br />
out PORTD, r16<br />
<br />
rcall wait_pause ; und die Pause hinten nach abwarten<br />
pop r18<br />
ret<br />
;<br />
wait_pause:<br />
ldi r19, 15<br />
w_paus_1: rcall wait_1ms<br />
dec r19<br />
brne w_paus_1<br />
ret<br />
;<br />
wait_1ms: ldi r18, 10 ; 1 Millisekunde warten<br />
w_loop2: ldi r17, 132 ; Es muessen bei 4 Mhz 4000 Zyklen verbraten werden<br />
w_loop1: dec r17 ; die innerste Schleife umfasst 3 Takte und wird 132<br />
brne w_loop1 ; mal abgearbeitet: 132 * 3 = 396 Takte<br />
dec r18 ; dazu noch 4 Takte für die äussere Schleife = 400<br />
brne w_loop2 ; 10 Wiederholungen: 4000 Takte<br />
ret ; der ret ist nicht eingerechnet<br />
;<br />
; r18 muss mit der Anzahl der Widerholungen belegt werden<br />
; vernünftige Werte laufen von 1 bis ca 160<br />
wait_puls:<br />
w_loop4: ldi r17, 10 ; die variable Zeit abwarten<br />
w_loop3: dec r17<br />
brne w_loop3<br />
dec r18<br />
brne w_loop4<br />
<br />
rcall wait_1ms ; und noch 1 Millisekunde drauflegen<br />
ret<br />
</avrasm><br />
<br />
Wie meistens gilt auch hier: Warteschleifen sind in der Programmierung nicht erwünscht. Der Prozessor kann in diesen Warteschleifen nichts anderes machen. Etwas ausgeklügeltere Programme, bei denen mehrere Dinge gleichzeitig gemacht werden sollen, sind damit nicht vernünftig realisierbar.<br />
Daher sollte die Methode mittels Warteschleifen nur dann benutzt werden, wenn dies nicht benötigt wird, wie zb einem simplen Servotester, bei dem man die Servoposition zb durch Auslesen eines Potis mit dem ADC festlegt.<br />
<br />
Ausserdem ist die Berechnung der Warteschleifen auf eine bestimmte Taktfrequenz unangenehm und fehleranfällig :-)<br />
<br />
== einfache Servoansteuerung mittels Timer ==<br />
<br />
=== Ansteuerung mit dem 16-Bit Timer 1 ===<br />
<br />
=== Ansteuerung mit dem 8-Bit Timer 2 ===<br />
<br />
Mit einem 8 Bit Timer ist es gar nicht so einfach, sowohl die Zeiten für den Servopuls als auch die für die Pause danach unter einen Hut zu bringen. Abhilfe schafft ein Trick.<br />
<br />
Der Timer wird so eingestellt, dass sich der Servopuls gut erzeugen lässt. Dazu wird der Timer in den CTC Modus gestellt und das zugehörige Vergleichsregister so eingestellt, dass sich die entsprechenden Interrupts zeitlich so ergeben, wie es für einen Puls benötigt wird. In einem Aufruf des Interrupts wird der Ausgangspin für das Servo auf 1 gestellt, im nächsten wird er wieder auf 0 gestellt. Die kleine Pause bis zum nächsten Servoimpuls wird so erzeugt, dass eine gewisse Anzahl an Interrupt Aufrufen einfach nichts gemacht wird. Ähnlich wie bei einer PWM wird also auch hier wieder ein Zähler installiert, der die Anzahl der Interrupt Aufrufe mitzählt und immer wieder auf 0 zurückgestellt wird.<br />
<br />
Die eigentliche Servoposition steht im Register OCR2. Rein rechnerisch beträgt ihr Wertebereich:<br />
<br />
1ms 4000000 / 64 / 1000 OCR2 = 62.5<br />
<br />
2ms 4000000 / 64 / 500 OCR2 = 125<br />
<br />
mit einer Mittelstellung von ( 62.5 + 125 ) / 2 = 93.75<br />
<br />
<avrasm><br />
.include "m16def.inc"<br />
<br />
.equ XTAL = 4000000<br />
<br />
rjmp init<br />
<br />
.org OC2addr<br />
rjmp Compare_vect<br />
<br />
init: <br />
ldi r16, HIGH(RAMEND) ; Stackpointer initialisieren<br />
out SPH, r16<br />
ldi r16, LOW(RAMEND)<br />
out SPL, r16<br />
<br />
ldi r16, 0x80<br />
out DDRB, r16 ; Servo Ausgangspin -> Output<br />
<br />
ldi r17, 0 ; Software-Zähler<br />
<br />
ldi r16, 120<br />
out OCR2, r16 ; OCR0 ist der Servowert<br />
<br />
ldi r16, 1<<OCIE2<br />
out TIMSK, r16<br />
<br />
ldi r16, (1<<WGM21) | (1<<CS22) ; CTC, Prescaler: 64<br />
out TCCR2, r16<br />
<br />
sei<br />
<br />
main:<br />
rjmp main<br />
<br />
Compare_vect:<br />
in r18, SREG<br />
inc r17<br />
cpi r17, 1<br />
breq PulsOn<br />
cpi r17, 2<br />
breq PulsOff<br />
cpi r17, 10<br />
brne return<br />
ldi r17, 0<br />
return: out SREG, r18<br />
reti<br />
<br />
PulsOn: sbi PORTB, 0<br />
rjmp return<br />
<br />
PulsOff: cbi PORTB, 0<br />
rjmp return<br />
</avrasm><br />
<br />
== Ansteuerung mehrerer Servos mittels Timer ==<br />
<br />
----<br />
<br />
{{Navigation_zurückhochvor|<br />
zurücktext=7-Segment-Anzeige|<br />
zurücklink=AVR-Tutorial: 7-Segment-Anzeige|<br />
hochtext=Inhaltsverzeichnis|<br />
hochlink=AVR-Tutorial|<br />
vortext=Watchdog|<br />
vorlink=AVR-Tutorial: Watchdog}}<br />
<br />
[[Category:AVR-Tutorial]]<br />
[[Category:Servos]]</div>Dl4aas