Wednesday, January 8, 2014

LEGO 2.4 GHz Power Functions Radio Control DIY Circuit

Update: The H Bridge chip this circuit uses has a voltage drop that makes devices that use it operate more slowly than they should.  An updated version 2 is in the works that uses the DRV8833.

When LEGO came out with the infrared controlled Power Functions system I was super excited.  I have dreamed of being able to build remote controlled LEGO cars and racing them with my friends since I was a little kid.  The actual system left a lot to be desired though.  If you want a nimble car, you have to use the LEGO 8885 infrared transmitter, but it only offers full speed forward and reverse, and if you are using it for steering it gives full left or right.  There is no proportional control.  You can’t go at half speed or steer just a little to the left.  You can use the other LEGO transmitter, the 8879, which gives you seven incremental speeds forward and reverse, or seven positions on the servo for steering.  That sounds perfect, but in reality it will only send a few commands per second, and if you try to give it more commands per second than that it will ignore them.  This means that it can take 3-5 seconds to steer from a full left to a full right, and your transmitter dial will be out of whack with where you expect it to be when you try to go straight again.  Suboptimal for sure.

I love the options the variety of Power Functions motors provide, but the control system needs improvement, so that is what I decided to do.  I am documenting it here so you can do it too.

My circuit uses a cheap 2.4 GHz radio transmitter to quickly control two Power Functions devices.  You can control two motors, or two servos, or one motor and one servo.  The 2.4 GHz receiver sends out servo control signals that are typically used to position a hobby servo or control an electronic speed controller.  Our LEGO motors and servos cannot use this signal though, so we are going to use a programmable microcontroller to translate the hobby servo signals into a pulsing signal that can be used to power our LEGO motors and servos.  The microcontroller we are going to use is the Picaxe 14M2.  I chose this microcontroller because it is small, cheap ($4), is easy to program in the BASIC programming language, and the only thing you need to buy to program it is a $6 cable if you have a serial port on your computer.  If you don’t have a serial port, you will need a USB programming cable, which is more expensive, at $26.  The Picaxe chip can’t output enough power to power our motors and servos, so we are going to feed the Picaxe output signals into an H-bridge motor driver chip, the SN754410.  I chose it because it is easy to use, tough, and cheap, at less than $3.  It can supply 1 amp of power to two different motors, which is enough for most Power Function situations, but I have not tested it with a L or XL motor yet.  I think it will handle the L motor ok, but I know the stall current of the XL is closer to 2 amps, and that’s way too much for the SN754410.  The SN754410 does have overcurrent protection though, so it will shut down before it does any damage to itself.  You can stack two SN754410s on top of each other, and solder their legs together to double the power it can handle, so if you are planning on running an XL hard, you should consider that.  The other part of the circuit is the 7805 5 volt voltage regulator, which takes the 9 volts from the battery pack and converts it to 5 volts, which is required to power the 2.4 GHz receiver, the Picaxe, and the logic functions of the SN754410.  The SN754410 also needs the full 9 volts to power the motors.  For the record, I am not using any external protection diodes on the SN754410, with no ill effects.  There is some debate about this on the internet.

Here's a video of the results:

And of the first road test:

Functional Concept:

The concept here is that the radio controlled receiver sends out a pulse of somewhere between 1 and 2 milliseconds every 20 milliseconds on each of the two channels we are using.  1 millisecond tells a servo to go full left, 2 milliseconds tells the servo to go full right, and 1.5 milliseconds tells the servo to go to its center position.  We are using the Picaxe PULSIN command to measure the length of that signal on each of the two receiver pins.  We then have the Picaxe perform some math on that data to end up with an output signal that we send to the SN754410.  Here is a link to a great page on what the pulse width modulation signal looks like coming out of the Picaxe and into the SN754410.

If we have a servo signal less than 1.5ms, then we need to send out a PWM signal to the SN754410 on its 1A pin, while sending out a constant 0v signal to its 2A pin.  As the servo signal becomes closer to 1ms, we need to increase the “on” time of the PWM signal to 1A.  If the servo signal becomes larger than 1.5ms, then we need to send 0v to the 1A pin, and start sending a PWM signal to 2A.  The math I used to do this is in my Picaxe code.  I made sure that there was a dead zone around 1.5ms so that the motors are sure to be stopped, and I also made sure with my code that the output signal could not be such that my PWM signal has a larger than 100% duty cycle. 

Here is what you will need to buy:

HobbyKing HK-GT2B 3CH 2.4GHz Transmitter and Receiver        $23
For $23 you can’t beat that deal.  If you already have a transmitter, you can use any receiver that works with your transmitter, but the pins may not match what I have on the etched board.

14M2 Picaxe chip                                 $4          
Picaxe Serial Programming Cable          $6          
SN754410 H-Bridge Motor Driver            $2.35      
7805 5v Voltage Regulator                     $1.25      
0.1 uF Capacitors (qty. 2)                      $0.25 ea.
Female Header                                     $1.50      
3.5mm audio jack                                 $1.50      
This is to connect the programming cable to a solderless breadboard to program your Picaxe.

