Forum: Mikrocontroller und Digitale Elektronik Ansteuerung mehrere Servos


von Steve M. (stevem123)


Angehängte Dateien:

Lesenswert?

Hallo,

nachdem ich schon seit Tagen mit dem Programm versuche mehrere Servos 
erfolglos anzusteuern (nicht wundern es sind gerade nur zwei 
angeschlossen)wollte ich nun hier mal fragen, wo denn mein Fehler liegt. 
Ich nutze einen Atmega328, dieser kann keine Probleme haben, da ich das 
Projekt in einem Simulationsprogramm namens Simulide aufgebaut habe. Ich 
nutze deshalb den CTC-Mode, da ich zu einem Zeitpunkt mit Multiplexern 
bis 18 Servos anschließen will.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Und was ist jetzt die Frage? Was geht nicht wie erwartet?


BTW: Warum ist die Dateiendung "txt"?

von Stefan F. (Gast)


Lesenswert?

Überprüfe die Servo-Signale mit einem Logic Analyzer und zeige und, was 
dabei heraus kam.

Bist du sicher, dass dein CENTER Wert stimmt? Es muss 1,5ms sein.

Und: Der Maximalwert ist keineswegs 2·Center sondern 2ms. Der Minimale 
Wert ist nicht 0,5·Center sondern 1ms. Ich würde mich aber n icht darauf 
verlassen. Viele Servos erreichen schon vorher die Endanschläge und 
gehen kaputt wenn du sie dagegen drücken lässt.

Ist dir bewusst, dass die Pausen zwischen den Impulsen sehr viel länger 
dauern müssen, als die Impulse?

von Steve M. (stevem123)


Lesenswert?

Ja, die Servos bewegen sich nicht. Hat keinen bestimmten Grund nächstes 
Mal lade ich sie als .c hoch:)

von Stefan F. (Gast)


Lesenswert?

Ich sehe gerade: Dein Programm geht sogar davon aus, dass der linke 
Anschlag 0 ms ist - falscher geht es nicht.

von Steve M. (stevem123)


Lesenswert?

Stefan ⛄ F. schrieb:
> Überprüfe die Servo-Signale mit einem Logic Analyzer und zeige
> und, was
> dabei heraus kam.
>
> Bist du sicher, dass dein CENTER Wert stimmt? Es muss 1,5ms sein.
>
> Und: Der Maximalwert ist keineswegs 2·Center sondern 2ms. Der Minimale
> Wert ist nicht 0,5·Center sondern 1ms. Ich würde mich aber n icht darauf
> verlassen. Viele Servos erreichen schon vorher die Endanschläge und
> gehen kaputt wenn du sie dagegen drücken lässt.
>
> Ist dir bewusst, dass die Pausen zwischen den Impulsen sehr viel länger
> dauern müssen, als die Impulse?

Der Logic Analyser zeigt nichts an jedoch sieht man in der MCU das im 
Hintergrund wohl der timer abläuft.

https://www.mikrocontroller.net/articles/Modellbauservo_Ansteuerung#Signalerzeugung_f%C3%BCr_1_Servo_mittels_Timer_(C)

Habe mich an folgendem Artikel orientiert, werde mir die Impulse nochmal 
anschauen.

von Stefan F. (Gast)


Lesenswert?

Das geht nicht:
1
SERVO_DDR = ServoPuls[0] | ServoPuls[1] | ServoPuls[2] | ServoPuls[3] |
2
  ServoPuls[4] | ServoPuls[5] | ServoPuls[6] | ServoPuls[7];

Dein Array hat nur zwei Elemente.

Wenn du Timer 1 startest, musst die ISR auch für Timer 1 (nicht Timer 0) 
sein:
1
ISR (TIMER0_COMPA_vect)

von Stefan F. (Gast)


Lesenswert?

Steve M. schrieb:
> Habe mich an folgendem Artikel orientiert

Da hast du aber einiges missverstanden. Da werden mehrere Servos 
nacheinander angesteuert, so dass jeder Servo ungefähr alle 20 ms einen 
Impuls bekommt.

Wenn du nur zwei Servos im Wechsel ansteuerst ohne zusätzliche Pause 
dazwischen, kommst du nicht auf die 20 ms.

von Stefan F. (Gast)


Lesenswert?

Jetzt habe ich es geschnallt:

MILLISEC_BASE ist 1 ms und wird immer zum ServoValue addiert. Daher muss 
der ServoValue zwischen 0 ms (links) und 1 ms (rechts) liegen.

