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
I saw you post this code earlier this week and I felt the urge to rewrite it. This does not solve you problem, but it might make it a bit more clear.
servocalc: do until b4=b7 and b5=b8 and b6=b9 ’ walk some more, until where you are = where you want to be if b4<b7 then let b4=b4+b10 max b7 endif if b4>b7 then let b4=b4-b10 min b7 endif
if b5<b8 then let b5=b5+b10 max b8 endif ’ why would this b5 overshoot b8? if b5>b8 then let b5=b5-b10 min b8 endif
if b6<b9 then let b6=b6+b10 max b9 endif if b6>b9 then let b6=b6-b10 min b9 endif gosub servomove loop return
Perhaps b5 would get out of whack when it overshoot 255. The max function would not notice. I doubt you are using values dangerously close the edge of the byte though.
I put a sertxd into the main calc loop and watched it go by during the whole loop. If I had a step of say 3, it would keep adding 3 to say b5 and it would not pass the max of b8. However, it would not equal b8 unless for some reason there was b8 was exactly devisable by 3. Let’s say the max was 20 and the start number was 0… It would be 0,3,6,9,12,15,18 and it would stop there. It would not add 3 more to the 18 because it would exceed the max of 20. It WILL NOT simply add 2 to get upto and including the max number. Again, this is the issue – 18 does not equal the max number and thus the final statement will never be true.
I do like however your do until/ loop system --I think it is more “programmerish” than a for/next loop.
In my simulator (!) I cannot reproduce your situation. This code simulates just fine as a picaxe28x1:
b4 = 2 b7 = 9 b5 = 2 b8 = 9 b6 = 2 b9 = 9 b10 = 3
gosub servocalc pause 2000 end ’ ALL bytes b4-b9 come out this end as 9 after three loops through the servocalc
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: ’ let’s pretend stuff happens here return
One way around Picaxe’s limited arithmetics could be something like this: symbol LIMIT = 20 symbol HYSTERESIS = 3 ’ +/- 3 pause 1000 b0 = 17 ’ Value to compare
’ Check if we were close enough to LIMIT if b1 <= HYSTERESIS then ’ Do something like … sound 0, (120,50) ’ … beep endif
The code above is a workaround for missing negative values and abs function. It of course cuts the usable value range by half (if b1 > 127). The idea is that if b1 = b0 - LIMIT results to negative value ( >127 means 8th bit is set which means negative value in 8-bit arithmetics) then we turn it to positive value. Getting the positive value is simply subtracting the result from 256 (i.e. how much did the original subtraction “underflow”).
The code above isn’t really tested so expect bugs. It seemed to run just fine in the simulator though
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.
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.
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
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).