Two 10k ohm and one 22k ohm resistors
You can buy these at Radio Shack in 5 packs, or in a big assortment.

Copper Clad and etchant
I love Electronic Goldmine’s scissor-cut copper clad.  Easy to drill and cut, and nearly clear, but you can use Radio Shack's too.  We only need single sided, so grind off the unused side if your copper clad is stiff.  I use Radio Shack PCB Etchant to etch my printed circuit boards.

LEGO Power Functions extension wire (qty. 2) short 8886           $3

Harbor Freight has an assortment of tiny drill bits that I use to drill my PCB holes.  I use the 0.8mm bit for most of my components, and just a bit bigger for the voltage regulator.  I file down the legs of the voltage regulator so they are nearly as skinny as the other components, so it sits flush against the PCB.

I’m going to assume you have some electronics, PCB etching, and soldering experience.  If not, here are some links to get you the background you need to get started on this project:

Toner Transfer PCB building:
I don’t use tape, but rather fold the paper over and push the copper clad into the crease.  Also, I have found that ironing for 3 or 4 minutes works well.  Don’t forget to rough up the surface and wash the board before you iron on the toner.  Sharpies work well for touching up before you etch.

Through Hole Soldering:
I absolutely LOVE my Sparkfun 937b soldering iron (part number TOL-10707).  My joints have improved drastically since I moved up from cheap irons.

Everything you could want to know about Picaxe:

Here are some pictures of the process:
Prototyping.  Note the HobbyKing receiver not yet de-cased.  Is that the top of a free-with-any-purchase Harbor Freight multimeter?
This is the best toner transfer etch I've ever done.  This is the first board I used AutoCAD to do my art.  For my previous PCBs I used Microsoft Paint, which works, but is not awesome. 
The HobbyKing receiver just plugs right into that socket I built out of 3 four pin headers side by side.

Here is the BASIC code that you need to program the Picaxe chip with. 

symbol bforward = B.2              ;the pin that outputs not 0 when motor B goes forward
symbol breverse = B.4              ;the pin that outputs not 0 when motor B goes reverse
symbol aforward = C.2              ;the pin that outputs not 0 when motor A goes forward
symbol areverse = C.0               ;the pin that outputs not 0 when motor A goes reverse

symbol cha = C.4                      ;the pin that receives the channel A pulsin
symbol chb = C.3                      ;the pin that receives the channel B pulsin

symbol chainput = w0                ;variable that channel A pulsin uses
symbol arevout = w2                 ;variable that gets output to motor A when in reverse (areverse pin)
symbol aforout = w3                 ;variable that gets output to motor A when in forward (aforward pin)

symbol chbinput = w4               ;variable that channel B pulsin uses
symbol brevout = w6                 ;variable that gets output to motor B when in reverse (breverse pin)
symbol bforout = w7                 ;variable that gets output to motor B when in forward (bforward pin)

output bforward                                    ;make pin bforward an output pin
output breverse                         ;make pin breverse an output pin
output aforward                         ;make pin aforward an output pin
output areverse                         ;make pin areverse an output pin


let aforout = 0                           ;set these variables to 0
let arevout = 0
let bforout = 0
let brevout = 0

pwmout aforward,249,aforout    ;all 4 pins start at 0v all the time
pwmout areverse,249,arevout
pwmout bforward,249,bforout
pwmout breverse,249,brevout

pulsin cha,1,chainput                 ;check the length of the pulse coming from channel A

if chainput < 102 then let chainput = 102 endif    ;you don’t want this less than 102 ever
w1 = chainput-102*22                                         ;intermediate math
if w1 > 1000 then                                               ;this all checks to see if it should be forward or reverse
arevout = 0
arevout = 1000-w1

if chainput < 152 then
aforout = 0
aforout = chainput-152*22

if arevout > 1000 then let arevout = 1000 endif    ;this makes sure that it doesn’t get more than 100%
if aforout > 1000 then let aforout = 1000 endif    ;duty cycle which locks things up at full throttle

pwmduty areverse,arevout                     ;output the reverse pwm signal for motor A
pwmduty aforward,aforout                     ;output the forward pwm signal for motor A

pulsin chb,1,chbinput                            ;this is pretty much the same thing as Amain but for B motor

if chbinput < 102 then let chbinput = 102 endif

w5 = chbinput-102*22
if w5 > 1000 then
brevout = 0
brevout = 1000-w5

if chbinput < 152 then
bforout = 0
bforout = chbinput-152*22

if brevout > 1000 then let brevout = 1000 endif
if bforout > 1000 then let bforout = 1000 endif

pwmduty breverse,brevout
pwmduty bforward,bforout

