RC-Empfänger PPM-Signal mit Arduino auslesen – Schritt-für-Schritt
Komponenten
| Bauteil | Anzahl |
|---|---|
| Arduino UNO (oder Nano/Pro Mini) | 1 |
| RC-Empfänger mit PPM-Ausgang (z. B. 6-Kanal) | 1 |
Software
- Arduino IDE
Grundlagen: PPM-Signal
Ein klassischer RC-Empfänger gibt pro Kanal ein separates PWM-Signal (1–2 ms Pulsweite, 20 ms Periode) aus. Das erfordert pro Kanal einen Arduino-Pin und bei vielen Kanälen mehr Interrupts, als der AVR bietet (nur 2 Hardware-Interrupts beim ATmega328P).
Lösung: Viele Empfänger bieten einen PPM-Ausgang (Pulse Position Modulation): Ein einziges Signal, das alle Kanäle nacheinander in einem Frame überträgt.
PPM-Frame-Aufbau
- Ein Frame besteht aus einer Serie von Pulsen (ein Puls pro Kanal + 1 Sync-Puls).
- Die Pausen zwischen den Pulsen kodieren die Kanalwerte (typisch 1000–2000 µs → 0–100 %).
- Eine lange Pause (~11,5 ms) markiert das Frame-Ende (Sync).
- Bei 6 Kanälen: 7 Pulse pro Frame (6 Kanäle + Sync).

Auswerte-Algorithmus (Interrupt-basiert)
- Interrupt an Pin 2 (INT0) auf fallende Flanke (Ende jedes Pulses).
- Im ISR: Zeit seit letzter Flanke messen (
micros()) → in Array speichern (15 Werte Puffer). - Im Hauptloop: Nach Pause > 10.000 µs suchen (Sync-Lücke).
- Die folgenden 6 Werte = Kanal 1–6 (minus 1000 µs Offset → 0–1000 Skala).
Arduino-Code (Komplett)
unsigned long a, b, c;
int x[15], ch1[15], ch[7], i;
void setup() {
Serial.begin(9600);
pinMode(2, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(2), read_me, FALLING);
}
void loop() {
read_rc();
for (int k = 1; k <= 6; k++) {
Serial.print(ch[k]);
Serial.print('\t');
}
Serial.println();
delay(100);
}
void read_me() {
a = micros();
c = a - b;
b = a;
x[i] = c;
i++;
if (i == 15) {
for (int j = 0; j < 15; j++) ch1[j] = x[j];
i = 0;
}
}
void read_rc() {
int j = -1;
for (int k = 14; k >= 0; k--) {
if (ch1[k] > 10000) { j = k; break; }
}
if (j >= 0) {
for (int k = 1; k <= 6; k++) {
int idx = (j + k) % 15;
ch[k] = ch1[idx] - 1000; // 0..1000
}
}
}
Erklärung der Funktionen
read_me() (ISR)
- Wird bei jeder fallenden Flanke am PPM-Pin (Pin 2) aufgerufen.
- Misst die Zeitdifferenz
c = a - bzwischen zwei Flanken → Puls-Pause-Dauer. - Speichert 15 aufeinanderfolgende Werte im Ringpuffer
x[], kopiert nach 15 Werten inch1[].
read_rc() (Main Loop)
- Sucht in
ch1[]den Indexjdes Sync-Gaps (> 10.000 µs). - Liest die darauffolgenden 6 Werte als Kanal 1–6.
- Subtrahiert 1000 µs (Mittelstellung) → Wertebereich ca. 0–1000.
Anwendung & Tipps
- Die ausgelesenen
ch[1]..ch[6]können direkt für Servos (map(val, 0, 1000, 0, 180)), Motoren oder Logik verwendet werden. - Für mehr Robustheit: Mittelwertbildung über mehrere Frames, Plausibilitätsprüfung (Werte im erwarteten Bereich?).
- Failsafe: Wenn keine Frames empfangen werden → Default-Werte setzen.
- Der Code funktioniert auch mit 8-Kanal-Empfängern (dann 9 Pulse, Array-Größe anpassen).
Erweiterungsmöglichkeiten
- PPM → PWM-Wandler für klassische Servos (z. B. für Flugregler ohne PPM-Eingang).
- Kombination mit Joystick-Emulation (USB HID) für PC-Spiele/Simulatoren.
- Telemetrie-Rückkanal (SmartPort, CRSF) – erfordert bidirektionale Kommunikation.
Herstellungsprozess
- Heimtemperatur mit Raspberry Pi Dashboard überwachen
- DTMF-Decoder mit Arduino bauen – ganz ohne zusätzlichen IC
- Monitor-Ambilight selbst bauen mit Arduino Nano & WS2812B LEDs
- Ultraschall-Schwebegerät mit Arduino bauen – Akustische Levitation Schritt für Schritt
- ATmel AT89-Serie mühelos mit Arduino Uno programmieren – Schritt-für-Schritt-Anleitung
- Intelligentes Voltmeter mit Arduino & Smartphone bauen – Einfaches DIY-Projekt
- Echtzeit-IoT-Herzfrequenzmonitor mit Arduino & MAX30100
- Arduino UNO WiFi Webserver: LED per Browser steuern
- Intelligenter Parkplatzzähler: Echtzeit-Fahrzeugverfolgung mit Arduino, Processing & PHP
- Echtzeit-Herzschlag-LED-Visualisierung per EKG