I am using the 24V Devantech motor set, that comes with the Devantech MD49 motor controller. I am using the tx and rx of an Arduino uno to send control signals/receive information to/from the MD49.
I am trying to use the encoders to move the motors a specific distance, however my code is acting buggy and I’m not sure exactly how to solve it. Basically, I am sending the get encoder signal, reading the 4 byte response, and bit shifting to obtain a 32 bit integer result, just like the specification recommends. You may find my least buggy version of the code below: (Note, I have stripped the code of everything but the encoder reading functionality, to focus on the issue)
#define CMD (byte)0x00
#define GET_ENC1 0x23
#define ENC_RESET 0x35
// reads the value of encoder 1 into an unsigned 32 bit int
uint32_t encoder1() {
char chars[4];
uint8_t ints[4];
uint32_t encoder = 0;
Serial.write(CMD);
Serial.write(GET_ENC1);
if (Serial.available() > 0) {
Serial.readBytes(chars, 4);
for(int i=0; i<4; i++)
ints i] = (uint8_t) chars i];
encoder = ((ints[0] << 24) +
(ints[1] << 16) +
(ints[2] << 8) +
(ints[3] << 0));
return encoder;
}
else
return NULL;
}
void enc_reset() {
Serial.write(CMD);
Serial.write(ENC_RESET);
}
void setup() {
Serial.begin(9600);
enc_reset();
}
void loop() {
Serial.print(encoder1());
}
It works fine most of the time, but about 1 in every 10 times running the code, the returned integer value jumps by orders of magnitude, rather than by single integer values, as the motor spins.
I did some debugging and when printing the individual byte values to the serial monitor (i.e. those stored in “ints” in the code above), I noticed it appeared to be a timing issue with the sampling of these bytes, so the bytes would be shifted out of place.
For example, an encoder value of [0, 2, 0, 234], when incorrect, may be sampled as [2, 0, 234, 0] or [233, 0, 2, 0], etc. I have made sure that the code is written so that the only code in between the serial write of GET_ENC1 and the serial read is the Serial.available() function, which is routinely used (and written for the purpose of) being called right before a read, and shouldn’t throw off the timing. As well, I have also done this using a for loop with Serial.read() rather than Serial.readBytes(), but the result has been identical. It works ~90% of the time, but every now and again, the bytes are shifted, ruining the functionality of the encoder.
I have not found any solutions to (or even mentions of) this problem online. By the specification, it appears that only the 4 bytes are sent from the MD49, and that there is no checksum.
Is there anything else I can do, or any way I can get around this problem. It really defeats the purpose of having bought these motors if the encoders are unreliable, and thus useless.
Thanks for your help