sertxd ("chA",#chainput," AF",#aforout," AR",#arevout,"  chB",#chbinput," BF",#bforout," BR",#brevout,13,10)  ;for tuning on the computer screen

goto Amain

You can copy and past all of the above into the free Picaxe programming editor, then upload it to the chip.  Read the Picaxe manual #1 to get an idea of how to do it.

Below is a link to the pdf of the etch artwork.  You will use this to print with a laser printer onto thinish glossy paper, then iron it onto your blank copper clad.  I also have several component placement guides on that page.  I put 4 copies of the art on one page so you can have 4 tries with a single print.  Sometimes it takes that many.  Also, save this file and print it with your own pdf viewer.  The whiteish lines you see on the black areas are ok on your screen, but not on your paper.  Google Doc's print puts the lines on the print, but Acrobat reader does not seem to.

The Future:
What does the future hold?  I have a few upgrades planned, and here they are:
1) I'm going to find a smaller voltage regulator, as that is currently the tallest part.  Replacing it with a shorter one will enable this whole thing to be under two bricks tall.  Currently I have to use 3.  Also, as long as I'm replacing the voltage regulator, I'm going to find a low-drop-out one to replace it with so my batteries can go even lower before replacing them.  EDIT: I cut the heat sink of the regulator off through the middle of the hole, and now it fits in a 2 brick high space, with no ill effects.  Also, my batteries will get so low that they will only barely drive the motors before the dropout voltage comes into play.
2)  I want to make a 6 channel board, since a 6 channel HobbyKing transmitter and receiver is hardly any more money than the 3 channel I'm using now.
3) I would love to make an 11.1v battery pack out of hobby lithium batteries.  Smaller, lighter, cheaper, more powerful than alkaline.  
4) Maybe someday I will gut a servo motor and replace the 7 increments with a true resistor strip circuit like every other hobby servo on the planet, and have full proportional steering.  Why didn't LEGO do this in the first place?  EDIT:  In practice the 7 segments feel very much like full proportional steering on a LEGO car.  I'm not going to worry about modifying their servos for this anymore.
5)  I want to build this circuit again with surface mount components.  I can buy a SMT voltage regulator, capacitors, and resistors easily.  The Picaxe 14M2 is offered in a hand-solderable SMT package (but shipped from the UK).  Now all I need to find is a hand-solderable SMT version of the SN754410 motor driver chip.  The ship LEGO uses on the new V2 of the infrared receiver is the TI  DRV8833 but it is difficult to solder (and etch a board for) and the maximum voltage is 10.8v, and I eventually want to use a 3S LiPo at 11.1v.


  1. Cool !
    I was considering developping the same kind of device, to use with my plane transmitter (Devo7e + DeviationTX). Looks like I'm a little late !

  2. You should go ahead and build one of these for sure. Turn your attention then to a good way to use a 3S 11.1v LiPo battery with low voltage cutoff protection, in the stock battery box, with the thermal shutdown circuit bypassed. Now that I've got this circuit working, and playing with it, I feel like everything I build needs more speed now. Plus, I have realized that the SN754410 has a voltage drop that makes just a tad less power to the motors than plugging them straight into the battery pack.

  3. Yeah, i'm looking forward to building one, and maybe starting right away with a 4 channel receiver, but for that, I can't use your design and i'm a total newbie when it comes to electronics design (soldering is OK). However I've requested some help from my cousin who's a RF engineer, I hope he can spare me some time.
    What i intend to do, to be more specific, is to have the PCB prototyped by a pooling service and then encase the whole stuff in a 3D printed casing (That at least I can do since I'm an industrial designer).
    For the LiPo battery pack, I've been thinking of that too. What I find tough is selecting one correct sized LiPO from HobbyKing.
    I'll keep you posted !

  4. I'm planning on building a 4 channel unit here soon. It's going to work the exact same way, except that it will have a second Picaxe chip reading channels 3 and 4, and outputting its signals to a second SN754410. The program on the second chip will even be exactly the same. I guess the board will be bigger.

    I'm thinking something like this for a battery:

    It has about the same mAh capacity as AA batteries, which is fine, and it's pretty small. I just need to find a good over-discharge protection circuit for it, and build that.

    If you buy the MAKE Electronics book, you will probably be up to speed as much as you would need for a circuit like these. It turns out that etching your own pcb is pretty easy. Unless you needed super fancy boards with multiple layers you would be best to learn to etch your own. It has changed my electronics life!

    1. Thanks, the MAKE Electronics book looks really interesting. It's in my Amazon wishlist now.
      For the battery, I'm afraid the one you picked is too long to fit into a BBox (your LiPO is 77mm long whereas an AA battery is 50). I've searched for some time and I can't seem to find a stock LiPO with more than 500mAh which will fit. The only thing I can think of for now is using 6x 650mAh round cells in a 3S2P arrangement...

  5. Hi Brian, a fantastic work!!! Have you managed to test with 11.1v? I would like to build such circuits and I think I should be able to. Something is not clear to me - if I want to use 4 L-motors (1 on each wheel) and lets say one or two servo motors (steering) on a model - will I have to have 3 receivers and 3 circuits or can I connect the 3 circuits to one receiver - 2 circuits on one channel and 1 circuit on the other?

    You say:

    but I don't see how are they connected to each-other. Maybe I haven't red carefully enough :blush:

    The 11.1v are very important to me since I find the L-motors need over 11v to perform according to my needs - building rock-crawlers and also planning to build a fast car.

    Also which is the UK site you found that is selling the components - if I understood correctly that there is one?

    Thank you very much!!