• Die Forumsregeln und Nutzungsbedingungen findet ihr in der Navbar unter Impressum !
    Bitte unbedingt beachten!
    Wie überall im Leben gibt es Spielregeln, so auch hier!
    Die Datenschutzerklärung zum DSGVO findet ihr ebenfalls in der Navbar unter Datenschutzerklärung !
    Hinweis nach DSGVO :
    Es ist hier keinerlei Angabe erforderlich. Alle Angaben in diesem Bereich sind öffentlich sichtbar und werden freiwillig gemacht. Mit einem Eintrag in diesem Bereich erkenne ich dieses an, und bestätige die Datenschutzerklärung zur DSGVO für das Forum gelesen zu haben.

    Danke
  • Hallo Gast, beschränke dich hier bitte auf den Bereich der Elektronik. Die Fahrzeuge oder Gebäude, wo diese Elektronik eingebaut wird bitte in dem passenden Fachbereiich behandeln. Auch wenn Teile des Projektes dadurch im Forum doppelt vorhanden sind! Danke.

Arduino Futaba/Robbe Multiswitch Decoder mit Arduino

Magraina

New member
Registriert
17.03.2010
Beiträge
237
Hey,

Ich weiß nicht ob das schonmal jemand gemacht hat aber da ich die Möglichkeit nutze will ich sie euch zeigen.
In diesem kleinen Beispiel zeige ich wie man das Signal vom Empfänger zum Multiswitch-Decoder auswertet und mit einem Microcontroller(Arduino) nutzen kann.

Da ich in meinem LKW sowieso einen Microcontroller(Arduino) nutzen will für diverse Funktionien welche sowieso die meisten von den Multiswitchschaltern kommen und ich nicht sonderlich Platz habe kam ich auf diese Idee.
Außerdem sind die Multiswitch decoder teuer wenn man sie in jedem Fahrzeug nutzt.

Um das nachzumachen benötigt man etwas Erfahrung mit Microcontrollern(bzw. Arduino und C-Programmierung) und Elektrotechnik.

Ich nutze eine Futaba F14 und als Empfänger einen Futaba FP-R118F

Am Empfänger wo der Decoder angeschlossen wird liegt ein PPM Signal an.
Das Signal Besteht aus einem Startimpuls und 8 Impulsen.
Der Startimpuls(Sync) hat immer die selbe länge und dadurch kann man festellen wo der Anfang ist um die Reihenfolge beizubehalten.
Die anderen 8 Impulse(S1-S8) Stellen die Schalter des Multiswitch dar sie varieren mit der Länge je nach Schalterstellung.

Mann kann das Signal mit einem Oziloskop darstellen bzw. es mit einem Microcontroller beobachten.

Hier mal eine kleine Skizze um das zu verdeutlichen:
PPM Multiswitch.jpg

Also habe ich folgendes gemacht:
Ich habe meinen Arduino mit der Spannungsversorgung des Empängers verbunden und das PPM Signal auf einen Eingang gelegt.

Ich habe ein Programm auf den Arduino geladen womit ich die Impulslängen der einzelnen Impulse auf einem Seriellen Monitor sehe.

Programm:
Code:
void setup() {
  Serial.begin(57600);
  pinMode(3, INPUT); //Pin an dem das Signal anliegt.
}

void loop() {
  Serial.println(pulseIn(3, HIGH));
}

Damit bekamm ich fortlaufend Werte die etwa so aussahen:

915
1600
1600
1024
1600
1900
1900
1900
1900

Diese Zahlen sind die Zeit in Microsecunden die die Impulse auf High waren.

915 stellt denn Startimpuls dar und die restlichen die 8 Schaltkanäle.
Der 3. Schalter ist in diesem Beispiel geschaltet deshalb ist die Zeit für diesen geringer.
Bei allen Schaltern habe ich im geschalteten zustand einen Zeit wert von 1024 Microsekunden bekommen.
Ansonsten war der Wert zwischen 1600 und 1900.

Daraus habe ich dann folgendes Programm gemacht:
Code:
#define schalter 8 //Anzahl der Schalter bzw. Impulse
int value[schalter];

