You are on page 1of 15

FINAL PROJECT: WALL FOLLOWING ROBOT

EG 6380G Microcomputer Interfacing

Submitted by,
Ashutosh Jaiswal
Introduction
The primary aim of the project is to learn about interfacing external
peripherals such as sensors and motors, to a microcontroller and program it
to behave in an expected manner, based on the information collected. This is
done by designing a wall following robot which collects information from its
IR sensors and outputs information to the motors which drive the robot. The
main task of the robot is to move parallel to a wall and at the same time
avoid any kind of collision with the wall. It is however necessary to design
some interfacing circuits to drive the motors and to receive data from the
sensors in a way that the microcontroller would understand.

Project Description
The project may be divided into three main parts. Each of these parts
will then be explained in detail.

1. Robot Hardware (Body)

2. Interface Circuitry

3. Algorithm/Program

1. Robot Hardware:

The robot’s body was constructed using two hard plastic sheets which
were cut into circular plates. The two plates where then mounted on top of
each other using stand-off’s, creating gap in between them, which was used
to mount the battery. Two motors with gear box were used to drive the robot
using a differential wheel arrangement. The wheels were mounted on the
gear box and then entire assembly was fixed on the lower plate.

The HCS12 evaluation board was mounted on the top plate and all
circuits were designed on the prototype board provided along with the
evaluation board. Three sensors were mounted on the right hand side of the
top plate, which would help in following the right wall and one sensor was
mounted in the front to detect a wall in the front.

A picture of the robot is shown in Fig 1.


2. Interface Circuitry:

The interface circuitry was required in order to control high current


hardware (such as motor) using the microcontroller and to understand the
signals given out by the IR sensor. The two main circuits used are,

a. Motor Driver Circuit

b. IR Sensor Circuit

Interface

Evaluation

Upper
Right
Lower

Motor with gear Front


box

Battery

Fig 1: Hardware Description of the robot

A variable power supply circuit was also used in order to supply


sufficient voltage and current to the driving motors. The power supply circuit
made use of the variable voltage regulator LM1086. The circuit used for this
is shown in Fig 2,
Fig 2: Variable power supply circuit for the motors

Motor Driver Circuit: The motor driver circuit was used to act as a
buffer between the microcontroller port and the high current motors. The IC
used as a motor driver is L293D. The pin diagram of the IC along with the
connections is shown in Fig 3. The digital control signal provided by HCS12
does not deliver sufficient current to drive the motor. Hence, a driver circuit,
which is capable of changing the direction of motor using the logic signals
and is capable of being driven at high current, is used. The IC is capable of
driving motor with voltage up to 36V.

Fig 3: Schematic of the motor driver circuit using L293D

In the above circuit, Vin is the supply voltage for the IC as well as for
the motor. D1 and D2 are the inputs which are used to control the direction
of the motor. Both D1 and D2 are TTL logic level inputs. The table below
(Table 1) shows the different combinations of D1 and D2, with its effect on
motor’s operation,

Table 1: Combinations of D1 and D2 for controlling motor


direction
D1 D2 Motor Direction
1 0 Clockwise Direction
0 1 An-Clockwise Direction
1 1 BRAKE (STOP)
0 0 BRAKE (STOP)

This is implemented in the microcontroller program in order to change


the motor direction or in order to stop the motor, based on the action
required to be taken. The same connections are made for the other motor of
the robot.

IR sensor circuit: The IR sensor circuit made use of the TCRT5000


sensor module as the sensing device, along with some external circuitry for
sensitivity control. The circuit is shown in Fig 4. The TCRT5000 sensor module
consists of an IR LED which emits IR rays and a IR photo transistor which is
mounted next to it is the IR receiver. As the distance between the module
and the wall decreases the amount of light being reflected off the wall
increases, thereby increasing the IR light on the IR receiver. This promoted
more conduction and thereby varies the output voltage. In an essence, the
output voltage is a function of the distance and is directly proportional to it.
However, the circuit here is designed such that; as the distance is decreased
the output voltage decreases and with more distance the output voltage is
higher. Based on this the HCS12 was programmed to detect when the robot
was too close to the wall or too far from the wall, or at the right distance
from the wall.
Fig 4: IR sensor circuit used for detecting wall

