Servo / PWM Signal einer Taranis (RC Sender) am Arduino einlesen und auswerten

Hallo zusammen,

ich möchte gerne die Beleuchtung eines RC-Flugzeugs per Arduino steuern.
Dazu wird ein Programm die LEDs ansteuern, klar ...

Per Schalter am Sender möchte ich aber nun verschiedene Programme, bzw Beleuchtungs-Modi abrufen.
AUS - Modus1 - Modus2 soll über einen Schalter mit 3 Schaltstellungen geschaltet werden.

Dieser Schalter ist eigentlich für Servo-Positionen gedacht und gibt scheinbar werte von -100, 0, 100 aus.
Das müsste aber, nach meinen Recherchen ein PWM-Signal sein.

Wie werte ich dieses Signal nun am Arduino aus.
Auch zur Vorschaltung (falls nötig) benötige ich bitte Hilfe.

Bin nicht ganz sicher, wie ich da ran gehen soll.
Habe zwar schon etwas gegoogelt und erste Hinweise gefunden, kann die aber noch nicht so ganz einsortieren.

Könnt ihr mich mal in die richtige Richtung schubsen?

Vielen Dank
Cappy

Nimm die read()-Funktion aus der Library da: Servo - Arduino Reference und werde glücklich :slight_smile:

Hi,

danke für die schnelle Antwort.

Allerdings verstehe ich die Library nicht, oder Du hast mich missverstanden.

Ich möchte NICHT einen Servo steuern, sondern ein Signal aus dem RC-Empfänger (das eigentlich zu einem Servo gehen soll) entgegen nehmen und verarbeiten.

Cappy

Servo-Signale sind nicht wirklich PWM.
Es kommt nicht auf das Verhältnis Puls/Pause an, sondern auf die Dauer des Pulses ( 1 .. 2 ms )
Die Pause bzw. Zyklusdauer (ca. 20 ms) ist nicht so relevant.

Wenn dir Blockaden in dieser Größenordnung (20 ms) nichts ausmachen, ist pulseIn das Einfachste.

servo.read() liefert nur zurück, was das letzte servo.write() gesetzt hat. Ist also nicht deine Lösung. Richtig erkannt.

Hi nochmal,

okay. Über pulseln bin ich schon irgendwo gestolpert.
Das sehe ich mir mal an.

Mit den Blockaden bin ich nicht ganz sicher.
Meinst Du, dass das Programm dann 20 ms lang steht?
Wann genau würde es das tun?

Der Plan wäre so:

Schalter Pos 1: alles aus
Schalter Pos 2: mehrere LEDs an + blitzende LEDs (millis)
Schalter Pos 3: mehrere LEDs an + blitzende LEDs (millis) + weitere LEDs an

Bin nicht sicher, ob ich das richtig beschrieben habe.

Cappy

Wann genau würde es das tun?

Wenn du pulseIn (pin, HIGH) aufrufst, geht der Sketch erst weiter, wenn das RC-Signal danach von HIGH zu LOW wechselt. Und sagt dir, wie lang der HIGH-Puls war. Das kann also 20 ms dauern. Ist aber OK wenn du nichts schnelleres als eine blitzende LED brauchst

Hi nochmal,

ok ... da komme ich, glaube ich, mit.

Das heißt also das Signal sagt nur "es gibt ne Änderung" steht aber nicht die ganze Zeit auf HIGH bis ich den Schalter wieder umlege?

Ich glaube ich muss mal ne Schaltung aufbauen und ein wenig rumprobieren.
Ist ja alles sehr theoretisch so lange.

Bisher sind nämlich nur die LEDs im Flieger.

Noch eine Frage nebenbei, die hier sicherlich nicht 100%ig richtig ist.

Wenn ich die LEDs ansteuern will, geht das direkt per Vorwiderstand ... bisher jedenfalls.
Würdet Ihr mir empfehlen lieber nen Transistor zwischenzuschalten?

Cappy

Wenn ich die LEDs ansteuern will, geht das direkt per Vorwiderstand ... bisher jedenfalls.
Würdet Ihr mir empfehlen lieber nen Transistor zwischenzuschalten?

Wenn es mehrere LED sind, die hintereinander mehr als 5V oder parallel mehr als 20 mA brauchen, geht das nicht direkt an einem Arduino-Pin.