void setup()
{
  pinMode(3, INPUT); //Pin 3 als input
  pinMode(4, OUTPUT);
}
void loop()
{
  while(pulseIn(3, HIGH) > 1000){} //Wait for the beginning of the frame
  for(int x=0; x<=schalter-1; x++)//Loop to store all the channel position
  {
    value[x]=pulseIn(3, HIGH);
  }
  
  if ((value[0] < 1100) && (value[0] > 1000)) {
    digitalWrite(4, HIGH);
  } else {
    digitalWrite(4, LOW);
  }
}

Das Programm bleibt in der while-schleife bis der Startimpuls kommt da dieser als einziger kleiner als 1000 Microsekunden ist.
Dannach werden die Werte der 8 Impulse in den array "value" geschrieben.
Im Beispiel schalte ich den Ausgang 4 wenn der Schalter geschalten ist.

Sollte die Verbindung zur Ferbedienung unterbrechen geht der Wert von "value" nach einer bestimmten zeit auf 0 da kein Signal mehr kommt.
Man könnte mit der funktion pulseIn() auch einen Timeout bestimmen.

Sollte man einen Multiswitch mit proportionalen Funktionen haben wird vermutlich die zeit zwischen 1024 -2000 Microsekunden variieren je nach Stellung.
Das kann ich nicht testen da ich so ein Modul nicht besitze.

Hier noch ein Video zum veranschaulichen(Leider waren ein par sehr helle LEDs dabei).
Um diese Inhalte anzuzeigen, benötigen wir die Zustimmung zum Setzen von Drittanbieter-Cookies.
Für weitere Informationen siehe die Seite Verwendung von Cookies.

Ich hoffe der eine oder andere kann damit was anfangen.
Über Fragen oder Kritik würde ich mich freuen.

Für die Rechtschreibfehler kann ich nichts die sind angeboren;)

Links für Interisierte:
Eine erklärung zu PPM: http://www.rconline.net/magazin-2001/pcm-ppm/pcm-ppm.shtml
Bild zu PPM: http://www.rconline.net/magazin-2001/pcm-ppm/frame_ppm.gif
Arduino pulseIn() Reference: http://arduino.cc/de/pmwiki.php?n=Reference/PulseIn

MFG MetazeR
 
if ((value[0] < 1100) && (value[0] > 1000)) {
digitalWrite(4, HIGH);
} else {
digitalWrite(4, HIGH);
}
}

Hi Marvin,

Arduino.... noch so ein interessantes Thema...

Nur am Rande: Beim obigen Code-Ausschnitt müsste der Befehl nach dem "else" vermutlich

digitalWrite(4, LOW);

heissen? Würde sonst keinen Sinn machen.
 
Ja da hast du recht da hat sich ein Fehler eingeschlichen.
Ich habe es zu abgeändert.
 
@ Gino und Marvin.
:thx
Ich habe es in dem anderen Thread auch geändert!
 
Hallo Marvin,

ist ein interessantes Thema. Deine Software wird so lange funktioneren wie der Programmcode noch kurz ist, danach wirst du vermutlich Laufzeitfehler bekommen. Die Abfrage der Pulse über einen "normalen" digitalen Eingang ist zu langsam. Da musst du mit einem Interrupt arbeiten.
Ich habe vor einigen Wochen einen Servotester gebaut, da kannst du dir die Sache mit dem Interrupt mal ansehen.

Ansonsten mach weiter mit dem Projekt, hört sich interessant an und kann man immer brauchen :ok
Vielleicht kannst du dir ja auch gleich ein Sendermodul bauen das die PPM Pulse ausgbit ?
 
Man könnte die Sache auch anderes angehen.
Claus Pottermann hat ein Multiswitch auf PIC gebaut und gibt die Anleitung und/oder auch Bausätze raus.
Das habe ich bei mir am werkeln und bin hoch zufrieden. Die Bauteile für ein Decoder und Coder kosten inkl. Schaltern ca. 25€(wenn man bissel rumschaut).
Somit hat man alles zusammen und braucht nur noch bissel aätzen und löten.

In der jetzigen Software im Decoder ist auch schon ein Blinkmodus vorhanden, bei mir leider nicht, deshalb hab ich einfach *** Attiny13 für diese Tätigkeit verdonnert und
über einen Attiny25 steuer ich ein Servo mittels dem Multiswitch an.

