Forum: Mikrocontroller und Digitale Elektronik Servo: Ansteuerungsproblem


von André K. (freakazoid)


Lesenswert?

Hallo,

für meinen ersten Servotest hab ich ein kleines Programm geschrieben,
welches folgenden Teil in einer ISR alle 20ms ausführt:

[asm]
    sbi     PORTA, 0
    ldi     XL, lo8(n)  1
    ldi     XH, hi8(n)  1
    L1:
    sbiw    XL, 1       2
    brne    L1          2/1
    nop                 1
    cbi     PORTA, 0    1
[/asm]

Die Anzahl der Takte zwischen sbi und cbi sind also: 7+4*(n-1)
Mit F=7372800Hz lassen sich die Zeiten für Links-Rechts-Anschlag
berechnen: n = (Zeit*F-7)/4+1

Leider hab ich zwischen den errechneten Werten und den tatsächlichen
Werten (Ausprobieren) große Abweichungen.

  1ms   ~ 1842 (gerechnet) 1200 (Ausprobieren)
  1,5ms ~ 2764 (gerechnet)
  2ms   ~ 3686 (gerechnet) 4000 (Ausprobieren)

Woran kann das liegen?

Grüße, Freakazoid

von Jens D. (jens) Benutzerseite


Lesenswert?

Hallo, Poste mal das gesamte Programm..

mit dem Fetzen kann man nix anfanngen

von André K. (freakazoid)


Lesenswert?

???
Generell versteh ich Dein Anliegen, aber die ISR ist nicht viel länger
;-)
Wenn aber das 'Brimborium' drumherum von Interesse ist, bitte:

#define __SFR_OFFSET 0
#include "avr/io.h"

.global main
.global TIMER0_COMP_vect

#define Crystal     7372800

main:
    ldi     18, 0xff                                // PortA -> Output
    out     _SFR_IO_ADDR(DDRA), 18

    ldi     18, (1<<WGM01)|(1<<CS02)|(1<<CS00)      // CTC, Prescale
1024 -> 7200 Zählererhöhungen/Sek
    out     _SFR_IO_ADDR(TCCR0), 18
    ldi     18, 144-1
    out     _SFR_IO_ADDR(OCR0), 18

    ldi     18, (1<<OCIE0)
    out     _SFR_IO_ADDR(TIMSK), 18

    sei

    L0:
    rjmp    L0

TIMER0_COMP_vect:
    push    18
    in      18, _SFR_IO_ADDR(SREG)
    push    18

    sbi     PORTA, 0
    ldi     XL, lo8(1500)
    ldi     XH, hi8(1500)
    L1:
    sbiw    XL, 1
    brne    L1
    nop
    cbi     PORTA, 0

    pop     18
    out     _SFR_IO_ADDR(SREG), 18
    pop     18
    reti

Denke aber trotzdem, daß der Fehler im 'Fetzen' liegt. Die ISR wird
alle 20ms aufgerufen.

Grüße, Freakazoid

von Jens D. (jens) Benutzerseite


Lesenswert?

7372800Hz / 1024(Pre) / 144(OCR) macht 50Takte / Sekunde also alle 20mS
ein Interrupt, wenn ich mich nicht verguckt habe


Du solltest ersteinmal versuchen den Interrupt alle 2mS (wenn
Nullstellung Servo) ausloessen lassen, und dann toggeln
in asm zB. mit
eor wert, bit

Wie lannge die ISR braucht ist fuer dich unwichtig.

Mit dem Wert in OCR0 kannst du dann die Position bestimmen

von André K. (freakazoid)


Lesenswert?

> 7372800Hz / 1024(Pre) / 144(OCR) macht 50Takte / Sekunde also
> alle 20mS ein Interrupt, wenn ich mich nicht verguckt habe
Das ist Richtig und soll auch so sein (Zykluszeit)

