Forum: Mikrocontroller und Digitale Elektronik RC-Empfänger zu Arduino - die 100ste Variante?


von Tom H. (toemchen)


Lesenswert?

Hallo zusammen,

trotz fortgeschrittenem Alters und immer wieder Berührung mit 
Microcontrollern in den letzten 20 Jahren, bleibe ich irgendwie 
bekennender Laie...

Für meine aktuelle Hobby-Aufgabe habe ich mir den Arduino Uno 
geschnappt.

Die Aufgabe: 5 RC-Empfänger Kanäle auslesen, mit Sensorwerten 
verwursteln, einen einfachen P-Regler für eine Lageregelung, und die 
Ergebnisse wieder als 5 RC-Signale ausgeben.

Bei der Online-Suche bin ich mit hunderten Triviallösungen für EINEN 
Servo und wenigen unbefriedigenden Ansätzen für mehrere Kanäle, sowie 
der Ahnung, daß der hübsch einfach zu programmierende Arduino dafür doch 
zu lahm wegen Overhead ist, hängengeblieben.

Meine momentane Idee fürs Einlesen: Alle 5 Signale mit Dioden und 
Pulldown verodern. Und fünfmal PulseIn() am gleichen Pin aufrufen. Die 
Signale sind nämlich auch bei modernen 2,4GHz-Empfängern schön 
nacheinander und durch ca. 40us Pausen voneinander getrennt.
Dazu Detailfrage: Reicht diese Pause, um PulseIn() abzuschließen, den 
Wert einer Variablen zu übergeben und das nächste PulseIn() zu starten, 
ohne daß man einen der 5 Werte "verschluckt" und PulseIn() erst den 
nächsten sieht?

Für das Berechnen hätte ich dann ca. 10ms Zeit und würde wieder das 
erste PulseIn() aufrufen, das dann halt wartet, bis das nächste 5er 
Paket Impulse kommt. Damit würde sich die loop im Arduino automatisch 
auf die 20ms/50Hz Wiederholrate der RC-Impulse synchronisieren.

So weit, so gut. Ihr könnt mir sicher erzählen, ob das Unsinn ist oder 
so geht.

Dann kommt die AUSGABE. Da gibt es die wunderbare Servo.h, aber da weiß 
ich wieder überhaupt nicht, wie die intern funktioniert, wieviel Zeit 
und Interrupt-Ressourcen die verbraucht. Einfach fünfmal hinereinander 
servo.WriteMicroseconds() raushauen und klappt schon im Hintergrund, 
ohne das andere zu stören? Oder verbrauchen die fünf Aufrufe 5 mal ca. 
1,5ms in der loop?

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


Lesenswert?

Tom H. schrieb:
> Alle 5 Signale mit Dioden und Pulldown verodern.
Dann musst du noch den "Anfang" finden, denn falls du da einen Puls 
verlierst oder zu viel siehst (EMV...) dann bist du neben der Rolle...

> Oder verbrauchen die fünf Aufrufe 5 mal ca. 1,5ms in der loop?
Geh einfach mal genau davon aus. Das ist Arduino.

> aber da weiß ich wieder überhaupt nicht, wie die intern funktioniert
Du hast als zentrales Problem die Eingabe und die Ausgabe und weißt 
nicht, ob oder wie das mit dem Arduino geht. Das ist eine schlechte 
Basis...

Ich würde das Ding direkt auf dem uC ohne die Klassenbibliotheken des 
arduino aufsetzen. Dann bin ich selber schuld, wenn etwas nicht klappt, 
muss aber auch selber das Datenblatt lesen.

Der Hardwareaufwand wäre dann
6 Eingangspins
1 Timer A für die Zeitmessung
6 Ausgangspins für das PWM Signal
1 Timer B mit Interrupt für die Pulsausgabe