ein Signal aus dem RC-Empfänger (das eigentlich zu einem Servo gehen soll)

Das heißt also das Signal sagt nur "es gibt ne Änderung" steht aber nicht die ganze Zeit auf HIGH bis ich den Schalter wieder umlege?

Wenn du mit einer Fernsteuerung einen Servo ansteuerst, kriegt der regelmäßig (alle 20 ms) seine 1..2 ms Pulse abhängig von der Hebelstellung an der Fernbedienung.

Ui ... ich sehe schon, da muss ich echt mal ne Runde üben.

Der Servo bekomme alle 20ms Pulse, ok.
Die werden dann länger oder kürzer, je nach Hebelstellung, ja?

Cappy

Schaue mal, ob Dich die Erklärung zur Puls-Pausen-Modulation weiterbringt.

PPM hat nur bedingt was damit zu tun. PPM sind aneinandergereihte Servosignale der verschiedenen Kanäle.

Ich nehme an, du willst folgendes:
Ein Kanal der Funke steuert einen Empfängerausgang
Der Empfängerausgang geht auf den Arduino
Entsprechend des gesendeten Wertes (-100 bis +100) soll der Arduino verschiedene Lichtsettimgs abspielen

Korrekt?

Genau so ist das, ja!

Habe die ersten Zeilen auch schon gecodet.
Poste ich Morgen mal.

Cappy

meine Empfehlung:
Kein pulseIn verwenden, sondern eine ISR verwenden. Es gibt auch fertige Bibliotheken dafür.
Falls dein Empfänger irgendein summensignal aller Kanäle wie Ibus, Sbus, PPM oder so liefert, würde ich sogar das nehmen, dann ist es leichter, später einen zweiten Kanal einzubinden.

Im Arduino bekommst du dann Werte für den Kanal, z.B. in Mikrosekunden, zwischen 500 und 2500.
1000 entspricht dann -100 am Sender, 1500 ist 0, und 2000 ist +100. Du kannst an der Taranis aber auch auf +/-150 gehen, wenn du z.B. einen 10-Positionen-analog-Drehschalter verwendest

Da fragst du dann einfach auf den Wert ab, allerdings nicht mit
wert==1500, sondern mit wert>1450 && wert < 1550
Weil die gelieferten Werte immer etwas zappeln.

Evtl. wäre für dich auch eine Schaltkanalerweiterung (früher „Nauticmodul“) interessant, ist wahrscheinlich aber Overkill.

Mahlzeit,

ich habe nun mit pulseIn angefangen und kann den zwei-stufigen Schalter abhören.
Daher werde ich das Projekt jetzt auch erstmal damit fertig stellen.

Beim nächsten könnte ich mir dann mal diese ISR Sache ansehen.
Was spricht für Dich denn gegen pulsIn? "Nur" die Sache mit den Kanälen?

Was ich ehrlich gesagt noch nicht so ganz blicke sind diese ms-Werte!?
Welche Zeit ist das? Die Zeit wie lange ein HIGH je Zyklus am Kanal steht?

Es war etwas schwierig, die Zeiten auf die besagten -100 bis +100 umzustricken.
Jetzt habe ich's aber :slight_smile:

Cappy

-100 entspicht 1,0ms, +100 entspicht 2ms am Empfängerausgang.

Gegen pulseIn spricht, dass es blockiert. Du solltest also ein kurzes Timeout nehmen, z.B. 30ms
Bei normalen Servosteuersignalen kommt alle 20ms (nennt man Framelength, die Länge kann abweichen nach Hersteller) ein Signal von 0,5ms bis 2,5ms, bei normaler Einstellung des Senders eben von 1,0ms bis 2,0ms.

Und die Zeit ist proportional zum Ausschlag des Servohorns.

Schaue dir das mal mit einem Oszi oder LA an, dann geht dir ein Licht auf.

Ich weiß nicht, ob das hier noch aktuell ist.

Bin selbst noch Anfänger ( beim Arduino, nicht beim RC-Fliegen ).
Hab mir einen Sketch gemacht für die Beleuchtungssteuerung mit einem 3-Positionsschalter.
Die Funktion ist angelehnt an die Manntragende Fliegerei.
Wenn man in einen Flieger steigt, ist die erste Aktion nach dem "Hauptschalter ein", das Anticollisionslicht.
Das ist das rote Blinklicht, oft noch mit Glühbirne.
Und damit das richtig "Scale" aussieht, gibt es hier eine auf und abschwellende LED.
Diese startet, sobald Spannung anliegt und der Przessor gebootet ist.

Der Schalter am Sender steht dazu noch in der Endstellung "aus".
Moderne Sender fragen die Schalter ab, und schalten HF nur ein, wenn alle Schalter "richtig" im Sinne von einer Vorgabe, wwas richtig ist, stehen.

An weiteren Lichtern haben wir zunächst die NAV-Lights. Links rot, rechts Grün und hinten weiß, alles Dauerlicht.
Dazu noch die Strobelights, die weißen Blitzlichter. Die guten alten Wheelen Strobes, die mit Xenon-Blitzleuchten arbeiten, haben oft vierml schnell hintereinander kurz gebltzt, dann kam eine Pause, dann wieder 4 Blitze sehr schnell.

Diese beiden Beleuchtuingselemente ( NAV und Strobe ) gehen an, wenn der Schalter in die Mittelstellung kommt.

Am Ende des Fluges, '( oder auch manchmal zum Start ) geht zusätzlich noch das Landelicht an.
Die passiert hier, indem der Schalter in die "AN"-Endstellung gebrcht wird.

Das alles ist sehr konventionell geschrieben, da ich mich mit den wirklich harten Programmiertricks noch nicht auskenne
So findet man die Routine zum Auf- und Abschwellen des ACL ( Antikoillisionslicht, rotes Blinklicht ) gleich zweimal.
Einmal für sich mit verändertem delay ( das ist die Zeit, die die Blitze brauchen würden, wenn sie schon eingeschaltet wären ), und einmal zusammen mit den Blitzen.
Das passt vom Timing her aber sehr gut, und da der Arduino hier nichts anderes machen soll, können wir den Speicherplatz auch für diese Vereinfachungen "verschwenden". Das geht auch, was das Umschalten und das Auf- und Abschwellen angeht, nahtlos ineinander über. ( machmal ist delay echt nützlich:-) )
Sieht echt "Echt" aus. Sehr schön für Scale-Flieger.

Wenn man einen einfachen Sender hat, der keine 3-Punkt-Schalter hat, kann man das ganz leicht auf zwei 2-Punkt-Schalter umschreiben.

Schalter 1, Zuschalten von Stobe und NAV Lights.
Schalter 2 Landelicht.

Das hat allerdings den Nachteil, das man sich dafür zwei Kanäle wegnimmt, die dann für andere Funktionen nicht mehr zur Verfügung stehen.

Die Ausgänge gebe ich über FET´s an Power-LED´s, die man auch am Tag sehr gut sieht.

Wer möchte, gerne PM, dann schicke ich den Code zu.
Ich habe mich gerade hier erst angemeldet, und weiß nicht, ob man Codes so einfach posten darf.

skyfox60:
Ich habe mich gerade hier erst angemeldet, und weiß nicht, ob man Codes so einfach posten darf.

Darfst du natürlich!

Wenn du auch Videos/Bilder zeigen willst gerne im Thread "Zeigt her eure geilen Projekte" oder so ähnlich.

Hier ein fertiger Sketch für eine Flugzeugbeleuchtung, angelehnt an die manntragende Fliegerei.

Es werden 4 Lampengruppen bedient:

  1. ACL ( Immer an, solange Stron da ist )
  2. NAV-Lichter ( hinten weiß, links rot, rechts Grün )
  3. Strobes, Bltzlichter

2 und 3 werden hier gmeinsam geschaltet, damit man alles mit einem Steuerkanal, 3-Positions-Schalter erledigen kann.

  1. Landescheinwerfer

Wer mag, kann den Sketch gern nutzen.

Folgende Anmerkungen:

Wer in meinem Code Spaghetti findet, darf sie auch aufessen.
Ich bin blutiger Anfänger, und als ich das geschrieben habe, hielt ich millis noch für Bakterien, und Timer für Armbanduhren.
Trotzdem funktioniert es prima!