3. Algorithm and Program:

The algorithm described below is based on the labeling shown in Fig 5,

Fig 5: Figure shows labeling used in the algorithm

In Fig 5, “A” corresponds to the value given by the front sensor


depending on its distance from the wall. In a similar fashion B, C and D
correspond to the values given out by the sensors on the right side of the
robot.

Algorithm:
START: if A<x then
{
Turn left 90 degrees
else
go to CHECK1
}

CHECK1: if C=B
{
if C=D
{
Move front
}
else
go to CHECK2
}
CHECK2: if C>B
{
Tilt Left
else
if C>D
{
Tilt Right
}
else
go to CHECK_U

CHECK_U: if A>y
{
if B>y
{
if C>y
{
if D>y
{
Perform U turn operation
}
}
}
}
else
go to START

x= optimal value derived by trial and error to define least distance of the
sensor from wall
y= optimal value derived by trial and error to define farthest distance of
the sensor from wall

Based on the algorithm defined above, the program has been written
in ALP for controlling the robot and is given in the next section,

Program:
#include reg9s12.h ; include register equates
ORG $1000
JSR openAD0 ; initialize and configure ATD0
JSR openlcd ; initialize and configure LCD
MOVB #$0F, DDRA ; Set Port A as output port
;****************************************************************************************
***********
;Check if button is pushed
;****************************************************************************************
***********

Push_Button LDAA #$80 ; set DDRAM address to 0000000


JSR cmd2lcd
LDX #Push_Button_msg ; point to 1st message character
JSR puts2lcd ; output it to LCD screen
LDAA PORTA ;Load input value in port A
STAA Push ;Store the input value in memory
BRCLR Push,PSH,Countdown ;Check for Bit 4 --- if it is
reset then start countdown
JMP Push_Button ;If not reset then stay in loop
;****************************************************************************************
*************
;Start Countdown before starting algorithm
;****************************************************************************************
*************

Countdown JSR three


JSR two
JSR one
JMP forever

three LDAA #$80 ; set DDRAM address to 0000000


JSR cmd2lcd ;
LDX #Count3_msg
JSR puts2lcd
LDX #100
JSR hlfsec
RTS

two LDAA #$80 ; set DDRAM address to 0000000


JSR cmd2lcd
LDX #Count2_msg
JSR puts2lcd
LDX #100
JSR hlfsec
RTS

one LDAA #$80 ; set DDRAM address to 0000000


JSR cmd2lcd
LDX #Count1_msg
JSR puts2lcd
LDX #100
JSR hlfsec
RTS

Forever MOVB #$97,ATD0CTL5 ; start conversion at PAD7 and set


conversion for multi-channels
MOVB #$96,ATD0CTL5
MOVB #$95,ATD0CTL5
MOVB #$93,ATD0CTL5

cclp BRCLR ATD0STAT,SCF,cclp

; wait till conversion is complete


JSR sens_ad ; convert A/D value to voltage
LDAA #$C0 ; set DDRAM address to 0000000
JSR cmd2lcd ;
LDX #lcdmsg ; point to 1st message character
JSR puts2lcd ; output it to LCD screen
LDAA #46 ; create 460 ms delay

JSR START
JMP Forever

;****************************************************************************************
**********
;Algorithm Starts ....
; F -Sens1 (Front sensor)
; A -Sens2 (1st on right)
; B -Sens3 (Middle)
; C -Sens4 (Last)
;****************************************************************************************
**********
START LDD #900 ; Check if Front wall is present
CPD Adr00h
BHI Front_Detect ; If present then perform left by 90
degree operation
JSR Front ; If not present go Front
JMP Check1
Front_Detect JSR Brake
JSR Back
JSR Lefta
JSR Front
RTS

Check1 LDD Adr01h ; Load D with sensor A's value


CPD Adr02h ; Compare it with sensor B
BLO Check1a ; If A<B then robot is tilted right
JMP Check2

Check1a LDD Adr02h ; Check if B<C


CPD Adr03h
BLO Tilt_Left ; If true then robot is tilted right
so tilt left
RTS

Check2 LDD Adr01h ; Check if A > B, if true then robot


is tilted left
CPD Adr02h
BHI Check2a
JMP Check_uturn ; Finally check for U-turn

Check2a LDD Adr02h ; Check if B>C


CPD Adr03h
BHI Tilt_Right ; If true then robot is definitely
tilted left, so tilt right
RTS

Check_uturn LDD Adr01h ; Load sensor A's value in D


CPD #995 ; Compare D with a little less than the
highest possible sensor value
BHI CompB ; Branch to CompB is D is higher (NO WALL
DETECTED)
JMP Forever
CompB LDD Adr02h ; Load sensor B's value in D
CPD #995 ; Compare D with a little less than the
highest possible sensor value
BHI CompC ; Branch to CompB if D is higher (NO WALL
DETECTED)
JMP Forever
CompC LDD Adr02h ; Load sensor C's value in D
CPD #995 ; Compare D with a little less than the
highest possible sensor value
BHI CompF ; Branch to CompB if D is higher (NO WALL
DETECTED)
CompF LDD Adr02h ; Load sensor F's value in D
CPD #995 ; Compare D with a little less than the
highest possible sensor value
BHI Uturn ; Branch to Uturn if D is higher (NO WALL
DETECTED)
JMP Forever
;****************************************************************************************
************************
;Commands
;****************************************************************************************
************************

Tilt_Left JSR Left


JSR Front_short
JSR Right
RTS

Tilt_Right JSR Right


;JSR Front_short
RTS

Uturn JSR Brake


LDAA #$80 ; set DDRAM address to 0000000
JSR cmd2lcd
LDX #Uturn_msg ; point to 1st message character
JSR Front_Ustart ; Go straight
JSR Right90 ; Turn right by 90 degrees
JSR Fronta ; Go straight so that the obstacle is
crossed
JSR Right90 ; Turn right by 90 degrees
JSR Front_Ustart2 ; Go straight enough to make sure wall is
detected
RTS

;****************************************************************************************
***********
;MOTOR DIRECTION CONTROL SUBROUTINES
;****************************************************************************************
***********
Front MOVB #$0A,PORTA
LDAA #$80 ; set DDRAM address to 0000000
JSR cmd2lcd
LDX #Front_msg ; point to 1st message character
JSR puts2lcd
LDX #85 ; Load X with 5 for counting purposes gives
460ms
JSR hlfsec
RTS

Front_Ustart MOVB #$0A,PORTA


LDAA #$80 ; set DDRAM address to 0000000
JSR cmd2lcd
LDX #Uturn_msg ; point to 1st message character
JSR puts2lcd
LDX #150
JSR hlfsec
RTS

Front_Ustart2 MOVB #$0A,PORTA


LDAA #$80 ; set DDRAM address to 0000000
JSR cmd2lcd
LDX #Uturn_msg ; point to 1st message character
JSR puts2lcd
LDX #400 ;
JSR hlfsec
RTS

Front_short MOVB #$0A,PORTA


LDAA #$80 ; set DDRAM address to 0000000
JSR cmd2lcd
LDX #Front_msg ; point to 1st message character
JSR puts2lcd
LDX #85 ;
JSR hlfsec
RTS

; Long Front drive after U turn detect


Fronta MOVB #$0A,PORTA
LDAA #$80 ; set DDRAM address to 0000000
JSR cmd2lcd
LDX #Uturn_msg ; point to 1st message character
JSR puts2lcd
LDX #625
JSR hlfsec
RTS

;Regular Left turn


Left MOVB #$09, PORTA
LDAA #$80 ; set DDRAM address to 0000000
JSR cmd2lcd
LDX #Left_msg ; point to 1st message character
JSR puts2lcd
LDX #35
JSR hlfsec
RTS

;90 degree left turn for front sensor


Lefta MOVB #$09, PORTA
LDAA #$80 ; set DDRAM address to 0000000
JSR cmd2lcd
LDX #Wall_msg ; point to 1st message character
JSR puts2lcd
LDX #480
JSR hlfsec
RTS

Back MOVB #$05, PORTA


LDAA #$80 ; set DDRAM address to 0000000
JSR cmd2lcd
LDX #Back_msg ; point to 1st message character
JSR puts2lcd
LDX #150 ; Load X with 5 for counting purposes gives
460ms
JSR hlfsec
RTS

Right MOVB #$06, PORTA


LDAA #$80 ; set DDRAM address to 0000000
JSR cmd2lcd
LDX #Right_msg ; point to 1st message character
JSR puts2lcd
LDX #30 ; Load X with 5 for counting purposes gives
460ms
JSR hlfsec
RTS

Right90 MOVB #$06, PORTA


LDAA #$80 ; set DDRAM address to 0000000
JSR cmd2lcd
LDX #uturn_msg ; point to 1st message character
JSR puts2lcd
LDX #500 ; Load X with 5 for counting purposes gives
460ms
JSR hlfsec
RTS

Brake MOVB #$00, PORTA


LDX #35 ; Load X with 5 for counting purposes gives
460ms
JSR hlfsec
RTS

;****************************************************************************************
*************
;0.5 sec delay
;****************************************************************************************
*************
hlfsec LDY #60000 ; (60000 X 4)/24 = 10 ms
mlsec DEY
BNE mlsec
DBNE X,hlfsec
RTS
;****************************************************************************************
*************
;Reading Sensor values
;****************************************************************************************
*************
sens_ad LDD Adr00h ; get result of conversion
LDY #10 ; multiply result by 10 to be
EMUL ; able to divide it by 2046
LDX #2000 ; note! result only sitting in D
IDIV ; integer part of the result is in X
XGDX ; D has the remainder, swap them
ADDB #$30 ; make it ASCII
STAB sens1

LDD Adr01h ; get result of conversion


LDY #10 ; multiply result by 10 to be
EMUL ; able to divide it by 2046
LDX #2000 ; note! result only sitting in D
IDIV ; integer part of the result is in X
XGDX ; D has the remainder, swap them
ADDB #$30
STAB sens2

LDD Adr02h ; get result of conversion


LDY #10 ; multiply result by 10 to be
EMUL ; able to divide it by 2046
LDX #2000 ; note! result only sitting in D
IDIV
XGDX
ADDB #$30
STAB sens3

LDD Adr03h ; get result of conversion


LDY #10 ; multiply result by 10 to be
EMUL ; able to divide it by 2046
LDX #2000 ; note! result only sitting in D
IDIV
XGDX
ADDB #$30
STAB sens4

RTS

;****************************************************************************************
***
;INITIALIZE A to D
;****************************************************************************************
***
openAD0 MOVB #$E0,ATD0CTL2
LDY #120 ; 120 X 4 / 24 = 20 us
;****************************************************************************************
***
;LCD SUBROUTINE
;****************************************************************************************
***
ad0lp DEY
BNE ad0lp

cmd2lcd PSHA ; save the command in stack


BCLR PORTK,RS ; select the instruction register
BSET PORTK,E ; pull the E signal high
ANDA #$F0 ; clear the lower 4 bits
LSRA ; match the upper four bits
LSRA ; with the LCD data pins
ORAA #E ; Maintain the E signal value
STAA PORTK ; send the command along w/ RS & E
NOP ; extend the duration of E pulse
NOP
NOP
BCLR PORTK,E ; pull the E signal low
PULA ; retrieve the LCD command
ANDA #$0F ; clear the upper four bits
LSLA ; match the lower four bits
LSLA ; with the LCD data pins
BSET PORTK,E ; pull the E signal high
ORAA #E ; maintain the E signal value
STAA PORTK ; send the lower 4-bit w/RS & E
NOP ; extend the duration of E pulse
NOP
NOP
BCLR PORTK,E ; clear E signal to complete the operation
LDY #240 ; 240 x 4 = 960 cycles = 40 micro_s
sdly DEY ; 1 cycle
BNE sdly ; 3 cycles
RTS

openlcd MOVB #$FF,DDRK ; configure port K for output


JSR d_10ms ; wait for LCD to be ready
LDAA #$28 ; set 4-bit data, 2-line display, 5x8 font
JSR cmd2lcd
LDAA #$0F ; turn on display, cursor, and blinking
JSR cmd2lcd
LDAA #$06 ; move cursor right (entry mode set
JSR cmd2lcd ; instruction)
LDAA #$01 ; clear the screen and return to home
JSR cmd2lcd ; position