Das wird die Berechnung der ServoValue Werte wohl so passen. Aber wie 
gesagt: Quäle den Servo nicht indem du ihn gegen die Anschläge fahren 
lässt.

Das Beispiel von dem du abgeguckt hast nimmt jedoch überhaupt keine 
Rücksicht auf die 20ms Intervalle. Wenn alle 8 Servos nach links 
gefahren werden sind es nur 8ms und wenn sie alle nach rechts gefahren 
werden sind es 16ms. Finde ich nicht gut, damit provoziert man Probleme.

Baue das lieber so, dass die 20ms wenigstens ungefähr eingehalten 
werden. Vielleicht magst du von meinem Projekt abgucken: 
http://stefanfrings.de/servocontroller/index.html

von Steve M. (stevem123)


Lesenswert?

Okay vielen Dank schaue ich mir auf jeden Fall mal an!
Das Projekt (das im Rahmen des Studiums stattfindet) wird leider Corona 
geschuldet vorerst nicht über die Simulation hinaus gehen, deshalb sind 
die Servos sowieso nur virtuell.

von STK500-Besitzer (Gast)


Lesenswert?

> MILLISEC_BASE  ( F_CPU  PRESCALER  1000 )

Welche Einheit hat MILLISEC_BASE laut dieser Berechnung?
Vielleicht sowas wie "Hz"?
Dann kann die restliche Rechnerei gar nicht funktionieren.
Ich kann mich aber auch irren, weswegen ich frage.

von Stefan F. (Gast)


Lesenswert?

In meinem Projekt konfiguriere ich den Timer so, dass er alle 4 ms 
überläuft. Ich steuere damit 5 Servos im Wechsel an -> Macht zusammen 4 
mal 5ms = 20 ms Intervalle aus Sicht der Servos.

Bei mir beginnen die Impulse immer mit dem Overflow Interrupt (wenn der 
Zähler auf 0 geht).
Die Impulse enden mit dem COMPA Interrupt, wenn die gewünschte 
Pulsbreite erreicht wurde.

Den COMPB nutze ich parallel dazu um weitere 5 Servos mit gleichzeitig 
anzusteuern.

von Stefan F. (Gast)


Lesenswert?

STK500-Besitzer schrieb:
> Welche Einheit hat MILLISEC_BASE laut dieser Berechnung?

MILLISEC_BASE sind die Anzahl der Timertakte für 1ms.

Ergibt sich auch Systemtakt geteilt durch den Prescaler geteilt durch 
1000. Ich denke, die Berechnung stimmt so.

