The 0ILUS is a watercraft capable of navigating the SEA. Key requirements that the software had to handle were
Wireless communication (both processing and sending commands)
Controlling the boat via differential propulsion
Controlling the pump
Keeping track of fuel status
Indication of paired status
Since nearly all actions that the 0ILUS needed to take as well as all state transitions needed to be triggered by the arrival of wireless commands, it was decided to merge the 0ILUS' finite state machine with the wireless communication service into a single service (BoatXBeeService.c).
The state diagram for the 0ILUS is shown below. The three states of this FSM were as dictated by the Communication Committee: Unpaired, Waiting4FirstCommand, and Paired. In the Unpaired state, the 0ILUS could only respond to Pairing Request commands. After receiving such a command, the 0ILUS would save the address of the device that sent the request (and send all future commands to this address until becoming unpaired) and switch to the Waiting4Command state. In this state, the 0ILUS would send Pairing ACK commands every 200 ms until receiving an action command (either a Control command or a Refuel command), at which point it would transition to the Paired State, where all subsequent action commands were processed and the appropriate event(s) were posted to the appropriate service(s) . After processing such a command, the 0ILUS would send a Fuel Status command back to the device that sent the action command. The 0ILUS would stay in the Paired state until not receiving an action command for 4 seconds (as dictated by the Communication Committee), at which point the 0ILUS would turn off all motors and return to the Unpaired state.
Both drive motors were controlled by DriveMotorService.c. This service received events to drive either motor, with the desired duty cycle as the event parameter. Nonzero duty cycles were only set if the 0ILUS had fuel (FuelService.c had a getter function that reported whether or not the 0ILUS had fuel). Once a nonzero duty cycle was set, the service posted an event to FuelService.c indicating that fuel was being consumed. Once the duty cycle was set to zero, an event was posted to FuelService.c indicating that fuel was no longer being used. The service could also turn off both motors if an event was received that indicated that the 0ILUS was out of fuel. In addition, this service had getter functions that reported whether a motor was on (used in FuelService.c).
PumpService.c used PWM to modify the flowrate from the pump. Upon receiving an event to turn on the pump, the duty cycle was set to 50%. Events to increase or decrease the flowrate changed the duty cycle in 5% increments (but only while the pump was already on). Similar to DriveMotorService.c, the pump could only be turned on if the 0ILS had fuel and was turned off when the 0ILUS ran out of fuel. Also similar to DriveMotorService.c, turning on/off the pump sent events to FuelService.c to indicate the start/stop of fuel consumption. The service additionally had a getter function that reported whether the pump was on (used in FuelService.c).
FuelService.c utilized a framework timer to monitor all fuel consumption of the 0ILUS. Whenever an event was received indicating that fuel was being consumed, the Fuel Timer was started (if the timer had already been started, then the event was ignored). If an event to stop the timer was received, the timer would only be stopped if all motors were turned off (verified by calling the getter functions in DriveMotorService.c and PumpService.c). If fuel ran out, then the service posted an event to DriveMotorService.c and PumpService.c to stop all motors. When the Fuel Timer was not running, the remaining time was stored in a variable. Whenever a refuel command was received, this variable was updated accordingly and used to set the Fuel Timer. The variable was capped at 15000 ms since an 0ILUS could not hold more than 15 seconds of fuel. This service had a getter function that would report the value of this variable (called by BoatXBeeService.c when sending Fuel Status commands). This service also had another getter function that would report whether there was any fuel left (used by DriveMotorService.c and PumpService.c to determine whether motors could be turned on).
To indicate pairing status, a block-letter 1 was 3D printed and mounted to a servo. If the 1 was horizontal, then the boat was unpaired. If the 1 was vertical, then the boat was paired. The service that handled the simple PWM switching was PairedServoService.c.