I agree with you that using a one wire PPM receiver is a lot more efficient than a full-house receiver. As an example I add below my Corona project for our flying club. To increase the social distance between teacher and student, we needed some wireless buddyboxes.
One Arduino accepts two PPM receivers (cheap Banggood drone receivers are fine). and receiver #1 (chan #8) defines which receiver is operating the plane via chan 1-4. Chan 5&6 are always linked to the teacher.
/*
* Arduino as Wirless Buddybox RC switch
* https://youtu.be/ZxOkK0N1Gtw
* reads two CPPM receivers connected to digital pins 2 (teacher) and 3 (student)
* Outputs 6 PWN servo channels on digital pins 4-9
* CPPM Channel 8 (teacher) defines if servo PWM outputs channels 1-4 (pins 4-7) come from teacher or student. If teacher LED goes on.
* Channel 5-6 (pin 8-9) always come from teacher
*
* V1 Hans Meijdam, Jan 2021
* V1.1 Hans Meijdam, Jan 2021 should now compile on any standard Arduino IDE environment.
*/
#define RC_CHANS 8
volatile uint16_t rcValue_A[RC_CHANS] = {1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500}; // interval [1000;2000]
volatile uint16_t rcValue_B[RC_CHANS] = {1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500}; // interval [1000;2000]
#include <Servo.h> // If you get a "not found" compilation error here. The servo library can be added via the Arduino IDE library manager, if not already standard included these days.
// you can change the 6 Servo PWM output pins, but not the 2 CMMP input pin numbers 2 and 3 (see below)
#define SERVO1_PIN 4
#define SERVO2_PIN 5
#define SERVO3_PIN 6
#define SERVO4_PIN 7
#define SERVO5_PIN 8
#define SERVO6_PIN 9
#define NEUTRAL_US 1500 /* Default position in case of no pulse at startup */
#define NOW 1
enum {AILERON = 0, ELEVATOR, THROTTLE, RUDDER, AUX1, AUX2, SERVO_NB}; /* Define servo's index AND the amount of servos */
Servo ServoMotor[SERVO_NB]; /* Table Creation for all servo objects */
void setup() {
// put your setup code here, to run once:
pinMode(LED_BUILTIN, OUTPUT); // led wil turn on when teacher controls servos.
ServoMotor[AILERON].attach(SERVO1_PIN); //I use AETR servo order, but you can change as you like
ServoMotor[ELEVATOR].attach(SERVO2_PIN);
ServoMotor[THROTTLE].attach(SERVO3_PIN);
ServoMotor[RUDDER].attach(SERVO4_PIN);
ServoMotor[AUX1].attach(SERVO5_PIN);
ServoMotor[AUX2].attach(SERVO6_PIN);
// note that the external interrupts on Arduino based on atmega 328/168 can only be on pin 2 and 3. don't chenge these
attachInterrupt(digitalPinToInterrupt(2), rxInt_A, RISING); //Arduino PIN 2 (PD2, INT0)
attachInterrupt(digitalPinToInterrupt(3), rxInt_B, RISING); //Arduino PIN 3 (PD3, INT1)
}
void loop() {
if (rcValue_A[7] < 1300) {
digitalWrite(LED_BUILTIN, HIGH);
ServoMotor[AILERON].writeMicroseconds(rcValue_A[0]);
ServoMotor[ELEVATOR].writeMicroseconds(rcValue_A[1]);
ServoMotor[THROTTLE].writeMicroseconds(rcValue_A[2]);
ServoMotor[RUDDER].writeMicroseconds(rcValue_A[3]);
}
else {
digitalWrite(LED_BUILTIN, LOW);
ServoMotor[AILERON].writeMicroseconds(rcValue_B[0]);
ServoMotor[ELEVATOR].writeMicroseconds(rcValue_B[1]);
ServoMotor[THROTTLE].writeMicroseconds(rcValue_B[2]);
ServoMotor[RUDDER].writeMicroseconds(rcValue_B[3]);
}
ServoMotor[AUX1].writeMicroseconds(rcValue_A[4]);
ServoMotor[AUX2].writeMicroseconds(rcValue_A[5]);
}
/**************************************************************************************/
/*************** PPM SUM RX Pins reading ********************/
/**************************************************************************************/
void rxInt_A(void) {
uint16_t now_A, diff_A;
static uint16_t last_A = 0;
static uint8_t chan_A = 0;
now_A = micros();
sei();
diff_A = now_A - last_A;
last_A = now_A;
if (diff_A > 3000) chan_A = 0;
else {
if (900 < diff_A && diff_A < 2200 && chan_A < RC_CHANS ) { //Only if the signal is between these values it is valid, otherwise the failsafe counter should move up
rcValue_A[chan_A] = diff_A;
}
chan_A++;
}
}
void rxInt_B(void) {
uint16_t now_B, diff_B;
static uint16_t last_B = 0;
static uint8_t chan_B = 0;
now_B = micros();
sei();
diff_B = now_B - last_B;
last_B = now_B;
if (diff_B > 3000) chan_B = 0;
else {
if (900 < diff_B && diff_B < 2200 && chan_B < RC_CHANS ) { //Only if the signal is between these values it is valid, otherwise the failsafe counter should move up
rcValue_B[chan_B] = diff_B;
}
chan_B++;
}
}