Generate PPM signal with Arduino

In the beginning of this year I’ve written a short tutorial how to read PWM signals from RC radio with Arduino. While it is can be useful when building own RC equipment, it does not help much when one has to deal with PPM (CPPM) signal. Let’s be honest, PPM is much more useful than PWM: all RC channels are sent over single wire. On one side, it simplifies electrical design. On the other, it makes software part more “complicated”, since there is a need to encode multiple PWM channels into single PPM line in transmitter, and then decode PPM signal into multiple PWMs in receiver. And there are very little “ready and working out of the box” solutions in Arduino world.

In this short article I will show how to generate PPM (CPPM) signal using solution prepared few years ago by David Hasko. Originally it was posted of Google Code. But Google Code is not closed and who knows for how long it still will be available. So, let’s not let the knowledge got lost.

Code is relatively simple, and almost all work is done inside ISR(TIMER1_COMPA_vect) that is executed in the background by timer . Everything user has to do, is to put desired values to ppm array inside loop function. This code can generate both positive and negative signal. It can be easily ported to almost any project, as long as TIME1 is free to use.

Slightly more advanced example is available on GitHub.

17 thoughts to “Generate PPM signal with Arduino”

  1. Hello, this is Dominik from Germany.

    I found your post and find it very interesting. A few months ago I tried the original code without success.

    Might I ask a few questions about your additional code?

    You added a switch for what purpose? Binding?

    What is the switch_step parameter used for?

    The ppm signal pin is channel_to_modify? Right?

    Did you try an frsky 8ch DIY? This is the one I got here and which is not working for unknown reason 🙂

    Look here:

    Thanks for your patience

    Regards Dominik

    1. Button was added, coz I needed to change value of 1 channel. Every press of button was increasing channel value by switch_step.

      PPM output in on sigPin , in this case Arduino PIN 10.

      No, never tried that receiver.

  2. Hello.
    I’ve used your code with Arduino Mega. However, while checking output with oscilloscope I’ve found that it outputs incorrect pulse lengths. E.g. it outputs 1.800ms wide pulse while respective value in ppm array is 2090.

    1. My experiments with this code and Chinese clone of Arduino Pro Mini and original UNO R3 shows around 20us difference

  3. Hello everyone,
    Does anyone have a working code for reading the analog values (joysticks)?
    The map function like:

    “joystick = analogRead(joy1);
    joystick = map(joystick, 0, 1023, 0, 180); ”

    is supposed to be not soo accurate.

    Any ideas?

    Thanks Dominik

      1. Hello all.

        I have tried the rc_fake_ppm_receiver code for a PS2 Joystick to send PPM to the trainer port of a Flysky i6 without success.
        Can someone modify the code?

  4. Hi DZIKU,

    I just added your code without success. This problem occurs almost with every code I tried.
    As far as I know the problem is the false ppm signal. Unfortunately I can figure out the right combination of Signal length and Pulse length etc. I uploaded a video where this can be seen.

    As long as the false ppm signal is connected the servo spins like hell. At the end of the video I pulled the ppm cable and the problem stops. Also the orange light indicates that there is no valid ppm signal 🙁

    Any suggestions?

    Greetings from Cologne

  5. Hello Dziku,

    Thanks for the code! It works very nicely with my DX6i transmitter. I wonder now, if it’s possible to switch to 11 ms frame length? Changing just the FRAME_LENGTH constant does not help.

    I am trying to resolve an issue with a large time lag (~ 70 – 90 ms) between sending data to Arduino board and the moment when receiver detects the change.

    Best regards,

  6. I am using this sketch with success when using SmartPropoPlus and vJoy with RC sims like AeroFly and ClearViewRC.
    But I can’t get Real Flight 7 usb dongle to detect the signals.
    When using and old Art-Tech FM TX with audio output, it works ok.
    I even changed to polarity to match that of the Art-Tech and even increased the pulse length from 300 to 400 and both (SmartPropoPlus) scope images seem to be identical. But to no avail, the usb dongle will note detect any signal from the Arduino.

Leave a Reply to Dziku Cancel reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.