16 additional analog inputs via PPM and SPI

Inspired by Helle's extension in conjunction with the APM mode switch (presented here), I've built a development for a project that provides a total of 16 additional analog inputs for additional input devices by networking two Arduino Nano. I did not use the APM mode switch because I do not need it.

The two Arduinos communicate with each other via SPI. One of the Arduinos is the master who controls the SPI communication. It initiates the data exchange, sends a PPM stream via the SPI lines, which includes the status of all 8 analog ports as servo signals, and ends the SPI communication again.

The slave in turn receives the PPM stream, combines it with the values of its own 8 analog inputs (also as servo signals) and composes a common PPM stream with 16 servo signals. This stream is then output via pin 9 and can be further processed in the Taranis or other suitable transmitters.

Details on SPI communication

In choosing the protocol for communication between the two Arduinos, my choice fell on SPI for two reasons:

  • it is the fastest serial protocol on the Arduino
  • it does not need analog ports (unlike I2C)

It isn't hard to get over the fact that you need more physical lines between the two Arduinos: SPI requires three lines for the actual communication and another for each slave that is to be addressed. Since it stays here with only one slave, I need a total of four lines for SPI.

The wiring is simple: the four ports used are simply connected one to one between the two nanos. The following pins are used:

  • (Pin D10) SS - Slave Select: contact the desired slave
  • (Pin D11) MOSI - Master Out Slave In: Data is sent from master to slave
  • (Pin D12) MISO - Master In Slave Out: Data is sent from slave to master
  • (Pin D13) SCK - Serial Clock: the clock signal for the synchronization of the communication

The master starts communication by pulling the SS pin low. This puts the slave connected to the other end in receive mode. Now the master sends the desired data serially over the other lines and finally terminates the communication by setting the SS pin high again.

Implementation of SPI communication

When creating the two sketches, I've built on the examples of Nick Gammon (see here) for SPI communication.

The master is relatively simple because it simply sends its data every 100 milliseconds.

The slave is more complicated because it responds
interrupt-controlled with the purpose to immediate and secure reception of data. As soon as the master pulls the SS pin low, an interrupt is triggered in the slave, which starts the corresponding receive routine.

I also use a Nick Gammon-based local library called SPI_anything.h, which greatly simplifies serial sending and receiving of different types of data over the SPI protocol.

It should also be noted that the use of the serial terminal of the Arduino development environment is only possible to a very limited period because it conflicts with the SPI communication. As a result, the slave Arduino hangs
after a few moments when written to the terminal and an interrupt is triggered by SPI at the same time. The serial output commands contained in the slave sketch should therefore be temporarily activated only when needed and for debugging purposes.

Creating the PPM signal

Both Arduinos each generate a PPM signal from their 8 analog ports. The read-in values are converted via a map command to the standard format for servo signals, ie from 1 to 2 ms depending on the status.

Since it is much easier to send data from the master to the slave, the slave will continue to process the entire data
after receiving the data from the master. It connects the two PPM signals to a common stream and outputs it on pin 9.

The PPM signal thus reaches a frame length of 38.5 ms and the used remote control transmitter must be able to handle this frame length. That's no problem with the Taranis. In order for the PPM signal to have exactly the right duration in every situation, an interrupt is also used here (timer 1).

Circuit diagram for master and slave

The circuit diagrams for master and slave are almost identical and differ only in one single detail: only the slave is connected to pin 9 with the DSC socket of the remote control transmitter. All other circuits are the same and consist only of a few resistors and capacitors.


Attention: It is recommended to protect the Arduinos from reverse polarity by using a diode. It is also important to use a 0.5 A fine-wire fuse between the Arduino's power supply and transmitter electronics. This serves to protect the transmitter electronics from accidental short circuits in the self-made circuit (I learned this painfully and subsequently learned how to install a new mainboard in my transmitter ...).

A few notes on the three representations above:

The breadboard view documents my experimental setup. Only the ends of each wire are actually plugged in, the kinks are only for clarity and have no electrical connection to the underlying slots.

The circuit diagram and the board layout are individually tailored to my requirements. The connector SV1 is used to connect all input devices such as potentiometers, switches with resistors, etc. and also supplies ground and + 5V. On the breadboard display, a potentiometer is shown as an example.

The other plug SV3 receives all other lines for power supply, SPI and PPM output at the slave. Jumpers J1 to J8 are just a tool to easily solder in the lines on the top, which are red in the board layout.

Configuration in the transmitter (OpenTX)

Note: Since I have only one transmitter with German OpenTX available, I'm not sure exactly how the English menus and options are called. I hope you can deduce this from the context.


The configuration of the extension to the teacher / student socket is model-specific.

At the bottom of the "Model Setup" under the menu item "Trainer mode" the mode "Master" is set.

In the "Sticks" menu, each of the 16 additional inputs can now be assigned to any input I01 to I32. The additional inputs are referenced under the designation TR1 to TR16 (for trainers). Here you can also test their function. Simply edit the desired line, highlight "Source" and select the desired input TRxx. If the corresponding input device is moved, the changes should be displayed accordingly in the adjacent coordinate system.

Further processing is then as usual with any source via mixers.


Komprimiertes Archiv im ZIP Format 5.0 KB