Introduction: How to Control a Motor Through a Serial Port Without a Microcontroller

About: Pudding is my co-pilot

You don’t need an Arduino, PIC or any other microcontroller to make a robot. It’s possible to connect your project directly to a computer through a usb port, using a serial-usb adapter (or directly through a serial port if your computer has one). This will let you attach wheels to your laptop and drive it around your apartment without having to buy an extra Arduino, or whatever project you can imagine. USB-Serial adapters can be very cheap ($4 USD) so they make a nice alternative to microcontrollers for simple projects.

Need:
USB-Serial adapter (RS-232)
Motor bridge (TA7291P or others)
One or Two DC motors (this project uses 3v motors)
2x 1kΩ resistors

And one of the below (not needed if you have a 5v motor)
5Ω  (or less) resistor with 2w rating or higher
Lots of 100Ω or 50Ω resistors with 1/4w rating (what I used)

Step 1: Hacking the Serial Plug (RS-232)

The first thing to do is hack the USB-Serial adapter. There are nine pins, but you only need three. The way a serial connector works is by sending 5v logic signals to say it’s ready to send or receive a message, along with that message itself. Instead of sending any messages, we’ll just be using those 5v logic pins. The data transmit pin is possible to use, but would require an IC to decode it (like  a shift register), or a transistor to amplify the weak current it sends. If you do that, binary ‘0’ is a high voltage on RS-232 and binary ‘1’ is low.

On the serial plug, there is a guard around the pins which you might want to remove to make it easier to solder the pins, but you don’t need to. I was lucky that the pins on the serial plug were hollow. I could clip off the ends and slide a wire inside them which held it in place as I soldered. Solder a wire to the DTR, RTS and ground pins. Solder one to the Transmit Data pin (TD) if you want to play around with that too. Since this part will not get hot when operating the circuit, you can insulate it using a glue gun if need be.

Step 2: The Circuit

Next we need to make the circuit. It is a simple motor bridge connection. The only problem is that TA7291P needs 4.5v to operate, but the motors are 3v. There are two ways to fix this: get higher voltage motors or put in a resistor to limit the current. The resistor would need to be 2 - 5Ω with high wattage (2w or more). However if you bought 1/4 watt resistors in bulk (like I did) you can can put enough in parallel to divide that wattage since eight 1/4 watt resistors can take 2w. Since resistors in parallel divide their resistance, 20 resistors at 100Ω = 5Ω (as would 10 resistors at 50Ω). That is a lot of resistors, but at about $0.02 each, that beats buying an extra 2w resistor. You can see my 100Ω resistor cluster in the photo. You don’t need the switch I’ve put into the circuit, but sometimes the serial pins are set to high when the USB turns on which will make your motor(s) rev before your program can start up and turn them off.

With only one motor bridge, to go forward the robot must ‘waddle’ with each motor being turned on for a few ms before the other is turned on. You could also just get another USB-to-Serial cable and set up another motor bridge for better forward control and power.

Step 3: The Basic (Testing) Program

Now all you need left is the program. I used Python, but it is possible to write it in almost any language. Just Google for how to control a serial port in your preferred language. My program connected to the internet to get commands, but you could also use UDP, TCP/IP, or store the commands in an array. Here is the basic code to test if everything is working. After plugging in your USB device, you have to look in your device manager to see what the connection is called. If you’re in Windows, it will be COM6 or something like that. In Linux, it will be something like /dev/ttyUSB0.

import time
import serial

###initialize the serial connection
#for windows (change COM6 to match the USB device)
#ser = serial.Serial("COM6", 2400)

#for linux (change /dev/ttyUSB0 to match the USB device)
ser = serial.Serial("/dev/ttyUSB0", 2400)

ser.open() #open the connection

#Make sure RTS and DTR are off
ser.setRTS(False)
ser.setDTR(False)
print("initialization finished")

###main loop
c = 1
while c:
   ser.setRTS(False)
   ser.setDTR(True)
   time.sleep(2)
   ser.setRTS(True)
   ser.setDTR(False)
   time.sleep(2)

Step 4: A Sample Program

If you have two motors on one motor bridge, here is sample code for how you can move forward. There are many ways to feed the robot commands like making a list of them or communicating directly with the robot with UDP or TCP/IP. I used an indirect method with AJAX and storing the next command on a web server. Here is a video of my robot moving. The lag in response is because I'm slowly punching in the commands on my webserver (located in Canada) while the robot fetches them (from Japan). The waddle as it moves forward is hardly detectable. It is running without the 5 ohm resistor, and the right and left turns are also operated in pulses so that they aren't too much more powerful than the forward drive. You'll notice the wheels are different in the video because the treads (seen in the other photos) were too weak to support the weight of a laptop reliably. More about the project can be found here.

import time
import serial

###initialize the serial connection
#for windows (change COM6 to match the USB device)
#ser = serial.Serial("COM6", 2400)

#for linux (change /dev/ttyUSB0 to match the USB device)
ser = serial.Serial("/dev/ttyUSB0", 2400)

ser.open() #open the connection

#Make sure RTS and DTR are off
ser.setRTS(False)
ser.setDTR(False)
print("initialization finished")

### function to waddle forward (for one motor bridge with two motors)
def move_forward(times):
   while times > 0:
      ser.setRTS(True)
      ser.setDTR(False)
      time.sleep(0.2)
      ser.setRTS(False)
      ser.setDTR(True)
      time.sleep(0.2)
      times -= 1

###main loop
c = 1
while c:
   move_forward(6)
   time.sleep(2)

123D Circuits Contest

Participated in the
123D Circuits Contest