www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Poti-Servoansteuerung AVR


Autor: Michi K------ (Firma: keine) (cube)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo ich würde gerne n bißchen Kritik an meinenm Programm und evtl. 
Hilfestellung von euch bekommen.
Ich möchte über ein poti einen Servo ansteuern und habe das jetz erstmal 
wie folgt gelöst oder versucht bin absoluter Anfänger also seid bitte 
nicht zu hart :-)
Ist das so richtig und stimmen meine berechnungen ?

Vielen Dank !

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jetzt sind die Leute schon zu blöd
eine Assemblerdatei mit der Endung .asm zu speichern.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du machst den klassischen Anfängerfehler aller Servoansteuerer.
Du klebst an den 20ms.
Dadurch ergeben sich für die Servo-PWM bei dir nur noch 9 mögliche 
Servopositionen, weil du nur 9 gültige Werte für die PWM hast.


Vergiss die 20ms! Sieh zu, dass du den Einstellbereich der PWM für die 1 
bis 2ms vernünftig ausnutzen kannst. Und was dann noch übrig bleibt - 
das Servo ist damit zufrieden.

Wenn du es so hindrehen kannst dass zb du die 1 bis 2 ms mit 64 Werten 
abbilden kannst, dann kannst du den ADC Wert in den OCR Wert umrechnen 
und bist nicht mehr auf lediglich 3 Servowerte fixiert. Dein Servo 
bewegt sich dann einigermassen flüssig mit dem Poti mit anstelle bei nur 
3 Servopositionen 'einzurasten'.

Modellbauservo Ansteuerung

Autor: Kurt Harders (Firma: KHTronik) (kurtharders)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Vergiss die 20ms! Sieh zu, dass du den Einstellbereich der PWM für die 1
> bis 2ms vernünftig ausnutzen kannst. Und was dann noch übrig bleibt -
> das Servo ist damit zufrieden.

Leider ist das in der Allgemeinheit nicht richtig. Die meisten Servos 
mögen keine Pausenzeit unter ca.15ms. Selbst bei den neuen 
Fernsteuerungen, die mit sehr geringer Pausenzeit < 10ms arbeiten, kann 
man auf 20ms umstellen, damit alte Servos verwendet werden können.
Ich habe mit meinen Weichenantrieben ca. 50 Servotypen getestet, und nur 
ganz wenige konnten Pausenzeiten <10ms.

Autor: Knut Ballhause (Firma: TravelRec.) (travelrec) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Eigentlich doch kein Problem: Man nehme 2 Timer, einen 16-Bit-Timer mit 
PWM und einen anderen 8-Bit-Timer für die Wiederholung. Das PWM wird auf 
rund 1ms bis rund 2ms limitiert (mit einer Auflösung von mindestens 
8Bit) und im Compare-Interrupt wird der PWM-Timer dann abgeschaltet und 
der Wiederholtimer gestartet. Dieser läuft mit einem Overflow oder 
Compare auf 20ms. Ist der 2. Timer abgelaufen, wird in dessen Interrupt 
der 2. Timer gestoppt und der PWM-Timer wieder angestossen. Somit hat 
man eine komplett in Hardware laufende Ausgabe und muss lediglich noch 
die OCR-Register für das PWM updaten. Wenn man 2 oder mehr PWM-Ausgänge 
an dem 16-Bit-Timer hat, kann man die entsprechende Zahl an Servos fast 
komplett in Hardware steuern. Die CPU kann dann andere Peripherie (ADC, 
UART) bedienen oder Werte auf Display oder PC ausgeben.

Autor: Kurt Harders (Firma: KHTronik) (kurtharders)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn man einen 16-Bit-Timer hat, lässt man den mit ca. 20ms Zyklus 
laufen. In meinen Weichenatrieben habe ich den Timer einfach bis 20000 
zählen lassen. Mit den Compare-Registern hat man dann eine PWM mit 1µs 
Auflösung. Das sind dann, bezogen auf den Impuls, 0,1%. Diese Auflösung 
wird von keinem servo erreicht, und der Totbereich eines Servos liegt 
typisch bei >2µs.
In einem ATMega8 kann man dann ohne jeden Interrupt o.ä. 2 Servos 
steuern. Die Software setzt einfach nur die Compare-Register.

Autor: Michi K------ (Firma: keine) (cube)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Erstmal vielen Dank

