RC controller to Arduino hack

I needed some way to remotely control my BB-8 droid at a very low cost and I also wanted to use an Arduino to do speed control using Pulse Width Modulation (PWM). So I bought a remote control toy truck at a yard sale and hacked together a circuit to convert the remote control's output to something the Arduino would understand.

RC receiver to Arduino converter circuit.
RC receiver to Arduino converter circuit.
Parts in bottom of BB-8 (v2) (WIP).
RC receiver to Arduino converter circuit in bottom half of BB-8.
RC toy truck and controller.
RC toy truck and controller.
Top of truck removed.
Top of RC truck removed showing the RC reveiver, drive motor
      and steering motor.

As shown above, the central part of the truck was an RC receiver and batteries. Two wires came out of that to go the the drive motor and two more wires came out to go to the steering motor.

From testing shown below, both sets of wires produced the same outputs when being controlled. When a stick on the remote control was pushed up or to the right, depending on which stick, a set of RC receiver wires put out a positive voltage, around 2.8 volts. When a stick on the remote control was pushed down or to the left, a set of RC receiver wires put out a negative voltage, around -2.8 volts.

Note that the voltages were either fully 2.8 or -2.8 volts, or 0 volts. There was no gradual change. It was either on or off, meaning I wouldn't be able to control motor speed using the remote controller, only rotate the motors in either direction or turn them off. They're basically on/off switches.

Remote control sticks: drive and steer
Remote control sticks for drive, up/down, and steer, left/right.
Testing RC receiver output.
Testing votlage of the the RC receiver output.

I didn't need the whole toy truck or its motors so, as shown below, it was a simple matter of removing one screw and then using some gentle pressure to snap the central part from the toy truck out, that being the RC receiver and the battery case attached to it. The batteries were 2 AA batteries connected in series. But to get a longer battery life I hot glued on a second battery case, also with 2 AA batteries in series, and then paralleled that set with the first set.

Removing RC receiver from truck.
Removing the RC receiver from the toy truck.
Extra batteries case and RC receiver.
The RC receiver and extra batteries case.
Extra batteries case and RC receiver.
RC receiver and extra batteries case hot glued on.

Next came figuring out a circuit to convert the 2.8V and -2.8V from the RC receiver to things that the Arduino could understand. The following is the high-level diagram of what ended up being done. Notice that in some cases the 2.8V and -2.8V were converted to 5V except one case where the 2.8V was given to the Arduino unchanged. The sections below explain the circuit in detail.

RC receiver to Arduino high-level diagram.
Radio control receiver to Arduino high-level diagram.

Handling the 2.8V from the RC receiver

Handling the 2.8V was easy. The Arduino has analog input pins that accept from 0V to 5V. The Arduino the converts that to a number from 0 to 1023 (0 for 0V and 1023 for 5V) which your Arduino program can get using the AnalogRead() function. Here's the part of the circuit for handling the 2.8V. But be careful. Those analog input pins can handle at most 20mA of DC current. Below is part of the circuit for handling the 2.8V only.

Simple analog input.
Simple analog input for the RC to Arduino conversion.

Why the 470 ohm resistor? As I said above, the Arduino's analog input pins can handle at most 20mA of current. One way of limiting the current is to run it through a resistor, and waste some of the energy as heat, reducing the current that way. To know what size resistor to use I first made sure I had new batteries in the RC receiver side of things. I put a meter in series for measuring the current, as shown below, and tried different sized resistors, starting with very large values. Starting with large values resulted in current much lower than 20mA. I tried lower and lower value resistors until I got something close to 20mA, but still less than 20mA. I settled on 470 ohms.

Position of the meter.
Position of the meter for measuring the current.

Instead of trying a bunch of different valued resistors, you can use a potentiometer (variable resistor), provided you have one in a suitable range. You can also get close by doing a simple calculation. As shown below, ohms law states that V = IR, voltage equals the current multiplied by the resistance. Rearranging to solve for the resistance we get R = V/I, resistance equals the voltage divided by the current. So 2.8V divided by 20mA gives a resistance of 140 ohms. But suspecting that the maximum voltage might be higher than 2.8V and wanting to keep the current safely below 20mA by a bit, you might instead calculate 3.5V/15mA = 233 ohms.

