RC Kanalumschalter

Hallo,
durchsuche seit Tagen das www aber finde keine Lösung...

Es geht um folgendes Vorhaben:

Ich möchte mit einer Nano mehrere RC-Empfänger Ausgangssignale auswerten.

Eingänge: Schalter, Steuerstick Achse 1
Ausgänge: Schalter (wird immer durchgeschleift), Steuerung Achse 1, Servo

an 1 kommt ein Flightcontroller, an 2 ein Servo

Schalterstellung 0: Schaltersignal wird duchgeschleift, Achse 1 wird durchgeschleift, das servo an 2 soll auf Mittelstellung

Schalterstellung 1: Schaltersignal durchschleifen, Achse 1 zum Flightcontroller soll ein durch die Arduino erzeugtes Mittelstellungssignal bekommen, Achse 2 wird nun über den Stick gesteuert

Wenn ich wieder auf 0 schalte, möchte ich, dass das Servo langsam in Mittelstellung zurück fährt, Achse 1 wird wieder durchgeschleift

Vielleicht kann mir jemand helfen

Das ist das Signal, wird vom RC Empfänger ausgegeben, geht dann an Servos, Brushlessregler, Flightcontroller

Spannung 5V, kommt vom Flightcontroller und versorgt den Empfänger

Die RC geben ein PPM Signal aus ( einen Impuls von 1 bis 2 mS alle 20mS falls es keine Hubschraubersteuerung ist) .
Das mußt Du einlesen und Verarbeitenund wieder als PPM für die Servos ausgeben.

Hast Du versucht etwas selbst zu programmieren?
Grüße Uwe

Ist ein PPM Signal

Bin nur auf die pulseIn Funktion gestoßen. Habe aber leider nichts die Ausgabe bzw. die Erstellung eines PPM Signals gefunden

Pins müssen noch angepasst werden

const int chA=1;  //Gas
const int chB=2;  //Yaw
const int chC=3;  //Switch


const int chAout=4; //Gas
const int chBout=5; //Yaw
const int chCout=6; //Switch
const int chDout=7; //Neigung Kamera
const int chEout=8; //Yaw Kamera
const int chFout=9; //Switch durchgeschliffen


int ch1;
int ch2;
int ch3;




void setup() {

  Serial.begin(115200);

  pinMode(chA, INPUT);
  pinMode(chB,INPUT);
  pinMode(chC,INPUT);

  
  pinMode(chAout,OUTPUT);
  pinMode(chBout,OUTPUT);
  pinMode(chCout,OUTPUT);
  pinMode(chDout,OUTPUT);
  pinMode(chEout,OUTPUT);
  pinMode(chFout,OUTPUT);

}


void loop() {

  ch1 = pulseIn (chA,HIGH);
  Serial.print ("Ch1:");
  Serial.print (ch1); 
  Serial.print ("|");
 
  ch2 = pulseIn (chB,HIGH);
  Serial.print ("Ch2:");
  Serial.print (ch2);
  Serial.print ("|");

  ch3 = pulseIn (chC,HIGH);
  Serial.print ("Ch3:");
  Serial.print (ch3);
  Serial.print ("|");

  
  chC == chFout;
  
  if (ch3>950 && ch3<1050)
  {
    chA == chAout;
    chB == chBout;
  }
  
  else if (ch3>1950 && ch3<2050)
  {
    chA == chDout;
    chB == chEout;
  }

}

chC == chFout; ecc
das doppel= ist ein Vergleich und man braucht es in den bedingungen wie IF ecc.
Zuweisungen sind mit Einfach=
also: chC = chFout;
Grüße Uwe

Kennst du meine Seite?

www.rcarduino.tk

Da hab ich zumindest was die PPM Dekodierung angeht eine Bibliothek. Ausgänge wären dann ganz normale Servos?
Tut mir leid, aber weder aus deinem Programm, noch aus deiner Beschreibung werd ich richtig schlau.
Mal doch mal ein Bild?

Hier mal ein Blockschaltbild

Kann ich so meine PPM-Signale erzeugen?

void setup(){
  pinMode(13,OUTPUT); // set pin 13 witch is no HW PWM pin as output
}

void loop(){

  digitalWrite(13,HIGH); // set it to High

  delayMicroseconds(1500); //wait for 1500us. this gives a PPM signal of 1500us (50% throttle or servo's middle position)

  digitalWrite(13,LOW); // set it to LOW

  delayMicroseconds(500); // let it stay 500us at low state to have a overall loop time of 2000us (500Hz)

}

Wenn das das einzige ist, was Arduino di ganze Zeit lang machen soll JA.
Was willst Du mit 500Hz?

Ansonsten könntest Du die servo-h Bibliothek im IDE nehmen.
Grüße Uwe

einfach im netz kopiert ohne nachzudenken

Brauche ja 50Hz, heißt ein delayMicroseconds(18500)

Meinst du das?

#include <Servo.h>

Servo servo1;
Servo servo2;

void setup()
{
servo1.attach(3);
servo2.attach(4, 1000, 2000);

servo1.writeMicroseconds(1500);
servo2.write(90); // set servo to mid-point (90°)
}
void loop() {}