> Du solltest ersteinmal versuchen den Interrupt alle 2mS (wenn
> Nullstellung Servo) ausloessen lassen, und dann toggeln
> in asm zB. mit eor wert, bit
Hm. Dann ist die Zykluszeit aber 4ms (2ms low, 2ms high).
Meines Wissens nach - und ich denke genau da ist das Problem g - ist
die Zykluszeit 20ms mit einer variablen Pulsdauer (High-Phase) von
1...2 ms, oder?

> Wie lannge die ISR braucht ist fuer dich unwichtig.
Ja. Sonst hätte ich auch keine 'Warteschleife' in der ISR gebastelt.
Ich weiß, daß das böse ist.

Ist mein erster Versuch mit Servos und ich wollte das Programm so
einfach wie möglich gestalten.

Grüße, Freakazoid

von André K. (freakazoid)


Lesenswert?

Noch was:

> Du solltest ersteinmal versuchen den Interrupt alle 2mS (wenn
> Nullstellung Servo) ausloessen lassen
Wieso hast Du 'Nullstellung' dazugeschrieben? Ist es nicht der Sinn
eines Servos eine Stellung abhängig von der Impulsdauer anzufahren?
Dann sollte die Startstellung doch irrelevant sein, oder?

Grüße, Freakazoid

von Jens D. (jens) Benutzerseite


Lesenswert?

Schau mal..

der Timer generiert alle 1mS +/- 0,5mS einen INT..
du Springst in die INT rein (Timer MUSS im ctc mode laufen) und kannst
sogar den Timer über PWM den Portpin toggeln lassen..
Nur muss der Timer eben mit der doppelten frequenz laufen.

(Tiny 45)
    ldi wr0,  (1<<WGM01)
    out TCCR0A, wr0

    ldi wr0,  (1<<CS02 | 1<<CS00)
    out TCCR0B, wr0

    ldi wr0,  (39)
    out OCR0A, wr0

von Karl heinz B. (kbucheg)


Lesenswert?

> tatsächlichen Werten (Ausprobieren) große Abweichungen.
>
>  1ms   ~ 1842 (gerechnet) 1200 (Ausprobieren)
>  1,5ms ~ 2764 (gerechnet)
>  2ms   ~ 3686 (gerechnet) 4000 (Ausprobieren)

Hast du die Zeiten gemessen oder einfach das Servo
angehängt und solange probiert bis du am Linksanschlag
warst?

Die meisten Servos kommen auch mit Pulsen kürzer
als 1 ms bzw. länger als 2 ms ohne Probleme zurecht.

von André K. (freakazoid)


Lesenswert?

?

1. Version:
> Du solltest ersteinmal versuchen den Interrupt alle 2mS (wenn
> Nullstellung Servo) ausloessen lassen,

2. Version:
> der Timer generiert alle 1mS +/- 0,5mS einen INT..

Das verwirrt mich ;-)

> du Springst in die INT rein (Timer MUSS im ctc mode laufen) und
> kannst sogar den Timer über PWM den Portpin toggeln lassen..
> Nur muss der Timer eben mit der doppelten frequenz laufen.
Das ist klar.

ABER:
Warum INTs in so kurzen Abständen? Ich hab ja nichts gegen Deinen
Vorschlag, aber WARUM funktioniert das Programm oben nicht, wenn der
INT alle 20ms aufgerufen wird?
Ich weiß, daß der AVR mir mit der PWM viel abnehmen kann. Das ist aber
nicht der Punkt.
Nachdem was ich gelesen habe sollte es funktionieren. Tut es ja auch,
aber eben nicht so exakt wie berechnet. Das ist mein Problem ;-(

Halt mich bitte nicht für stur (ich bin Dir sogar dankbar für die
Tipps), aber ich würde gerne erstmal in dem simplen Programm oben den
Fehler finden, bevor ich 1000 andere Kniffe ausprobiere.

Grüße, Freakazoid

von André K. (freakazoid)


Lesenswert?

> Hast du die Zeiten gemessen oder einfach das Servo
> angehängt und solange probiert bis du am Linksanschlag
> warst?
Letzteres.

> Die meisten Servos kommen auch mit Pulsen kürzer
> als 1 ms bzw. länger als 2 ms ohne Probleme zurecht.
Okay. Das heißt also er würde sich nicht selbst zerstören ;-)
Aber warum erreicht er die Anschläge nicht wie berechnet?
Kann man sich eigentlich auf das 1..2 ms verlassen, oder haben Servos
große Abweichungen? Ich hab auch mal sowas wie 0,8 .. 2,2 gelesen ;-(

Grüße, Freakazoid

von Karl heinz B. (kbucheg)


Lesenswert?

> aber WARUM funktioniert das Programm oben nicht, wenn der
> INT alle 20ms aufgerufen wird?

Weil es so ist, dass die 20 ms so ziemlich das unwichtigste
bei der ganzen Servoansteuerung sind. Die Pulsdauer ist
wichtig. In welchen Abständen die Pulse kommen interessiert
normalerweise kein Servo. OK, die 20ms sollte man nicht
länger machen, aber kürzer ist kein Problem.

-> Für das allerunwichtigste (20ms) benutzt du ein tolles
Hardwarefeature (Timer), dass dich von allen Sorgen befreit.
Für das wirklich kritische, nimmst du eine Loop in einem
Interrupt und handelst dir damit auf lange Sicht ne Menge
Probleme ein.

Allerdings: So wie du das programmiert hast, müsste das
ohne Probleme gehen (in diesem Testfall).
Daher die Frage: Wie hast du die 1 ms ausgemessen?
Mit Messgerät oder mit der Annahme dass, wenn das Servo auf
Linksanschlag liegt, auch 1ms anliegen.

von Karl heinz B. (kbucheg)


Lesenswert?

> Kann man sich eigentlich auf das 1..2 ms verlassen

Absolut nicht.
Servos unterliegen Streuungen. Ausserdem würde es
kein Hersteller wagen, ein Servo bei 1 ms in den mechanischen
Anschlag zu treiben. Ist auch kein Problem im Modellbau.
Das Servo dreht so weit wie es eben dreht und den Weg stellt
man sich durch das Gestänge ein (war früher mal so), bzw.
man stellt Senderseitig die Endpunkte ein. Und auf so manchem
Sender findet mann dann schon mal eine Einstellung von 110%
für die Endlage.

von André K. (freakazoid)


Lesenswert?

> Weil es so ist, dass die 20 ms so ziemlich das unwichtigste
> bei der ganzen Servoansteuerung sind.
Oha. Dachte, daß die 'Kraft' des Servos davon abhängig wäre (in
grobem Rahmen). Zykluszeiten von >50ms sind angeblich schlecht.

> OK, die 20ms sollte man nicht länger machen, aber kürzer ist kein
> Problem.
Also doch. Auch wenn 'kürzer' kein Problem ist (das hab ich ja auch
nie behauptet), ist es eine höhere Last für den AVR. NUR für
Servoansteuerung wäre okay, aber das Baby soll vielleicht noch was
anderes machen ;-)

> -> Für das allerunwichtigste (20ms) benutzt du ein tolles
> Hardwarefeature (Timer), dass dich von allen Sorgen befreit.
> Für das wirklich kritische, nimmst du eine Loop in einem
> Interrupt und handelst dir damit auf lange Sicht ne Menge
> Probleme ein.
Ey. Das ist unfair. Wie ich schon oben erwähnt habe, weiß ich das eine
Loop in einem ISR böse ist. Das ist ein TESTPROGRAMM. Das wird nie,
nie, nie so später aussehen. Es soll nur simpelst sein.
(BTW: Ich würde auch nie sleep(xxx) in einem Programm - vor allem der
ISR - verwenden oder andere zeitintensive Sachen in ISRs machen. Glaube
mir g)

> Allerdings: So wie du das programmiert hast, müsste das
> ohne Probleme gehen (in diesem Testfall).
Okay. Danke. Back to the roots ;-)

> Daher die Frage: Wie hast du die 1 ms ausgemessen?
> Mit Messgerät oder mit der Annahme dass, wenn das Servo auf
> Linksanschlag liegt, auch 1ms anliegen.
Letzteres (Datenblatt). Deswegen auch oben die Frage bezüglich der
möglichen Abweichungen.