Ohm's law calculations for current limiting resisance.
Ohm's law calculations for current limiting resisance.

Why did I put a 10 kilohm resistor connected to ground in the above circuit? That was so that when the RC receiver is off, any stray current will go through the 10 kilohm resistor to ground instead of causing false readings at the Arduino. This is called a pull-down resistor. I'm not sure it's needed in this case. What effect does it have when the RC receiver is on though? Since it's such a high resistance value, very little current will go through it normally. The value, 10 kilohm, is a typical value for this use.

Handling the -2.8V from the RC receiver

Handling the -2.8V was harder. That's because the Arduino doesn't accept negative voltage for anything on any of it's input pins. So I either had to turn the -2.8V into 2.8V or cause the -2.8V to result in something else. I chose to do the latter.

If you give the Arduino 5V on one of its digital pins then if you do a DigitalRead(Pin) then it will return HIGH. If the same pin has 0V on it then it will return LOW. Luckily the Arduino has a 5V source you can use for this purpose.

So I needed some way for -2.8V from the RC receiver to result in one of the Arduino's digital pins getting 5V from the Arduino's own 5V source. One easy way to do that it using a relay, as shown below.

Relay not energized.
Turning -2.8V into 5V for an Arduino.
Relay energized with -2.8V.
Relay energized with -2.8V to give the Arduino 5V.

In the first schematic above, this is what happens when there is 0V from the RC receiver (see voltages shown in blue lettering.) The relay's coil is not energized. You can tell this by looking at the switch in the bottom part of the relay. The switch is open, meaning that no current will flow through the path highlighted in blue. As a result, the Arduino will see 0V at the pin that the circuit is connected to, digital pin 4 in this case. This causes a call to DigitalRead(4) to return the value LOW, which in this case means the remote control has not been activated and either nothing should be done or something that was going on should be stopped. With my BB-8 this indicates that a motor should be stopped.

But in the second schematic above, the relay is energized. The RC receiver has put either 2.8V or -2.8V across the relay's coil, it doesn't matter which. That closes the switch, connecting the two parts highlighted in blue on either side of the switch. The Arduino will now see 5V at digital pin 4. This causes a call to DigitalRead(4) to return the value HIGH, which in this case means the remote control has been activated and something should be done. With my BB-8 this indicates that a motor should start turning.

The 10 kilohm resistor is again there as a pull-down resistor. After the relay's switch opens there may still be some stray noise on the wire going to the Arduino's pin and voltage won't be 0V at the pin as it should be. With the 10 kilohm resistor, stray current will have a path through the resistor to ground, pulling the voltage firmly down to 0V. But what about when the switch is closed? When the switch is closed the 10 kilohms of resistance is so much higher than the practically 0 ohm resistance through the wire going to the Arduino's pin that relatively no current will go through the 10 kilohm resistor path.

In the circuit below you can also see an optional resistor. You may want to put one there in order to limit the current through the relay's coil and, just as importantly, through the Arduino. In my case I tried resistances here all the way down to 4.7ohms, but the current wouldn't close the relay with even that resistance. Once I went to 0ohms here, i.e. no resistor, the relay closed. The current was 70mA when it finally closed.

Optional resistor.
Optional resistor for the relay circuit.

The complete circuit

Below is the complete circuit. Note the one simple sub-circuit highlighted in green for taking 2.8V from the RC receiver and giving analog input to the Arduino, as talked about above. Then note the three relay sub-circuits highlighted in the other colors for taking either 2.8V or -2.8V and giving 5V to the Arduino, also as talked about above.

Here is the parts list for the RC receiver to Arduino converter board:

  • resistors: 4 x 10kΏ, 4 x 470Ώ
  • diodes: 4 x 1N4002
  • relays: 3 x 10A SPDT, coil: 3VDC/120MA
  • female headers (pin headers): to plug wires into the board from the RC receiver and to go to the Arduino I put on some female headers. You can buy a pack of 5 36-pin 0.1" female headers from adafruit.com. You can see them labeled in a photo below and a closeup in another photo below that.

