# How to code "almost equals" or "pretty close"?

June 13, 2010

****Full code is attached****

In the code, b19 is increased all over the place. This variable is used in the "ran" select case subroutines to get a "random" move.

I use a simple subroutine for some of Walter's head moves. The calculation is simple, it is "where you are now" compared to "where you want to go". The sub routine knows "where the head is now" and recieves the 3 bytes as to "where the head should finish". It then calculates all the steps to get from A to B. In each loop, a check is made to see if we have gotten to our end point yet. Here is where my question lies. So here is the code:

servocalc:

for b11= 1 to 255 step 1

if b7>b4 then let b4=b4+b10 max b7

endif

if b4>b7 then let b4=b4-b10 min b7

endif

if b8>b5 then let b5=b5+b10 max b8

endif

if b5>b8 then let b5=b5-b10 min b8

endif

if b9>b6 then let b6=b6+b10 max b9

endif

if b6>b9 then let b6=b6-b10 min b9

endif**if b4=b7 and b5=b8 and b6=b9 then ****return****endif**

gosub servomove

pause 20

inc b19

next b11

return

servomove:

I2CSLAVE $C2, i2cslow, i2cbyte 'this is the i2c for the servo driver

writei2c 1,(b4)

writei2c 2,(b5)

writei2c 3,(b6)

pause b15

inc b19

return

Now, B4 B5 and B6 is where the head is now, and B7 b8 and b9 are where we are going. B10 is how big of steps we should take to get there (this is speed). The line at issue here is the one in bold.

**if b4=b7 and b5=b8 and b6=b9 then ****return****endif**

If I use a value other than 1 in b10, the steps won't always add up to be an end number exactly and the line above will not ever be true. I need to code in something like this:

**if b4=b7 +or- 2 and b5=b8 +or- 2 and b6=b9 +or-2 then return**

Attachment | Size |
---|---|

playback_test_of_table_head_moves.bas | 5.48 KB |

## more...

I have found I have the same problem at the other end. You need to have room it seems for the min/max to catch stuff, I guess...

I have added this and everything is fixed. I still don't know why

lookupmove:

readtable b14,b7,b8,b9

if b7=1 then let b7=b10+1

endif

if b8=1 then let b8=b10+1

endif

if b9=1 then let b9=b10+1

endif

if b7>230 then let b7=254-b10

endif

if b8>230 then let b8=254-b10

endif

if b9>230 then let b9=254-b10

endif

return

## room

The picaxe first calculates the number and then checks the MIN MAX rules so

b1 = b1 - b10 MIN b7

will wrap around when b1 - b10 < 0 because the result (<0) is a large number that will be compared with b7.

e.g. b1=5 : b10=7 and b7 = 4

step 1) the picaxe calcs b1 - b10 = -2 => 253

step 2) compare result 253 with the number 4

step 3) concludes the outcome 253 > 4 and therefore doesn't need to be corrected to 4.

To make your code takes this into account with any speed setting on both ends of the byte, it should look like this.

let b0 = 255-b10

let b7 = b7 MIN b10 MAX b0

## simulator confirms - half of it

The mystery is almost put to bed. As am I.

This hard coded program demonstrates

b1 = 250 ' 250

b1 = b1 + 9 max 252 ' 252 (as expected)

b1 = 6 ' 6

b1 = b1 - 9 min 2 '

253(wrap around)Is it because internally the calculation is done in a word, but even words have a bottom value of zero?

## Best practise from now on

Do you min'ing and max'ing BEFORE your subtracting and adding.

b1 = 250 ' 250

b1 =

b1 max 243+ 9 ' 252b1 = 6 ' 6

b1 =

b1 min 11- 9 ' 2## word to ya calculator!

w1 = 65530 ' 65530

w1 = w1 + 9 max 65532 ' 3

w1 = 6 ' 6

w1 = w1 - 9 min 2 ' 65533

## Yup, that's it...

I added this to the "look up move routine" and it has solved all problems. It was the 1 and I don't know why.

lookupmove:

readtable b14,b7,b8,b9

if b7=1 then let b7=8

endif

if b8=1 then let b8=8

endif

if b9=1 then let b9=8

endif

return

## workaround

That workaround will only work for step size 7 or less. Perhaps if you said

if b7=1 then let b7=b10

you would regain a flexible stepsize again.

BUT, what if b7 urns out to be 2, or 3? or 4 or 5 or 6 or 7? I propose (still a workkaound):

if b7 < b10 then b7 = b10

which is equivalent to

b7 = b7 min b10

ting? I don't think so. See my other comments for a better loop that needs no work around (just crossed fingers).

## You are right, rik

I just went through a lot of debugging data and found something weird... You are right, the code will goto and include the min/max number... Just not always! I saw a bunch of numbers where the last move did not equal the step used and the number was indeed "caught" by the min/max and became the min/max. Other times, it is missed. It seems that if the "going to" number is 1 it has issues. I am going to try another run-through converting 1 into a number bigger than the step used and see what happens.

## Some data for you

I updated the post, there is a video showing the problem. Here is some sertxd data showing some numbers during the problem...

(This is stepping by 7)

<B4>38 <B5> 175 <b6> 64 'current servo pos

<B7> 1 <B8> 175 <b9> 64 'where we want to go --b8 and b9 have gotten there, just waiting for rotate to catch up

<B4>31 <B5> 175 <b6> 64

<B7> 1 <B8> 175 <b9> 64

<B4>24 <B5> 175 <b6> 64

<B7> 1 <B8> 175 <b9> 64

<B4>17 <B5> 175 <b6> 64

<B7> 1 <B8> 175 <b9> 64

<B4>10 <B5> 175 <b6> 64

<B7> 1 <B8> 175 <b9> 64

<B4>3 <B5> 175 <b6> 64

<B7> 1 <B8> 175 <b9> 64

<B4>252 <B5> 175 <b6> 64 '<<<< the loop starts over here. we want b7 to be one but it skips past and goes to 252.

<B7> 1 <B8> 175 <b9> 64

<B4>245 <B5> 175 <b6> 64

<B7> 1 <B8> 175 <b9> 64

<B4>238 <B5> 175 <b6> 64

<B7> 1 <B8> 175 <b9> 64

<B4>231 <B5> 175 <b6> 64

<B7> 1 <B8> 175 <b9> 64

<B4>224 <B5> 175 <b6> 64

<B7> 1 <B8> 175 <b9> 64

## it DOES get to 1

Only AFTER reaching one does it go "under". This tells me that your loop needs reprogramming indeed. Your code makes one more "loop for the road". Make it stop in time!

The do ... loop until construction elsewhere on this page will set you free.

*crosses fingers*

12next ›last »