Wednesday, November 20, 2013

Homemade PPM Encoder

This project is a spin off from my PPM decoder project. The overall goal is to translate the individual PPM signals from an RC receiver (like THIS one) into usable data that can be sent via serial, I2C, or a simple analog pin. Breaking that down, we get three smaller goals. If you have no idea what I'm talking about, read up on the subject HERE.
1) Combine the different channels into one "PPM Stream"
2) Decode this stream using a microcontroller
3) Do something useful with this decoded information

This post will tackle the first issue. To decode the signals coming from the RC receiver we first want to combine all the different channels (e.g. aileron, rudder, elevator...) into one channel. We want to do this so that later we can decode all the channels with one hardware interrupt (a single pin). 

Before you begin, you should consider your different options
1) Buy a PPM encoder ($25) - This seems to be the most popular one. There are a few others floating around Ebay
2) Buy a receiver with a PPM Stream output - Various receivers have this functionality. There have also been reports of people using satellite receivers like THIS. I can neither confirm nor deny the feasibility of that.
3) Hack your existing receiver - Funny enough, your receiver probably has the signal in the form we want at one time or another. It then decodes it to separate out the channels for the different servos. If you can find the correct place to solder on a wire, you're in business. HERE is a great write up on this. I preferred a noninvasive approach.
4) Make your own external PPM Encoder- Read on!

Now, there are several ways you can make your PPM encoder. The most complicated way is described HERE. If you choose to go that route, I will forgive you. I have no doubt that it probably is more robust and "correct" than the way I am going. The schematic is included as well as the PCB gerber files, so if you have access to all the materials have at it.

The method I am using is pretty simple. Put a diode on each channel with a pull down resistor at the end. The schematic is below.

Note that the receiver is running at a 3.3V logic level. For some microcontrollers this is not a problem; the Arduino DUE operates at 3.3V logic. However, for a standard Arduino like the Uno or Mega2560 operating at 3.3V is flaky. While it may work, fluctuations could cause glitches. At any rate, I included a built in 3.3V to 5V logic level converter circuit.

The circuit consists of 4 resistors and 2 transistors. I based mine off of the circuit found HERE. It is worth noting that there are other ways to convert 3.3V logic to 5V. I am not qualified to explain all of them, but I can say that ready made solutions are available from many different vendors.

When you combine these two circuits, the following schematic emerges.

Running a quick LTSpice simulation on it yields the graph below. Note that blue is the output on the 5V side. Red is the input on one of the channels (in real life this will be digital, but I just did a voltage sweep from 0 -3.3). Green is the voltage at the 3.3V output. Note the slight voltage drop. While this is insignificant when using the logic level shifter, it is something to note if you are using a 3.3V microcontroller.

Now to assemble it.

Bill of Materials:

  • 1 - Protoboard
  • 9 - Male Headers 
  • 6 - 1N4148 Diodes
  • 2 - 2N3904 NPN Transistor
  • 3 - 1k Ohm Resistor
  • 1 - 10k Ohm Resistor
  • 1 - 1.5k Ohm Resistor

1N1418 Diode Array

Finished Product

Underneath Side

The keen eyed observer may spy that I substituted a 1k resistor for the 1.5k, and it works fine. I didn't have a 1.5k. You may also notice that it could be made a bit smaller with a little effort. That will be work for v2. 

On the finished product picture above, the six male headers are the six 3.3V inputs. The two male pins the the right are the 5V and GND connections. The single male header at  the bottom is the 5V encoded output. Below is a picture of it connected up to my Arduino Mega 2560 and 6 channel OrangeRx receiver.

Here are the results. The first picture is the signal when all the pins of the receiver are just straight wired together. The second picture is when the signals are run through my encoder without the logic level converter.The third is the full encoder output with the logic level converter. The main difference is the peak voltage. Without the encoder, each peak is about 500mV. With the encoder, each peak is about 4.9V. All three circuits are on channel 1 on the oscilloscope. See the scale in the bottom left of the oscilloscope screen.
Without Encoder
Encoder Without Logic Level Converter Circuit
Full PPM Encoder Output
As you can see, the encoder works perfectly. Each signal is distinguishable from every other signal and is large enough to be read by an Arduino. It is ready to be fed into one of the Arduino's hardware interrupts to be decoded. To decode the RC receiver signals go to my other post, Arduino PPM Decoder: Decoding an RC Receiver with an Arduino.

Let me know if this works for you! If you have problems, comment below and I will do my best to help you. 


  1. hey Matthew, nice work!! I tried to follow your post but it didn't work for me...I have some questions that maybe you can throw some light. First the transistors are PNP or NPN? i put 2 NPN transistors but what i have on my oscilloscope is a 5V 50Hz square signal, nothing about ppm signal, thanks for you help!

  2. You raise an excellent point. They are NPN. I used a 2N3904, but for some reason typed that it was a PNP (I will fix that).

    As for getting a square wave, that is interesting. If I had to guess I would say that the wave is actually all of the signals getting lumped together. This would mean either a) your scope is not reading it fast enough to catch the fall and rise divisions of the individual signals or b) your receiver works differently and actually changes each channel simultaneously ( ie channel 2 falls at exactly the same time as channel 3 rises so that no space in between them is visible). If "a" is the case, then the Arduino code should still work even if you can't see the divisions on the scope. If "b" is the case, then you may be out of luck, you would probably have to divide the channels into even and odd and read them that way. I can't imagine this being the case, but maybe with higher quality receivers it is.

    You might try moving the transmitter sticks and verifying that the square wave is indeed square or if it actually changes when you move the stick. That could give you a clue.

    Hope that helps,

  3. Matt, why have you gone through all this when your receiver has AUX port???