LDY #10000 ; 10000 x 4 = 40,000 cycles = 1.67ms


dly1 DEY ; 1 cycle
BNE dly1 ; 3 cycles
RTS

d_10ms LDY #60000 ; 60000 x 4 = 240,000 cycles = 10ms


dly DEY ; 1 cycle
BNE dly ; 3 cycles
RTS

putc2lcd PSHA ; save the command in stack


BSET PORTK,RS ; select LCD data register
BSET PORTK,E ; pull the E signal high
ANDA #$F0 ; clear the lower 4 bits
LSRA ; match the upper four bits
LSRA ; with the LCD data pins
ORAA #$03 ; keep E & RS signals unchanged
STAA PORTK ; send the upper 4-bit along w/ RS & E
NOP ; extend the duration of E pulse
NOP
NOP
BCLR PORTK,E ; pull the E signal low
PULA ; retrieve the LCD command
ANDA #$0F ; clear the upper four bits
LSLA ; match the lower four bits
LSLA ; with the LCD data pins
BSET PORTK,E ; pull the E signal high
ORAA #$03 ; keep E & RS signals unchanged
STAA PORTK ; send the lower 4-bit w/RS & E
NOP ; extend the duration of E pulse
NOP
NOP
BCLR PORTK,E ; clear E signal to complete the operation
LDY #240 ; 240 x 4 = 960 cycles = 40 ?s
dly2 DEY ; 1 cycle
BNE dly2 ; 3 cycles
RTS

