Wednesday, November 20, 2013

Arduino PPM Decoder: Decoding an RC Receiver with an Arduino

In this post I will detail how to decode the PPM signals from an RC receiver using an Arduino. Specifically, I will decode the signals from a 6 channel OrangeRx receiver using an Arduino Mega 2560 r3 and my custom PPM encoder board that I describe HERE.

As most interested people know, the only good way to do this is with interrupts. While pulseIn will work for a few channels, more than 2 or 3 will bog it down too much to do anything useful.

Step 1
Access PPM Stream. THIS site describes what I mean by that. In short, we want to combine the single signal from the six individual pins into six signals on an individual pin. This allows us to decode all 6 channels with one hardware interrupt. That's something any Arduino can handle.

Like I mentioned above, you will need my PPM Encoder to do that (there are other options that I discuss in that post as well). Luckily, it is fairly cheap and easy to make. You may ask, "Why can't I just wire all the pins together?" In short, it doesn't work. I tried. This is because when one pin is high, five are low. Again, more details are in my other post.

6 Channel PPM Stream

Step 2
Decode the PPM Stream. As you can see in the picture above, the PPM stream consists of six spikes that we need to decode. Now, there are many descriptions online about how to decode these signals using interrupts, but I wanted a hardware independent approach. I didn't want to have to worry about my timers not working when this code is running or anything like that. For that reason, I wrote some fairly simple code that runs right in the Arduino sketch (vs tucked away in a library). I just set a hardware interrupt that triggers from a rising signal and subtract the times between each. (Read more on interrupts HERE). This of course causes a problem for channel 6 which doesn't have a signal coming after it. For this reason we have to do a few other things when we get to channel six.

HERE is my code. Look at it for yourself. It reads the values from the RC receiver, scales them to 1-100 and then prints them to the Serial Monitor. I'm not entirely happy with the way that I handled channel 6 at this point, but it works fine. I initially tried getting its value inside Spike(), but the micros() function does weird things inside it. I may revisit my approach someday, but it works for now. Though I wouldn't put anything life threatening on channel 6 (or any of the channels for that matter..). Below is an example output.


There you have it. A simple Arduino PPM signal decoder. Now you can get inputs from virtually any RC receiver and use them in your projects, library free. Hopefully you found this useful. As always, if you have any problems comment below and I'll see if I can help. If you had success, great! I'd love to hear about that as well. If you like this post, check out some of my others by clicking on a label that interests you.

Best of luck,
Matthew

2 comments:

  1. Hi Matthew, Thank you. It is very useful.

    ReplyDelete
  2. It looks like if for instance a copter, uses a standard RX decoder and if signal is lost copter just crashes? But here I can program whatever behavior I want.

    ReplyDelete