How to read RC radio signals with Arduino using PPM signal

4.6/5 - (8 votes)

In drones the RC transmitter is a fundamental part of the system.

In this article, I will show how to use coded PPM RC signal. In this example, I am using the Turnigy 9XBC RC receiver.

Receiver

Why do we want to use PPM RC signals?

The main reason is to spare pins of the main controller. Also, to reduce the number of cables considerably. For the case of aerial vehicles, weight is a critical factor and reduce the number of wires is one optimization to enlarge the flight time.

Differences between reading Servo signals or PPM signals:

Performance and simplicity in code are the reasons for intercept the PPM signals instead of servo signals.

The advantage of the PPM (Pulse Position Modulation) is that you can collect all the radio channel within one input. In that way, you can read all the channels with only one Arduino’s pin.

Less wires = less problems.

The idea is to read all radio channels within an interrupt routine of Arduino. Another workaround is to use a dedicated microcontroller and send the processed data to the main Arduino board by SPI or i2C.

Besides, if we disassemble the receiver housing and all input pins, we lose almost 70% weight and also save space. Very useful for drones.

radio signals

PPM and PWM are two different protocols for radio information.

PPM has the advantage that you can get all the channels information through one port only. Some call it “PPM sum”, since it’s the sum of all channels. That helps a lot when you have limited number of connectors to your flight controller.

So, the drone has a PPM receiver. The receiver talks with my flight controller (the ArduPilot) over 1 single coded line. Then the flight controller will send PWM outputs to the ESCs and the servos for the camera mount of my drone.

By using the PPM input, I can embed now 10 PWM outputs from my Open Pilot Copter Control instead of 6 PWM outputs. That is for obvious reasons essential for me, because my camera mount needs 2 servo outputs plus the 6 ESC outputs for the hexacopter.

RC transmitters often have two operating modes:  PPM (Pulse Position Modulation) and PCM (Pulse Code Modulation).

To receive correct signals from the radio, the RC transmitter must be set to PPM and ACRO mode, without TRIM, without DUAL-RATE and neither EXPONENTIAL. By this configuration, we avoid to distort the values sent by the transmitter software and by transmitting raw values.

With the Turnigy 9X 8C V2 does not have a PPM output and also you can not extract the PPM signal anywhere from the PCB. The reason is that the receiver works with two microprocessor: a receiver and a decoder. They talk by SPI between them. Another hardware solution is to add an extra chip to decode the SPI signal.

Here you can check a big list with a lot of common receiver and how to get the PPM signal. LIST

 

PPM Signal Detection

If you don’t know where is your PPM signal, you can upload this Jordi’s code to try to find the right pin in our receiver board. With one wire connected to pin 3, start touching every pins and spots of your receiver until you see random values on the Arduino Serial Monitor between 300 to 9000. That means you found it. Don’t forget connect ground to ground.

void setup()
{
Serial.begin(57600);
pinMode(3, INPUT);
}
void loop()
{
Serial.println(pulseIn(3, LOW));
}
The programs below were written by Jordi Muñoz and uploaded to Arduino’s Forum 1st de January 2008.
 Basic PPM reader with Arduino
#define channumber 6 //How many channels have your radio?
int channel[channumber]; //read Channel values
int PPMin = 4;

void setup()
{
  Serial.begin(9600); //Start serial
  pinMode(PPMin, INPUT); // Pin 4 as input
}

void loop()
{
  //waits ultil synchronize arrives > 4 miliseconds
  if(pulseIn(PPMin , HIGH) > 4000) //If pulse > 4 miliseconds, continues
  {
    for(int i = 1; i <= channumber; i++) //Read the pulses of the remainig channels
    {
 channel[i-1]=pulseIn(PPMin, HIGH);
    }
    for(int i = 1; i <= channumber; i++) //Prints all the values readed
    {
 Serial.print("CH"); //Channel
 Serial.print(i); //Channel number
 Serial.print(": "); 
 Serial.println(channel[i-1]); //Print the value
    }
    delay(200);//Give time to print values.
  }
}

PPM reader with glitch filter:

#define channumber 6 //How many channels have your radio???
#define filter 10 // Glitch Filter
int channel[channumber]; //read Channel values
int lastReadChannel[channumber]; //Last  values readed
int conta=0; //couter


void setup()
{
  Serial.begin(9600); //Serial Begin
  pinMode(4, INPUT); //Pin 4 as input
  pinMode(13, OUTPUT); // Led pin 13
}

void loop()
{

  if(pulseIn(4, HIGH) > 3000) //If pulse > 3000 useconds, continues
  {
    for(int i = 0; i <= channumber-1; i++) //Read the pulses of the channels
    {
 channel[i]=pulseIn(4, HIGH);
    }
    for(int i = 0; i <= channumber-1; i++) //Average the pulses     { if((channel[i] > 2000) || (channel[i] <100))//If channel > max range, chage the value to the last pulse
 {
  channel[i]= lastReadChannel[i];
 }
 else
 {
 channel[i]=(lastReadChannel[i]+channel[i])/2; //Average the last pulse eith the current pulse
 conta++; //increment counter
 }
    }

    }
    if(conta > filter)//If counter is > than filter, then prints values
    {
 for(int i = 0; i <= channumber-1; i++) //Cycle to print values
 {
   Serial.print("CH"); //Channel
   Serial.print(i+1); //Channel number
   Serial.print(": "); 
   Serial.println(channel[i]);
   lastReadChannel[i]=channel[i];
 }
 if(channel[4] > 1000) //If channel 5 is > than 500 turn on the led
 {
   digitalWrite(13, HIGH);
 }
 else
 {
   digitalWrite(13, LOW);//If not turn it off
 }
 delay(400); //Delay
 conta=0;//Restart counter.
    }
  } 

11 thoughts on “How to read RC radio signals with Arduino using PPM signal”

  1. Perdon por la ignorancia, pero tengo el mismo receptor que tenes vos, entiendo que no puedo leer el PPM, pero podre leer el pwm canal por canal?

  2. was wondering how to go about connecting a spektrum 6ch receiver to my arduino, and then have my arduino output the signal like a trainer port would on a dx6i, reason i ask is i have a basic 4ch spektrum remote that has no trainer output

  3. Hi. I have just bought a remote and receiver, I am trying to use 4x DC motor with hacking the receiver. I tried each step except the hacking inside, firstly I tried to read a ppm from a pin (channel 1 ) but it gave me random numbers, it didnt change when I play with remote. I have K-8X receiver, can you help me a bit please? thanks a lot for this very explanatory description

  4. Hey there! I’ve been following your website for a long time now and finally got the bravery to go ahead and give you a shout out from Atascocita Texas! Just wanted to tell you keep up the great job!

  5. There is a bug in the first code example:
    This: if(pulseIn(PPMin , HIGH) > 4000); //If pulse > 4 miliseconds, continues
    Should be: if(pulseIn(PPMin , HIGH) > 4000) //If pulse > 4 miliseconds, continues

    Note the ; char has been removed.

  6. Hi Alberto,
    I have a flysky fsi6 I use with my arduino remote control snow blower.

    I have connected a raspberry pi 4 to my arduino mega 2560 using the USB port for communication. Using the firmata protocol uploaded to the Arduino as slave and using the pi as master.
    My question is :Would you happen to know how I can read RC channel inputs from the arduino on the raspberry pi 4 ? There is not very much info out there on the subject.

Leave a Comment

Your email address will not be published. Required fields are marked *