puts2lcd LDAA 1,X+ ; get a character from string


BEQ done_puts ; reach NULL character?
JSR putc2lcd ; if not, output to screen
JMP puts2lcd ; continue till whole string is outputed
done_puts RTS

getchar EQU $EE84


RS EQU $01
E EQU $02

count1 RMB 1
count2 RMB 1

lcdmsg FCC 'F:'

sens1 RMB 1
FCC ' A:'
sens2 RMB 1
FCC ' B:'
sens3 RMB 1
FCC ' C:'
sens4 RMB 1

DB 0
Front_msg FCC 'GOING FRONT '
DB 0
Back_msg FCC 'GOING BACK '
DB 0
Right_msg FCC 'GOING RIGHT '
DB 0
Left_msg FCC 'GOING LEFT '
DB 0
Uturn_msg FCC 'U TURN '
DB 0
Push_Button_msg FCC 'PUSH TO START'
DB 0

Count3_msg FCC 'STARTING IN 3 '


DB 0
Count2_msg FCC 'STARTING IN 2 '
DB 0
Count1_msg FCC 'STARTING IN 1 '
DB 0
Wall_msg FCC 'OOPS!...A WALL!! '
DB 0

SCF EQU $80,$C0


PSH EQU $10
Push RMB 1

END

Result and Conclusion


The robot worked as expected. It completed the maze fully and
detected U turn and front walls perfectly. However, there were many
difficulties that came across during the course of the project. One of them
was driving the motors. Whenever the motor dragged more current under
higher load, it would reset the evaluation board as the drop out voltage of
the regulator was too close to the output voltage. In this case the board
would automatically reset itself. In order to overcome this problem, the
voltage to the motors was controlled using the adjustable voltage regulator,
in such a way that at maximum load, the motor drops out the voltage of the
board’s supply, just enough to keep it at 5V mark. This would not reset the
evaluation board. Another problem was sensitivity of the IR sensors. The
output voltage from the IR sensor circuit was first derived from the emitter of
the photo transistor. However, it was found that the voltage range would be
from 3 to 5 volts. This was because the impedance of the analog port along
with the impedance of the photo-transistor, forced the voltage range to be
limited. However, if the voltage was derived from the collector, a full range
from 0 to 5 volts was attained.

You might also like