Here is the JOYSTICK code, almost unchanged from mbot_firmware.ino, that causes the problem. In the code I will eventually use, I pass a third parameter, runtime, that specifies the # of ms that the motors run, but in this simplified version, I just define runtime locally. This code runs properly when called sequentially about 8 times and then fails (same if I pass the 3rd parameter- runtime):
case JOYSTICK:{
int leftSpeed = readShort(6);
dc.reset(M1);
dc.run(leftSpeed);
int rightSpeed = readShort(8);
dc.reset(M2);
dc.run(rightSpeed);
int runtime = 2000; //run motors for 2 secs
delay(runtime);
dc.reset(M1);
dc.run(0);
dc.reset(M2);
dc.run(0);
}
break;
On the chance that delay() is not blocking correctly, I looked at another blocking routine - TONE. buzzer.tone(hz,tone_time) blocks for tone_time while it is making the tone. And one can call TONE sequentially as many times as you like and it never blocks. So I looked at how that was implemented in MeBuzzer.cpp in the Makeblock library. Interesting! It uses a command I had never used: wdt_reset().
void MeBuzzer::tone(uint16_t frequency, uint32_t duration)
{
int period = 1000000L / frequency;
int pulse = period / 2;
pinMode(buzzer_pin, OUTPUT);
for (long i = 0; i < duration * 1000L; i += period)
{
digitalWrite(buzzer_pin, HIGH);
delayMicroseconds(pulse);
digitalWrite(buzzer_pin, LOW);
delayMicroseconds(pulse);
wdt_reset();
}
}
Could that be a way of blocking serial transfer? So I used this in the code above instead of delay(). To make that work, I had to load #include <avr/wdt.h> in the mbot firmware (normally it is loaded just in MeBuzzer.cpp), but then it compiled and ran fine.
int period = 100; // length of delay in each execution of the loop, in microseconds
uint32_t duration = 2000; //delay for a total of 2 secs
for (long i = 0; i < duration * 10L; i += period) //so a total of 2000 * 10 = 20000 loops
{
delayMicroseconds(period);
wdt_reset();
}
This code works fine as a delay in JOYSTICK but still fails to work in a sequential call to more than about 15 commands of “run forward”. Also, I tried this using both the serial cable connection to the mbot or the wireless 2.4GHz connection, and it works the same.
Is it possible that serial.read() keeps reading the commands from the computer even during the delay. Can that process be paused? Is that what wdt_reset() does in TONE?
Thanks for taking the time to look at this!