Introduction
This car is a toy that carries a camera and, being controlled by software from a PC, is driven to the place of user’s interest. Its locomotion is controlled by two DC motors (one on each side) with their speed reduced by gear boxes. I will not discuss the detail of the mechanical and the electronic part of the car and of course the video display part of the software on a PC here. So, inputs and output modules of the car are just represented as blocks. Here is the sketch I have drawn using the Google SketchUp.
In the following figure, the whole project is decomposed into modules.
Background
As I tried to show in the diagram above, there are two main parts of the project: PC and the car. Between the two is an RF link for transmitting commands and a separate wireless video link, which isn’t shown here, for video transmission. I made the RF link a one way communication because the RF components I found support this mode of operation.
At the top-left corner of the diagram, you can see an IR LED and an IR sensor. These are circuits used for avoiding collision with obstacles. Electrical pulses are regularly sent to fire the IR LEDs ON and OFF and two readings are taken during a single period of a pulse, so that the controller “knows” the real reading from the IR sensor. This is done with a simple logic described in the table below.
Output recorded during:
|
Deduction
|
On pulse
|
Off time
|
1
|
0
|
There is an obstacle
|
1
|
1
|
The sensor is saturated by ambient light
|
0
|
0
|
There is no obstacle
|
0
|
1
|
This reading is not logical (Sensor error)
|
You may refer here about building a simple IR sensor circuit.
The next thing is an RF receiver. Commands are constantly transmitted from the RF transmitter connected to the serial port of a PC as a form of series of bits and received by the RF receiver located on the car. I have created a simple C# application for command bits generation and for video display and replay functionalities. The SerialPort
class is responsible for sending these series of bytes depending on user’s inputs. The RF transmitter accepts these data from the serial port and transmits them through its antenna with a proper modulation. I used ICs from Linx for creating an RF link between my car and PC. The transmitter and receiver data sheets with their application can be found here and here.
To control DC motors on my RC car, I used two H-bridges as shown before. These two H-bridges are driven by outputs of micro-controller through one of parallel port pins. A very good introduction and application about H-bridges can be found here.
Using the Code
PC Program
The PC program has two main parts: a video display and replay, and a car control module.
The video display and replay module uses DirectShow
libraries to access video data from wireless video receiver but since this software part is not my concern, I am not discussing it right now. As a reference, you may check a really nice article by Andrew Krillov on codeProject (here).
The car control module is implemented using a SerialPort
object, seven buttons for direction control and a combo box for listing available serial ports. Just remember to include the following namespace:
using System.IO.Ports;
On form load event handler, I fetch all available ports in a combo box:
string[] availablePorts;
availablePorts = SerialPort.GetPortNames();
for (int i = 0; i < availablePorts.Length; i++)
{
cboPort.Items.Add(availablePorts[i]);
}
On each button click, a SendToSerialPort(string data)
method is called with its respective string
parameter as explained below:
private void SendToSerialPort(string data)
{
SerialPort ser = new SerialPort();
byte[] command = new byte[2];
command[0] = (byte)Convert.ToByte(data, 16);
ser.BaudRate = 9600;
ser.DataBits = 8;
ser.Parity = Parity.None;
ser.StopBits = StopBits.One;
ser.PortName = cboPort.Text;
if (command != null)
{
if (!ser.IsOpen)
ser.Open();
ser.Write(command, 0, 1); ser.Close();
}
}
The motor drivers (H-bridges) are connected to the micro controller's Port1
and are arranged as follows:
- Port1 pin 0 and 1 – for right hand motor driver (H-bridge) and
- Port1 pin 4 and 5 – for left hand motor driver (H-bridge)
The direction control is realized by controlling both DC motors' directions. For example, to turn right, we drive the left motor forward and stop the right motor. And the individual motor direction is controlled by switching the four transistors ON and OFF which is represented by the byte values in the braces.This lets us decide which series of bits is to be sent from our application to the serial port and then to the RC car. Accordingly, forward (“00100010”), backward (“00010001”), right (“00100000”), left (“00000010”), stop (“00000000”), spin clockwise (“00100001”) and spin counter clockwise (“00010010”).
Micro-Controller Program
Before going through the coding stuff, let us see the flow of the instructions of the whole program.
After initializing ports, the IR sensor is read as a reference for the debugging of IR sensor output and is saved as a variable. Then the IR LED is fired ON and ON state reading of IR sensor is saved as a second variable. Then come a series of comparison of these two readings and follows taking appropriate action.
If the OFF state reading is HIGH, there is either a problem of sensor’s saturation by high ambient light or a problem with the sensor itself which is to be determined by looking at the ON state reading (See table above). For each case, the corresponding debugging LEDs (High Ambient Light and Sensor Error LEDs) are set ON and the program jumps to the next step.
If the OFF state reading is LOW, we have no problem with the issues discussed before. So, if the second (ON state) reading is HIGH, there is definitely an obstacle in front and both motors shall be driven backward for a second. If the ON state reading is LOW, then there is nothing in front of the sensor so the program goes to accepting commands from RF receiver and sends them to DC motors.
This whole process is repeated indefinitely, so I put the code in a while(1)
loop.
After each reading from and writing to ports procedure is finished, I wanted to wait for some time. So, I used a 50ms delay function delay_50ms(void)
in the program which is implemented using timers in the microcontroller itself. Here the microcontroller frequency is assumed to be 12MHz with 12 oscillation cycles. The definite amount of time (integral multiples of 50ms) to be waited, is given as a parameter to a wait(int sec)
function.
void delay_50ms(void)
{
TMOD &= 0xF0; TMOD |= 0x01; ET0 = 0; TH0 = 0x3C; TL0 = 0xB0; TF0 = 0; TR0 = 1; while (TF0 == 0); TR0 = 0; }
The serial port (of the microcontroller) initializing function is given as follows (9600 baud rate, no parity and 1 stop bit are assumed):
void serial_init(void)
{
TMOD = 0x20; SCON = 0x50; TH1 = 0xFD; TL1 = 0xFD;
TR1 = 1; }
Command reading task from a serial port is to be managed by the following method which returns value that is read as a char
.
unsigned char serial_read(void)
{
bit over = 0;
while(!RI || !over)
{
wait(500);
over = 1;
RI = 0;
return SBUF;
} }
The whole other stuff is handled in the main function of the program and here are given the main( void )
function and the wait(int sec)
function (responsible for delaying the program execution for some time set in the input parameter sec).
void wait (int sec)
{
unsigned int i;
for ( i = 0; i < (sec / 50); i++ )
{
delay_50ms();
}
}
void main( void )
{
P0 = 0; P1 = 0; P2 = 0;
while(1)
{
unsigned char val = 0x00;
unsigned char var1 = 0x00;
unsigned char var2 = 0x00;
var1 = P2; wait(50); P2 = num[1]; wait(200); var2 = P2; wait(50); P2 = num[0];
if(var1 == num[2])
{
if(var2 == num[1])
P0 = num[2]; if(var2 == num[3])
P0 = num[1];
serial_init();
val = serial_read(); P1 = val; }
if(var1 == num[0])
{
if(var2 == num[3])
{
P1 = num[4]; wait(1000); P1 = num[0];
}
if(var2 == num[1])
{
serial_init();
val = serial_read(); P1 = val; }
P0 = num[0]; }
}
}
Summary
I compiled the C code above and simulated on the Proteus Simulation program with the following diagram:
For simulation purpose, I used Virtual Serial Port Driver (It has 14 days evaluation period and free trial download can be found here to create a virtual port pair and connected my PC software to one of these COM pair's end port and COMPIM serial port of the Proteus Simulation to the other end. The two H-bridges at the bottom are made using NPN and PNP BJT transistors.
That is it. If you want details, just let me know!
History
- Article submitted - Nov. 12, 2010
- Just some grammar editing - Jan. 10, 2012