RC Receiver

Author: Dipl.-Ing. Wilfried Klaas
Board: Arduino Duemilanove, Arduino Uno, Arduino Leonardo (mit Einschränkungen)

Für die verschiedenen Projekte hier, habe ich mal eine kleine Bibliothek geschrieben, die die Anbindung an einen Modellbauempfänger etwas einfacher macht. Die Bibliothek beinhaltet ein Objekt RCReceive, welches für die Anbindung zuständig ist.
Die Bibliothek ermittelt automatisch den Nullpunkt aus den ersten 10 Werten. Weiterhin wird der Wertebereich automatisch auf den Bereich von 0..255 beschränkt. Neu ist die Fehlererkennung. Werden mehr als 3 fehlerhafte Impulse vom Empfänger erkannt, kann man das in seinem Programm abfragen und entsprechend reagieren, z.B. Failsafe oder RTH.

21.08.2015 Neue Version 1.4.0 in Github
Die Bibliothek ist nun im Library Manager der Arduino IDE zu finden und wird auch auf GITHUB gehosted.
(RCReceiver auf Github)
Die aktuellen Releases findet man ab sofort hier RCReceiver Releases

Die Bibliothek gibt's hier: RCReceiver (letzte Änderung 09.04.2014)
2 Programmtemplates sind mit dabei.

09.04.2014 Neue Version 0.2.0
Jetzt funktioniert die Lib auch endlich mit einem Arduino Mega 256 sauber. Viel Spass damit.

06.10.2013 Neue Version
Ich habe jetzt etliche Tage an einer neuen Version gebastelt. Ziel war es, das ganze zusammen mit einer einfachen Servo Bibliothek auf den ATTiny 25/45/85 zum laufen zu bekommen. Das ist mir auch geglückt. Deswegen gibt es jetzt hier eine neue Version.

31.01.2013 Es gibt eine neue Version.
- Verbesserte Fehlererkennung
- einfachere Initialisierung im Interruptmodus
- Werte nun auch als ms abholbar
- schnellere Interruptroutine durch eigene Timerinitialisierung
- Unterstützung von Arduino Mega und Arduino Leonardo
Benutzt wird dabei der Timer1, der auch von der Servo Bibliothek benutzt wird. Da ich die gleiche Initialisierung mache, ist das aber kein Problem.

Installation

Die Installation ist einfach, Für die Installation einfach das ganze Zip in das Sketchverzeichniss auspacken. Danach sollte dort ein libraries Verzeichniss extistieren und dortdrin sind 2 neue Libs. RCRecive und MCSTools.

Einbinden

Zum Einbinden einfach auf [Sketch]/[Library importieren…], und schon sind in ihrer Quelldatei einfach folgende Zeilen hinzugefügt:

#include <RCReceive.h>

Das gleiche bitte auch mit der MCStools Bibliothek.

#include <debug.h>
#include <makros.h>
#include <RCReceive.h>

Für den ATTIny 8 und für den Mega gibt es noch 2 extra #define's.

  • ATTiny8

über

#define USE_TIMER_1

kann der Timer 1 anstatt der internen micros() benutzt werden. Dadurch wird die Messung genauer und evt. braucht man den Timer0 noch für was anderes.

  • ATMega256

über

#define USE_TIMER_5

kann der Timer 5 anstatt des Timer 1 benutzt werden. Dadurch werden dei PWM Ports auf den Pins 11,12,evt. 13 nicht mehr beeinflußt und evt. braucht man den Timer1 noch für was anderes. Bei Timer 5 gehen dann die PWM auf 44, 45 und 46 (die sind auf dem XIO Stecker) aber nicht mehr.

Die defines kann man entweder direkt in der RCReceive.h aktivieren oder aber man schreibt diese vor dem

#include "RCReceive.h"


Beispiel:

#define USE_TIMER_5
#include <RCReceive.h>

Hardwareanbindung

