Overview

The firmware is responsible for interacting with the physical hardware to make the robot move (i.e. motors, limit switches, buttons). To accomplish this through robust serial communication, motor control, and homing sequences.

Serial communication parses every incoming string into a command type and then values associated with that command. For example, as message like “M,0,0,0,0,1,50” will be parsed as “move to (0,0,0) with suction on and servo at 50 degrees”. A message is always composed of a char and 6 floats, even if the command doesn’t require six values. Our objective types include MOVE, HOME, SUCCESS, and FAIL. Move and home both move the robot and home it, respectively, while success and fail reports back whether the current robot state matches the intended robot state command sent from the control terminal. If they match, we send a success signal back so we are free to accept new objectives.

We are using the very popular AccelStepper library to control our stepper motors. The library functions have to called in a non-blocking manner, which means they should be called pretty quickly inside the main control loop and avoid using delays. So when it receives and move command, it is parsing the coordinates and calling stepper.moveTo(position) until it reaches the desired position. AccelStepper’s .moveTo() function compares the input argument against the current stepper position at every call, and stops moving when they are the same. This is why it’s ok to call the same function repeatedly with the same position arguments.

Homing also has to be non-blocking, not only because it involves moving the motors, but because any delay from reading limit switch data could catastrophically destroy the robot as it will continue to try and move where it is physically incapable of going. This is solved with a while loop inside our homing function that continuously moves the motors in the desired direction and stopping them when its respective limit switch is hit.

jenga