Hab noch nie mit servo.h gearbeitet und mich bei meiner ganzen Suche immer nur auf PPM beschränkt :sleeping:
Macht servo.h denn genau die 50Hz, also in Mittelstellung 1,5ms High + 18,5ms low?

jansen2612:
Macht servo.h denn genau die 50Hz, also in Mittelstellung 1,5ms High + 18,5ms low?

Ja, genau.
Und Du kannst nebenbei etwas anderes in Sketch machen.
Grüße Uwe

Nein bitte so nicht, da kriegste das Timing nicht hin, denn der Arduino muss ja auch noch andere Dinge machen.
Nimm dafür zumindest die interne Servo Bibliothek.
4 RC Kanälen auswerten kannst du bei meiner Lib nur mit dem Mega. Weil ich die direkten Intterrupts verwende.

Es gibt aber auch eine andere Lib, die den Pinchange Interrup einer Gruppe von Pins auswerten kann. Beispiel: Arduino Playground - ReadReceiver

Übrigens gibt dein Empfänger dir bereits ein Servokompatibles 50Hz Signal. Einfach auf einen nicht benutzen Kanal syncronisieren...

Das habe ich bis jetzt zusammengetragen:

#include <Servo.h>

// Variablen
const int chA=1; //Gas Kanal 1
const int chB=2; //Yaw Kanal 2
const int chC=3; //Schalter Kanal 5
const int chD=4; //Drehschalter Kanal 6

int ch1; //Varibles to store and display the values of each channel
int ch2;
int ch3;
int ch4;

Servo gas; //Gas out
Servo yaw; //Yaw out
Servo kanal5; //Schalter Kanal 5
Servo yawservo; //Servo Yaw out
Servo nick; //Brushless Nick out

void setup()
{
// initialize serial communication at 9600 bits per second:
Serial.begin(115200);

//Input Pins
pinMode(ch1, INPUT);
pinMode(ch2,INPUT);
pinMode(ch3,INPUT);
pinMode(ch4,INPUT);

//Servo Output Pins
gas.attach(5);
yaw.attach(6);
kanal5.attach(7);
yawservo.attach(8);
nick.attach(9);
}

//Main Program
void loop()
{
// read the input channels
ch1 = pulseIn (chA,HIGH); //Gas
Serial.print ("Ch1:");
Serial.print (ch1);
Serial.print ("|");

ch2 = pulseIn (chB,HIGH); // Yaw
Serial.print ("Ch2:");
Serial.print (ch2);
Serial.print ("|");

ch3 = pulseIn (chC,HIGH); // Schalter Kanal 5
Serial.print ("Ch3:");
Serial.print (ch3);
Serial.print ("|");

ch4 = pulseIn (chD,HIGH); // Drehschalter Kanal 6
Serial.print ("Ch3:");
Serial.print (ch3);
Serial.print ("|");

//Auswertung
if (ch3>1450 && ch3<1550)
{
gas.writeMicroseconds(ch1); //Gas durchschleifen
yaw.writeMicroseconds(ch2); //Yaw durchschleifen
kanal5.writeMicroseconds(ch3); //Schalter durchschleifen
yawservo.writeMicroseconds(1500); //Servo Mitte
nick.writeMicroseconds(ch4); //Drehschalter durchschleifen
}

else if (ch3>950 && ch3<1050)
{
gas.writeMicroseconds(1500); //Gas
yaw.writeMicroseconds(1500); //Yaw
kanal5.writeMicroseconds(ch3); //Schalter durchschleifen
yawservo.writeMicroseconds(ch2); //Kanal Nick auf Servo
nick.writeMicroseconds(ch1); //Kanal Gas auf Brushless Nick
}

}

Das funktioniert ganz gut, wenn die Kanäle in der loop() auch genau in dieser Reihefolge kommen.
Wenn nicht, dann hast du ganz heftige Verzögerungen in deiner Loop.
Wenn z.B. der Enpfänger alle Servo-Signale zum gleichen Zeitpunkt sendet (das machen die neueren 2,4GHz System gerne)
dann wird dein Verarbeitungsteil nur mit alle 80ms mal aufgerufen.
Wenn die in der richtigen Reihenfolge kommen, dann alle 20ms.
Allerdings ist das jetzt sowieso noch egal, weil durch deine "Debugausgaben" eh das gesamte Timing hin ist...

Leider werden beim pulseIn auch die Aktualisierung der Servos mit eingerechnet, sodaß die Werte der pulsIn Funktion nicht genau sind. Da kommen schon mehr ein paar heftige Jitters mit rein. Faustregel, je mehr im Interruptbetrieb auf dem Controller los ist, umso ungenauer ist die pulsIn Funktion.
z.B. würde ich den Kanal5, der ja immer wie Kanal 3 ist, nicht über dne Arduino schleifen, sondern einfach per Y-Kabel belegen.
Dann hast du schon mal einen Servo weniger...

Das mit dem Y-Kabel ist eine gute Idee und einfach umzusetzen.

Wüsste jetzt nicht was ich noch verbessern könnte, mein Wissen zu Arduino und Programmierung ist leider begrenzt. Daher habe ich wahrscheinlich einiges nicht berücksichtigt.
Tipps nehme ich gerne entgegen :slight_smile: