# Need Help With Modifying This PIC Code

#### Utkarsh Verma

Joined Oct 30, 2016
102
Here's the code:
Code:
'****************************************************************
'*  Name    : LineFollower.BAS                                  *
'*  Author  : Mohammd Yousefi                                   *
'*  Notice  : Copyright (c) 2010                                *
'*  Date    : July 2008                                         *
'*  Version : 1.0                                               *
'*  Notes   :  Program for controling a line follower robot     *
'*          :  using PIC16F84A and four IR sensors              *
'****************************************************************

Symbol MBtn = PORTA.0            'Mode Button
Symbol LBtn = PORTA.1            'Left Motor Button
Symbol RBtn = PORTA.2            'Right Motor Button
Symbol MLED = PORTA.3            'Mode Indicator LED   OFF = Default   ON = Custom based on Motors   Blink = Custom based on Sensors
Symbol LMotorB = PORTB.0         'Left Motor Forward
Symbol LMotorF = PORTB.1         'Left Motor Backward
Symbol RMotorF = PORTB.2         'Right Motor Forward
Symbol RMotorB = PORTB.3         'Right Motor Backward
Symbol FSensor = PORTB.4         'Right Sensor
Symbol RSensor = PORTB.5         'Middle Sensor
Symbol MSensor = PORTB.6         'Left Sensor
Symbol LSensor = PORTB.7         'Front Sensor

lmf var bit             'Left Motor Forward
lmb var bit             'Left Motor Backward
rmf var bit             'Right Motor Forward
rmb var bit             'Right Motor Backward
OnLine var bit          'Is robot on line?
MustTurn var bit        'Is the path lost?
MustTurnLeft var bit    'Indicates direction on turning
FastRotate var bit      'Indicates fast rotating

lls var bit             'Last state of Left Sensor
lrs var bit             'Last state of Right Sensor
lms var bit             'Last state of Middle Sensor

lcb var bit             'Last state of Custom Button
llb var bit             'Last state of Left Motor Button
lrb var bit             'Last state of Right Motor Button

i var byte
s var byte
ModeVar0 var bit        'Mode state variable 0
ModeVar1 var bit        'Mode state variable 1
cms var Byte[16]        'Custom mode values
schngd var bit          'Custom mode values changed

CycleCounter var byte   'Count cycles (used for LED blinking)

PORTA = 0
PORTB = 0
lmf = 1
lmb = 0
rmf = 1
rmb = 0
OnLine = 1
MustTurn = 0
mustturnleft = 0
FastRotate = 0
lls = 0
lrs = 0
lms = 0
lcb = 0
llb = 0
lrb = 0
ModeVar0 = 0
ModeVar1 = 0
CycleCounter = 0

TRISA = %10111
TRISB = %11110000

main:

' Default Process

if (((lsensor <> msensor) and (rsensor <> msensor)) or ((lsensor <> Fsensor) and (rsensor <> Fsensor))) then
'On line, move forward fast
lmf = 1
lmb = 0
rmf = 1
rmb = 0
online = 1
mustturn = 0
else
'Save sensors state at the begining
if (online = 1) then
lls = lsensor
lrs = rsensor
lms = msensor
online = 0
endif
if (mustturn = 1) then
if (mustturnleft = 1) then
lmf = 0
lmb = FastRotate
rmf = 1
rmb = 0
else
lmf = 1
lmb = 0
rmf = 0
rmb = FastRotate
endif
else
if ((lsensor <> lls) or (rsensor <> lrs)) then
'It's not a damage in path, I really lost the path
mustturn = 1
if (Rsensor <> lrs) then mustturnleft = 0
if (Lsensor <> lls) then mustturnleft = 1
'FastRotate = 0
'if (MSensor = lms) then FastRotate = 1
endif
endif
endif

' Mode Button

if ((MBtn = 0) and (lcb = 1)) then
if ((Modevar0 = 1) and (Modevar1 = 1)) then
Modevar0 = 0
Modevar1 = 0
low mled
else
if ((Modevar0 = 1) and (Modevar1 = 0)) then
Modevar1 = 1
for i = 16 to 31
cms[i - 16] = 255 - s
next i
else
if ((Modevar0 = 0) and (Modevar1 = 0)) then
Modevar0 = 1
high mled
for i = 0 to 15
cms[i] = 255 - s
next i
endif
endif
endif
lcb = 0
endif
if (MBtn = 1) then lcb = 1
if ((Modevar0 = 1) and (Modevar1 = 1)) then
if (CycleCounter < 85) then
high MLED
else
low mled
endif
endif