Die Programmstruktur etwa so:
Es wird gewartet, ob irgendwo ein Servopuls aktiv wird (Polling). Dann 
wird zuerst ein Zeitstempel vom Timer A genommen und dann genau am 
"selben" Servo gleich mal ein Impuls ausgegeben. Die Dauer für diesen 
Puls wird in den Timer B eingetragen.
Jetzt wird gewartet, bis entweder der Puls am Eingang weggeht (z.B. 
Polling), oder der Timer B abläuft (Timerinterrupt).
Wenn der Puls weggeht wird ein erneuter Zeitstempel genommen und die 
Differenz berechnet --> Eingabe beendet.
Wenn der Timer B abläuft werden alle Ausgänge inaktiv geschaltet.
Mit ein paar (Pinchange-)Interrupts lässt sich das Ganze noch 
verfeinern.

Das wars und das packt jeder schäbige AVR mit 1MHz...

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Tom H. schrieb:
> Die Aufgabe: 5 RC-Empfänger Kanäle auslesen, mit Sensorwerten
> verwursteln, einen einfachen P-Regler für eine Lageregelung, und die
> Ergebnisse wieder als 5 RC-Signale ausgeben.

 Auch wenn dir Lothar M. schon beantwortet hat:

 Was, womit und wie willst du genau "verwursteln" ?

von Tom H. (toemchen)


Lesenswert?

Nackter AVR schön und gut, aber ich habe keine Entwicklungsumgebung, 
keinen Pragrammer und vor allem nicht die Eier in der Hose, mich darin 
einzuarbeiten.
Den Arduino habe ich erstmals vor zwei Wochen angefaßt und seitdem in 
Summe drei Stunden damit verbracht. Für mich sehr angenehmes Spielzeug, 
genau meine Kragenweite. Eine einkanalige Lösung (Lageregelung eines 
kleinen Getriebemotors, der mit einem Modellbaufahrtregler gesteuert 
wird) steht auch schon.

Das mit dem erstmaligem Erkennen des ersten Impulses stimmt, das ist ein 
Problem.
Dirty Lösung: Was nach den fünf PulseIn() in der loop kommt, dauert 
immer ca. 10ms. Dann würden bei falscher Synchronisierung gewisse 
Impulse verschluckt, die Synchronisierung ändert sich, bis die lange 
Pause des Empfängers mit der langen Verarbeitungs/Wartezeit in der loop 
zusammenpasst.
Andere Lösung: Doch die 5 Empfängerkanäle auf 5 Pins legen. Dann muß man 
aber auf die Reihenfolge der PulseIn()-Aufrufe achten, daß diese 
zeitlich eng aufeinanderfolgen können.

von Tom H. (toemchen)


Lesenswert?

Klar kann ich die Anwendung noch näher beschreiben, ich wollte nur den 
Anfangspost nicht so ellenlang werden lassen.

Es geht um ein Kinderfahrzeug (Trettraktor), das mit Elektromotor und 
Servolenkung versehen wird.
Es soll reiner Fernsteuerbetrieb und Bedienung durch ein draufsitzendes 
Kind möglich sein, und sogar gemischt (durch Fernsteuerung bremsen oder 
gegenlenken, wenn das Kind Mist baut :-) ) Deshalb auch die hochtrabende 
"Servolenkung".

Kanal 1: Gasgeben
Eingänge, die verwurstet werden: Gaspedal-Poti und Empfängerimpuls. Ein 
Bewegen des Knüppels an der Fernsteuerung sperrt die Bedienung durch das 
Gaspedal, eine Zeitlang in Ruhe lassen läßt das Gaspedal wieder zu.
Ausgabe: RC-Impuls für einen Modellbau-BLDC-Regler (Flugregler, eine 
Fahrtrichtung)

Kanal 2: Schalten vor- rückwärts und 2. Gang vorwärts
Eingänge: Analogeingang über Schalter auf GND-2,5V-5V gelegt, und 
Empfängerimpuls.
Ob Fernsteuerung oder Schalter am Fahrzeug das Sagen haben, wird auch 
über den Kanal 1 getriggert.
Ausgaben: Schaltkanal für Relais, die 2 Motorphasen vertauschen und 
RC-Impuls für ein Modellbauservo, das die Gänge schaltet.

Kanal 3: Lenkung
Eingänge: Empfängerimpuls, Poti für Ist-Stellung der Lenkung und 
Drehmomentsensor an der Lenkradwelle.
Lageregelung der Lenkung. Verhalten Fernsteuerung/Kind ähnlich wie beim 
Gasgeben. Evtl. Lenkausschlag-Begrenzung bei höheren Geschwindigkeiten.
Ausgabe: RC-Impuls für einen kleinen Modellbau-Fahrtregler für 
DC-Motoren, der den Getriebemotor der Lenkung steuert.

Kanäle 4 und 5:
Reserve für spätere Anbaugeräte.
Eingänge: jeweils Empfängerimpuls und ein Poti eines lokalen Joysticks 
oder Schalters.
Ausgabe: RC-Impuls für kleine Modellbau-Fahrtregler.

Das Umschalten des Modus "Kind" oder "Fernsteuerung" kann eigentlich 
gemeinsam für alle Kanäle passieren.

von Jan L. (ranzcopter)


Lesenswert?

ich glaube, ich würde mir als "Startpunkt" anschauen, wie die 
Receiver-Auswertung bei "MultiWii" (RC-Controller auf Arduino-Basis) 
gelöst wurde.
Möglicherweise liesse sich gleich das ganze Ding auf die eigenen Zwecke 
umbiegen; das allerdings dürfte etwas mühsam sein, da eigentlich auf 
Multicopter ausgelegt...

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Tom H. schrieb:
> Es geht um ein Kinderfahrzeug (Trettraktor), das mit Elektromotor und
> Servolenkung versehen wird.

 5 PWM Ausgänge hast du ja beim UNO. (Kanäle 1-3, 2xRes. Kanäle)
 6 ADC Eingänge auch.   (1xGas, 1xSchalten, 1xLenk, 1xSensor, 2xRes)
 2 Digitale Ausgänge auch.   ( 2xRelais)
 5 Digitale Eingänge auch (Empfängerimpuls Kanäle 1-3, 2xRes. Kanäle)

 Mit Interrupts wird es schlecht gehen, Polling oder Abfragen ist
 m.E. viel besser.
 Wenn es nur ein Empfänger ist, erstmal Kanaltrennung rausfinden.
 Das ist auch der Grund, warum Polling besser ist als Interrupts.

 Wenn Fernsteuerung stumm ist (Mittellage bei allen Kanälen), werden
 die Ausgänge entsprechend der Poti- oder Schalterstellungen am Auto
 per PWM angesteuert.
 Sobald sich bei der Fernsteuerung etwas ändert, werden die Fernsteuer
 eingänge 1:1 übertragen. Nachdem alle wieder in Mittellage sind,
 etwa 1s abwarten und dann dem Kind die Kontrolle zurückgeben.

 Bleiben nur noch die Begrenzungen (Lenkung, Geschwindigkeit), das
 muss aber in beiden Modis kontrolliert werden, kann als gemeinsame
 Routine bleiben.

 Und die evtl. 20ms Verzögerung ist nicht so schlimm, oder ?

von Tom H. (toemchen)


Lesenswert?

Ich denke auch, mit der Ausstattung an Anschlüssen (Pins) ist das schon 
möglich. Aber das Timing...

Dem Fahrzeug wird ein bestimmtes Sender-Empfänger-Paar zugeordnet und 
bleibt auch so. (Spektrum DX5e) Auf verschiedene Fernsteuersysteme muß 
sich das System gottseidank nicht einstellen.

Wie muß ich das mit dem Polling verstehen?
In der loop alles nacheinander abfragen, wenn sich an einem Eingangspin 
was getan hat, irgendwie den Timerwert (micros) merken und Variablen mit 
den Zeitdifferenzen belegen?
Wird denn die loop schnell genug durchlaufen, daß sich da eine 
vernünftige Auflösung ergibt?
Oder alle Impulse nacheinander auf Anfang und Ende abfragen, wie 
PulseIn(), nur zu Fuß? Was wäre der Vorteil?

