Zoot
08-31-2008, 05:37 AM
Hey all -- I'm reading encoder info into a BS2p40. I'm pretty sure I've got my math right, but I'm getting garbage (values all over the place) on my theta.
The encoders are delivering accurate ticks info. See relevant code for comments. In the case of figuring theta (rads to brads) I'm working fixed point (256.256). If I get this working right, I may use some of Tracy Allen's long division/mult. to get better resolution, but as it stands, where I might expect to get 0 change in theta sometimes because of the resolution, I get swings all over the place. The raw dist (distL + distR/2) and in a straight line it's pretty much dead nuts on. The posx and posy are off because the theta jumps all over.
Note that the encoder deliver the signed word *change* since the host last requested a sample; the actual range is about -40 to 40 each sample MAX, with average being around -15 to 15).
Any suggestions, comments, mistakes pointed out, are welcome.
ioWord VAR Word
buffer0 VAR Word
buff0 VAR buffer0.LOWBYTE
buff1 VAR buffer0.HIGHBYTE
buffer1 VAR Word
buff2 VAR buffer1.LOWBYTE
buff3 VAR buffer1.HIGHBYTE
buffer2 VAR Word
buff4 VAR buffer2.LOWBYTE
buff5 VAR buffer2.HIGHBYTE
buffer3 VAR Word
buff6 VAR buffer3.LOWBYTE
buff7 VAR buffer3.HIGHBYTE
buffer4 VAR Word
buff8 VAR buffer4.LOWBYTE
buff9 VAR buffer4.HIGHBYTE
motos VAR Word
motoL VAR motos.LOWBYTE
motoR VAR motos.HIGHBYTE
moto VAR motoL
accL VAR Byte
accR VAR Byte
ioByte VAR Byte
SPaddr VAR Byte
i VAR Nib
sign VAR Bit
sign2 VAR Bit
WHEEL_BASE_CM CON 296' in 10th cms
'WHEEL_BASE CON WHEEL_BASE_CM * CMtoTicks_HM >> 16 + 1
WHEEL_BASE CON 114 ' in ticks 113.664
WHEEL_BASE_HALF CON WHEEL_BASE + 1 >> 1 ' FOR ROUNDing
'WHEEL_BASE_HM CON $10000 + WHEEL_BASE_HALF / WHEEL_BASE '431.651315789474
' 1 / wheel_base * $10000 = 576.576576576577 with **
WHEEL_BASE_HM CON 576' for using ** instead of / WHEEL_BASE
'convert to brads 40.7436654315252 '128/PI 256/TWOPI '6.283185307
RadsToBrads_M CON 41 ' 256/2PI = with *
RadsToBrads_HM CON 48737 ' 256/2PI = 4.7436654315252 * $10000 = 48,736.8577204355 with ** + hi
RadsToBrads_Hi CON 04 ' equiv to -- 256/2PI -- x ** .74 + ( x * 4 )
RadsToBrads_Hi256 CON RadsToBrads_Hi * 256 ' but we're working fixed decimal place in 256ths
' / base * toBrads = 0.358457079035800253378378378378 * $10000 with ** 23491.843131690205405405405405381
DivWBtoBrads_HM CON 23492
'--------------------------------------
'preloads signed encoder ticks change since last sample
'buffer0 -- signed Word -- L ticks change since last reading
'buffer1 -- signed Word -- R ticks change since last reading
GOSUB Get_Odometry
' dist = (left_dist + right_dist) / 2.0;
buffer2 = buffer0 + buffer1 ' add change since last reading
sign = buffer2.BIT15 ' save sign
buffer2 = ABS buffer2 + 1 >> 1 ' /2 with rounding
buffer2 = -sign ^ buffer2 + sign ' restore sign
' theta += (r_dist - l_dist) / WHEEL_BASE;
buffer3 = buffer1 - buffer0 ' note that distances AND wheel base are in units of "ticks"
sign = buffer3.BIT15 ' save sign
buffer3 = ABS buffer3 << 8 ' work in 256ths, i.e., fixed decimal point number from -127.255 to 127.255
buffer3 = buffer3 ** DivWBtoBrads_HM ' equiv to below two statements, in one single high-multiply ...
'above equivalent to:
' ( ( r_dist - l_dist ) / wheelbase ) * ( 256/TWOPI )
'buffer3 = buffer3 ** WHEEL_BASE_HM ' / wheel_base
'buffer3 = buffer3 ** RadsToBrads_HM + ( buffer3 * RadsToBrads_Hi256 ) 'convert rads to brads * 40.7436654315252 or 128/PI 256/TWOPI (6.283185307)
buffer3 = -sign ^ buffer3 + sign ' restore sign -- signed theta change in brads, fixed decimal point
GET theta, Word ioWord ' add to running theta (256ths)
ioWord = ioWord + buffer3
PUT theta_LSB, ioWord.BYTE0
PUT theta_MSB, ioWord.BYTE1
ioByte = ioWord + 128 >> 8 ' round to whole brads for sine and cosine ops
' X_pos += inches * COS(theta);
' Y_pos += inches * SIN(theta);
sign = buffer2.BIT15 ' buffer2 is distance traveled since last sample from first steps
buffer2 = ABS buffer2
buffer0 = COS ioByte ' x pos
sign2 = sign ^ buffer0.BIT15 ' save sign, XOR with dist sign
buffer0 = ABS buffer0 */ 516 ' normalize -- sin/127 = x/256 for use with */
buffer0 = buffer2 * buffer0 MAX $FF7F + 128 >> 8 ' equiv to */ with rounding
buffer0 = -sign2 ^ buffer0 + sign2 ' restore sign
buffer1 = SIN ioByte ' y pos cos
sign2 = sign ^ buffer1.BIT15 ' save sign, XOR with dist sign
buffer1 = ABS buffer1 << 1 ' * 2 = normalize -- sin/128 = x/256 for use with */
buffer1 = buffer2 * buffer1 + 128 >> 8 ' equiv to */ with rounding
buffer1 = -sign2 ^ buffer1 + sign2 ' restore sign
GET posx, Word ioWord ' add to running x position
ioWord = ioWord + buffer0
PUT posx_LSB, ioWord.BYTE0
PUT posx_MSB, ioWord.BYTE1
GET posy, Word ioWord ' add to running y position
ioWord = ioWord + buffer1
PUT posy_LSB, ioWord.BYTE0
PUT posy_MSB, ioWord.BYTE1
'--------------------------------------
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
When the going gets weird, the weird turn pro. -- HST
1uffakind.com/robots/povBitMapBuilder.php (http://1uffakind.com/robots/povBitMapBuilder.php)
1uffakind.com/robots/resistorLadder.php (http://1uffakind.com/robots/resistorLadder.php)
Post Edited (Zoot) : 9/7/2008 2:26:10 PM GMT
The encoders are delivering accurate ticks info. See relevant code for comments. In the case of figuring theta (rads to brads) I'm working fixed point (256.256). If I get this working right, I may use some of Tracy Allen's long division/mult. to get better resolution, but as it stands, where I might expect to get 0 change in theta sometimes because of the resolution, I get swings all over the place. The raw dist (distL + distR/2) and in a straight line it's pretty much dead nuts on. The posx and posy are off because the theta jumps all over.
Note that the encoder deliver the signed word *change* since the host last requested a sample; the actual range is about -40 to 40 each sample MAX, with average being around -15 to 15).
Any suggestions, comments, mistakes pointed out, are welcome.
ioWord VAR Word
buffer0 VAR Word
buff0 VAR buffer0.LOWBYTE
buff1 VAR buffer0.HIGHBYTE
buffer1 VAR Word
buff2 VAR buffer1.LOWBYTE
buff3 VAR buffer1.HIGHBYTE
buffer2 VAR Word
buff4 VAR buffer2.LOWBYTE
buff5 VAR buffer2.HIGHBYTE
buffer3 VAR Word
buff6 VAR buffer3.LOWBYTE
buff7 VAR buffer3.HIGHBYTE
buffer4 VAR Word
buff8 VAR buffer4.LOWBYTE
buff9 VAR buffer4.HIGHBYTE
motos VAR Word
motoL VAR motos.LOWBYTE
motoR VAR motos.HIGHBYTE
moto VAR motoL
accL VAR Byte
accR VAR Byte
ioByte VAR Byte
SPaddr VAR Byte
i VAR Nib
sign VAR Bit
sign2 VAR Bit
WHEEL_BASE_CM CON 296' in 10th cms
'WHEEL_BASE CON WHEEL_BASE_CM * CMtoTicks_HM >> 16 + 1
WHEEL_BASE CON 114 ' in ticks 113.664
WHEEL_BASE_HALF CON WHEEL_BASE + 1 >> 1 ' FOR ROUNDing
'WHEEL_BASE_HM CON $10000 + WHEEL_BASE_HALF / WHEEL_BASE '431.651315789474
' 1 / wheel_base * $10000 = 576.576576576577 with **
WHEEL_BASE_HM CON 576' for using ** instead of / WHEEL_BASE
'convert to brads 40.7436654315252 '128/PI 256/TWOPI '6.283185307
RadsToBrads_M CON 41 ' 256/2PI = with *
RadsToBrads_HM CON 48737 ' 256/2PI = 4.7436654315252 * $10000 = 48,736.8577204355 with ** + hi
RadsToBrads_Hi CON 04 ' equiv to -- 256/2PI -- x ** .74 + ( x * 4 )
RadsToBrads_Hi256 CON RadsToBrads_Hi * 256 ' but we're working fixed decimal place in 256ths
' / base * toBrads = 0.358457079035800253378378378378 * $10000 with ** 23491.843131690205405405405405381
DivWBtoBrads_HM CON 23492
'--------------------------------------
'preloads signed encoder ticks change since last sample
'buffer0 -- signed Word -- L ticks change since last reading
'buffer1 -- signed Word -- R ticks change since last reading
GOSUB Get_Odometry
' dist = (left_dist + right_dist) / 2.0;
buffer2 = buffer0 + buffer1 ' add change since last reading
sign = buffer2.BIT15 ' save sign
buffer2 = ABS buffer2 + 1 >> 1 ' /2 with rounding
buffer2 = -sign ^ buffer2 + sign ' restore sign
' theta += (r_dist - l_dist) / WHEEL_BASE;
buffer3 = buffer1 - buffer0 ' note that distances AND wheel base are in units of "ticks"
sign = buffer3.BIT15 ' save sign
buffer3 = ABS buffer3 << 8 ' work in 256ths, i.e., fixed decimal point number from -127.255 to 127.255
buffer3 = buffer3 ** DivWBtoBrads_HM ' equiv to below two statements, in one single high-multiply ...
'above equivalent to:
' ( ( r_dist - l_dist ) / wheelbase ) * ( 256/TWOPI )
'buffer3 = buffer3 ** WHEEL_BASE_HM ' / wheel_base
'buffer3 = buffer3 ** RadsToBrads_HM + ( buffer3 * RadsToBrads_Hi256 ) 'convert rads to brads * 40.7436654315252 or 128/PI 256/TWOPI (6.283185307)
buffer3 = -sign ^ buffer3 + sign ' restore sign -- signed theta change in brads, fixed decimal point
GET theta, Word ioWord ' add to running theta (256ths)
ioWord = ioWord + buffer3
PUT theta_LSB, ioWord.BYTE0
PUT theta_MSB, ioWord.BYTE1
ioByte = ioWord + 128 >> 8 ' round to whole brads for sine and cosine ops
' X_pos += inches * COS(theta);
' Y_pos += inches * SIN(theta);
sign = buffer2.BIT15 ' buffer2 is distance traveled since last sample from first steps
buffer2 = ABS buffer2
buffer0 = COS ioByte ' x pos
sign2 = sign ^ buffer0.BIT15 ' save sign, XOR with dist sign
buffer0 = ABS buffer0 */ 516 ' normalize -- sin/127 = x/256 for use with */
buffer0 = buffer2 * buffer0 MAX $FF7F + 128 >> 8 ' equiv to */ with rounding
buffer0 = -sign2 ^ buffer0 + sign2 ' restore sign
buffer1 = SIN ioByte ' y pos cos
sign2 = sign ^ buffer1.BIT15 ' save sign, XOR with dist sign
buffer1 = ABS buffer1 << 1 ' * 2 = normalize -- sin/128 = x/256 for use with */
buffer1 = buffer2 * buffer1 + 128 >> 8 ' equiv to */ with rounding
buffer1 = -sign2 ^ buffer1 + sign2 ' restore sign
GET posx, Word ioWord ' add to running x position
ioWord = ioWord + buffer0
PUT posx_LSB, ioWord.BYTE0
PUT posx_MSB, ioWord.BYTE1
GET posy, Word ioWord ' add to running y position
ioWord = ioWord + buffer1
PUT posy_LSB, ioWord.BYTE0
PUT posy_MSB, ioWord.BYTE1
'--------------------------------------
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
When the going gets weird, the weird turn pro. -- HST
1uffakind.com/robots/povBitMapBuilder.php (http://1uffakind.com/robots/povBitMapBuilder.php)
1uffakind.com/robots/resistorLadder.php (http://1uffakind.com/robots/resistorLadder.php)
Post Edited (Zoot) : 9/7/2008 2:26:10 PM GMT