Top Topics

74*245 Motor Driver

H-Bridge Driver

Simple PWM Gen.

Handy Method Measuring RPM

Measuring RPM via Photo reflector

Introduction to Robotic

DC, Stepper,and Servo Motor

Related Link

Microcontroller Tutorial

Computer Interface
Tutorial

.............more links

 

 

 

BACK

Complete Schematic

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.

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.

4. Software for the PIC

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.

First, we name the registers and bits that we will use throughout the rest of the program:

;****** 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


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.

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

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.

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


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, updateMotor and pause, are shown later; updateMotor sends a 4-byte command to the motor controller based on BYTE3 and BYTE4, and pause stops both motors for 50 ms. pause 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.

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


Finally, here are the subroutines called from the main loop. The updateMotor subroutine sends the motor controller the 4-byte control sequence of 0x80 and 0x00 followed by the motor number and direction, specified in BYTE3, and the speed, specified in BYTE4. 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.

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


Note: 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.

5. Results and Conclusion
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.

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.

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. In sample project 3 (coming soon), we'll make the robot more interesting by adding on our IR beacon to allow the robot to run away from another robot.

BACK