Aber deine Idee ist natürlich etwas eleganter, jedoch würde mich das Andurio ansich stören,
denn das nimmt ja auch Platz usw weg.

Bin gespannt wies weiter geht:ok
 
Kuck dir mal den Arduino Mini an, der iste ewtas größer als ein Euro und kostet unter 5€.
 
@Winni
Danke für die Änderung.

@Bording
Da hast du Recht wenn das Programm zu lang ist brauch ich einen Interrupt. Allerdings hatt mein Programm momentan keine sonderliche Größe das es stört bzw. weiß ich noch nicht was alles rein soll.
Deinen Servotester werde ich mir noch anschauen.
Ein Sendermodul wäre ansich kein Problem allerdings habe ich zur Zeit nich vor so etwas zu bauen.

@BenjaminDD
Das ist auch eine gute möglichkeit.
Aber wie auch bereits erwänt gibt es auch kleine Arduinos sollte man auf dieser Platform bleiben.
Zum Beispiel: Arduino Mini / Arduino Nano / Arduino Micro / Arduino Mini Pro
 
Ich habe mir überlegt ob ein Interrupt überhaupt sinn macht.
Wenn ich keinen Interrupt verwende führt das dazu das es zu einer verzögerung kommen kann wenn das Programm zu groß ist mehr nicht.

Wenn ich aber einen Interrupt mache lege ich die priorität auf das PPM Signal was eventuell mein restliches Programm lamlegt.

Also hab ich mir kurzerhand einfach mal ein Programm gebastelt mit Interrupt:

Code:
#define channumber 8 //How many channels have your radio?
volatile int value[channumber];
volatile int value2;
volatile int x = 0;

void setup()
{

pinMode(3, INPUT);
attachInterrupt(0, ppmInterrupt, CHANGE);
pinMode(4, OUTPUT);

}
void loop()
{
  
 if (value[0] < 1100) {
    digitalWrite(4, HIGH);
  }
  if (value[0] > 1100) {
    digitalWrite(4, LOW);
  }

}

void ppmInterrupt() {

    value2=pulseIn(3, HIGH);
    if (value2 < 1000){
    x = 0;
    }else {
      value[x] = value2;
      x++;
      }
  
  }

Das Ergebnis ist es funktioniert wunderbar mit nur einem Entscheidenden Problem.
Durch die häufigkeit der Impulse ist der Controller hauptsächlich in der Interrupt funktion und arbeitet das Programm extrem langsam ab.
Man kann etwa sagen es dauert 10 sec bis eine Aktion erfolgt.

Daher bleibe ich erstmal bei einem Programm ohne Interrupt das funktionert wunderbar.

Für einen besseren Vorschlag bin ich gerne offen.
 
Hallo Marvin,

in deiner Interruptroutine fragst du ab, ob der Puls kleiner 1000 ist, ansonsten zählst du value x einen hoch. Da hast du aber kein Limit drin, heißt er zählt bis 32167 hoch.
Wenn du da eine Begrenzung einbaust wie z.B:

if (x >= 2100) {x = =};

sollte es klappen.
 
Ich glaube das x ist nicht das problem habe aber mal so eine bedingung zur sicherheit eingebaut.
Ich denke es liegt an der pulsIn() funktion.
Diese Funktion wartet auf die nächste flanke da sie die flanke die den Interrupt auslöst nicht mitbekommt.
Dadurch bleibt der Controller länger als gedacht im Interrupt was zu einer größeren Verzögerung führt.

Habe die Abfrage jetzt änlich wie Bording beim Servotester gemacht.
Und es funktioniert Problemlos bisher habe es etwa eine halbe stunde getestet.

Code:
// Variablen die in Interrupt Verwendet werden mit "volatile"
volatile int value[8] = {0};
volatile int x = 0;
volatile long nMicros = 0;
volatile long nDifference = 0;
volatile long lastChange = 0;


