Software:

The software was the core of this project, bringing together all of the various components implemented for the various functions necessary for the performance of our Automated Bartender. We choose to keep all of the software written in assembly, as there was no complexity involved that would have proven to be simpler if implemented in C, thus it was easier to keep everything in a single language.

The software was composed of many separate functions, each of which responded to select inputs from the hardware. The code was essentially an endless loop, with interrupts coming from a user via the keypad or controller, or interrupts from sensors resulting in the execution of various functions as necessary. Controls to insure a robust design were also implemented. For example, cups placed in front of the sensors to be sent down the conveyor belt without valid drink selections or commands to pour drinks while in manual mode when a cup wasn't underneath the current solenoid were ignored. Our software also was designed to remain as flexible as possible and provide good code reuse. For example, separate functions were not written for each solenoid, but instead a single function was developed that would read in the current location of the cup relative to the dispenser, since this was being kept track of for other purposes as well, and activate the appropriate solenoid.

We had to consider real time issues during our implementation of the Automated Bartender. The main issue was with respect to the proper operation of the solenoids. During the execution of preprogrammed drinks, the software would execute a command for the stepper motor to begin moving and would sometimes follow that with a call for the proper solenoid to open. Obviously it takes some amount of time for the motor to move the end of the tube for the proper solenoid into position, so we had to add a delay loop after any stepper motor operation to make up for the time spent turning. We also used delay timers to control the duration of time that the solenoids were to remain open for.

We used level-triggered interrupts to received information from the sensors, keypad, and NES controller. We then used edge-triggered interrupts to recognize the EOC signal from the ADC. Our external devices, the keypad and the NES controller threw the same interrupt, so we would poll each to see which had thrown the interrupt in order to take appropriate action. Initially we had priority given to interrupts from the sensors since them sensing a glass before it crashed or fell off of the conveyor belt was more important than getting an interrupt from an external input device. However, the EOC was being thrown so quickly compared to the interrupts from either the keypad or the NES controller that behavior was erratic and often times keypad and NES interrupts would not be recognized. Reversing the priority of the interrupts proved successful and data was still being received from the sensors quickly enough that the glass was seen and stopped before it passed the sensors.

Click here for a high level visual of our software design!

The University of Michigan, EECS 373 - Winter Semester 2006