Low precision with Devantech MD23 encoders
Cats92
Posts: 149
It seems hard to obtain precise odometry with Devantech MD23 encoders
I tried with Chris Clarke drivers and obtain less than 5 % precision using encoders (or time)
Here is the program used , how can i improve it ?
Thanks for help
'TestMD23encoder.spin
'Uses simplified I2C for Devantech - Chris Clarke
CON 'constants
_CLKMODE = xtal1 + pll16x
_xinfreq = 5_000_000
'pin definitions
i2cSCLLine = 13 'scl on device at A13
i2cSDALine = 12 'sda on device at A12
'md23 address and register definitions
MD23_ADDR = $B0
SPEED1_REG = 0
SPEED2_REG = 1
ENC1A_REG = 2
ENC1B_REG = 3
ENC1C_REG = 4
ENC1D_REG = 5
ENC2A_REG = 6
ENC2B_REG = 7
ENC2C_REG = 8
ENC2D_REG = 9
MOT_CUR1_REG = 11
MOT_CUR2_REG = 12
SOFT_VER_REG = 13
COMMAND_REG = 16
VAR
long encoder1,encoder2 ,delay1,delay2,speed1
byte version
Long stack1[noparse][[/noparse]50]
OBJ 'defines external modules to be included, so the can be called, i.e i2cobject.
i2cObject : "i2cObject" 'i2c routines Chris Clarke
PUB main
delay1:= clkfreq /1000
delay2:= clkfreq/100
speed1:=158
i2cObject.init(i2cSDALine,i2cSCLLine) 'Passes the I2C pin details to the I2c routines in "i2cobject"
i2cObject.Writelocation(MD23_ADDR,COMMAND_REG,32) 'command of 32 to command reg clears encoder count
run1(325) ' about 324 for one turn Uses encoder
'run2(130) ' about 130 for one turn Uses time
stop
PUB run1 (maxtick) 'low precision > 5% position error
'runs until encoder=maxtick
i2cObject.Writelocation(MD23_ADDR,COMMAND_REG,32)
i2cObject.Writelocation(MD23_ADDR,COMMAND_REG,50)
i2cObject.Writelocation(MD23_ADDR,SPEED1_REG,speed1) 'motor1 slow speed forwards
repeat while encoder1 <maxtick
i2cObject.Writelocation(MD23_ADDR,SPEED1_REG,speed1)
encoder1 := (i2cObject.readLocation(MD23_ADDR,ENC1A_REG))<<24 'grab enc1 count high bit, must be first(sample bit)
encoder1 += (i2cObject.readLocation(MD23_ADDR,ENC1B_REG))<<16
encoder1 += (i2cObject.readLocation(MD23_ADDR,ENC1C_REG))<<8
encoder1 += i2cObject.readLocation(MD23_ADDR,ENC1D_REG)
waitcnt(delay1 + cnt) 'delay
PUB run2 (Ntimes) | time2 'low precision > 5% position error
'runs during time = delay*Ntimes
time2:=cnt
i2cObject.Writelocation(MD23_ADDR,COMMAND_REG,32)
i2cObject.Writelocation(MD23_ADDR,COMMAND_REG,50)
i2cObject.Writelocation(MD23_ADDR,SPEED1_REG,speed1) 'motor1 slow speed forwards
waitcnt(time2+=delay2 * Ntimes )
PUB stop
i2cObject.Writelocation(MD23_ADDR,COMMAND_REG,32)
i2cObject.Writelocation(MD23_ADDR,SPEED1_REG,128) 'motor1 stop speed 0
waitcnt(clkfreq/10 + cnt) 'delay
I tried with Chris Clarke drivers and obtain less than 5 % precision using encoders (or time)
Here is the program used , how can i improve it ?
Thanks for help
'TestMD23encoder.spin
'Uses simplified I2C for Devantech - Chris Clarke
CON 'constants
_CLKMODE = xtal1 + pll16x
_xinfreq = 5_000_000
'pin definitions
i2cSCLLine = 13 'scl on device at A13
i2cSDALine = 12 'sda on device at A12
'md23 address and register definitions
MD23_ADDR = $B0
SPEED1_REG = 0
SPEED2_REG = 1
ENC1A_REG = 2
ENC1B_REG = 3
ENC1C_REG = 4
ENC1D_REG = 5
ENC2A_REG = 6
ENC2B_REG = 7
ENC2C_REG = 8
ENC2D_REG = 9
MOT_CUR1_REG = 11
MOT_CUR2_REG = 12
SOFT_VER_REG = 13
COMMAND_REG = 16
VAR
long encoder1,encoder2 ,delay1,delay2,speed1
byte version
Long stack1[noparse][[/noparse]50]
OBJ 'defines external modules to be included, so the can be called, i.e i2cobject.
i2cObject : "i2cObject" 'i2c routines Chris Clarke
PUB main
delay1:= clkfreq /1000
delay2:= clkfreq/100
speed1:=158
i2cObject.init(i2cSDALine,i2cSCLLine) 'Passes the I2C pin details to the I2c routines in "i2cobject"
i2cObject.Writelocation(MD23_ADDR,COMMAND_REG,32) 'command of 32 to command reg clears encoder count
run1(325) ' about 324 for one turn Uses encoder
'run2(130) ' about 130 for one turn Uses time
stop
PUB run1 (maxtick) 'low precision > 5% position error
'runs until encoder=maxtick
i2cObject.Writelocation(MD23_ADDR,COMMAND_REG,32)
i2cObject.Writelocation(MD23_ADDR,COMMAND_REG,50)
i2cObject.Writelocation(MD23_ADDR,SPEED1_REG,speed1) 'motor1 slow speed forwards
repeat while encoder1 <maxtick
i2cObject.Writelocation(MD23_ADDR,SPEED1_REG,speed1)
encoder1 := (i2cObject.readLocation(MD23_ADDR,ENC1A_REG))<<24 'grab enc1 count high bit, must be first(sample bit)
encoder1 += (i2cObject.readLocation(MD23_ADDR,ENC1B_REG))<<16
encoder1 += (i2cObject.readLocation(MD23_ADDR,ENC1C_REG))<<8
encoder1 += i2cObject.readLocation(MD23_ADDR,ENC1D_REG)
waitcnt(delay1 + cnt) 'delay
PUB run2 (Ntimes) | time2 'low precision > 5% position error
'runs during time = delay*Ntimes
time2:=cnt
i2cObject.Writelocation(MD23_ADDR,COMMAND_REG,32)
i2cObject.Writelocation(MD23_ADDR,COMMAND_REG,50)
i2cObject.Writelocation(MD23_ADDR,SPEED1_REG,speed1) 'motor1 slow speed forwards
waitcnt(time2+=delay2 * Ntimes )
PUB stop
i2cObject.Writelocation(MD23_ADDR,COMMAND_REG,32)
i2cObject.Writelocation(MD23_ADDR,SPEED1_REG,128) 'motor1 stop speed 0
waitcnt(clkfreq/10 + cnt) 'delay
Comments
Main issue for me was managing the electrical noise from the motors and its interference with other I2C lines.
Other than that I am happy.
James
I also tried different delays in the loop reading the encoders , without result.
Strangely , functions for forward, right, left, backwards moves work rather well when tested alone (precision put aside) , but if they are used to follow a rectangular course the bot stops after 2 or 3 moves. Perhaps it comes from the same origin ?
Jean Paul