Schliessen Sie einfach die Masse und den Impulspin an den Arduino an. Masse an den entsprechenden Massepin vom Arduino und der Impulspin an den Pin, den Sie im Programm definiert haben.
Beim Testen des Programms ist es sinnvoll, das man den Empfänger vom Arduino mitversorgen kann. Dann, und auch nur dann, können Sie auch den mittleren Pin vom Servokabel an den +5V Pin des Arduino anschliessen. Bitte vermeiden Sie, den Empfänger in dem Fall anderweitig mit Strom zu versorgen. Denken Sie bitte auch daran, daß manche Fahrtregler eine eingebaute Versorgungsfunktion (BEC) haben. Eine Versorgung aus 2 verschiedenen Quellen kann sowohl für den Arduino wie auch für den Empfänger, ESC gefährlich sein. Im Zweifel benutzen Sie dann den Vin Pin bzw. den DC-Anschluss des Arduinos.

Im Pollingbetrieb kann jeder Pin verwendet werden. Beim Interruptbetrieb können nur die Pins 2 und 3 benutzt werden.

Benutzung

Möchten Sie nun einen Kanal auswerten, müssen Sie zunächst einen Pin zur Verfügung stellen. Die korrekte Initialisierung übernimmt die Bibliothek. Dazu müssen Sie pro Kanal eine Variable vom Typ RCRecive definieren und diese mit dem Pin verbinden.

...
// Hardwareanbindung für Arduino Hardware, Empfängerkanäle
const byte PIN_RC_STE = 3; 
RCReceive rcReceiver;
...
void setup() {
...
  // und Pin mit dem Objekt verbinden
  rcReceiver.attach(PIN_RC_STE);
...
}

Soweit so einfach. Es gibt 2 Varianten der Einbindung.

Polling

Beim Polling müssen Sie dem Objekt, denn darum handelt es sich nun, sagen, wann es den Wert vom Empfänger lesen soll. Dieses geschiet mit der Methode poll(). Am besten macht man das z.B. am Anfang in der loop() Methode.

void loop() {
  // neuen RC Wert für Steuerservo lesen.
  rcReceiver.poll();
...
}

Die ersten 10 Werte gehen immer in die Nullpunktbestimmung. d.h. wenn man den Arduino einschaltet und dieser vernünftige Werte vom Empfänger erhält, sind die 10 ersten Werte nur für die Nullpunktbestimmung relevant. Das geschiet automatisch im Hintergrund. Es gibt eine Funktion zur Abfrage, ob der Nullpunkt bereits gelesen wurde. hasNP()
Den Nullpunkte sollte man also abfragen und solange mit der eigentlichen Funktion warten, bis dieser korrekt bestimmt worden ist.
Machen kann man das z.B. so:

...
 
void loop() {
...
  // Aktuellen RC-Wert lesen
  rcReceiver.poll();
 
  // Nullpunktsbestimmung ?
  if (rcReceiver.hasNP() && !rcReceiver.hasError()) {
    doWork();
  } else if (rcReceiver.hasError()) {
    // Fehlerbehandlung failsafe oder sowas...
  }
...
}

Auch kann man an dieser Stelle nach Fehlern abfragen und entsprechend reagieren.
Um im Programm jetzt den aktuellen Wert herauszulesen, muss man folgende Methode aufrufen:

...  
  byte value = rcReceiver.getValue();
...

Damit erhält man den gemittelten Wert der letzten 10 Werte. Die Mittlung mache ich deswegen, damit etweige Fehler in der Übertragung nicht so ins Gewicht fallen. Natürlich hat das eine Verzögerung zur Folge. Und zwar von genau 200ms.
Nachteil Wenn Sie den Polling Mechanismus einsetzten wollen und zus. noch weitere Bibliotheken, die mit Interrupts arbeiten, kann es sein, das der Wert nicht konstant ist, sondern unruhig wird. Die zur Messung des Empfängerwertes verwendete Funktion pulseIn() wird dann von den im System vorhandenen Interrupts gestört.
Natürlich kann man vor dem pulseIN() mit cli() die Interrupts abschalten und mit sei() wieder einschalten, dann wird der gemessene Wert wieder schön ruhig, aber leider funktionieren dann evt. die anderen Bibliotheken nicht mehr richtig. Sehr Ärgerlich ist, daß gerade die für uns wichtige Servo Bibliothek einer der Störenfriede ist. Und die Servo Bibliothek reagiert ganz schlecht auf das Ausschalten des Interruptes.

