PICAXE Maths

alband

Senior Member
Hi again everyone.

As mentioned before in a few threads I'm building a tank with a gun the I want to adjust itself depending on the angle of the tank.

I've currently got the accelerometer mounted on a servo, working nicely on a 28X2 working at 32Mhz.

To start off with I tried running a simple routine of:

Code:
if accelerometer > desired pos then: let servo = servo -1
else: let servo = servo +1
(obviously this is just the general "gist" of the code
The reasoning behind this code is that the scale the accelerometer works on (about 485-715) is different to the scale of the servo (75-225). This routine worked quite well but as you can imagine was a bit sluggish when the error is large.

So, I need to be able to convert the readings on the accelerometer to their corresponding servo values. To do this I first took a reading a the the endpoints of the servo (75 & 225) then filled in the gaps. After much calculating and re-arranging to stop the numbers overflowing, I got a formula working. I debugged this in real time on the PICAXE but found that only the endpoint values were correct and that when the sensor was in-between the endpoints, it produced a slightly incorrect number.
So, I had to find out what was going on in the middle:
Code:
sertxd ("start,")
main:		servopos B.7,b5
		pause 500
		readadc10 1,w0
		sertxd (#w0,",")
		let b5 = b5 + 1
		if b5 = 225 then end
		endif
		goto main
Attached is what I found. I shoved the numbers into excel and plotted a graph and before long I realised that (obviously) it was roughly a cosine graph: The difference on the sensor between 89-90 degrees is minimal but between 0-2 is a lot. (attached is my excel muking arounds. Rename it to .xls)

I then used excel to create a trendline for this graph (because the actual readings aren't accurate) and it could also give the equation for this trendline:
Code:
y = 0.0001x3 - 0.028x2 + 0.3857x + 710.63
Where each "x" is actually the servo position minus 74)
This trendline is very accurate but when put in the form of "x=" (to get the servo value from the accel' reading) it becomes very complicated and would never work on PICAXE.

I also created my own cosine graph which is quite close (and should be what's expected from the accelerometer but isn't due to something):
Code:
y=(COS(((x-74)/48.5)-0.105)*103)+608.35
Where "x" is again the servo reading minus 74
When this formula is put in the form of "x=" it isn't too bad but obviously involves the function "cos^-1" which (I don't think) PICAXE can do.

Is this the only way to get the accelerometer readings to a corresponding servo position:

Code:
if reading = 716 then: let reading = 75: endif
if reading = 714 then: let reading = 76: endif
if reading = 713 then: let reading = 77: endif
etc...
Which will of course take ages to run through, even at 32Mhz.

Thanks in advance, I've read my maths limit :(:rolleyes:
David.

P.S. I will attach in a reply my "standard" code that I use as the base for muking everything around and trying new things.
 

Attachments

hippy

Ex-Staff (retired)
This routine worked quite well but as you can imagine was a bit sluggish when the error is large

The general solution there would be not increment and decrement by one but an amount proportionate to the error

If actual > desired Then
pos = pos - ( ( actual-desired ) * K )
Else
pos = pos + ( ( desired-actual ) * K )
End If

You can have a different routine depending upon how great the difference is between actual and desired which will help get greater accuracy as actual approaches desired. Pursue that line of thought and you'll end up with PID algorithm. This is probably just a primitive version of PID ( I've no idea which part though ! ).
 

BeanieBots

Moderator
Yep, that's the "I" part.

If you're bored, have a look at my "Pb Charger" code.
It uses a crude version of that approach for both "P" and "I" to manipulate the PWM.

(Did warn you about the maths if you took the accellerometer path in your 'tank turret' thread a while back)
 

alband

Senior Member
Right, I've just remembered something.
This routine worked quite well but as you can imagine was a bit sluggish when the error is large
That wasn't the reason, sorry! :eek: It overcompensates if I do that.

I've tried this:
Code:
#PICAXE28X2

symbol reading = w0
symbol err = w1
symbol red1 = w2
symbol red2 = w3
symbol red3 = w4
symbol pos = b15
symbol temp = b16

adcsetup = 5
pause 10
high B.5
'high B.4
setfreq em32
servo B.7,150
let pos = 180




main:		readadc 3,b12

		if reading > 600 then: let err = reading - 600: let err = err / b12: let pos = pos + err: endif
		if reading < 600 then: let err = 600 - reading: let err = err / b12: let pos = pos - err: endif
		
		'if reading > 600 then: let pos = pos + 1: endif
		'if reading < 600 then: let pos = pos - 1: endif
		servopos B.7,pos
		'sertxd (#pos,",")
		'sertxd (#reading,",")
		'sertxd (#err,",")
		'pause b0
		goto main
But is still impossible to find a constant "k" that works for all ranges of error. My idea to solve this was to use a y=((x^2 + k)^0.5)-(k^0.5) to give full error compensation at low errors but lower compensation at larger errors where momentum seems to have more effect.
Before I can put this into action properly though, I need to convert the reading into a servo position, so that the error can be accurately calculated.

Thanks for reading.

Oh, BB just got your reply. Will do, got to go now though.
The qyro's just aren't designed for this though, they all have a small amount of oscillation (unless they are over £100), which on a tail rotor of a heli is fine but looks ridiculous on the gun of a tank. :)
Thanks.
 

BeanieBots

Moderator
Easy mistake and often fall for it myself.
The clue is whenever you see a line like:-

Var=Var+error
within a loop.

A value which accumulates with error is an integral.

Var = Constant*error would be proportional.

Differential is easy to mistake for integral but is given away by the sign.
It is such that the "D" will oppose whatever the P & I terms are trying to do in order to get closer to setpoint so that the rate at which setpoint is reached is reduced. (damping).
 
Top