dann muss ich mich mal noch dahintersetzen,
momentan habe ich allerdings nur einen Attiny13 der hat nur 8bit Timer ?
ist es mit dem 13er überhaupt möglich Servos vernünftig anzusteuern oder 
kann ich das mit dem eher vergessen ?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es geht auch mit 8-Bit Timern.
Allerdings darfst du dann nicht mehr auf Hardware PWM setzen, sondern 
musst dem Teil mit einer ISR etwas unter die Arme greifen und die Pins 
in Software ansteuern.
Aber ansonsten ist das kein Problem. Ich steuere mit einem 8-Bit Timer 
12 Servos (allerdings nicht mit einem Tiny, der hätte nicht genug Pins).

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab mal ein wenig gerechnet.
Mit den 9.6Mhz geht sichs nicht besonders gut aus.
4.8Mhz wären besser

Bei 4.8Mhz Taktfrequenz und einem Vorteiler von 64 hast du eine 
Durchlauffrequenz des Timers von 0 bis 256 mit 292.9 Hz
Das sind 3.4 ms

Das heisst um Zeiten zwischen 1 und 2 ms einzustellen, bewegt sich der 
Comparewert zwischen 75 und 150. Das wären dann immerhin 75 Positionen, 
die das Servo anfahren kann. Sollte eigentlich reichen.

Meine Strategie wäre deshalb:

Ich klemm mich an den Overflow Interrupt
  Ich zähle die Aufrufe der ISR mit. Bei jedem 5.ten Aufruf mache ich:
    Den Servo-Pin auf 1 schalten
    Ins Compare Register den Vergleichswert für die Zeit laden
    Sicherheitshalber das Interrupt Flag für den Compare Interrupt
    löschen
    Den Compare Interrupt einschalten

Im Compare Interrupt
  Den Pin wieder auf 0 setzen
  den Compare Interrupt ausschalten.


Dadurch ergibt sich automatisch ein Timing, dass einen Puls mit der 
gewünschten Länge erzeugt und eine Pause hinten nach, die sich im 
Bereich von ca 17ms bewegt. Und damit sollte jedes Servo zufrieden sein.

Der Trick besteht darin, dass der Pulsanfang vom Overflow Interrupt 
erzeugt wird und das Pulsende vom Compare Interrupt. Der Overflow 
Interrupt richtet gleichzeitig auch alles so ein, dass der Compare 
Interrupt zum gewünschten Zeitpunkt nach dem Pulsanfang aufgerufen wird.

Autor: Michi K------ (Firma: keine) (cube)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
also software PWM wie im Beispiel: 
http://www.mikrocontroller.net/articles/AVR-Tutorial:_PWM

mit den verschiedenen Helligkeitswerten, nur anstatt den Werten für 
versch. Helligkeit, setze ich dafür meine verschiedenen positionen des 
Servos verstehe ich das so richtig ?
und wie im Beispiel der PWMcount ist dann meine (20 oder 10ms) Pause ?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Man könnte auch (etwas einfacher), nur mit dem Compare Match (dem OCR0A 
Register) arbeiten, indem man den CTC Modus benutzt.
Den stellt man so ein, dass der CTC die gewünschte Pulszeit ergibt. 
Zusätzlich benötigt man noch einen Softwarezähler, der die Anzahl der 
ISR Aufrufe mitzählt.
Ist der zähler auf 0, so wird der Ausgangspin auf 1 gesetzt
Ist er auf 1, so wird der Pin wieder abgeschaltet
Hat der Zähler 10 erreicht, so wird der Zähler wieder auf 0 zurück 
gesetzt.


Auch das ergibt ein Timing, mit dem ein Servo etwas anfangen kann.

Autor: Kurt Harders (Firma: KHTronik) (kurtharders)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mit dem ATTiny geht es sicher auch, bei meiner PIC-Version hatte ich 
auch nur einen 8-Bit-Timer. Wenn der Prozessor nichts anderes zu tun 
hat, kann man das per Software machen. Wenn allerdings, wie bei meinen 
Weichenantrieben, alle 50µs noch ein Interrupt kommt, kann man alle 
Softwarelösungen vergessen, denn ein Jitter von > 4µs bringt das Servo 
zum Brummen oder sogar Zappeln. Wenn Du es also einfach und sicher haben 
willst, nimm so etwas wie den ATMega8 und mache es in Hardware.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michi K------ schrieb:
> also software PWM wie im Beispiel:
> http://www.mikrocontroller.net/articles/AVR-Tutorial:_PWM
>
> mit den verschiedenen Helligkeitswerten, nur anstatt den Werten für
> versch. Helligkeit, setze ich dafür meine verschiedenen positionen des
> Servos verstehe ich das so richtig ?

Nicht ganz.

> und wie im Beispiel der PWMcount ist dann meine (20 oder 10ms) Pause ?

Nicht wirklich.
Das Prinzip ist ähnlich, aber doch ganz anders.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kurt Harders schrieb:

