Support »
PIC-Based, Obstacle-Avoiding Robot

View document on multiple pages.
You can also view this document as a printable PDF.
- 1. Introduction
- 2. Materials and Tools
- 3. Hardware Construction
- 4. Software for the PIC
- 5. Results and Conclusion
1. Introduction
<table class="picture_with_caption center"><tr><td><img alt="" class="" data-gallery-pictures="[{"id":"0J304","caption":"\u003cp\u003ePIC-based obstacle-avoiding robot.\u003c/p\u003e","url_tiny":"https://a.pololu-files.com/picture/0J304.98x98.jpg?83e49f936fc6358aa7b17068adbd0fbf","url_medium":"https://a.pololu-files.com/picture/0J304.600x480.jpg?83e49f936fc6358aa7b17068adbd0fbf","url_full":"https://a.pololu-files.com/picture/0J304.1200.jpg?83e49f936fc6358aa7b17068adbd0fbf","longest_side":400}]" data-picture-id="0J304" data-picture-longest_side="400" src="https://a.pololu-files.com/picture/0J304.400.jpg?83e49f936fc6358aa7b17068adbd0fbf" /></td><p></tr></table></p>
<p>One of the biggest challenges in building your own robot is controlling its motors. You can find new or surplus motors and gearboxes in many places, and low-cost microcontrollers and books on how to use them abound. However, microcontrollers cannot directly drive DC motors, leaving robotics beginners with the possibly overwhelming challenge of building their own motor controller. This task is even more complicated if the motors require bidirectional operation and speed control.</p>
<p>This project demonstrates how easy it is to make a simple robot controller using the <a href="/product/410">Pololu micro dual serial motor controller</a> with a <a href="http://www.microchip.com/">Microchip</a> PIC16F628 microcontroller. We then use the circuit with the <a href="/product/250">Pololu robot chassis</a> to create a small, obstacle-avoiding robot that can serve as a starting point for more advanced projects. The low-voltage operation of the motor controller allows a small, 3.6 V cordless telephone battery pack to power the entire robot. Since the motor controller only requires two of the PIC’s 13 I/O lines, there is plenty of opportunity for expansion.</p>
2. Materials and Tools
<p>Here are the essential parts you will need if you want to build a similar robot. These items are available either from Pololu or from most electronic component distributors.</p>
<ul>
<li><a href="/product/410">Pololu micro dual serial motor controller</a></li>
<li><a href="/product/250">Pololu robot chassis plate</a></li>
<li>Parts to build the robot chassis, which come with our chassis combination kits:
<ul>
<li><a href="/product/61">Tamiya twin-motor gearbox</a> (Tamiya #70097)</li>
<li><a href="/product/66">Tamiya ball caster</a> (Tamiya #70144)</li>
<li><a href="/product/65">Tamiya truck tires</a> (Tamiya #70101)</li>
</ul></li>
<li><strong>PIC16F627</strong> or <strong>PIC16F628</strong> microcontroller in a DIP (dual in-line package) from <a href="http://www.microchip.com/">Microchip</a>. The 16F62X microcontrollers are the only 18-pin PICs that have a built in UART (universal asynchronous receiver and transmitter), which makes transmitting data serially (to the motor controller) very simple. The code presented in this project should be portable to any other PIC with a hardware UART; with the other PICs, you would have to write your own serial routines (which isn’t that bad since you only need to transmit, and the motor controller should handle any baud rate you come up with).</li>
<li><strong>Clock source</strong> for the PIC. We used a 4 MHz ceramic resonator with built-in capacitors; any crystal, resonator, or oscillator in the 1-20 MHz range should be fine.</li>
<li><strong>18-pin DIP socket</strong> for the PIC. You may also want a socket for your motor controller; a crude way of obtaining a 9-pin SIP (single in-line package) socket is to cut an 18-pin DIP socket in half.</li>
<li>Two <strong>long-lever, snap-action switches</strong> for use as bumpers switches.</li>
<li><strong>3.6 V, 650 mAh cordless telephone battery pack</strong> (or three AA size NiCd or NiMH batteries in a battery holder). Cordless phone batteries are available in many consmer electronics stores (e.g. Radio Shack, Best Buy) and discount stores (e.g. Wal-Mart) for around $10, making them a great power source for small robots.</li>
<li>General-purpose <a href="/category/32/prototyping-pcbs">prototyping PC board</a> (or proto board) with space for two 18-pin DIP sockets, the ceramic resonator, and whatever other electronics you might want to fit. Such boards are available from most electronics component stores, including Radio Shack (e.g. part number 276-150A). To avoid soldering, this project could also be done using a small <a href="/product/350">wireless breadboard</a>, such as the one used in <a href="/docs/0J3">project 2</a>.</li>
<li><a href="/product/354">Hook-up wire</a> and <strong>solder</strong> for making all of your connections.</li>
<li><strong>Double-sided foam tape</strong> provides a quick way of temporarily mounting items such as the battery pack. Alternatively, you could use standard mounting hardware or cable ties for fixing your components to the chassis.</li>
</ul>
<p>You will probably also want to use the following:</p>
<ul>
<li>Pushbutton switch and 10k resistor for a reset circuit</li>
<li>Two 0.1 uF capacitors to solder across the motor terminals</li>
<li>Power switch</li>
</ul>
<p>You will also need these basic tools:</p>
<ul>
<li><a href="/category/5/tools">Soldering iron</a></li>
<li><a href="/product/159">Diagonal cutters</a></li>
<li><a href="/product/161">Wire strippers</a></li>
<li>Scissors</li>
<li><a href="/product/158">Phillips screwdriver</a> (for building the gearbox and ball caster)</li>
<li>Hot glue gun (optional)</li>
</ul>
3. Hardware Construction
<table class="picture_with_caption right"><tr><td><img alt="" class="" data-gallery-pictures="[{"id":"0J312","caption":"\u003cp\u003eBattery pack on PIC-based obstacle-avoiding robot.\u003c/p\u003e","url_tiny":"https://a.pololu-files.com/picture/0J312.98x98.jpg?a321681aa3271d6db694740f808b4f42","url_medium":"https://a.pololu-files.com/picture/0J312.600x480.jpg?a321681aa3271d6db694740f808b4f42","url_full":"https://a.pololu-files.com/picture/0J312.1200.jpg?a321681aa3271d6db694740f808b4f42","longest_side":300}]" data-picture-id="0J312" data-picture-longest_side="300" src="https://a.pololu-files.com/picture/0J312.300.jpg?a321681aa3271d6db694740f808b4f42" /></td><p></tr></table></p>
<p>Begin by assembling the robot chassis. You should mount the battery pack on the rear of the robot, above the ball caster, to balance the weight of the motors. Double-sided foam tape is a convenient method of attaching the battery pack; it can also be secured with cable-ties by using the rectangular holes on both sides of the ball caster. If you are using a battery holder, you can easily drill mounting holes through the holder or the chassis if existing holes do not line up.
<br clear="all"/></p>
<table class="picture_with_caption right"><tr><td><img alt="" class="" data-gallery-pictures="[{"id":"0J313","caption":"\u003cp\u003eCapacitors across motor leads on the PIC-based obstacle-avoiding robot.\u003c/p\u003e","url_tiny":"https://a.pololu-files.com/picture/0J313.98x98.jpg?76bdde5f070315d727a985d5e26f950a","url_medium":"https://a.pololu-files.com/picture/0J313.600x480.jpg?76bdde5f070315d727a985d5e26f950a","url_full":"https://a.pololu-files.com/picture/0J313.1200.jpg?76bdde5f070315d727a985d5e26f950a","longest_side":300}]" data-picture-id="0J313" data-picture-longest_side="300" src="https://a.pololu-files.com/picture/0J313.300.jpg?76bdde5f070315d727a985d5e26f950a" /></td><p></tr></table></p>
<p>When soldering to the motor leads, be careful not to damage them. Soldering a small capacitor across the motor leads can improve the performance of the motor controller and lower interference with other electronics on your robot. We used a 0.1 uF ceramic capactitor.</p>
<p>The picture to the right shows a resistor in series with the capacitor. In general, such a resistor limits the current wasted by the PWM (pulse width modulation) in charging and discharging the capacitor. However, the relatively low, 600 Hz PWM frequency of the motor controller makes this resistor unnecessary; we saw no added benefit when we added the resistor.
<br clear="all"/></p>
<table class="picture_with_caption right"><tr><td><img alt="" class="" data-gallery-pictures="[{"id":"0J314","caption":"\u003cp\u003eStrain relief for motor wires on PIC-based obstacle-avoiding robot.\u003c/p\u003e","url_tiny":"https://a.pololu-files.com/picture/0J314.98x98.jpg?c524708e10168df13bfa6b19a3b3529a","url_medium":"https://a.pololu-files.com/picture/0J314.600x480.jpg?c524708e10168df13bfa6b19a3b3529a","url_full":"https://a.pololu-files.com/picture/0J314.1200.jpg?c524708e10168df13bfa6b19a3b3529a","longest_side":300}]" data-picture-id="0J314" data-picture-longest_side="300" src="https://a.pololu-files.com/picture/0J314.300.jpg?c524708e10168df13bfa6b19a3b3529a" /></td><p></tr></table></p>
<p>Because the motor leads are fragile, it is important to provide strain relief for the wires you connect to the motor. For our example, we hot-glued the leads to the side of the gearbox, as shown in the picture. Securing the wires this way will allow you to manipulate the other end of the wires without worrying about breaking off the motor leads. Note that the glued wires prevent removal of the motors from the gearbox. Hot glue has the advantage of not being entirely permanent; if necessary, it’s not too difficult to free the wires.</p>
<p>We have kept the motor capacitor exposed for the purposes of these pictures, but it’s a good idea to protect them as much as possible, especially since they are low to the ground and on the front end of the robot.
<br clear="all"/></p>
<table class="picture_with_caption right"><tr><td><img alt="" class="" data-gallery-pictures="[{"id":"0J315","caption":"\u003cp\u003eSwitches on PIC-based obstacle-avoiding robot.\u003c/p\u003e","url_tiny":"https://a.pololu-files.com/picture/0J315.98x98.jpg?e11c239cce1a6e2e650f1582ded184fe","url_medium":"https://a.pololu-files.com/picture/0J315.600x480.jpg?e11c239cce1a6e2e650f1582ded184fe","url_full":"https://a.pololu-files.com/picture/0J315.1200.jpg?e11c239cce1a6e2e650f1582ded184fe","longest_side":300}]" data-picture-id="0J315" data-picture-longest_side="300" src="https://a.pololu-files.com/picture/0J315.300.jpg?e11c239cce1a6e2e650f1582ded184fe" /></td><p></tr></table></p>
<p>To keep this project as simple as possible, we limit our sensors to two snap-action swtiches for front collision detection. Of course, you can add more sophisticated sensors for more interesting behavior.
<br clear="all"/></p>
<table class="picture_with_caption right"><tr><td><img alt="" class="" data-gallery-pictures="[{"id":"0J316","caption":"\u003cp\u003eElectronics on PIC-based obstacle-avoiding robot.\u003c/p\u003e","url_tiny":"https://a.pololu-files.com/picture/0J316.98x98.jpg?2655e865b20240c42e56d40973d96bc6","url_medium":"https://a.pololu-files.com/picture/0J316.600x480.jpg?2655e865b20240c42e56d40973d96bc6","url_full":"https://a.pololu-files.com/picture/0J316.1200.jpg?2655e865b20240c42e56d40973d96bc6","longest_side":300}]" data-picture-id="0J316" data-picture-longest_side="300" src="https://a.pololu-files.com/picture/0J316.300.jpg?2655e865b20240c42e56d40973d96bc6" /></td><p></tr></table></p>
<p>As you can see in the picture to the right, there isn’t much to the electronics. We soldered the circuit on a small perforated board, but you can also use a solderless breadboard. The small pushbutton switch on the top right and the resistor below it make up an optional reset circuit. The only other components are the PIC, the resonator (lower right), and the motor controller. No additional resistors are required for the bump switches because we use the PIC’s internal pull-up resistors on port B.
<br clear="all"/></p>
<table class="picture_with_caption center wide"><tr><td><img alt="" class="wide" data-gallery-pictures="[{"id":"0J317","caption":"\u003cp\u003eSchematic for electronics on the PIC-based obstacle-avoiding robot.\u003c/p\u003e","url_tiny":"https://a.pololu-files.com/picture/0J317.98x98.jpg?e50dc5cecfdebe7a25470a28271e7bda","url_medium":"https://a.pololu-files.com/picture/0J317.600x480.jpg?e50dc5cecfdebe7a25470a28271e7bda","url_full":"https://a.pololu-files.com/picture/0J317.1200.gif?e50dc5cecfdebe7a25470a28271e7bda","longest_side":640}]" data-picture-id="0J317" data-picture-longest_side="640" src="https://a.pololu-files.com/picture/0J317.640.gif?e50dc5cecfdebe7a25470a28271e7bda" /></td><p></tr></table></p>
<p><br clear="all"/></p>
<p>The main reason for using the PIC16F628 is that it has a hardware UART; to make use of it, we must connect the TX pin, pin RB2, to the motor controller’s serial input. Connecting the motor controller reset pin is optional, but using it prevents any baud rate detection problems during power-up. If you don’t have any extra I/O lines, you can connect the reset input to the PIC reset circuit.</p>
<p>Note that the bumper switches must be connected to port B pins in order to make use of the PIC’s internal pull-up resistors. Nine of the PIC I/O lines are unused and available for expansion. As you add additional electronics, you may need to add 0.1 uF bypass capacitors from power to ground to keep the power supply clean.
As you can see in the picture to the right, there isn’t much to the electronics. We soldered the circuit on a small perforated board, but you can also use a solderless breadboard. The small pushbutton switch on the top right and the resistor below it make up an optional reset circuit. The only other components are the PIC, the resonator (lower right), and the motor controller. No additional resistors are required for the bump switches because we use the PIC’s internal pull-up resistors on port B.
<br clear="all"/></p>
4. Software for the PIC
<p>Using the motor controller is very simple, even if you program your PIC
in assembly. This sample program makes our little robot drive forward
until it hits an obstacle; once it does, it backs up, turns away from
the side where the collision occured, and resumes moving forward.
All of the code below uses the standard assembly language
supported by Microchip’s MPLAB development software. Even if you are
using a different assembler or compiler, this example should give you a
good start.</p>
<p>First, we name the registers and bits that we will use throughout
the rest of the program:</p>
<pre>
;****** Equates ****************************************************************

Bank0RAM equ 020h ;start of bank 0 RAM area

SMC_PORT equ PORTB ;motor controller on port b
BMP_PORT equ PORTB ;bumper switches on port b

;bit equates
SOUT equ 2 ;serial output to motor controller
SRST equ 3 ;to reset pin on motor controller
LBMP equ 4 ;left bumper switch
RBMP equ 5 ;right bumper switch

;****** Variables **************************************************************

 cblock Bank0RAM
 ARG1L
 ARG1H
 BYTE3 ;for storing bytes 3 and 4 in the serial protocol
 BYTE4
 endc</pre>
<p>It’s also convenient to have a subroutine for making precise pauses.
This routine takes the 16-bit value in ARG1H and ARG1L and delays for
approximately that many milliseconds. Of course, the length of the
delay is dependent on the clock speed, which is 4 MHz in our example.</p>
<pre>
milliDelay
 movlw .250 ;outer loop
 addlw 0xFF ;inner loop
 btfss STATUS,Z
 goto $-2 ;goto inner loop

 movlw 1 ;16-bit decrement
 subwf ARG1L,f
 btfss STATUS,C
 decf ARG1H,f

 movf ARG1H,f ;16-bit test if zero
 btfsc STATUS,Z
 movf ARG1L,f
 btfsc STATUS,Z
 return
 goto milliDelay</pre>
<p>We are now ready to approach the main program, which begins by
configuring the UART and resetting the motor controller. The 2
millisecond pause at the end gives the motor controller some time
between resetting and receiving serial input.</p>
<pre>
 org 0x05
startMain
 ;set up I/O ports and serial port for 19,200 baud UART
 bsf STATUS,RP0
 movlw b'11110111' ;smc reset is the only normal
 movwf TRISB ; output--all others inputs or serial out
 bcf OPTION_REG,NOT_RBPU ;enable PORTB pull-up resistors
 movlw .12 ;set baud rate to 19,200 (assuming BRGH=1)
 movwf SPBRG ;(address 99h)
 movlw b'00100100' ;bit 6 clear - 8-bit transmission
 ;bit 5 set - enable transmit
 ;bit 4 clear - UART asynchronous mode
 ;bit 2 set - high baud rate mode
 ;bits 7, 3, 1, 0 - don't care
 movwf TXSTA ;address 98h
 bcf STATUS,RP0 ;select bank 0
 movlw b'10010000' ;bit 7 set - enable serial port
 ;bit 6 clear - 8-bit reception
 ;bit 4 set - continuous receive
 ;bits 5, 3:0 - don't care
 movwf RCSTA ;address 18h
 ;reset motor controller
 bcf SMC_PORT,SRST
 nop
 nop
 bsf SMC_PORT,SRST
 movlw 0x00
 movwf ARG1H
 movlw 0x02
 movwf ARG1L
 call milliDelay</pre>
<p>The program is now ready to run its main loop, in which it
checks the bumper switches and takes the appropriate action.
Two supporting subroutines, <code>updateMotor</code> and <code>pause</code>, are
shown later; <code>updateMotor</code> sends a 4-byte command to the
motor controller based on <code>BYTE3</code> and <code>BYTE4</code>, and <code>pause</code> stops
both motors for 50 ms. <code>pause</code> is used to keep the motors
from having to instantly switch from forward to reverse,
which causes a current surge that can exceed the
motor controller’s maximum current specification of 1 A.</p>
<pre>
mainLoop
 btfss BMP_PORT,LBMP
 goto left_bump
 btfss BMP_PORT,RBMP
 goto right_bump
 ;no bumps, so just go straight
 movlw 0x00 ;right motor, forward
 movwf BYTE3
 movlw 0x7F ;full speed
 movwf BYTE4
 call updateMotor
 movlw 0x02 ;right motor, forward
 movwf BYTE3
 movlw 0x7F ;full speed
 movwf BYTE4
 call updateMotor
 goto mainLoop

left_bump
 call pause
 movlw 0x03 ;right motor, backward
 movwf BYTE3
 movlw 0x7F ;full speed
 movwf BYTE4
 call updateMotor
 movlw 0x01 ;left motor, backward
 movwf BYTE3
 movlw 0x3F ;half speed
 movwf BYTE4
 call updateMotor
 movlw HIGH .1500 ;pause 1.5 seconds (1500 ms)
 movwf ARG1H
 movlw LOW .1500
 movwf ARG1L
 call milliDelay
 call pause
 goto mainLoop

right_bump
 call pause
 movlw 0x03 ;right motor, backward
 movwf BYTE3
 movlw 0x3F ;half speed
 movwf BYTE4
 call updateMotor
 movlw 0x01 ;left motor, backward
 movwf BYTE3
 movlw 0x7F ;full speed
 movwf BYTE4
 call updateMotor
 movlw HIGH .1500 ;pause 1.5 seconds (1500 ms)
 movwf ARG1H
 movlw LOW .1500
 movwf ARG1L
 call milliDelay
 call pause
 goto mainLoop</pre>
<p>Finally, here are the subroutines called from the main loop. The <code>updateMotor</code>
subroutine sends the motor controller the 4-byte control sequence of 0x80 and 0x00
followed by the motor number and direction, specified in <code>BYTE3</code>, and the
speed, specified in <code>BYTE4</code>. To keep this example program simple,
this subroutine does not exit until all four
bytes have been copied to the transmit buffer. The program could be
made more efficient by using interrupts, allowing the PIC to perform
other tasks while the UART is busy transmitting.</p>
<pre>
updateMotor
 btfss PIR1,TXIF
 goto updateMotor
 movlw 0x80
 movwf TXREG
 nop
updateMotor2
 btfss PIR1,TXIF
 goto updateMotor2
 movlw 0x00
 movwf TXREG
 nop
updateMotor3
 btfss PIR1,TXIF
 goto updateMotor3
 movf BYTE3,W
 movwf TXREG
 nop
updateMotor4
 btfss PIR1,TXIF
 goto updateMotor4
 movf BYTE4,W
 movwf TXREG
 return

pause
 movlw 0x02 ;right motor off
 movwf BYTE3
 movlw 0x00
 movwf BYTE4
 call updateMotor
 movlw 0x00 ;left motor off
 movwf BYTE3
 movlw 0x00
 movwf BYTE4
 call updateMotor
 movlw HIGH .50 ;pause 0.05 second (50 ms)
 movwf ARG1H
 movlw LOW .50
 movwf ARG1L
 call milliDelay
 return</pre>
<table class="warning"><tr><td>
<strong>Note:</strong>
Make sure the watchdog timer is disabled in the configuration bits.
The brown-out detection feature must also be turned off for the PIC
to operate off of the 3.6 V power source.</td><p></tr></table></p>
5. Results and Conclusion
<p>Our robot performed as expected, and it was fairly entertaining to watch it bounce around the room. The bumper switches are far from perfect, with a blind area in the center of the robot that can get the robot stuck behind table legs and other obstacles too narrow to trigger either of the switches. This problem could be avoided by adding a third, center switch, or by making the robot turn randomly every once in a while.</p>
<p>One serious problem we did initially encounter was with changing the direction of the motors from full speed in one direction to full speed in the other direction. In highly cluttered areas, in which the robot frequently hit obstacles and changed directions, the motor controller would sometimes heat up to the point where the thermal cutoff kicked in, causing the robot to stop for approximately one second. After adding the 50 ms pauses between switching directions, we did not have any problems with the motor controller overheating.</p>
<p>This project shows that building a small robot is very simple when using the Pololu motor controller. In only a few hours, we built a functioning robot that can serve as a starting point for more complicated robots. If you are ready to tackle a new project, you might try adding on our <a href="/product/701">IR beacon</a> to allow the robot to run away from another robot.</p>