Need Help With Modifying This PIC Code

Thread Starter

Utkarsh Verma

Joined Oct 30, 2016
102
Here's the code:
Code:
'****************************************************************
'*  Name    : LineFollower.BAS                                  *
'*  Author  : Mohammd Yousefi                                   *
'*  Notice  : Copyright (c) 2010                                *
'*          : All Rights Reserved                               *
'*  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
                    read i, s
                    cms[i - 16] = 255 - s
                next i
            else
                if ((Modevar0 = 0) and (Modevar1 = 0)) then
                    Modevar0 = 1
                    high mled
                    for i = 0 to 15
                        read i, s
                        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,787
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:
Top