Use Raspberry Pi to Create Obstacle Avoiding Robot Chassis

Raspberry Pi is quite suitable for robot creation.  Its GPIO pins could be used to control the motors and sensors, and itself could work as a server, and get controlled via Internet.

The Plan

I am going to create a robot chassis, which could automatically avoid obstacle on the ground. Here is my plan:
Screen Shot 2014-01-18 at 2.41.21 PM

Hardware Assembling

I bought a 4WD chassis kit from Internet.  After assembling the kit, I got a 295mm x 150mm x 40mm chassis with 4 DC motors installed.  The motors have built-in low gears and the actual speed is about 50 rpm, which is slow enough to avoid the calibration for the speed of each wheel.  The 4 wheels have very soft tires, which improve the road holding, thus the chassis could get along on the slope.
I will use a 7.4V Li-Po battery pack (2S) to power the entire chassis.  In order to obtain 5V to power Raspberry Pi, I need a UBEC, which works like voltage regular but has much higher performance.  UBEC is widely used by RF models, and has many types.  In my case a 5V/3A UBEC is good enough.
Please notice that, using a 3A UBEC doesn’t mean you could really get 3A current in reality.  The actual current that could be provided also limited by the Li-Po battery.  When choosing the battery pack, please pay attention to its C rating value.  What is C rating?  C rating is a measurement for charge and discharge rates for battery, and 1C means 1 time the rated mAh capacity of the battery.  Say you have 500mAh battery, then 1C means it could be charged/discharged with 500mA, while 2C means 1,000mA.  My battery pack is 5,000mAh, 20-30C discharge, so it could provide up to 15A current.  So in my case, the UBEC could really output 3A current.
The GPIO pin on Raspberry Pi can output signal but it is not capable to drive the DC motors.  So I will need the motor driving board, which could be done by using a L298N IC. You can buy some ready-to-go driving boards from Internet, but I will just create a small board to do the job.  The basic circuit diagram is shown below:
It is very simple and it can work without other components. If A1=1 and A2=0, motor A will go forward.  If A1=0 and A2=1, motor A will go backward.  If A1=A2, motor A will stop.  B1, B2 just have the same behavior.
I can use two L298N ICs to control 4 DC motors, but it is not necessary in my case.  The motor speed is quite low (by using the built-in gears), and the speed difference between motors could be ignored.  So I could connect the two motors on the same side parallelly, and use only one L298N IC to drive the 4 motors (two groups).
I used a 3cm x 7cm universal PCB to finish the wiring:
When the driving board get powered, it will draw quite a lot current at the first moment, and may cause the Raspberry Pi reboot (if you use the same power supply for both). To avoid this, a 100uF capacity is used between VCC and GND.  The L298N IC is not soldered but plug into a modified IC slot.  The +5V will be taken from the Raspberry Pi.
The connectors in green are for the motors (group A and B), while the connectors in blue are for power supply (+7.4V and +5V).  I installed the driving board into the chassis.  The UBEC is also connected to the +7.4V connector, so it can generate +5V to power Raspberry.  Here I have to solder a micro-USB plug on the output of UBEC, so it could connect to Raspberry Pi.  The +5V needed by the driving board will be taken from the +5V pin on Raspberry Pi.
An ultrasound sensor is used to detect obstacle.  It has four pins: VCC, Trig, Echo, and GND. To initialize the sensor, a pulse (at least 10us) should be sent to the Trig pin.  After that we could wait and measure the width of the pulse on the Echo pin.  The wider the pulse is, the longer distance is between the sensor and the object.
Measuring the distance of object in front of the chassis is not enough, as we need to define the strategy to make the chassis turn left or right.  Hence the sensor should not be fixed on the chassis, instead it should be able to “look around” and face to different directions in front of the chassis.  So I solder the sensor on a small PCB and then fix that PCB on a servo, which will then be mounted on the chassis.  That small PCB also converts the output on Echo pin from 5V to 3.3V, by using two divider resistances.  I need to do so because the GPIO pins on Raspberry Pi is working on 3.3V bias, while the Echo pin on the sensor could output 5V (as we powered it with 5V from Raspberry Pi). The plastic seat of the servo is made with my 3D printer.  The servo could be SG-90 or other models that have similar size.
The servo’s signal line is connected to the GPIO 18 pin on Raspberry Pi, which is the only one that could generate PWM signal with hardware.  You may wonder if it is safe to drive servo directly with the GPIO pin, the answer is positive.  For Raspberry Pi, the recommended current for each GPIO pin is 3mA, and the maximum current is 16mA.  While the servo’s signal line, will only draw about 0.02mA (i.e. 20uA) current, which is safe enough.
Here is how to wire the 7 used GPIO pins:
GPIO_wiringAnd here is a picture of the real wiring:
The Raspberry Pi and the Li-Po battery are placed on the upper plane.  Here is how the whole chassis looks like:
The ultrasound sensor looks like the robot’s big eyes:


The program is written in C language.
The first task is to drive the servo.  I am using Frank Buss’s example, and put it in a header file:

After calling the initHardware() method, the setServo() method could be used to set the servo position.
The second part is distance measurement, or object detection.  The GPIO 8 pin will be set high for 10us, and then the pulse width will be measured on GPIO 7 pin.  The pulse width (in us) divided by 58 will be the distance (in cm) between sensor and the object.
In order to control GPIO pins, I used the WiringPi library, which allows me to easily set GPIO pin high/low.  You may also notice that WiringPi project also has a library to support software PWM, which means any GPIO pin on Raspberry Pi could output PWM signal by using that library.  The reason that I don’ use it, is that I only need one pin to generate the PWM signal, which is already provided by Raspberry Pi’s hardware, so I don’t want to use more CPU time to output the software PWM.  However if your project needs multiple pins to output PWM signal, you could consider using this library, or use an Arduino as extension of Raspberry Pi to get more pins that can output PWM with hardware.

The getAvgDistance() method accepts a parameter to indicate the number of tests that should be done before calculating the average distance.  This will get much better result than measuring only once, in reality.  This method also takes care of some error cases, if the result of measurement is out of a good range, it will drop that result.
I also put some methods in the “driver.h” header file, to control the motors:

Below is the main program of the chassis, which includes the 3 header files above.
It starts a new thread to keep collecting the data from sonar sensor, which is rotated by the servo.  The servo can have 11 possible positions (from 0% to 100%, 10% per step), the distance data will be stored in an array that has 11 elements.  The main thread of the application, will keep checking the data in that array, and decide which direction is the better one to go ahead.  In case all directions are bad, the chassis will back off, and try again later.

To compile it, in Raspberry Pi console you run:

You can also check out the videos on the right sidebar, to see how it works.

See also