von STK500-Besitzer (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> In meinem Projekt konfiguriere ich den Timer so, dass er alle 4 ms
> überläuft. Ich steuere damit 5 Servos im Wechsel an -> Macht zusammen 4
> mal 5ms = 20 ms Intervalle aus Sicht der Servos.

Die 20ms sind (inzwischen) irrelevant. Digitale Servos kann man noch 
schneller antreiben.

Und die Aussage, dass 1ms und 2ms schon der Anschlag sind, ist auch 
überholt.
Viele (moderne) Servos haben einen etwas gespreizteren Puls.

von Stefan F. (Gast)


Lesenswert?

STK500-Besitzer schrieb:
> Und die Aussage, dass 1ms und 2ms schon der Anschlag sind, ist auch
> überholt.

Dann ist es aber blöd, dass der Code von Steve (bzw. sein Vorbild im 
Artikel) wegen der hart codierten Addition von 1 ms niemals kürzere 
Impulse erzeugen kann.

Da ist mein Code flexibler, er erlaubt alle Werte zwischen 0 und 4 ms. 
Allerdings (das will ich nicht verheimlichen) nur mit 8 Bit Auflösung, 
weil ich einen 8 Bit Timer verwende. Ich hate mal mit einem 16 Bit Timer 
experimentiert und dabei herausgefunden, dass zumindest meine Servos 
sich sowieso nicht feiner steuern lassen als diese 8 Bit her geben.

von Crazy Harry (crazy_h)


Lesenswert?

Und das ganze einem externen Controller zu überlassen scheidet aus? Ich 
werf mal den PCA9685 in den Ring, der könnte 16 Servos via TWI bedienen.

von STK500-Besitzer (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Dann ist es aber blöd, dass der Code von Steve (bzw. sein Vorbild im
> Artikel) 1 ms als minimalen Wert festlegt.

Das ist ein sicherer Wert. Vielleicht verwendet er ja noch welche von 
anno dazumal. Grundig Varioprop (von Graupner vertrieben) hatte mWn eine 
invertierte Ansteuerung.

von Steve M. (stevem123)


Lesenswert?

Crazy H. schrieb:
> Und das ganze einem externen Controller zu überlassen scheidet aus? Ich
> werf mal den PCA9685 in den Ring, der könnte 16 Servos via TWI bedienen.

Ist leider leider nicht möglich da in dem Simulationsprogramm nicht 
vorhanden deshalb soll das ganze mit drei Multiplexern umgesetzt werden. 
Jeder soll dann 6 Servos ansteuern. Das ganze soll dann für einen 
Hexapod verwendet werden.

von Mike J. (linuxmint_user)


Lesenswert?

Worin liegt denn dein Problem genau, was geht nicht?

Weißt du wie ein Servosignal auszusehen hat?

Du sendest alle 20ms (25ms) einen Puls zum Servo der eine Länge von 1ms 
bis 2ms hat. Mittelposition sind 1,5ms.

Versuche doch erst mal einen einzigen Servo anzusteuern und das kannst 
du dann später erweitern.

Zum Timer:
 12,288 MHz : 1024 (Prescaler) = 12000 Hz

1ms würde ja dann bei 12 maligem ausführen des Interrupts vergangen 
sein.
Nach 24 Interrupts wären das dann 2ms. Ist das nicht eine etwas grobe 
Einstellmöglichkeit?

"MILLISEC_BASE" wäre in deinem Fall ja dann 12.
 Rechne da doch noch mal nach ob er das macht was du möchtest.

von Hermann Kokoschka (Gast)


Lesenswert?

Steve M. schrieb:
> Ja, die Servos bewegen sich nicht. Hat keinen bestimmten Grund...
WAS soll der Unsinn bedeuten: "hat keinen bestimmten Grund.."
Natürlich HAT DAS einen Grund!

Steve M. schrieb:
> Der Logic Analyser zeigt nichts an...
Dann fehlen eben die ServoSignale, falls Du den LA korrekt kontaktiert 
und ausgelesen hast. Also DA ERSTMAL ansetzen, solange KEINE Signale am 
Servo ankommen ist alles andere sekundär.

Natürlich ist das Timing wichtig und in tausenden Online-Quellen 
hinreichend dokumentiert. Variiert teils aber je nach Servo-Typ etwas.

Puls-Pausen-Verhältnis ist relevant, wie schon geschrieben wurde.
Die Grundfrequenz ist aber eher unkritisch, manche Servos "knurren" 
weniger, wenn die Grundfrequenz "servo-abhängig" optimal gewählt ist.

Wie auch bereits gesagt wurde:
Projekt in PHASEN aufteilen, erstmal EIN Servo zum laufen bringen,
DANACH skalieren, egal ob per MPX oder sonstwie.

Dir fehlen (noch) völlige Grundlagen zu Servos, dennoch fängst Du als 
Anfänger direkt mit 18 Servos und MPX-Kram an. So arbeitet man nicht!

UND, MIT VERLAUB:
Reiss Dich jetzt bitte mal etwas zusammen, Steve!
"...hat keinen bestimmten Grund..."
"...Logic Analyser zeigt nichts an..."
Das ist undefinierter Kokolores und hilft nicht weiter.

GUT:
Der STK500 Hinweis auf "alte GR..-Servos", die tatsächlich invertierte 
Signale wollten, eher unwahrscheinlich aber für Dein Projekt, bis auf 
Exoten arbeiten ModellbauServos heute mit pos. Impulsen.

WICHTIG:
Die Infos von STEFANUS wirst Du sehr zu schäzen wissen!
Bei Schritt-2.

ALS ALLER-ERSTES findest Du jetzt mal heraus,
OB überhaupt Signale am Servo ankommen!
Das ist Schritt-1, insofern verstehe ich die Vorredner wenig...

DANN geht es weiter, und wenn Du Dich jetzt wirklich mal konzentrierst 
kriegst Du das auch hin!
Hilfe wirst Du hier bekommen, Servos kriegt man absolut in den Griff!

von Rolf M. (rmagnus)


Lesenswert?

Stefan ⛄ F. schrieb:
> Das Beispiel von dem du abgeguckt hast nimmt jedoch überhaupt keine
> Rücksicht auf die 20ms Intervalle. Wenn alle 8 Servos nach links
> gefahren werden sind es nur 8ms und wenn sie alle nach rechts gefahren
> werden sind es 16ms. Finde ich nicht gut, damit provoziert man Probleme.

Nein, das darf kein Problem sein, denn das passiert auch an einer 
klassischen Fernsteuer-Anlage, wenn auch nicht dauerhaft, sondern mit 
starkem Jitter versehen.

: Bearbeitet durch User
von Steve M. (stevem123)


Lesenswert?

@Hermann Kokoschka
Als erstens mal kein Grund von dir so aus der Haut zu fahren, verstehe 
wirklich nicht weshalb du so eine Umgangsformen ansetzt. Im übrigen war 
das "hat keinen bestimmten Grund" auf das Dateiformat bezogen, hättest 
du die Antwort ganz gelesen wüsstest du das. Bisher waren alle Antworten 
sehr konstruktiv und haben mir sehr weiter geholfen. Weshalb ich deine 
Herangehensweise hier nicht ganz verstehe..

Auf jeden Fall trotzdem noch eine Gute Nacht und Morgen frohe 
Weihnachten

von Hermann Kokoschka (Gast)


Lesenswert?

@Steve M.
Bleibe doch einfach ganz ruhig und erläutere
PUNKT-FÜR-PUNKT (aber wirklich im Detail)
wo ich mich Deiner Meinung nach irre... ;-)

Gute Nacht und ein schönes Fest auch für Dich!

von Gerald M. (gerald_m17)


Lesenswert?

Steve M. schrieb:
> Das ganze soll dann für einen Hexapod verwendet werden.

Kannst du vielleicht mehr zur Anwendung schreiben? Wir steuern auch 
Hexapoden an, aber ein AVR würden wir hierfür nicht benutzen. Ist der 
fix?
Wo passiert die Verrechnung der einzelnen Beine zum Koordinatensystem? 
Wie referenziert ihr, und gibt es vielleicht die Möglichkeit die 
Plattform anstatt der Beine mit einem Sensor zu messen?

von Mike J. (linuxmint_user)


Lesenswert?

Gerald M. schrieb:
> Wir steuern auch
> Hexapoden an, aber ein AVR würden wir hierfür nicht benutzen.

Er wird die Servos mit dem AVR ansteuern und nicht die I/O-Pins des 
Controllers nehmen und damit dann auch Rechenaufwand und damit 
Komplexität auslagern. Ist doch schöner dem AVR nur die entsprechenden 
Soll-Positionen zu geben, dann ist das auch modularisiert und kann auch 
mal ausgetauscht werden.

von Wolfgang (Gast)


Lesenswert?

Hermann Kokoschka schrieb:
> Puls-Pausen-Verhältnis ist relevant, wie schon geschrieben wurde.

Das stimmt doch nicht.
Bei den meisten Modellbauservos wird die Position einzig durch die Länge 
eines positiven Pulses gesteuert. Die Wiederholfrequenz bestimmt die 
Aktualisierungsrate.
Das Puls-Pausen-Verhältnis ist völlig unkritisch. Das verwechselst du 
wohl mit einer Helligkeitssteuerung o.ä. per PWM.

von Gerald M. (gerald_m17)


Lesenswert?

Mike J. schrieb:
> Er wird die Servos mit dem AVR ansteuern

Ja, ich muss sagen ich dachte bei servos an DC Motoren mit Encoder, und 
dass dieser geregelt werden muss.
Einfach nur ein Signal stellen ist ok mit dem AVR, auch wenn ich hierfür 
einen ST Mikrocontroller genommen hätte, der einfach genug Timer hat. 
Dann muss man keine Klimmzüge machen. Das kann man in CubeMX 
konfigurieren und das einzige was man an Code schreiben muss ist der 
Timerwert ins Register des Timers schreiben.

von Oliver S. (oliverso)


Lesenswert?

Rolf M. schrieb:
> Nein, das darf kein Problem sein, denn das passiert auch an einer
> klassischen Fernsteuer-Anlage, wenn auch nicht dauerhaft, sondern mit
> starkem Jitter versehen.

Sollte aber nicht. Die klassische analoge Übertragung hatte 20ms.

Und da die Servos heutzutage nicht aus der Zeit der steinzeitlichen 
Analoganlagen stammen, können die mit kürzeren Framelängen klarkommen, 
müssen aber nicht. Ist aber zunächst egal, denn

Steve M. schrieb:
> Der Logic Analyser zeigt nichts an jedoch sieht man in der MCU das im
> Hintergrund wohl der timer abläuft.

Oliver

von Wolfgang (Gast)


Lesenswert?

Oliver S. schrieb:
> Sollte aber nicht. Die klassische analoge Übertragung hatte 20ms.

Und das steht wo genau?
Beim gemultiplexten Analogsignal gibt es die Pulse, deren Dauer die 
Servostellung steuert und die festen Pausen dazwischen, von den eine 
länger ist, um die Synchronisation zu ermöglichen.
https://www.multiplex-rc-history.de/technische_beschreibung_-101.htm

von STK500-Besitzer (Gast)


Lesenswert?

Wolfgang schrieb:
> Beim gemultiplexten Analogsignal gibt es die Pulse, deren Dauer die
> Servostellung steuert und die festen Pausen dazwischen, von den eine
> länger ist, um die Synchronisation zu ermöglichen.

Die Pause ist aber nicht füs Servo, sondern für den Empfänger, damit der 
den Kanalzähler resetten kann.

von Rolf M. (rmagnus)


Lesenswert?

Oliver S. schrieb:
> Rolf M. schrieb:
>> Nein, das darf kein Problem sein, denn das passiert auch an einer
>> klassischen Fernsteuer-Anlage, wenn auch nicht dauerhaft, sondern mit
>> starkem Jitter versehen.
>
> Sollte aber nicht. Die klassische analoge Übertragung hatte 20ms.

Das schon. Allerdings variiert die Lage der Servo-Pulse innerhalb des 
20ms-Intervalls und damit auch die Pausendauer, die ein Servo sieht.  Im 
Schnitt sind es 20 ms, aber das ist in einem Frame mal weniger, in einem 
anderen mal mehr. Das ist bei der klassischen PPM-Übertragung ein 
inhärenter Bestandteil, und daher müssen alle Servos zwingend damit klar 
kommen.
Abgesehen davon waren auch die 20ms nicht fest vorgeschrieben.

> Und da die Servos heutzutage nicht aus der Zeit der steinzeitlichen
> Analoganlagen stammen, können die mit kürzeren Framelängen klarkommen,
> müssen aber nicht.

Wie gesagt: In gewissen Grenzen müssen sie.

: Bearbeitet durch User
von Wolfgang (Gast)


Lesenswert?

STK500-Besitzer schrieb:
> Die Pause ist aber nicht füs Servo, sondern für den Empfänger, damit der
> den Kanalzähler resetten kann.

Das macht er mit der verlängerten Pause.

von Oliver S. (oliverso)


Lesenswert?

Um mal wieder aufs Thema zurückzukommen:

Compilieren bringt bei mir ein gefültes dutzendmal die Warnung:
1
../main.c:71:55: warning: array subscript 2 is above array bounds of 'uint8_t[2]' {aka 'unsigned char[2]'} [-Warray-bounds]
2
   71 |    SERVO_DDR = ServoPuls[0] | ServoPuls[1] | ServoPuls[2] | ServoPuls[3] |

Solche grundlegenden Fehler solltest du als erstes Mal beheben.

Oliver

von Oliver S. (oliverso)


Lesenswert?

Steve M. schrieb:
> Der Logic Analyser zeigt nichts an jedoch sieht man in der MCU das im
> Hintergrund wohl der timer abläuft.

Unwahrscheinlich.
1
  // initialize counter
2
  TCNT1 = 0;
3
  OCR1A = MILLISEC_BASE + ServoValue[0];
4
  TIMSK0 |= (1<<OCIE1A);
5
  TCCR1B = (1<<WGM12) | PRESCALER_BITS;  // CTC mode

Finde den Fehler...

Oliver

von Rainer V. (a_zip)


Lesenswert?

So und jetzt?? Nun haben wir zig-mal darüber gestritten, welche Pause 
und welches Signal das Servo nun haben möcht...auch die "modernen" 
digitalen Servos wurden angesprochen...

Wolfgang schrieb:
> von den eine
> länger ist

...die Ente kommt nicht ins Wasser!

von Steve M. (stevem123)


Angehängte Dateien:

Lesenswert?

Hallo, an alle und noch ein schönes neues Jahr!

Hab mein Programm nun, mit einigen Änderungen zum Laufen gebracht.

Ich würde es mal hier reinstellen, eventuell hilft es ja noch jemandem 
der ähnlich Probleme hat.

Danke für euere Hilfe

Grüße

Steve

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.