Eine Verbesserung bringt da das 2. Messverfahren.

Interrupts

Für die Messung des Empfängersignales kann man auch Interrupts verwenden. Dazu müssen aber die Pins 2 und 3 verwendet werden. Andere Pins gehen dann nicht. (Nur Deumillanove und Uno) Nur diese Pins sind mit den Softwareinterrupts 0 und 1 verbinden. D.h. Pin 2 ist für den Interrupt 0 zuständig und Pin 3 für den Interrupt 1.
Um den Interrupt zu benutzen müssen wir lediglich zum Initialisieren eine andere Methode verwenden. Also ändert sich der setup()-Code zu:

void setup() {
  rcReceiver.attachInt(PIN_RC);
  // put your setup code here, to run once:
}

Wichtig ist die attachInt() Funktion. Der Parameter bezeichnet den richtigen Pin und nicht die Interruptnummer. Die Umsetzung erfolgt intern.
Ein poll() in der loop() Funktion kann jetzt entfallen.

Hier mal eine Auflistung der verschiedenen möglichen Pins der verschiedenen Boards.

  • Duemillanove, Uno (328): Pins 2 und 3
  • Leonardo: Pins 3, 2, 0, 1 (Wichtig: 2 und 3 sind vertauscht, macht für uns aber nix, da die Bibliothek alles richtig verdrahtet.)
  • Mega2560: Pins 2, 3, 21, 20, 19, 18

Methoden

Hier jetzt mal alle Methoden auf einen Streich.

  void attach(byte pin);

Verbindet das Objekt mit einem Arduino Pin.

  void attachInt(byte pin);

Verbindet das Objekt mit einem Arduino Pin und startet den Interruptmodus.

  void detachInt(byte pin);

zugewiesenen Interruptroutine lösen.

  byte getValue();

Holt den aktuellen gemittelten Wert im Bereich von 0-255.

  int getMsValue();

Holt den aktuellen gemittelten Wert in ms.

  byte poll();

Den aktuellen Wert vom Empfänger holen.

  byte hasNP();  

Nullpunkt wurde ermittelt.

  byte getNP();  

Aktuellen Nullpunkt holen.

  byte hasError();  

Es wurden mehr als 3 fehlerhafte Pakete vom Empfänger übermittelt.

Diskussion