Mir scheint, ich habe ein generelles Timing-Problem, wenn ich das alles 
per "Pin Banging" erledigen will:
Da sind 5 Impulse von 1-2ms Dauer nacheinander, wenn ich die ganz sauber 
nach meinem Programmierverständnis reinkriegen will, verbrauche ich 
damit max. 10ms.
Dann will ich 5 ähnliche Impulse erzeugen, nach dem was das Tömchen kann 
und versteht dauert das auch max. 10ms.
Bleibt also in der 20ms Wiederholrate keine Luft zum Rechnen und 
Synchronisieren.

Will ich nun in die Trickkiste einsteigen, versuche ich die 5 zu 
erzeugenden Impulse gleichzeitig zu starten. Aber da bekomme ich doch 
Ungenauigkeiten, wenn alle etwa gleichzeitig zu Ende sein sollen und die 
Abfragen mit ihrer eigenen Abarbeitungszeit sich um den selben Zeitpunkt 
tummeln. Oder sehe ich das zu eng? Ist die Ausführungsgeschwindigkeit so 
hoch, daß da nichts jittert?

Oder will ich Timer und Hardware-PWM nutzen.
Entweder implizit, wenn ich die Funktionen PulseIn() und 
servo.Microseconds() nutze - wobei man irgendwie nirgends sichere 
Informationen findet, welche Ressourcen des ATMega328 dabei verwendet 
werden. Das muß man sich unglaublich mühsam zusammenklamüsern.
Oder explizit, aber ich sehe da momentan keine Möglichkeit für mich mit 
meinen Kenntnissen, in der Arduino-Programmiersprache da ranzukommen.

von ChrisMicro (Gast)


Lesenswert?

Hier habe ich es für einen Roboter mit zwei Kanälen gemacht:
https://github.com/ChrisMicro/freiBot/blob/master/Example_RadioControl/Example_RadioControl.ino

Nicht optimal, funktioniert aber.

von Frank (Gast)


Lesenswert?

Im Allgemeinen ist es so, das die einzelnen PWM signale durch den Sender 
auch hintereinander gesendet und im Empfänger auseinander  gewutstelt 
werden.
Früher (in zeiten analoger Fernsteuerungen) wurde der erste Kanal 
dadurch idendifiziert, das die Pause vor diesem Signal länger war als 
die zwischen den andern.
Dieses gesamtsignal konnte man an einigen Empfängern irgendwo abgreifen 
und so selbst auseinander wursteln und weiter verarbeiten.

Wenn das nicht mehr der Fall ist, kann man ja das signal des Ersten 
Kanals mit einer Diode auf einen zweiten Eingang legen und dieses als 
Startsignal dafür verwenden das nun das Telegramm anfängt.

Frank

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Tom H. schrieb:
> Wie muß ich das mit dem Polling verstehen?
> In der loop alles nacheinander abfragen, wenn sich an einem Eingangspin
> was getan hat, irgendwie den Timerwert (micros) merken und Variablen mit
> den Zeitdifferenzen belegen?

 Polling deswegen, damit nicht bei Kanal1_ISR Kanal2 dazwischenfunkt.

 Eigentlich (soweit ich mich noch erinnern kann), ist der Abstand
 zwischen den Kanälen etwa 0,5 bis 1ms. Das ergibt im schlimmsten Fall
 2ms + 1ms Pause * 5 etwa 15ms.
 Aber egal, selbst wenn es nicht so sein soll, ist die Pause vor dem
 ersten Kanal immer die längste, muss mindestens 5ms betragen.

 Bei Kanal_1 Timer1 auf Null setzen, danach einfach den Timerwert für
 den und die anderen Kanäle nacheinander ubernehmen, (Ende - Start)
 ergibt Impulsdauer.
 Wenn der entsprechende Kanal in Neutralposition ist, hast du mindestens
 1ms um den Input vom Auto einzulesen, entsprechend vorzubereiten und
 als PWM auszugeben.
 Da der Input über ADC geschieht, ist es normalerweise kein Problem
 (max.67us). Bleiben mehr als 900us um den Wert zu prüfen, evtl. zu
 korigieren und impuls rauszuschicken.

 Wie ich gerade gesehen habe, steuert der Arduino die PWM-Ausgänge mit
 fixen 490Hz, die sind also unbrauchbar, die Ausgänge musst du manuell
 ein- und ausschalten.

 In Assembler oder sogar in normalem C kein Problem, aber mit Arduino
 overhead ist es mehr als fraglich...