void setup() {

pinMode(3, INPUT); // Setze Pin 3 für PPM-Eingang
attachInterrupt(0, ppmInterrupt, CHANGE); //Starte Interrupt-Funktion wenn auf Interrupt 0(0 = Pin 3) sich das Signal ändert
// Lege Ausgänge fest Pin 4-11
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
pinMode(7, OUTPUT);
pinMode(8, OUTPUT);
pinMode(9, OUTPUT);
pinMode(10, OUTPUT);
pinMode(11, OUTPUT);
//Setzte Delay bis erste Werte in Variable value durch Interrupt geschrieben sind.
delay(1000);
  
}
void loop() {
 
 for(int y = 0; y <=8; y++) { //Zählschleife um alle Ausgänge zu Beschalten
   if ((value[y] < 1100) && (value[y] >1000)) { //Schalte Ausgang auf HIGH wenn Wert von value zwischen 1000 und 1100
     
    digitalWrite(y+4, HIGH); // Erser Ausgangs-Pin ist 4 also y+4
  }
  else {
    digitalWrite(y+4, LOW); // Wenn erste Bedingung nicht erfüllt ist schalte Ausgang auf LOW
  }
   }
   
   
}
/*
ppmInterrupt
Wird Ausgeführt wenn die Flanke von Pin 3 fällt oder steigt
Wenn die 
*/
void ppmInterrupt() {
  nMicros = micros(); //Speichere aktuelle Zeit
  nDifference = (nMicros - lastChange); //Errechne Zeit seit der letzten Flanke
  if((nDifference > 700) && (nDifference < 2200)) { //HIGH Impuls herausfiltern | Wenn Zeit zwischen 700 und 2200 handelt es sich um einen HIGH Impuls
    if((nDifference > 850) && (nDifference < 950)) { //Startimpuls von 915 herausfiltern
      x = 0; //Index x auf 0 setzen damit nächste Impulse ab value[0] geschrieben werden.
      } else {
        if (x >= 8) { // Sicherheit falls Variable x zu groß wird
          x = 0;
          }
        value[x] = nDifference;// Schreibe Zeit auf Array
        x++; //Erhöhe Index um 1 für den nächsten Impuls
        }
    }
  
  lastChange = nMicros;// Speichere aktuelle Zeit für den nächsten Interrupt
  }

Muss mir aber mal nochmal den impuls auf dem Ozziloskop anschauen glaube der abstand zwischen den Impulsen ist größer was aber dem code egal ist.
 
Für den Code ist es zwar nich ganz so relevant aber die Gesamtzeit des PPM signal ist deutlich länger.
Ich hielt das zuerst für einen Messfehler bzw. hab ich vielleicht nicht genau hingeschaut.
Ich habe mich da an das Sendereigene PPM Signal Orientiert diese hat eine länge von 22,5ms
Mir viel das erst richtig auf mit dem ersten versuch mit Interrupts.
Das erklärt auch die lange zeit die es gedauert hat bis eine Aktion kam.
Die Pausen zwischen den Impulsen sind etwa 20ms lang.
Habe das ganze mit dem Oziloskop überprüft und komme auf das selbe ergebnis wie wenn ich es mit dem Arduino messe.
Ich vermute das ist so weil acht Schalter auf einem Kanal übertragen werden müssen.

Das macht aber im Code nicht viel aus aber ich würde nach der Feststellung sagen das ein Interrupt sinvoller ist.
Ohne Interrupt geschieht eine aktion frühestens nach ca. 160ms in abhänigkeit zur Programm Performance was zwar tragbar ist aber nicht sein muss.
Mit Interrupt dauert es ein par millisekunden bis hin zu ca. höchstens 180ms mit nicht zu starker abhängigkeit zur Programm Performance.

PPM Multiswitch.jpg

Ich hoffe dass ich jetzt keinen müll erzähle und wenn doch dann belehrt mich eines besseren.
 
Hallo Magraina

dein/e Programm/e hier sind genau das, was ich schon länger gesucht habe, funktionieren einwandfrei und bringen mich bei meiner Realisierung der Steuerung über den Arduino enorm weiter.
Vielen Dank für die Bereitstellung des/r Sketch/e.
 
Hallo Magraina

dein/e Programm/e hier sind genau das, was ich schon länger gesucht habe, funktionieren einwandfrei und bringen mich bei meiner Realisierung der Steuerung über den Arduino enorm weiter.
Vielen Dank für die Bereitstellung des/r Sketch/e.

Hallo Thomas,

freut mich dass ich helfen konnte!
 

Servonaut
Zurück
Oben Unten