Hinweise:

  1. Direkt am Anfang hinter void Loop() steht "// goto Mainloop"
    Wenn man dort die // wegnimmt, schaltet man den für mache einen nervigen Lampen Blitz-blinkt-
    rotier Test aus.

  2. Die Strobes stehen dort mit einem Blitz/Pauseverhältnis von 40/60ms
    Man kann das ändern, und solange die Summe 100 beträgt, also z.B. 70/30
    ( was die Blitze aber dunkler werden läßt ) oder 50/50, ist alles gut.

Sobald die Summe anders ist z.B. 60/60, ergibt ja 120mS, dann muss im Loop davor ( ACL only )
unten die Delay-Zeit angepasst werden. Sie beträgt Summe * 4, ( jetzt 400, dann also 480 )
Bei 40/40 ensprechend 320 ( 40+40 )*4

Für Anfänger empfehle ich den Sketch zweimal abzuspeichern, und einen zum experimentieren zu verwenden.

Viel Spaß beim Fliegen damit. Sieht mit ensprechender Außenbeschaltung und Powerled´s echt gut aus, auch an hellen Tagen.

/*
  Scale like anticollision-light, strobe-light, NAV-lights and landing-light for RC-Aircraft

  Free to use by everyone!
  Skyfox60

  Digital Channels Output
  NAV_light    = D5  ( Left = red, Right = green, Back = white ) digital out
  ACL          = D6  PWM _ Channel for intensity regulation ( ACL = Anticollision Light )
  Landinglight = D7  digital out
  Strobe       = D8  digital out
 
  Receiverchannel Inputs:
  Input a Servochannel from Receiver to D10, Try-State Switch is recommended ( 1000µs, >1500µs, 2000µs )
 
  In normal ( out ) condition ( a > 1600µS a <2100µS ) only the mainloop and ACL_only-routine is ruinning. 
  This makes the ACL ( anticollision-light ) running as soon as the battery is plugged on and the lamp-test ist finished.
  I made this because in real aircraft the first action after switching the main switch on, is to activate the ACL, there should be no need to activate a switch at the transmitter for that.
  Also, the ACL remains Fading up and down, until battery is unplugged and aircraft save.
  If you have a transmitter that allowes the switch-position-test at the beginning, set it so that the light switch has to be in 2000µs position before transmitter starts.
  When switch in appx mid position ( a <1400 ) the ACL_NAV_Strobe-Loop runs. You find at first a similar routine like in ACL_only.
  This was required due to the need of some other values to have the same visiual appearence of ACL the and nearly continuing as it was.
  there is a Lamptest to check all lamps. 10 flashes wake up for you, followed by single test and finally 10 flashes to finish and exit to Mainloop.
  
*/

  int NAV_light = 5;
  int ACL = 6;                     // the PWM pin the LED is attached to
  int Landinglight = 7;
  int Strobelight = 8;
  int brightness = 7;              // how bright the LED is, 0 at startup
  int brightness_increment = 7;    // How many points increment or decrement per step to fade the LED, if you change this value ( default is 7 ), you have also to change the counter1 steps ( default is 68 ), just for the case you changed it and do not remember 
                                   // Also max Brightness has to be altered, if you cange any of the values. ( default is 231 )

                                 
  int counter1 = 1;
  int counter2 = 0;


void setup()
{

  pinMode(5, OUTPUT);              // NAV_light
  pinMode(6, OUTPUT);              // output ACL
  pinMode(7, OUTPUT);              // output Landinglight 
  pinMode(8, OUTPUT);              // putput Strobelight
  pinMode(10, INPUT);              // reads a and cycles ACL and Strobelight 
  //Serial.begin(9600);

}



void  loop() {

//goto Mainloop;// set this line as // to execute the lamptest before start, otherwise it starts without lamptest. Your choice

// Lamptest to check all lamps. 10 flashes wake up for you, then single test and then 10 flashes finish and exit to Mainloop

  for ( int L1 = 0; L1 <= 10; L1++ )
{
  digitalWrite (Strobelight,HIGH); ; digitalWrite(NAV_light, HIGH);  digitalWrite(ACL, HIGH);  digitalWrite(Landinglight, HIGH); delay(50);
  digitalWrite (Strobelight,LOW); digitalWrite(NAV_light, LOW);  digitalWrite(ACL, LOW);  digitalWrite(Landinglight, LOW);delay(50);
}
  for ( int L = 0; L <= 1; L++) { digitalWrite (NAV_light, HIGH); delay(300);  digitalWrite (NAV_light, LOW);delay(300); digitalWrite ( ACL, HIGH ); delay(300); digitalWrite ( ACL, LOW );delay(300); digitalWrite (Landinglight,HIGH);
  delay(300); digitalWrite (Landinglight,LOW);delay(300);  digitalWrite (Strobelight,HIGH);delay(300);digitalWrite (Strobelight,LOW);delay(300);
}
  for ( int L1 = 0; L1 <= 10; L1++ )
{
  digitalWrite (Strobelight,HIGH); ; digitalWrite(NAV_light, HIGH);  digitalWrite(ACL, HIGH);  digitalWrite(Landinglight, HIGH); delay(50);
  digitalWrite (Strobelight,LOW); digitalWrite(NAV_light, LOW);  digitalWrite(ACL, LOW);  digitalWrite(Landinglight, LOW);delay(50);
  
}


  Mainloop:;    
  
 
  counter1 = 1;
  counter2 = 0;
 
  int    a = pulseIn(10,HIGH,25000);        // Read in pulse lenght, 3rd parameter has to be finetuned with receiver behavior
  
  if ( a >=1600 & a <=2100 ) { digitalWrite (NAV_light, LOW);  digitalWrite (Landinglight, LOW); goto ACL_only; }
  if ( a >950 & a <1200 )  digitalWrite (Landinglight, HIGH); 
  if ( a >1200 ) { digitalWrite (Landinglight, LOW);  } 
  if ( a >=950 & a <=1600) { digitalWrite (NAV_light, HIGH); goto ACL_NAV_Strobe; }
 
  
       
  ACL_only:;  
  
   analogWrite(brightness, 7);
   for (brightness <=7; brightness <252; brightness = brightness + brightness_increment) { analogWrite(ACL, brightness); delay(20); Serial.println(brightness); }    
   for (brightness <=253; brightness >=7; brightness = brightness - brightness_increment){ analogWrite(ACL, brightness); delay(30); Serial.println(brightness); }
      
   delay(400); // this delay is importand to have not jump in the brightness of ACL when switching NAV-lights and strobe on and of. do not change this value.
  
  goto Mainloop;
  

  
  ACL_NAV_Strobe:;
  
  counter1 = counter1+1;
  
  analogWrite(brightness, 7); // brightness = 7; // for synchronisation, to have small remaining brightness at the lower end, like a downgoing bulb at the ACL 
   for (brightness <=7; brightness <252; brightness = brightness + brightness_increment){ analogWrite(ACL, brightness); delay(20); Serial.println(brightness); }   
   for (brightness <=253; brightness >=7; brightness = brightness - brightness_increment){ analogWrite(ACL, brightness); delay(30); Serial.println(brightness); }
    // this two lines became necessary to synchronize the status of the ACL brightness when switching NAV lights and strobe on and off.
    //without the repeat of that two lines, a small jump occures, that is visible. Took me time to find out:)  
  
  
  
// the loop function Strobe runs 4 times ( 4 flashes ) and returns to Mainloop to check again the switch ( pulse ) status.

  Strobe:;
 
  counter2 = counter2+1;  
  digitalWrite(Strobelight, HIGH);         // turn the LED on by making voltge HIG
  delay(40);                               // wait for 50ms on time
  digitalWrite(Strobelight, LOW);          // turn the LED off by making the voltage LOW
  delay(60);   // wait for a second        // Wait for 50ms off time
  if ( counter2 == 4 ) { goto Mainloop; }  // the 4 is the number of flashes in each cycle
  { goto Strobe; }  

}

Warum stellst Du hier deinen goto-Spaghetti Code vor, der eigentlich nur als Abschreckung dienen kann?
Du weist doch eigentlich inzwischen wie es besser geht.

skyfox60:
Für Anfänger empfehle ich den Sketch zweimal abzuspeichern, und einen zum experimentieren zu verwenden.

Ich würde Anfängern eher empfehlen, sich diesen Code nicht als Vorbild zu nehmen, und auch nicht damit zu experimentieren - das führt nur in die Irre.