' Custom Process

if (Modevar0 = 1) then
' Variable Index
i = 0
if (Modevar1 = 0) then
if (lmf = 1) then i = i + 8
if (lmb = 1) then i = i + 4
if (rmf = 1) then i = i + 2
if (rmb = 1) then i = i + 1
else
if (RSensor = 1) then i = i + 8
if (MSensor = 1) then i = i + 4
if (LSensor = 1) then i = i + 2
if (FSensor = 1) then i = i + 1
endif

s = cms[i]
schngd = 0

' Left Motor Button
if ((LBtn = 0) and (llb = 1)) then
s = s + 1
if (s.2 = 1) then s = s & %11110000
cms[i] = s
schngd = 1
llb = 0
endif
if (LBtn = 1) then llb = 1

' Right Motor Button
if ((RBtn = 0) and (lrb = 1)) then
s = s + 16
if (s.6 = 1) then s = s & %00001111
cms[i] = s
schngd = 1
lrb = 0
endif
if (RBtn = 1) then lrb = 1

if (schngd = 1) then
if (Modevar1 = 0) then write i, 255 - s
if (Modevar1 = 1) then write i + 16, 255 - s
endif
endif

' Operate

if (PORTA.5) then
lmb = not lmb
lmf = not lmf
rmb = not rmb
rmf = not rmf
endif
if (Modevar0 = 1) then
if ((s.0 <> 0) or (s.1 <> 0)) then
LMotorB = s.1
LMotorF = s.0
else
LMotorB = lmb
LMotorF = lmf
endif
if ((s.4 <> 0) or (s.5 <> 0)) then
RMotorB = s.5
RMotorF = s.4
else
RMotorB = rmb
RMotorF = rmf
endif
else
LMotorB = lmb
LMotorF = lmf
RMotorB = rmb
RMotorF = rmf
endif

CycleCounter = CycleCounter + 1

goto main

end
I want to be able to modify the speed of the motors WHILE TURNING in the code only. I'm not planning on doing anything externally. I just want there to be a PWM value in the code, by modifying which, I'll be able to control the speed of the motors while turning. This code is of a Line Follower Robot. The problem with is that they are too fast for the project which leads to OVERTURNING of the robot and eventually it strays off track. I want to be able to reduce the speed of the motors either throughout the whole program or only while turning condition. Please tell me how!

#### JohnInTX

Joined Jun 26, 2012
4,667
One thing you will find out when trying to modify somebody else's code is that if it is not designed for that modification, it will likely be quite difficult to do. This is one of those cases.
The control is a simple bang-bang, direct output affair. The 16F84A hardware does not have hardware PWMs or motor control using H bridges etc.

If you want to try to do something with minimal impact to the existing code I might suggest something like this:

Create a software PWM using TMR0 as a period counter that interrupts the processor. Derive the PWM period from this interrupt by counting a register. Derive the duty cycle by counting another register that gets loaded when the period elapses. The PWM output is 'high' when the duty cycle counter >0 and 'low' when it reaches 0. It stays low until the period counter wraps around. Changing the initial count of the duty cycle register varies the duty cycle.

That's the PWM, now what to do with it? Since the code is not written to be aware of anything but its own direct IO, I might use the PWM 'output' to change the TRIS lines of the motor ports. TRIS=0 when the PWM 'output' is '1' to drive the motors normally. When, in the interrupt routine, the PWM duty cycle counter runs to 0 (PWM 'output' low) set the motor output TRIS lines to '1', making them inputs and removing the drive.

One serious potential problem with this approach is that bit-flipping on the ports directly might be an issue when you meddle with the TRIS, the dreaded r-m-w port problem.

To fix the r-m-w problem, redefine the motor bit variables, and any other outputs on the port, to map to some internal register. Bit-flips will go to that register. Then at every interrupt, write the contents of that image as a byte to refresh the port value. Never write any of those port bits directly. Change the TRIS lines in the same way i.e. write the entire register, not individual bits.

Given your constraints, old PIC, no hardware changes and copied code that's about the minimum footprint I can come up with.

Good luck.

Last edited: