5 RC-Signale lesen und 5 Servos treiben mit UNO

Hallo zusammen,

ich bin noch recht unerfahren mit Arduino und möchte folgende Aufgabe bewältigen:

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 :slight_smile: ) Deshalb auch die hochtrabende
"Servolenkung".

Der Arduino soll das erledigen, durch Einlesen der Signale eines Spektrum Modellbauempfängers und steuern verschiedener Fahrtregler, Servos und Schalttransistoren im Fahrzeug.

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.

So, das ist schon viel Text für den ersten Post.
Bis jetzt habe ich das Thema in microcontroller.net behandelt:
https://www.mikrocontroller.net/topic/401497#new
Im nächsten Post schreibe ich, was ich bisher programmiert habe und wo die Frage / das Problem liegt.

Das Einlesen der 5 RC-Kanäle funktioniert leidlich gut.

Ich habe es mit PulseIn() gelöst.

Da die 5 Pulse wie früher mit den analogen Empfängern schön nacheinander kommen, habe ich sie mit Dioden und einem Transistor als Inverterstufe zusammengelegt. Der Transistor deswegen, weil der Empfänger nur 3V-Pegel ausgibt und nach den Dioden zuwenig übrig war, um einen Arduino-Pin sicher zu triggern. Durch die Invertierung muß es halt PulseIn(xy, LOW) sein.

Nun rufe ich in der loop einfach 5 mal PulseIn(2, LOW) auf und habe dann die Werte in Variablen stehen. Danach kommt in der loop noch irgendwas, das ein bißchen Zeit braucht (z.b. delay(3) oder serielle Ausgabe der Werte zum Debuggen) - und schon synchronisiert sich das ganze wunderbar mit der Lücke, die der RC-Empfänger nach den 5 Impulsen läßt.

Das erste PulseIn in der loop wartet dann einfach so lange, bis der erste Impuls des Pakets kommt.

Die Wiederholzeit des Empfängers beträgt sogar 22ms und nicht 20ms.

Von diesen 22ms "verbrate" ich natürlich gleich mal 5-10ms mit den aufeinanderfolgenden PulseIn, aber das macht mir zunächst noch nichts. Soviel muß nicht gerechnet und nebenher getan werden.

Die Pulse werden mit einer Abweichung von +-3us gelesen, das reicht mir als Genauigkeit. Vielleicht sind sie sogar vom Empfänger aus nicht stabiler.

Bis hier noch keine Frage, das kommt dann im nächsten Post.

toemchen:
... noch keine Frage, das kommt dann im nächsten Post.

Das hast Du im ersten Posting auch schon versprochen :slight_smile:

Vielleicht stellst Du erst mal die Frage und erläuterst dann ... oder Du schreibst einen Roman und stellst den irgendwo online und postest hier nur einen Link ...

Gruß

Gregor

Nun zur Ausgabe.

Dazu habe ich jetzt einfach mal geradeaus die Servo.h verwendet.
Mein Sketch macht jetzt zunächst nichts anders als die 5 Signale nach der oben beschriebenen Methode zu lesen und als 5 Servosignale wieder auszugeben.

Als Ergebnis kann ich das kopieren, was ich in microcontroller.net geschrieben habe:

  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.

UND JETZT DIE FRAGEN AN EUCH:
Wie kann ich es besser machen?
Welche libs und Interrupts interferieren da miteinander?
Inwiefern kann ich Interrupts zeitweise abschalten?
Kann ich durch geschickte Wahl der Pin was beeinflussen? (Zur Zeit ist das summierte Empfängersignal auf Pin 2, die Servos liegen auf Pin 3, 5, 6, 9 und 10)
Für die Servos habe ich PWM-fähige genommen, aber das ist anscheinend gar nicht wichtig?

UND JETZT DIE FRAGEN AN EUCH:
Wie kann ich es besser machen?

Hallo, und du glaubst, wir lesen das durch und verstehen das auch? :wink:

Zeige deinen Sketch, ein Schaltbild und stelle dazu deine Fragen bzw. schreibe was nicht funktioniert.

Edit:
Haben dir die Aussagen hier (mikrocontroller.net) nicht gereicht.

Nee- tun wir nicht.
Aber ich weiss: so viele Kanäle zuverlässig bearbeiten wird mit nem UNO nix. Das klappt nur richtig gut mittels Interrupts-auch wenn weiter oben was anderes geschrieben wurde. PulseIn lässt keine Zeit für andere Aufgaben, wenn das denn einwandfrei funktionieren soll und PulseIn ist ne blockierende Funktion. Es ist also gar nicht möglich, so viele Kanäle wirklich "gleichzeitig" einzulesen.
Dafür aber hat der UNO gar nich genug Timer...

Mitm Mega geht das mit der Interrupt-Methode allerdings einwandfrei: RC Receiver [Arduino im Modellbau]
Hab ich selber schon gemacht, das läuft (auch sechs Kanäle).

Danke, das war schonmal hilfreiche Information.

Der Link zu den Arduino-RC-Projekten, vieles gut erklärt, wenngleich (für mich) viel Wiederholung von Bekanntem.

Ich steige halt erst langsam in die Arduino-Welt ein.

Ich sehe jetzt, der MEGA wäre für mich besser und als Clone auch billig zu haben - zuerst hatte mich der doppelte Preis gegenüber dem UNO (jeweils Original) abgeschreckt.

Nun, vielleicht mache ich eine "schmale" Version mit 3 Kanälen mit dem UNO, damit ich weiterkomme, derweil ich auf einen MEGA aus Hongkong warte.

konkrete FRAGE:
Wird PulseIn() präziser, wenn ich Interrupts abschalte?
Wird eine von Hand gestrickte Servosignal-Ausgabe mit DelayMicroseconds() präziser, wenn ich Interrupts abschalte?

Gruß
Tom.