The Art of Code Instrumentation
/I spent a chunk of today getting an ESP32 version of the Hull Pixelbot software running. Snag was, it was crashing when it tried to fire up the motors drivers. Each motor is controlled by four signals which drive the coils which turn the motor output. So I need eight outputs for two motors. But half way through turning these on the program exploded. I could have hooked up a debugger and stepped through the code but this is quite a slow business. So instead I did this:
void initMotorHardware()
{
Serial.printf("Motor initialisation 1\n");
pinMode(motorSettings.lpin1, OUTPUT);
Serial.printf("Motor initialisation 2\n");
pinMode(motorSettings.lpin2, OUTPUT);
Serial.printf("Motor initialisation 3\n");
pinMode(motorSettings.lpin3, OUTPUT);
Serial.printf("Motor initialisation 4\n");
pinMode(motorSettings.lpin4, OUTPUT);
Serial.printf("Motor initialisation 5\n");
pinMode(motorSettings.rpin1, OUTPUT);
Serial.printf("Motor initialisation 6\n");
pinMode(motorSettings.rpin2, OUTPUT);
Serial.printf("Motor initialisation 7\n");
pinMode(motorSettings.rpin3, OUTPUT);
Serial.printf("Motor initialisation 8\n");
pinMode(motorSettings.rpin4, OUTPUT);
Serial.printf("Motor initialisation 9\n");
leftTimer = timerBegin(0, 80, true);
Serial.printf("Motor initialisation 10\n");
timerAttachInterrupt(leftTimer, &onLeft, true);
Serial.printf("Motor initialisation 11\n");
rightTimer = timerBegin(1, 80, true);
Serial.printf("Motor initialisation 12\n");
timerAttachInterrupt(rightTimer, &onRight, true);
Serial.printf("Motor initialisation 13\n");
}
The posh name for this is “code instrumentation”. I call it “lobbing in lots of print statements”. When I ran the program the device crashed just after step 6. So I instantly knew which of the pins I really shouldn’t be using as an output (it turned out to be one which was connected to the onboard flash memory). I did a bit of digging and found some workable connections and I got all 13 messages. So I discarded all the changes on the source code file to get rid of all the print statements and got on with my life.
I could have wired up the in-circuit debugger, rebuilt all the code for debugging, downloaded the code into the device and then stepped through it until it broke. But I reckon this is quicker. If you have a tricky problem it is worth remembering that adding print statements that help you figure out what is going on is a good idea. You can even (whisper this) do horrible things like print out messages in interrupt handlers. Anything that helps you work out what’s going on is something you can do.
The next step in the project is to make builds for the different devices select different pin assignments. It might also be fun to create a flag variable that is checked after reboot so that the device can produce useful diagnostic information when it fails, rather than just stopping and leaving it to the user to figure out what went wrong. But that sounds a bit like scope creep to me, so I’ll not do it just yet.