Dirk, 2016/10/04 20:42
Hallo,
ich tüftle schon lange an einer Fahrwerkssteuerung mit 2 Servus und dem Schalter über 2,4, kHz Sender und Empfänger. Ausgelesen werden soll die Stellung eines 2 Wege Schalters am sender. Leider hapert es hier an meinem begrenzten Wissen. Wäre net wenn jemand dafür einen code hat
Jo, 2016/06/11 19:14
erst mal vielen Dank fuer die Bibliothek. Ohne die haetten wir uns wohl nie an die Sache ran getraut ;)
Wir sind eine Schulklasse ohne Programmiererfahrung. Fuer unser Solarboot basteln wir gerade einen MPP Tracker.
Der erste Test war vorgestern.
Unser Boot bleibt stehen wenn es soll, es faehrt rueckwaerts und auch vorwaerts. Erstaunlich ;)
Allerdings gibt es auch noch Probleme.
Die Steuerung reagiert stark verzoegert. Allerdings geben wir noch Werte ueber die serielle Schnittstelle aus und haben da noch delays drin. Vermutlich ist das der Grund.
Falls nicht, irgendwo weiter oben steht, dass man die Anzahl der Messwerte fuer die Mittelwertbildung verringern kann.
In RCReceive.h steht stackSize=10 drin. Reicht es diesen Wert zu verkleinern?
Was uns allerdings mehr Sorgen bereitet, manchmal laeuft der Motor nicht an.
Man kann den Gasknueppel mehrfach vor und zurueck bewegen ohne dass sich was tut.
Ploetzlich geht es dann doch wieder.
Irgendwie ist das nicht optimal fuer ein Rennen ;)
Haette da zufaellig jemand eine Idee was das sein koennte? Oder besser, wie man das abstellen koennte.
Die debug Option gibt Werte auf der seriellen Schnittstelle aus? Koennte sowas bei eingrenzen der Ursache weiter helfen?
Eine Abfrage auf Fehler haben wir nicht im Programm
Vielen Dank schon mal
Jo, 2016/07/23 11:13
Hallo
irgendwie scheinen sich die Bibliotheken RCReceive und Servo nicht zu mögen.
Es tauchen öfter Fehlermeldungen auf. Der Wert vn der Steuerung wird wohl nicht richtig gelesen. Die Folge sind Aussetzer
Die Kombination Arduino Nano mit RCReceive und ServoTimer2 hat die Problemem bei uns endgueltig (?) beseitigt.
Matthias, 2015/12/24 16:46
Hallo,
also ich bin auch noch Anfänger und beschäftige mich seit ein Paar Tagen damit ein Empfängersignal
auszulesen. Ich habe das Beispiel aus der Bibliothek genommen und um 2 Zeilen ergänzt um mir den Wert
des Signals mittels byte getValue(); zu holen und im seriellen Monitor anzuzeigen.

Leider funktioniert das nicht, hier mein code:

#include "makros.h"
#include "debug.h"
#include "RCReceive.h"