Parts can be found in electronics stores, automotive stores, online, and recycled from electronics that is being thrown out as garbage. If you can't find the same part numbers as mine then look for what are called equivalent parts.

The diodes - choosing which sub-circuits to use

Other things to note are the use of the 1N4002 diodes. As pointed out near the top of this page, the RC receiver has two sets of wires for output, one set for the driving motor and one set for the steering motor. In the schematic below you can see the two sides, each with two sub-circuits. On the left there are two relay sub-circuits (yellow and orange) and on the right there is one relay sub-circuit (blue) and a simple analog sub-circuit (green).

But something has to choose which sub-circuit to use on either side. On the right side, when the bottom of the RC receiver is 2.8V there will be 2.8V on the side of the diodes indicated by the number 1. The sides of the diodes indicated by the 2 and 3 will be 0V. Notice that the diodes are oriented in opposite ways. The one on the green path is pointing away from the number 1 side and the one on the blue path is pointing toward the number 1 side. If the number 1 side is at 2.8V with respect to the number 2 then current will flow through that diode on the green path. That's because current flows through a diode when the diode is pointing at the side that's more negative (0V is more negative than 2.8V). It flows from the positive to the negative (this is conventional current, not electron flow current.)

But when the number 1 side is -2.8V, current will flow through the diode on the blue path. That's because that diode will now be point toward the side that's more negative (-2.8V is more negative than 0V.)

And that's how the diodes select which sub-circuit will be used. Notice that the left side of the RC receiver also has two diodes which operate in the same way.

Grounding problem

Why are there that mix of sub-circuits? The relay sub-circuits were originally there because I needed a way to turn -2.8V into something the Arduino can understand. But on the left side you can see that I'm using a relay sub-circuit for handling 2.8V as well. Why didn't I just use a simple analog sub-circuit as I did on the right side?

In fact, I did do just that originally. But that meant that both sides of the RC receiver were connected to ground. In the above diagram I've indicated the one place where there's a ground connection going into the receiver, on the right side of the RC receiver, and that there isn't a ground connection on the left side. Having both sides connected to ground meant that those two points of the RC receiver were connected together and that caused weird outputs from the RC receiver overall. Connecting those two points must have interfered with whatever was going on in the circuit inside the RC receiver itself.

So to avoid having a ground connection from the RC receiver on the left side, I handled the positive 2.8V with another relay sub-circuit. On the right side, the simple analog sub-circuit needs the connection to the Arduino's ground because analog pin 1 expects the 2.8V voltage to be relative to the Arduino's ground.

Lastly, you might ask why I didn't just use a relay sub-circuit instead of the simple analog sub-circuit and have no ground connection to the RC receiver. The reason is that I wanted to save on the cost of a 4th relay.

The complete circuit

The complete circuit.
The complete radio control receiver to Arduino converter circuit.

The follow is the resulting circuit board. Note that I didn't have enough perf board so I drilled holes in some plastic and used that instead. The back view below is the reverse left-to-right of the front view since that's what happens when you flip it over to see the back. I also drilled extra holes on the right side in case I ever want to change the simple analog sub-circuit to also be a relay sub-circuit instead (plus there are extra holes that turned out to be not needed.)

Radio control receiver to arduino converter board - front.
Radio control receiver to arduino converter board - back.

In the photo below the circuit is connected to the RC receiver on the bottom and the Arduino on top. This was during the final testing of the circuit before putting it in the BB-8. Note the use of female pin headers for connecting to the rest of the circuit.

The circuit connected up.
The circuit connected up to the RC receiver and Arduino.
Female pin header.
Female pin header on circuit board.

Alternatives to relays - using opto-isolators

A problem with relays is that they require the coil to be energized for the entire time that the switch is to be closed (closed for a normally-open relay, or open for a normally-closed relay.) An alternative may be to use an opto-isolator in place of each relay. I haven't tried it myself, and have never worked with opto-isolators so I don't know how well it would work and what the limitations or issues would be. But it's an alternative to explore.

Liked this? Share it with: