# Car maintaining same speeds as the one ahead

I have previously posted in the beginners section but I feel this is more advanced than I had first anticipated.
Previously I was trying to code something that would react to a change in distance... but I've found a similar problem which would require the same bit of code however is much easier to explain and think about.

Say you decide to put a picaxe in your car so that when you're on the motorway you can switch a button and then the picaxe will accelerate/decelerate/hold-contstant-speed dependant on the car in front.

Now, my purposose for this programming is to place it into a coating machine im trying to build, which requires a tension arm to be steady. However, for all that matters its the same as the cruise control idea above.

(To make explaining easier, i think its best we talk as though its the cruise control from here on out)

What doesnt work?

Simply saying if the car gets x distance away accelerate and if its x distance too close decelerate. This is because it makes an  inverted bouncy ball effect. (the bounces get indefinately higher and higher) In other words, the car would start to get too close the car, then too far way, then even closer, then even further, then hit the car in front. This is because the pic isnt reacting intuitively enough.

I.e when it gets so far away I step down a potentiometer which will cause the car to go faster until it gets passed the upper limit (the point at which Ive said its too close) and then will step up the potentiometer and allow less voltage through which will cause the car to slow right down.

I need a system which will allow it to almost predict where the car will be in relation to the car infront and then speed up, slow down accordingly.

So if it gets  really close I need the system to step up the potentiometer so that the car returns to its desired distance from the car ahead and then step down just enough to stop the car getting any further away.

I hope this makes sense!

Any Ideas?

## Comment viewing options

Thank you Birdmun.

I have coded a PD controller using snippets of information from around the web and hopefully tailored it to my need.

'Tension Arm
symbol CS = 7

symbol UD = 5

symbol RLED = 6

symbol GLED = 4

symbol trig = 3 'Define output pin for Trigger pulse

symbol echo = 6 'Define input pin for Echo pulse

symbol range = w1 '16 bit word variable for range

symbol break = b1

'#############################################################'

' PID constants

symbol kP = 1

symbol kD = 100

symbol SV = 10

' software constants

symbol false = 0

symbol true  = 1

' software variables

symbol temp     = w6

symbol errAct   = w5

symbol errPrv   = w4

symbol PWR      = w3

symbol gain     = w2

symbol drange     = w1

symbol ErrNeg   = w9

symbol PErrNeg  = w8

symbol DGainNeg = w7

Init:

HIGH CS ; set the chip select high to disable serial control.

main:

gosub distance

' error calculation

errPrv = errAct

PErrNeg = ErrNeg

if range > SV then

errAct = range - SV

ErrNeg = false

else

errAct = SV - range

ErrNeg = true

endif

' proportional gain calculation

gain = errAct*kP

if ErrNeg = true then

PWR = PWR - gain max 1000

else

if ErrNeg = false then

PWR = PWR + gain

else

PWR = 0

endif

endif

' derivated gain calculation

drange = errAct

errPrv = errPrv

if drange =>errPrv then

gain = drange - errPrv

DGainNeg = false

else

gain = errPrv - drange

DGainNeg = true

endif

gain = gain*kD

if DGainNeg = true then

PWR = PWR + gain max 1000

else

if PWR > gain then

PWR = PWR - gain

else

PWR = 0

endif

endif

sertxd (#PWR)

if range > SV then goto Increment

if range < SV then goto Decrement

distance:

pulsout trig,2 'produce 20uS trigger pulse (must be minimum of 10uS)

pulsin echo,1,range 'measures the range in 10uS steps

pause 20 'recharge period after ranging completes

let range = range * 10 / 58 ;divide by 2 if PICAXE 28x2 instead of PICAXE 28x1

let range = 13 'just to test

'sertxd (#range)

return

Decrement:

if PWR = 0 then goto main

break =0

DO

HIGH RLED

LOW UD ; set U/D pin to low state to indicate decrement mode

LOW CS ; set CS pin low to enable serial control of the MCP4011

PULSOUT UD, 1 ; 1 msec pulse on the UD line to step down

HIGH CS ; Finished stepping down so must set CS pin high before can select a new mode.

LOW RLED

break= break +1

pause 80

LOOP UNTIL break=PWR

pause 400

GOTO Main

Increment:

if PWR = 0 then goto main

break=0

DO

HIGH GLED

HIGH UD ; set U/D pin to high state to indicate increment mode

LOW CS ; set CS pin low to enable serial control of the MCP4011

PULSOUT UD, 1 ; 1 msec pulse on the UD line to step up

HIGH CS

LOW GLED

break=break + 1

pause 80

LOOP UNTIL break=PWR

pause 400

GOTO Main

Does this look feasible to you?

symbol range = w1 '16 bit word variable for range

symbol drange     = w1

Otherwise, I am not sure I am up to the task of following that monster. I, myself, would probably attempt to convert the quick and dirty PID snippet. I can't believe it would be anywhere near the size of the code you are showing. I could be wrong.

Theres no way it could be something as (seemingly) simple as this?

```SetPoint       CON     0                     ' Set point
Kp             CON     10                    ' Proportionality constant
Ki             CON     10                    ' Integral constant
Kd             CON     10                    ' Derivative constant

Current        CON     0                     ' Array index - current error
Accumulator    CON     1                     ' Array index - accumulated error
Previous       CON     2                     ' Array index - previous error
Delta          CON     3                     ' Array index - change in error

sensorInput    VAR     Word                  ' Sensor input variable
error          VAR     Word(4)               ' Four different types of errors
p              VAR     Word                  ' Proportional term
i              VAR     Word                  ' Integral term
d              VAR     Word                  ' Derivative term
drive          VAR     Word                  ' Output

DO

DEBUG "Enter sensor input value: "
DEBUGIN SDEC sensorInput

' Calculate error.
error(Current) = SetPoint - sensorInput

' Calculate proportional term.
p = Kp * error(current)

' Calculate integral term.
error(Accumulator) = error(Accumulator) + error(Current)
i = Ki * error(Accumulator)

' Calculate derivative term.
error(Delta) = error(Current) - error(Previous)
d = Kd * error(delta)

' Calculate output.
drive = p + i + d

' Display values.
DEBUG CR, CR, "ERROR", CR,
SDEC ? SetPoint, SDEC ? sensorInput, SDEC ? error(Current), CR,
"PROPORTIONAL", CR,
SDEC ? Kp, SDEC ? error(Current), SDEC ? p, CR,
"INTEGRAL", CR,
SDEC ? Ki, SDEC ? error(accumulator), SDEC ? i, CR,
"DERIVATIVE", CR,
SDEC ? Kd, SDEC ? error(Delta), SDEC ? d, CR,
"OUTPUT", CR,
SDEC ? p, SDEC ? i, SDEC ? d, SDEC ? drive, CR, CR

' Save current error to previous error before next iteration.
error(Previous) = error(Current) ```

`Code is from a basic stamp tutorial`

Thank you, I'll try and convert the code you linked me too.

On this piece of code, he hasnt assigned any values to kp, ki or kd... is this because it is a geneneric PID.. or?

void SetTunings(double Kp, double Ki, double Kd) {
kp = Kp;
ki = Ki;
kd = Kd;
}

you will see that the values are set here. There is no reason for you to copy the code exactly. :)

BASIC being what it is, I would suggest you find a different way to go about setting the P I D variables, maybe via a serial connection to allow you to tune the values while the machine is running.

http://brettbeauregard.com/blog/2011/04/improving-the-beginners-pid-introduction/

I would suggest you just attempt to convert the code on the first page to BASIC. If you can't, let us know.

I found the following site http://www.engin.umich.edu/group/ctm/examples/motor/PID2.html which explains PID very well. It also gives an example code for matlab which is for a motor. (Could be similar to my problem?)

Their seems to be very little examples of PID for picaxe chips. Does anyone have any explained code samples? Or an idea of how I might go about coding it?

I dont understand how I can do a derivitave or integral on the chip or the exact equation I need to work from.

Regards,
Luke

Thank you very much Birdmun.

I will definately look into it and try and come up with some code that will make it work.

Cheers NilsB :)
Regards,
Luke

a PID algorithm. If you don't know what PID is, look it up. You will see it will cover the exact problem you are mentioning with the rubberband effect.

... also use this tip to learn from LMR about PID.