/*
RC_Template.ino - Template for RC Receiver enabled programs interrupt version - Version 0.2
Copyright (c) 2014 Wilfried Klaas. All right reserved.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

const byte PIN_RC = 2;

// Der Empfänger
RCReceive rcReceiver;

void setup() {
// RC Receiver in Interruptvariante
rcReceiver.attachInt(PIN_RC);
Serial.begin (9600);

// put your setup code here, to run once:
}

void loop() {
// nur wenn der Nullpunkt bestimmt worden ist,
// und es keinen Fehler gegeben hat soll die eigentliche Arbeit gemacht werden
if (rcReceiver.hasNP() && !rcReceiver.hasError()) {
doWork();
}
else if (rcReceiver.hasError()) {
// Fehlerbehandlung failsafe oder sowas...
}
}

void doWork() {
// put your main code here, to run repeatedly
byte value = rcReceiver.getValue();
Serial.println(rcReceiver);
// hier würde ich dann was zwischen 0 und 255 erwarten ????
// und bitte nicht steinigen..... :-)
}
Matthias, 2015/12/27 16:06
Hallo,
so nach den Feiertagen. Konnte ich mich nochmal hinsetzen. Mein Fehler war ja recht "dumm".
Die variable die es auszulesen gilt ist natürlich "value" nicht "rcReceiver". So als blutiger Anfänger
ist mir das noch nicht so geläufig eine Variable zu definieren und dann gleich zu verwende.
Wie auch immer ich krieg jetzt einen plausiblen Wert zurück.

Wie es scheint ist aber die Abtastung zu langsam?
Ich hab das heute mit so nem billigen Servotester probiert, wenn ich langsam drehe dann geht´s
wenn ich schnell drehe auch aber die Werte die "value" annimmt kommen nicht "mit"?
Wilfried Klaas, 2016/01/08 08:24
Hallo Matthias,

Das mit dem "langsam" kann die Mittelwertbildung sein. In Der Bibliothek wird automatisch fliessend aus den 10 letzen Werten ein Mittelwert gebildet. D.h. wenn dein Servotester mit 50 Hz arbeitet, wie es normalerweise genormt ist, kommen sprunghafte Änderungen erst nach ca. 200ms vollständig an. Und Sprünge werden verschleiert. weil der Wert gleitent in die Richtung geht. Du kannst, wie auf der RCReceiver Seite beschrieben, diese Mittelwertbildung minimieren. Dann ist die Bibliothek schneller.
und Tschoe
Willie
A.Meschke, 2015/08/24 14:34
Das auslesen bekomme ich zwar mit den examples hin und es werden Werte von 0-255 angezeigt, doch wie steuer ich jetzt meine H-Brücke an um einen Motor vor und rückwärts drehzahlgeregelt laufen zu lassen?
Patrick, 2015/03/19 10:01
Servus Willie 😀



Danke für diese super Binliothek ich hab nur leider zwei Probleme, leider bin ich noch nicht so gut im programmieren der Arduinos und ich finde 1.nicht heraus wie ich im Polling Beispiel das für mehrere Kanäle am Mega umwandle, 2.wie ich dann die Werte vom Empfänger am seriellen Monitor anzeige (mit den serial.printin) nur halt an welcher Position und Vorallem wie ich das empfängersignal dann verwende um daraus ein Relais und ein PWM Signal zu steuern...



Bitte um Hilfe! 😀



Und danke schon im Voraus

Gruß Patrick
Patrick, 2015/03/19 22:19
habs jetzt mal für einen Kanal geschafft weis aber leider nicht wie ich das ganze auf mehrere Kanäle erweitere besonders bei dem Ganzen rcReveiver.poll und so


Bitte um Hilfe!

Danke nochmal für die Schöne Arbeit
Markus, 2014/10/06 00:04
Hallo,

ein echt sehr gute Seite, ich bin absoluter Neuling was das Programieren angeht. Sehr viel habe ich mir da schon beigebracht, aber eine Sache will mir einfach nicht in den Kopf rein.
Mal als Beispiel:
Ich baue eine Tirpitz in 1:100,
darauf sitzen vorne 2 Geschütztürme (angetrieben mit Servo) und dadrin sind jeweils ein Servo für die Geschützrohle.
Die Spannungsversorgung würde ich jetzt für die Servos extern machen, da ja sonst der Arduino kaputt gehen würde.
Jetzt wollte ich ein Signal von dem Empfänger einlesen (das habe ich schon hin bekommen, hoffe ich zumindest)
Mein eigentliches vorhaben ist einen Propkanal nutzen um die beiden Geschütze sich langsam (ServoSlow) drehen zu lassen.
Links Mitte Rechts
0° 90° 180°

Dann kommt das bedenklichste für mich,

die Geschützrohre sollen sich dann auch heben, ab einem bestimmten Winkel des 2 Drehservo
der erste Turm soll sich ein ganz kleinen bischen langsamer drehen oder ein 1/4sekunde später.

wenn ich jetzt aber eine Taste am Modell drücke, sollen beide Geschütze in die 90° Position zurück kehren und da verharren, egal ob der Poti am Sender seinen wert verändert.

Das ganz möchte ich mit einem Arduino Uno verwirklichen ist dieses überhaupt möglich?
Wilfried KLaas, 2014/10/13 09:36
Hallo Markus,

'ne Tirpitz 1:100 hab ich auch noch hier in der Warteschlange. :-)
Zu deinem "Problem". Na klar geht das, das ist kein Problem.
ein paar kleine Tips:
- versuch erst mal einen Servo über den Arduino zu steuern. Dann den 2. auf einem anderen Pin. Die beiden Rohrservos an einen dritten Pin. Getrennte Spannugsversorgungen für die Servos ist klar. Aber nicht vergessen, die Massen (GND) miteinander zu verbinden. (Aber nicht den 5V +)
- mit dem SlowServo bist du schon auf der richtigen Fährte. Du müstest das ganze aber für 2 Servos machen, wobei der 1. Servo dann auf den aktuellen Stellwert des 2. reagiert und langsamer wird.
Der Anstellwinkel der Rohre wird dann einfach per Berechnung bestimmt.

- Für den Taster machst du eine einfache Schleife zum Entprellen und speicherst dann den Wert in eine Variable. z.B. bool pause oder so. Wird die dann true, dann legst du einfach den Wert, der eigentlich vom Empfänger auf einen festen Wert. Beim 2. Druck wird wieder auf den Empfänger umgeschaltet.

Wenn du willst, mach ich dir hier (http://wkla.no-ip.biz/ArduinoWiki/doku.php?id=arduino:ohter:pruser) eine eigene Seite auf. Dann kann ich dir da mal Beispielcode zeigen. Ist für andere auch interessant. Oder du machst im Schiffmodell-Forum ein neues Thema auf (http://www.schiffsmodell.net/forumdisplay.php?f=1472).
und Tschoe
Willie
, 2013/12/24 00:22
Hallo Willi,
Ich finde Dein Know-How-Paket resp die RC-Bibliothek sehr gut !
Gerne Deine Hilfe zu folgedener Routine für die Nullpunktbestimmung "rcReceiver.hasNP()":
Um was für einen Nullpunkt handelt es sich hier? Was wird hier genau bestimmt?
Danke!
Romeo
Wilfried Klaas, 2013/12/24 00:36
Hallo Romeo,

die Nullpunktbestimmung ist eine Funktion, die den Mittelwert der ersten 10 Impulse des Empfängers bestimmt. Wenn man also den Arduino anschaltet, mißt er die ersten 10 (gültigen) Empfängerimpulse und diese bilden dann den Nullpunkt. Diesen kann man dann verwenden um z.B. bei einer Car Fernsteuerung den Nullpunkt (Mitte) des Gashebels zu bestimmen. (Wenn man beim Einschalten am Sender einfach nix macht.) Das gleiche gilt z.B. für die Ruderstellung bei einer Knüppelsteuerung.
Aber ACHTUNG: ein eventueller Trimm am Sender wird mit eingerechnet. Es kann dann dazu kommen, daß man nach jedem Einschalten neu trimmen muss. Also zunächst Trimm raus dann einschalten und dann den Trimm neu setzen. BEsser ist es aber, wenn man das System so aufbaut, daß man keinen TRimm mehr braucht.
Lukacs, 2017/07/14 17:11
Hallo Willie



Danke für deine super Library. Ich brauche sie für eine Turbinensteuerung. Da ist aber das Thema, dass der Gaskanal welchen ich auswerten werde, standardmässig beim Einschalte der Fernsteuerung und auch sonst immer im Leerlauf ist (gerasterter Knüppel). Muss ich in der RCReceive.cpp diese Prüfung ausschalten oder verstehe ich etwas falsch unter dem Befehl: "rcReceiver_ser.hasNP() "



Bin gerade in den Ferien und habe leider keinen Sender/Empfänger da um das zu prüfen :-)







Danke für dein Nachfassen zu dem Thema!



Gruss Lukacs
Nymphenburg, 2013/09/19 22:59
HALLO WILLIE,

GEHT DEINE BIBLIOTHEK AUCH IN VERBINDUNG MIT EINEM Arduino Nano 3.0?

DANKE UND GRUß

MATTHIAS
Wilfried Klaas, 2013/09/19 23:40
Ich hab's bisher nicht getestet. Da der Nano wie der Uno aber auf einem Atmega 328 beruht, sollte es funktionieren.
Matthias Kaufmann, 2013/08/11 21:11
Hallo Zusammen,

vorne weg, ich habe noch keinerlei Erfahrung mit dem Arduino (in meinem Fall Leonardo), jetzt wollte ich das Interupt Beispiel ausführen (habs an Pin 0, 1, 2 und 3 versucht)

Wo kann ich bitte das TX Signal auslesen?

Danke und Gruß

Matthias
Wilfried Klaas, 2013/08/12 08:01
Hallo Matthias,

Zunächst probier erstmal das Pollingbeispiel. Erst wenn das mit deiner Schaltung funktioniert, würde ich das Interruptbeispiel versuchen.
Ausgelesen wird mit getValue(). Gepollt wird mit poll() an der jeweiligen Empfängervariablen.
Alex, 2013/07/26 15:14
Hi,
erstmal -> Super geile Sache die du da gemacht hast ;)
So, aber ich verstehe nicht, warum ich die Wert für die Lenkung (von Empfänger auf PIN2 | Arduino MEGA) richtig bekomme, die von "Gaspedal" aber nicht (auf PIN3)... Dort liegt immer der Wert 65 an... hier ein Codeauszug:

const byte PIN_RC_SER = 2; //SERVOPIN
const byte PIN_RC_THR = 3; //THROTTLEPIN
Servo myservo;
RCReceive rcReceiver_ser;
RCReceive rcReceiver_thr;
int value2 = 0;

void setup() {
// RC Receiver in Interruptvariante
rcReceiver_ser.attachInt(PIN_RC_SER);
rcReceiver_thr.attachInt(PIN_RC_THR);
myservo.attach(5);
Serial.begin(9600);
// put your setup code here, to run once:
}

void loop() {
// nur wenn der Nullpunkt bestimmt worden ist,
// und es keinen Fehler gegeben hat soll die eigentliche Arbeit gemacht werden
if (rcReceiver_ser.hasNP() && !rcReceiver_ser.hasError()) {
doWork();
}
else if (rcReceiver_thr.hasError()) {
Serial.println("ERROR THROTTLE");
}
}

void doWork() {
// put your main code here, to run repeatedly
byte vser = rcReceiver_ser.getValue();
byte vthr = rcReceiver_thr.getValue();

for(int i = 0; i<10; i++)
value2 += vser;

value2 = value2 / 10;


myservo.write(value2);
Serial.println(vthr);
Serial.println(value2);
}

Gruß
Willie, 2013/07/26 17:16
Hallo Alex,

das Problem mit der 65 kommt mir irgendwie bekannt vor (Andidi). Da war es der falsche Pin. Versuchs zunächst einmal im Pollingbetrieb. Erst wenn das richtig klappt, dann versuch es nochmal im Interruptbetrieb. Leider habe ich gerade keinen Mega da, weil im Urlaub, sonst würde ich das ausprobieren.
Dieter Kalkofen, 2013/03/31 12:15, 2013/03/31 19:01
Hallo,
Ein super Programm endlich ein Prozessor der RC Signale verarbeiten kann,
Hier ein groses Lob an den Programmierer,
Meine Frage zum Ardunio Uno wie kann Ich Pin 2 und Pin 3 gleichzeitig
Einbinden und auswerten ?,
Gruss Dietr,
Willie, 2013/04/01 00:30
Hallo Dieter,

Danke. 2 Kanäle auszuwerten ist auch ganz einfach. Man muss nur für den 2. kanal eine weitere RCReciver Variable erzeugen und entsprechend initialisieren. (Beispiel Kreuzmischer)

[code]
RCRecive escReciver;
RCRecive servoReciver;
[/code]

In der setup() dann...
[code setup()]
escReciver.attach(PIN_RC_THR);
servoReciver.attach(PIN_RC_STE);
[/code]

oder auch
[code setup()]
escReciver.attachInt(PIN_RC_THR);
servoReciver.attachInt(PIN_RC_STE);
[/code]

in der Loop dann
[code loop()]
if (escReceiver.hasError() || servoReceiver.hasError()) {
// hier z.B. den Failsafe
}
else if (escReceiver.hasNP() && servoReceiver.hasNP()) {
// Hier die eigentliche Arbeit
doWork();
}
[/code]

Im Pollingbetrieb in der Loop nicht das poll() auf beiden Variablen vergessen!
und Tschoe
Willie
Dieter Kalkofen, 2013/04/04 12:13
Hallo Wilie
Danke für das Programm klappt super.
was mir wohl aufgefallen ist das bei nutzung beider Kanäle (2 u. 3)
Die Funktion analogWrite(Pin, Value) Pei den Pins 9 und 10
alle Werte unter 255 gleich Ausgang O Volt ergibt.
Die anderen Dins 5 und 6 sind nicht beroffen.


#include "makros.h"
#include "debug.h"
#include "RCReceive.h"

int Kanal_5;
int Kanal_7;

const byte PIN_RC_2 = 2;
const byte PIN_RC_3 = 3;

// Der Empfänger
RCReceive escReceiver;
RCReceive servoReceiver;

void setup()
{
// RC Receiver in Interruptvariante
Serial.begin(9600);
escReceiver.attachInt(PIN_RC_2);
servoReceiver.attachInt(PIN_RC_3);
}

void loop()
{
escReceiver.poll();
servoReceiver.poll();

if (escReceiver.hasError() || servoReceiver.hasError())
{
// Hir Falsave
}

else if (escReceiver.hasNP() && servoReceiver.hasNP())
{
Kanal_5 = escReceiver.getValue();
Kanal_7 = servoReceiver.getValue();
}

Serial.println(Kanal_5);
}

Gruss Dieter
Willie, 2013/04/05 12:27
Ja, das kann sein.
Das liegt aber nicht nur am RCReciver, sondern kann man auch nur mit der Servo Bibliothek beobachten. Die beiden PWM Ausgänge 9/10 werden vom Timer1 aus gesteuert. Dieser Timer wird aber auch von der Servo Bibliothek, wie auch von meiner RCReciver Bibliothek verwendet. Ich brauche den Timer zum Zählen, die Servo Bibliothek braucht ihn auch zum Steuern der Ausgänge.
Andidi, 2013/02/26 12:21
Hallo,

wie nutze ich denn das "byte getValue();" ? Ich bekomme nämlich immer den Wert 65 zurück, egal was ich mache. Gibt es dafür ein einfaches Beispielprogramm mit Interrupts?
Willie, 2013/02/26 12:35
Ja, klar, wenn du die Bibliothek richtig installiert hast, findest du ein Beispiel unter
Datei/Beispiele/RCReceive/RC_Int_Template

Aus dem Beispiel:
void doWork() {
// put your main code here, to run repeatedly
byte value = rcReceiver.getValue();
}

An welchen Pin hast du den Empfänger angeschlossen?
Andidi, 2013/02/27 21:43
Ich habe einen Mega2560 und habe den digitalen Pin 22 und den analogen Pin 2 genutzt.
Mein Receiver scheint in Ordnung zu sein, denn Ihr Beispielprogramm mit Polling arbeitet einwandfrei.
willie, 2013/02/27 22:14
Beim Mega sind im Interruptbetrieb nur die digitalen Pins 2, 3, 18, 19, 20, 21 möglich. Also weder der Pin 22 noch der analoge Pin 2.
WIllie, 2013/01/31 09:29
In der aktuelle Bibliothek wird nun auch das Fehlen des Empfängersignales im Interruptbetrieb geprüft. Somit ist die Lib endlich vollständig.
lab, 2013/01/08 08:53
Hallo Willie,

was prüfst Du, um die fehlerhaften Pakete des Empfängers zu identifizieren?
Willie, 2013/01/08 11:03
Als Fehlerhaft werden Pakete erkannt, die kleiner als 900ms oder größer als 2100ms sind. Was der Bibliothek noch fehlt, ist eine Kennzeichnung wenn gar kein Signal mehr kommt. Aber da arbeite ich gerade dran. Bis zu 3 fehlerhafte Paket werden ignoriert, danach wird das Fehlerflag gesetzt (hasError()) Zus. werden 10 Werte vorgehalten und daraus der eiugentliche Wert berechnet. Größter und kleinster Wert fallen raus, aus den restlichen 8 wird dann der Mittelwert gebildet. Dadurch werden Steuerbefehle zwar verzögert und verschliffen, aber Störungen werden wirksam unterdrückt. Wer möchte kann natürlich sowohl die Schranken anders einstellen, wie auch den Mittelwert-Speicher verkleinern oder vergrößern.
Melden Sie sich an, um einen Kommentar zu erstellen.
arduino/modellbau/projekte/rcreciver.txt · Zuletzt geändert: 2018/11/04 11:51 (Externe Bearbeitung)
CC Attribution-Share Alike 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0