Mein Ziel ist es nicht die supertollste Ansteuerung zu konzipieren,
sondern Grundwissen zu sammeln, welches später hilfreich ist.
Sollte ein Servo z.B. große Abweichungen haben, wird es in komplexeren
Programmen später schwierig den Fehler zu finden.

Grüße, Freakazoid

von Jens D. (jens) Benutzerseite


Lesenswert?

Du weisst, dass der Timer weiter laeuft, wenn du in der ISR bist??

von Karl heinz B. (kbucheg)


Lesenswert?

> findet mann dann schon mal eine Einstellung von 110%
> für die Endlage.

Was aber immer noch nicht heisst, das man damit an den
mechanischen Grenzen des Servos angelangt ist. Der
mechanische Anschlag hat nur den einen Sinn zu verhindern
das das Servo rundum dreht. Mehr nicht! Ob dieser mechanische
Anschlag nun bei einer Auslenkung von 60° oder bei 90°
ins Spiel kommt, hängt einzig und allein von der mechanischen
Auslegung des Getriebes ab.
Wenn schon, dann könnte man Linksausschlag bzw. Rechtsausschlag
so definieren, dass die anliegen, wenn eine Auslenkung von
45° (oder 60° oder was auch immer) vorliegen. Aber: Im
Modellbaubereich interessiert das (mit Ausnahme von 180°
Servos) niemanden wirklich.

von Jens D. (jens) Benutzerseite


Lesenswert?

Hast du ein Datenblatt des Servos?

von André K. (freakazoid)


Lesenswert?

>> Kann man sich eigentlich auf das 1..2 ms verlassen
> Absolut nicht.
Damit ist das Problem wohl gelöst. Ich hatte nur Angst das Servo zu
zerstören, wenn es weiter getrieben wird als es kann:
'Dreh', 'Kann nicht', 'Sollst drehen Du Sau', 'Krrgh' ;-)

'Mechanischer Anschlag' hört sich zudem auch nach Endzeit an. Wenn
das Poti (also der Feedbackgeber) sagt: 'Noch nicht am Ziel' würde
ich vermuten, daß der Motor weiter angesteuert wird. Zudem würde wohl
der Stromverbrauch ansteigen (blockierte Motoren machen das gerne).

Grüße, Freakazoid

von Karl heinz B. (kbucheg)


Lesenswert?

> > OK, die 20ms sollte man nicht länger machen, aber kürzer ist kein
> > Problem.
> Also doch. Auch wenn 'kürzer' kein Problem ist (das hab ich ja
auch
> nie behauptet), ist es eine höhere Last für den AVR. NUR für
> Servoansteuerung wäre okay, aber das Baby soll vielleicht noch was
> anderes machen ;-)

Genau darum gehts:
Diese Pulse kann der Timer ganz alleine erzeugen.
Da braucht er keinen ISR dazu.
Timer eingestellt und er tickert dir den Pin im gewünschten
Zeittakt. Du möchtest das Timing ändern. Kein Problem.
Ein Register neu beschreiben und der Timer macht wieder den
Rest.

Noch besser als wenn praktisch 0% Rechenzeit dafür draufgehen
kannst du es nicht kriegen.

von Jens D. (jens) Benutzerseite


Lesenswert?

Eben, und einfach ist es auch noch, man muss nur den einfachen timer
kennen :D

von André K. (freakazoid)


Lesenswert?

Datenblatt leider nicht elektronisch ;-(
Aber ich hab nochmal nachgesehen. Die geben eine Abweichung in der
Pulsbreite von 0,6ms an. Das ist viel. Hab ich wohl übersehen.

> Du weisst, dass der Timer weiter laeuft, wenn du in der ISR bist??
Ja. Warum?

Denke der Thread kann geschlossen werden. Servos unterliegen also
größeren Abweichungen als ich dachte. Gut. Dafür sind sie billig ;-)

Grüße und Danke an Euch beiden, Freakazoid

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.