> Jitter von > 4µs

das bedeutet bei 4.8Mhz eine Verzögerung von 20 Takten.
Die hat er nie (wenn die Anwendung so bleibt, wie sie sich im Moment 
abzeichnet)

Autor: Knut Ballhause (Firma: TravelRec.) (travelrec) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wichtig ist nur, dass man die Servo-Pins direkt nach dem Einsprung in 
die ISR beeinflusst und bedingte Sprünge, die zwischendrin unbedingt 
sein müssen, mit "NOP" Instruktionen ausgleicht, so dass sich immer 
gleiche Codelaufzeiten ergeben, wenn das Timing kritisch ist. Einen 
Interrupt-Jitter von 0...3 Takten hat man ohnehin immer.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Knut Ballhause schrieb:
> Wichtig ist nur, dass man die Servo-Pins direkt nach dem Einsprung in
> die ISR beeinflusst und bedingte Sprünge, die zwischendrin unbedingt
> sein müssen, mit "NOP" Instruktionen ausgleicht, so dass sich immer
> gleiche Codelaufzeiten ergeben, wenn das Timing kritisch ist. Einen
> Interrupt-Jitter von 0...3 Takten hat man ohnehin immer.

Hattest du bei deiner Lösung damit Probleme?
Meine Erfahrung ist eher: die Unterschiede sind so minimal, das lohnt 
nicht, sich da groß den Kopf zu zerbrechen. Ob ein Puls mal 1/10 µs 
länger oder kürzer ausfällt, lässt das Servo völlig kalt. So genau sind 
die Potis (als mechanisches Bauteil) in den Servos gar nicht.

Autor: Kurt Harders (Firma: KHTronik) (kurtharders)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du hast recht, aber es sind nicht die Potis, sondern die eingebauten 
Elektroniken haben ca. 4µs Totzeit. Bei Digitalservos kann man diese 
Totzeit einstellen, bekommt dann aber eventuell massives Brummen des 
Servos mit sehr hoher Stromaufnahme.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab mich mal an den Assebmler geklemmt

benutzt hab ich die Variante: Alles im Compare Interrupt mit CTC.

Leider hab ich keinen Tiny13 da, sondern nur einen Mega16.
Daher kann ich den auch nicht mit 4.8Mhz laufen lassen, sondern nur mit 
4Mhz :-)
Die Timer Einstellung sollte aber sonst identisch sein. Vorteiler: 64

Das Servo wird verstellt, indem man an OCR0 neue Werte zuweist. Bei dir 
müssten das rein rechnerisch Werte zwischen 75 und 150 sein. Die im 
Programm momentan verwendeten 100, sind bei mir in etwa Mittelstellung 
meiner Servos, aber ich hab ja auch 4Mhz und nicht 4.8
Ach ja, ich erzeuge an PortA, Pin 7 das Signal. Hat keine besonderen 
Gründe, ausser dass ich da leicht mit dem Servokabel rankomme.
.include "m16def.inc"
 
.equ XTAL = 4000000
 
          rjmp    init

.org OC0addr
          rjmp    Compare_vect

init: 
          ldi      r16, HIGH(RAMEND)     ; Stackpointer initialisieren
          out      SPH, r16
          ldi      r16, LOW(RAMEND)
          out      SPL, r16

          ldi  r16, 0x80
          out  DDRA, r16                ; Servo Ausgangspin -> Output

          ldi  r17, 0                   ; Software-Zähler
            
          ldi  r16, 100
          out  OCR0, r16                ; OCR0 ist der Servowert

          ldi  r16, 1<<OCIE0
          out  TIMSK, r16

          ldi  r16, (1<<WGM01) | (1<<CS01) | (1<<CS00)  ; CTC, Prescaler: 64
          out  TCCR0, r16

          sei

main:
          rjmp main

Compare_vect:
          in   r18, SREG
          inc  r17
          cpi  r17, 1
          breq PulsOn
          cpi  r17, 2
          breq PulsOff
          cpi  r17, 10
          brne return
          ldi  r17, 0
return:   out  SREG, r18
          reti

PulsOn:   sbi  PORTA, 7
          rjmp return

PulsOff:  cbi  PORTA, 7
          rjmp return


Da der Wertebereich damit so ca 75 Werte umfasst, würde es sich 
anbieten, den Wert vom ADC (den du ja mittels ADLAR schon auf 0..255 
eingeschränklt hast) noch durch 4 zu dividieren (einfach um 2 Bit nach 
rechts schieben), noch 75 dazuzählen und ab damit ins OCR Register. Das 
ergibt dann 64 Servo Stellungen, die mit dem Poti abgefahren werden 
können.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Yep.
Funktioniert bei mir tadellos

