At $20, the cheapest ToysRus RC car isn't capable of much. But there is enough to make our own Gumstix powered RC car. 

 

Materials

  • Cheapest RC car you can find that you can fit the RoboVero in ($20)
  • RoboVero ($100)
  • Overo with Wifi (~$200) – this one is optional, but an RC car isn't much if it's tied down by a USB cable. 

Preparing your RC Car

 

Start by taking the top off your RC car. The one I had has screens tucked underneath the wheels, and some wires that connect LEDs. Get rid of all of those.

 

Once the top is off, we can see what this thing has. 

 

A board for communication with the controller. We'll be replacing this with the RoboVero.

 

One DC motor in the back to drive the wheels (rear wheel drive!!!)

 

One DC motor in the front (geared in a funny manner) that controls the steering.

 

We'd like to replace the front motor with a servo for more precision, and put more power into the back, but that's for another time. 

 

Connecting your RoboVero

 

You're going to need two H-bridges for this. For this example, we're using the SN75441ONE. Connect the two lines of your front motor to two outputs of your first H-bridge, and two outputs of the other motor to the other H-bridge. This setup isn't ideal, since if you draw too much current, you might reset your Overo, but we'll ignore that for now.

 

Now connect two GPIO pins to the corresponding input pins of your front motor on the H-bridge. This will be our steering. We've used P0_4 and P0_5. For our rear motor, we'd like a little more control, so we'll be using the motor control PWM pins. Connect MC0A0 and MC0A1 to the input pins for the rear motor. Connect power and you should be good to go.

 

SSH into your Overo, and run the following Python code. The controls are:

  • 'a' turn left
  • 's' slow down
  • 'd' turn right
  • 'w' speed up
  • 'r' reverse
  • 'q' stop
  • '~' FULL SPEED
  • any other key straightens the wheels

That's it! Now you have a Wifi enabled RC car (that was incredibly expensive), and you're free to do whatever you want with it. Now if you'll excuse me, I have to put lasers and ejector seats onto my car.

 

Code

 

from robovero.lpc17xx_mcpwm import MCPWM_Init, MCPWM_CHANNEL_CFG_Type, \
                      MCPWM_Start, MCPWM_WriteToShadow, MCPWM_Stop,    \
                      MCPWM_CHANNEL_EDGE_MODE, MCPWM_CHANNEL_PASSIVE_HI
from robovero.extras import roboveroConfig, heartbeatOff
from robovero.LPC17xx import LPC_MCPWM
from robovero.lpc_types import FunctionalState
from robovero.arduino import pinMode, digitalWrite, digitalRead, BTN, LED
from robovero.arduino import INPUT, OUTPUT, HIGH, LOW, P0_4, P0_5
from time import sleep

periodValue = 900
roboveroConfig()

MCPWM_Init(LPC_MCPWM)
channelsetup = MCPWM_CHANNEL_CFG_Type()
 
channelsetup.channelType = MCPWM_CHANNEL_EDGE_MODE
channelsetup.channelPolarity = MCPWM_CHANNEL_PASSIVE_HI
channelsetup.channelDeadtimeEnable = FunctionalState.DISABLE
channelsetup.channelDeadtimeValue = 0
channelsetup.channelUpdateEnable = FunctionalState.ENABLE
channelsetup.channelTimercounterValue = 0
channelsetup.channelPeriodValue = periodValue
channelsetup.channelPulsewidthValue = 0

MCPWM_ConfigChannel(LPC_MCPWM, 0, channelsetup.ptr)
MCPWM_ConfigChannel(LPC_MCPWM, 1, channelsetup.ptr)

# Disable DC Mode
MCPWM_DCMode(LPC_MCPWM, FunctionalState.DISABLE, FunctionalState.ENABLE, (0))

# Disable AC Mode
MCPWM_ACMode(LPC_MCPWM, FunctionalState.DISABLE)

MCPWM_Start(LPC_MCPWM, FunctionalState.ENABLE, FunctionalState.ENABLE, FunctionalState.DISABLE)

pinMode(P0_4, OUTPUT)
pinMode(P0_5, OUTPUT)

speed = 50
direction = 0

while True:
  print speed
  user_input = raw_input()
  if user_input == 'a':
    digitalWrite(P0_4, LOW)
    digitalWrite(P0_5, HIGH)
  elif user_input == 'd':
    digitalWrite(P0_5, LOW)
    digitalWrite(P0_4, HIGH)
  elif user_input == 'w':
    speed = speed + 5
    if speed > 100:
      speed = 100
    channelsetup.channelPulsewidthValue = speed * periodValue / 100
    MCPWM_WriteToShadow(LPC_MCPWM, direction, channelsetup.ptr)
  elif user_input == '~':
    speed = 100
    channelsetup.channelPulsewidthValue = speed * periodValue / 100
    MCPWM_WriteToShadow(LPC_MCPWM, direction, channelsetup.ptr)
  elif user_input == 's':
    speed = speed – 10
    if speed < 50:
      speed = 50
    channelsetup.channelPulsewidthValue = speed * periodValue / 100
    MCPWM_WriteToShadow(LPC_MCPWM, direction, channelsetup.ptr)
  elif user_input == 'r':
    if direction == 1:
      direction = 0
    else:
      direction = 1
    speed = 0
    channelsetup.channelPulsewidthValue = speed * periodValue / 100
    MCPWM_WriteToShadow(LPC_MCPWM, 0, channelsetup.ptr)
    MCPWM_WriteToShadow(LPC_MCPWM, 1, channelsetup.ptr)
  elif user_input == 'q':
    speed = 50
    channelsetup.channelPulsewidthValue = speed * periodValue / 100
    MCPWM_WriteToShadow(LPC_MCPWM, direction, channelsetup.ptr)
    digitalWrite(P0_4, LOW)
    digitalWrite(P0_5, LOW)
  else:
    digitalWrite(P0_4, LOW)
    digitalWrite(P0_5, LOW)