von Tom (Gast)


Lesenswert?

Ich bin ab jetzt im Wochenende ohne PC (Ferienhaus) und kann nicht mehr 
so gut mitquatschen...

Erstens, Impulstelegramm und Pause. Die Pulse sind nicht in einem festen 
Raster von 2ms, sondern hängen direkt hinteteinander. D.h. sind alle 
zufällig 1ms lang, verdichten sie sich auf ein Paket von 5ms + 4•40us 
Gesamtlänge. Da is nix mit "normalerweise hat man 500us Zeit zum 
Verarbeiten. In 40us muß die fallende Flanke des einen, die Dauer des 
einen über Zähler auslesen oder Differenzbildung erfasst sein, in 
Variable abgespeichert und die steigende Flanke drs nächsten erfasst 
sein.

Um das Einlesen der Impulse und Synchronisieren mit der Pause würde ich 
mir alleine keine Sorgen machen.Aber wenn ich danach nochmal fünf so 
Pulse generieren muss und es dank interferierender Interrupts oder 
interferierender Timerbenutzung der Arduino-Funktionen nur zu Fuss geht 
und hintereinander, dann reicht es nicht in 20ms...

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Tom schrieb:
> Erstens, Impulstelegramm und Pause. Die Pulse sind nicht in einem festen
> Raster von 2ms, sondern hängen direkt hinteteinander. D.h. sind alle
> zufällig 1ms lang, verdichten sie sich auf ein Paket von 5ms + 4•40us

 Wie gesagt, ich kann mich nicht mehr genau erinnern, aber es ist ja
 trotzdem nicht so schlimm, vorausgesetzt man arbeitet nicht mit
 Arduino IDE.
 Bestenfalls hast du ein Paket mit 7660us Lange, schlimmstenfalls ein
 Paket mit 10160us Lange.
 Wobei es schlimmstenfalls gar nicht geben kann - schon beim ersten
 Impuls der ungleich 1.5ms ist, wird auf 1:1 Übertragung übergegangen.

 Und 40us sind im Assembler 640 Takte oder im Schnitt etwa 500 Befehle.

 Da kann man ADC einlesen, Timer einlesen, starten, stoppen, auf Null
 setzen, Werte prüfen, einschreiben, Impuls vorbereiten, raussenden...

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


Lesenswert?

Tom H. schrieb:
> wobei man irgendwie nirgends sichere Informationen findet, welche
> Ressourcen des ATMega328 dabei verwendet werden.
Geh davon aus, dass diese Funktionen während ihrer Ausführungszeit 
annähernd 100% der Ressourcen verwenden. Und lediglich von OS Interrupts 
unterbrochen werden.

Tom schrieb:
> dann reicht es nicht in 20ms...
Mit dem von mir anfangs skizzierten Konzept reicht das locker. Und 
natürlich geht das auch mit Arduino.  Nur muss man dort die Hardware 
eben auch selbst in die Hand nehmen.  Aber das ist ja nicht schlimm,  es 
istnur ein einziger Timer...

von Tom H. (toemchen)


Lesenswert?

Gestern abend hatte ich wieder Zeit, ein bißchen Arduino zu spielen.

Das Aufnehmen von 5 RC-Impulsen funktioniert so, wie ich es mir gedacht 
hatte.

1. Alle 5 Kanäle mit Dioden verodert und auf Pin 3 des Arduino gelegt. 
Leider läßt der Spektrum AR600 Empfänger nur 3v-Impulse raus, nach den 
Dioden hat es nicht mehr gereicht, den Arduino-Eingang sicher zu 
schalten. Also noch eine Inverterstufe mit BC548 und Pullup nach 5V, 
dann gings.

2. Nacheinander 5 mal mit PulseIn(3,LOW) verschiedenen Integer-Variablen 
die Kanalwerte zuweisen. Danach die Werte erstmal seriell ausgeben.

3. Die Synchronisierung klappt 100%ig. Das serielle Ausgeben dauert ca. 
1,2ms (38400Baud, keine Ahnung, ob das bei der USB-Anbindung überhaupt 
relevant ist). Diese feste Zeit im Ablauf der Schleife reicht, um einen 
auf den (bei Falschsync vemeintlich) letzten Impuls folgenden weiteren 
Impuls nicht mitzubekommen. D.h. die Falschsync verändert sich so lange, 
bis es passt: Die serielle Ausgabe liegt zeitlich in der langen Pause 
zwischen den 5er-Paketen und stört da nicht.

4. Die gelesenen Werte scheinen mir stark zu zittern, das muß ich noch 
untersuchen. Z.B. indem ich mir die Abweichung von einem 1s-Mittel 
ausgeben lasse.

5. Ergebnisse nebenbei:

5a. Für die Timing-Untersuchungen habe ich per "Bit-Banging" (mir 
gefällt dieses Wort) kurze Peaks auf einem anderen Pin ausgegeben. Also 
nur zwei aufeinanderfolgende Zeilen mit WriteDigital(13,HIGH) und 
WriteDigital(13,LOW). So ein kurzer Puls dauert relativ zuverlässig 5us, 
nur manchmal verlängert er sich ca. aufs doppelte, da spukt dann wohl 
das "Arduino-Betriebsystem" rein.

5b. Die Wiederholzeit des Empfängers beträgt sogar 22ms statt 20ms, also 
noch ein Quentchen mehr Luft für die Impulsausgabe, die ich jetzt dann 
anpacken muß.

von Willst Du Arduino, den hier Anwesenden... (Gast)


Lesenswert?

> nur manchmal verlängert er sich ca. aufs doppelte, da spukt dann wohl
> das "Arduino-Betriebsystem" rein.

Ja, die Arduino Laufzeitumgebung (runtime environment).

Noch was Generelles: den einzelnen Servos/Drehzahlsteller ist es 
letztendlich egal ob sie die Steuerpulse gestaffelt nacheinander (wie 
vom RC-Empfänger) bekommen oder simultan.

D.h. m.M.n. um Jitterfreiheit + Präzision bei der Ausgabe der 
Steuerpulse zu erreichen dürfte es wohl am besten sein etwas eigenes zu 
Schreiben; basiert auf des 328'er Timer und/oder PWM-Ausgabe UND dies 
darf ruhig in anderer Zeitlicher Reihenfolge als wie vom RC-Rx 
ausfallen.
Nur die Wiederholrate würde ich nicht allzuviel langsamer als die 
üblichen 50Hz werden lassen.
(wobei ein Servo bei Pulsausfall in seiner letzten Position bleibt, ein 
Drehzahlsteller jedoch den Motor ausschaltet)

von Tom H. (toemchen)


Lesenswert?

Ok, korrekter Ausdruck für das, was ich meinte: Laufzeitumgebung und 
nicht "Betriebssystem". :-)

Das mit der Reihenfolge und Staffelung ist mir klar. Nur zum 
Auseinanderklamüsern der Empfängersignale brauche ich die Reihenfolge. 
Der einzelne Servo sieht natürlich an seinem Anschluß nur seinen 
wiederholenden Impuls ohne weiteren zeitlichen Bezug zu einem 
Synchronsignal. Der braucht nur die Breite des Impulses als Information.

Gestern hatte ich nicht so viel Zeit zum Basteln. Hab nur kurz zwei 
Dinge ausprobiert.

1. Von einem der 5 Kanäle zunächst einen Mittelwert gebildet und mir 
dann die Differenz zu diesem Mittelwert anzeigen lassen. Die vom Arduino 
mittels PulseIn() gemessene Pulsbreite schwankt ca. um +-3 us. (Zur 
Erinnerung: Der Wertebereich liegt bei ca. 1000us bis 2000us für die 
beiden Servo-Endstellungen). Also erträglich. Müßte mal messen, wie 
stabil der vom Empfänger gelieferte Puls eigentlich ist.

2. Mal spaßeshalber mit der Servo.h Bibliothek 5 Servosignale 
rausgelassen an den PWM-fähigen Pins 3, 5, 6, 9 und 10. Und zwischen den 
Aufrufen von writeMilliseconds() jeweils einen kurzen Puls an Pin13 
geschrieben, den ich mit dem Oszi sehen kann.
Ergebnis: Natürlich dauert das Aufrufen dieser writeMilliseconds() nur 
wenige us und scheint nur den Wert an die im Hintergrund laufende 
Routine zu übergeben. Also so doof, daß der Aufruf die gesamte 
Pulsbreite als Ausführungszeit bräuchte, ist die Routine auch wieder 
nicht.
Insgesamt kam das kurze Paket an Debug-Impulsen nach wie vor im 
22ms-Raster wie vom Empfänger vorgegeben, das Timing ist nicht aus dem 
Ruder gelaufen. Die Ausgabeimpulse für die Servos folgen dieser 
Synchronisierung nicht genau - ich vermute, sie halten sich eigenständig 
streng an das 20ms-Raster.
Also alles in allem gar nicht so übel.

Nun kann ich nochmal die Schwankung der gemessenen Impulsbreite ausgeben 
lassen, vielleicht wackelt das durch die gestiegene Timer- und 
Interruptbelastung jetzt stärker.
Und mal sehen, wie ich die Stabilität der Servosignale mit dem Oszi 
untersuchen kann. Sollte eigentlich kein Problem sein mit einem 
Picoscope.

von chris_ (Gast)


Lesenswert?

Du könntest Dein aktuelle Arduino Script posten, damit man mal auf den 
Code gucken kann. Das macht die ganze Sache einfacher.

von Tom H. (toemchen)


Lesenswert?

Nun muß ich aber doch mal ein bißchen patzig werden. Aber da ich zu 
meinen konkreten Fragen bis jetzt keine Antworten erhalten habe und dazu 
übergehen mußte, mir alles schrittweise selbst zu erarbeiten und eher 
nur die Ergebnisse hier zu posten...

Also, was soll das bringen, das Script hier zu posten?
Habe ich ein Problem mit dem Programm, daß es nicht tut was es soll?
Habe ich überhaupt derzeit eine Frage á là "wie programmiere ich das"?
Nein.

Was soll man an einem Script sehen, das so einfach und geradeaus ist, 
wie wenn man auf einen Lichtschalter drückt? Und funktioniert? Soll es 
besser funktionieren, wenn ich die Funktionsaufrufe kursiv oder groß 
schreibe?

Oder geht es doch eher um die Feinheiten der Arduino Laufzeitumgebung, 
inwiefern die Jitter verursacht?

Oder um beim Lichtschalter-Beispiel zu bleiben:
Ich drücke auf den Schalter, das Licht geht an, aber manchmal flackert 
es etwas, weil irgendwo weiter hinten in der Leitung ein Wackler ist.
Jetzt soll ich zeigen, wie ich auf den Lichtschalter drücke.
Damit mir dann jemand sagt: Ah neee, du mußt das Bein heben und unterm 
Knie durchfassen und auf den Lichtschalter drücken, dann gehts ohne 
Flackern. Kapiert? Bringt nichts.

Bisher gab es viele Antworten á là "du mußt den Lichtschalter selbst 
bauen, dann hat er keinen Wackler." Ok, verstehe ich. Kann sogar 
ungefähr ermessen, wieviel Aufwand und Kenntnis dazu nötig ist. Aber bis 
jetzt möchte ich es mit dem vorhandenen Lichtschalter lösen und es 
scheint, als würde es gehen. Denn der andere Aufwand ist mir zu viel.

von Tom H. (toemchen)


Lesenswert?

Vom Schimpfen zurück zum Thema.

Ich schreib einfach weiter von meinen Ergebnissen oder auch einfach nur 
"Erlebnissen" vielleicht kann ja irgendwann jemand was damit anfangen.

Gestern Abend schnell ein "breakout board" zum Anschluß von 5 Servos 
gelötet. Und mit der zuletzt beschriebenen Programmversion betrieben.

Ergebnis:
1. Die Servos zittern leicht.
2. Die Servos "pulsieren" gemeinsam mit einer Frequenz von ca. 2Hz.
3. Die agileren der 4 angeschlossenen Servos machen ab und zu (alle paar 
Sekunden) auch einen richtig heftigen Zuckerer.

Für meine Zwecke könnte ich mit 1. und vielleicht sogar 2. leben, denn 
an den Servo-Ausgängen hängen ja fast nur Modellbau-Fahrtregler. Die 
könnten mit entsprechendem Totband um die Nullzone herum trotzdem ruhig 
bleiben, und Geschwindigkeitsschwankungen beim Aussteuern wird man wohl 
nicht so leicht merken.
Aber 3. wird dann wohl doch der Sache den Garaus machen. Also zumindest 
so wie ich es bis jetzt angegangen bin.

Zum Vergleich habe ich dann schnell ein Sketch erstellt, das 
ausschließlich die 5 Servos betreibt und keinerlei Einlesen von 
RC-Impulsen mittels PulseIn().
Zunächst nur einmal im setup einen Wert zugewiesen - Ergebnis: Servos 
stehen absolut still und zittern kein bißchen.
Dann in der loop einen hin- und her-Sweep gefahren mit Increment von 1us 
alle 22ms. Ergebnis: Servos fahren ganz langsam und ruhig, kein 
Pulsieren, kein Zucken.

Die Ausgabe der Servoimpulse geschieht übrigens offenbar hintereinander 
versetzt. Ein Verbreitern eines vorangehenden Impulses versetzt auch den 
Start des nachfolgenden auf einem anderen Pin.

Meine laienhafte Analyse:
PulseIn() und der Betrieb von Servos teilen sich halt doch die gleichen 
Ressourcen oder interferieren bei den Interrupts. Dadurch, daß der 
Zyklus vom RC-Empfänger aus 22ms dauert und die Servos aber mit einer 
Zykluszeit von 20ms angesteuert werden (das habe ich jetzt 
nachgemessen), entsteht eine Art Schwebung. Alle halbe Sekunde trifft 
die Phase des Einlesens blöd auf die Phase des Ausgebens und sie stören 
sich gegenseitig.

Ich kann noch ein bißchen mehr herausfinden, was dabei gestört wird. Ich 
werde mir die gemessenen Pulszeiten ausgeben lassen und aufzeichnen - 
dann sehe ich, ob an diesen Störungsstellen zu große Werte für die 
Impulszeiten aufgzeichnet werden. In dem Fall könnte man evtl. filtern.
Sollten die gelesenen Impulszeiten halbwegs sauber sein, muß es so sein, 
daß die Ausgabe gestört wird. Daran werde ich nicht drehen können. Evtl. 
müßte ich dann eine Servosignal-Ausgabe "zu Fuß" programmieren. Die 
Zeit, die in der 22ms-Schleife zur Verfügung steht, könnte reichen.

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.