....

          ldi  r16, (1<<WGM21) | (1<<CS22) ; CTC, Prescaler: 64
          out  TCCR0, r16

          ldi  r16, (1<<ADLAR)| (1<<REFS0) | (1<<MUX1) | (1<<MUX0)
          out  ADMUX, r16
          ldi  r16, (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0)
          out  ADCSRA, r16

          sei

main:
          sbi   ADCSRA, ADSC
adc_wait: sbic  ADCSRA, ADSC
          rjmp  adc_wait

          in   r16, adch
          lsr  r16          ; durch 4
          lsr  r16
          subi r16, -75     ; +75 addieren!

          out  OCR0, r16
 
          rjmp main

...


Autor: Kurt Harders (Firma: KHTronik) (kurtharders)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Da der Wertebereich damit so ca 75 Werte umfasst

Bei 75 Schritten auf 90° Drehwinkel sind das 1,2° pro Schritt. Das ist 
sehr grob. Eine Auflösung von 512 Schritten sollte es für 
anspruchsvollere Bewegungen schon sein. Die Totzeit macht es schon 
schwer genug, langsame Bewegungen umzusetzen.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kurt Harders schrieb:
> Karl heinz Buchegger schrieb:
>> Da der Wertebereich damit so ca 75 Werte umfasst
>
> Bei 75 Schritten auf 90° Drehwinkel sind das 1,2° pro Schritt. Das ist
> sehr grob.

Zugegeben. Ich seh bei meinen Servos deutlich den Schritt (auch wenn es 
dann in Natura weit weniger dramatisch aussieht als es sich hier anhört)

Allerdings ist es mit den vorhandenen Mitteln nicht mehr so einfach, 
diese Auflösung zu erreichen.
Machbar ist es, keine Frage.
Aber lass den Fragesteller erst mal mit Timern und den Möglichkeiten 
vertraut werden und wie man mit ISR und Softwarezählern längere 
Zeiträume bei gleichzeitig hoher zeitlicher Auflösung abzählt.

Gegenüber seinen ursprünglich 9 Servostellungen sind 75 schon recht viel 
:-)

Autor: Knut Ballhause (Firma: TravelRec.) (travelrec) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Knut Ballhause schrieb:
>> Wichtig ist nur, dass man die Servo-Pins direkt nach dem Einsprung in
>> die ISR beeinflusst und bedingte Sprünge, die zwischendrin unbedingt
>> sein müssen, mit "NOP" Instruktionen ausgleicht, so dass sich immer
>> gleiche Codelaufzeiten ergeben, wenn das Timing kritisch ist. Einen
>> Interrupt-Jitter von 0...3 Takten hat man ohnehin immer.
>
> Hattest du bei deiner Lösung damit Probleme?
> Meine Erfahrung ist eher: die Unterschiede sind so minimal, das lohnt
> nicht, sich da groß den Kopf zu zerbrechen. Ob ein Puls mal 1/10 µs
> länger oder kürzer ausfällt, lässt das Servo völlig kalt. So genau sind
> die Potis (als mechanisches Bauteil) in den Servos gar nicht.

Jitter kann sich im ungünstigsten Fall addieren. Bei einem mit 
4Mhz-Controller kann der Jitter dann im Bereich von 2µs liegen, bei 
einer Software-Pin-Ansteuerung über Interrupt-Service. Ausserdem darf in 
dem Fall nur ein einziger Interrupt zu einer Zeit erlaubt sein, da sonst 
der Interrupt mit dem PWM auf einen anderen warten muss. Hier kann der 
Jitter dann so groß werden, dass das ganze Signal zusammenbricht. Bei 
einer Hardware-Steuerung des PWM über einen Timer und dessen 
OCR-Register ist der Jitter der steigenden PWM-Flanke praktisch "Null" 
und da das OCR mit dem Timerumlauf übernommen wird, gilt dies auch für 
die fallende Flanke. Am Oszi steht solch ein Signal wie eine 1 ;-). 
Software-PWM für Servos macht also nur auf einem Controller Sinn, der 
recht schnell getaktet ist und wo das Addieren von 
Interrupt-Reaktionszeit plus Portausgabe dann nicht mehr in´s Gewicht 
fällt.

Autor: Michi K------ (Firma: keine) (cube)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen vielen Dank für die Antworten ich muss jetz wenn ich wieder ein 
bißchen Zeit habe mich nochmal dransetzen und mir alles genau durchlesen 
und dann kommen bestimmt noch viele Fragen :-) wünsche jetz aber erst 
mal nen guten Rutsch !

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.