Automated Drink Mixer

Abstract

The automated drink mixer takes orders from a push-button menu, and moves a regular 16-ounce glass under a series of inverted bottles while dispensing specified amounts of mixers to make perfect non-alcoholic beverages.

Introduction

            If you’ve ever been to a crowded bar or restaurant and waited a long time just to get served an ill-prepared drink by someone that you still have to tip afterwards, then you understand the potential benefits of having an automated drink mixer. With this device, a user simply has to place his or her glass on the specified starting location, select a drink from the push-button menu, and wait less than 30 seconds for the beverage to be dispensed and the glass to be returned to its initial position. Drinks are made efficiently and consistently, as each drink is prepared the same way every time. In choosing this project, we wanted to do something both fun and relevant, with clear functionality in a real-world application.

            For this project, we used a bidirectional DC motor and solenoid valves to turn an ordinary Lazy Susan into a rotating platform system that could move a glass under inverted bottles and dispense liquids in a controlled manner, in order to make mixed drinks. Movement and liquid flow were controlled by an Atmel Mega1984 microcontroller, which was programmed using C software written in AVR Studio4, and the position of the glass was tracked by an Infrared (IR) sensor and feeback control loop. Drink orders are placed via a push-button menu. Ultimately, we were able to successfully implement our design for a menu consisting of five different non-alcoholic drinks: cherry coke, coke & lime, coke-sprite, Arnold Palmer, and Shirley Temple.

Design

            The design for our automated drink mixer focuses on simplicity, as to minimize the number of moving parts needed in the system and reduce mechanical error. A rotating Lazy Susan is centered on a wooden platform with five supports made of PVC pipe spaced around it evenly at 60 degree angles, leaving one space open for the user to initially place the glass. Each support holds a mixer above the rotating platform, contained in an inverted plastic bottle with a solenoid valve attached at the end to control its flow into the glass. A 12V bidirectional DC motor is attached to a 2 inch rubber wheel which is placed against the edge of the 14 inch rotating platform. The motor operates at approximately 70RPM when 12V is applied, thus rotating the platform at a speed of about 10RPM as to not spill or knock over the glass. The software run from the microcontroller is dictated by an overarching state machine, whose transitions are controlled by the status of the push-button. Initially, the system sits in an idle state where it polls for an input from one of the buttons. Once an input is received, the glass is moved under mixers according to what drink needs to be made. In order to control the position of the glass, an IR emitter and phototransistor detect black strips of tape along the edge of the platform, and a comparator digitizes the signal, which is then used to trigger an interrupt to count the number of 60 degree spaces the glass has moved. The liquid from each mixer is dispensed by simply opening and closing the corresponding valve for the appropriate amount of time. Once all the ingredients have been added, the glass is returned to its starting position, and the state machine is reset to its initial idle state.

            The idea for the automated drink mixer was original; however, different aspects of the design were borrowed from a similar amateur project found on the internet, as well as previous Cornell University ECE4760 labs. The idea of having a rotating circular platform which moved in predetermined steps was based on an “Automated Bartender” video on IEEE TV, which used a slotted Geneva drive to move a glass. The idea for using the IR sensor to track position came from the tachometer in Lab 4 which measured the speed of a rotating fan blade, and the state machine used to debounce the menu input was similar to that used on the DTMF dialer in Lab 2. Although our project is interesting, after viewing other projects on the internet, it does not appear that any single aspect of our design is unique enough to warrant any copyright/patent considerations or concerns.

            Throughout the design process, there were two main issues that largly determined the outcome of our final product: control of the glass position, and control of the flow of mixers into the glass. Initially we tried to move the glass by simply enabling and disabling the DC motor for a specified amount of time via the microcontroller, but found that this was not always accurate enough to keep the dispensing liquid within the circumference of the glass, and that any position error that existed accumulated over time, making the system hard to run repeatedly without physically reseting the platform. By implementing an IR feedback loop in the hardware instead, we were able to monitor the position of the glass in real-time and always knew if it was in the right position for dispensing due to the comparator input. In contrast, the control of the valves used to dispense the mixers was plagued by hardware issues. Because these types of solenoid valves are usually used for larger-scale plumbing, they have minimum pressure requirements needed to allow flow which could not be meet with the amount of liquid in a 2-liter bottle. In order to fix this problem, we needed to physically adjust the solenoid gasket mechanisms inside the valves, but in doing so, we introduced small amount of leakage in some of the valves. Furthermore, our original design idea implemented precision mixing by first dispensing liquid from each bottle into a compartment of a predefined volume before dispensing it into the glass; however, this idea had to be abandonned entirely due to problems with pressure. In the end, we simply had to use a single valve for each mixer and rely on timed measurements to know how much liquid would be dispensed. Overall, it took time to find the right balance between reliability of software versus hardware.

Hardware

            Our automated drink mixer concept was implemented as a circular rotating structure that places the user’s glass underneath inverted plastic bottles containing different mixers. The entire structure sits on a base board which holds the Lazy Susan, IR sensor, DC motor, and PVC pipe in place. Elbow adapters angle the PVC pipe to hold the solenoid vavles over the rotating platform on which the glass sits. The nozzles of the inverted bottles are attached to the valves, which are opened and closed by the microcontroller. An upper keystone board is used to support the bottles to prevent them from leaning when the weight of the liquid is added. The user input is received via a push-button menu near the front of the base board. During the drink making process, the location of the user’s glass is controlled by a feedback loop by means of an IR emitter and receiver pointed at the edge of the rotating platform. Diagrams of the final structure can be seen below:

Details of the major subsystems of our physical structure are as follows:

  • Base Board
    • A square 25″ x 25″ wooden particle board
  • Lazy Susan/ Rotating Platform
    • A 14″ diameter Lazy Susan fixed to the center of the base
    • Motion is allowed by 3 evenly spaced bearings that came with the Lazy Susan that sit between the base and the platform
    • The motor is fixed in a socket cut into the base, positioned such that the edge of the platform is in contact with the motor wheel
  • DC Motor
    • A bidirectional 12V DC 70RPM high torque (8Kg*cm) motor
    • The motor peg is attached to a 2″ diameter rubber wheel
    • The high torque ensured that we would have minimal slipping, and the 70RPM value ensured a rotation speed of approximately 10RPM for our glass, which we determined to be a safe value that did not risk toppling or spilling the glass (2″/14″ * 70RPM = 10RPM)
  • Bottle Support
    • 5 L-shaped 3/4″ diameter PVC supports
    • All of these are fixed in sockets cut into the base just outside the perimeter of the Lazy Susan, and are spaced 60 degrees apart
    • The solenoid valves connect to the support structures via threaded PVC adapters
    • The tops of all PVC supports are connected by a wooden “keystone” board to prevent the supports from leaning excessively when the bottles are filled
  • Solenoid Valves
    • 5 1/2″ 12V DC plastic solenoid valves
    • The valves are connected to the bottles via threaded PVC adapters and duct tape
    • Each valve contains a gasket that seals the flow when the valve is not activated. The seal is caused by a piston which is pushed into the gasket by a spring. When activated, the magnetic field of the solenoid pulls the piston in and compresses the spring. Pressure from the liquid then causes the gasket to collapse and allows liquid to flow
    • Originally, the gaskets had a minimum 3PSI pressure requirement, which prevented our mixers from flowing even when the solenoids were activated. Therefore, each valve was modified by super-gluing the piston to the gasket, so that when the solenoid was activated, the gasket was always pulled back by the piston regardless of the pressure of the liquid
  • IR Sensor/ Proto-Board Stand
    • IR emitter and receiver pointed toward the edge of the rotating platform
    • Detect black strips of electrical tape placed on the edge of the patform, positioned such that each strip corresponds to a pour station or the start station
    • The 6″ protoboard on which most of our circuitry was contructed is positioned near the edge of the Lazy Susan on an elevated surface, so that our IR Sensor is level with the edge of the platform
  • Push-Button Menu
    • 5 push-buttons on a 2″ solder board, fixed to a foam pad at the front of the base (circuitry described later)
    • Labels with the different drink orders are placed next to each of the buttons

During construction, our structure had to be modified from our original design concept.. Our original design did not have the motor directly in contact with the Lazy Susan. Instead, the two were separated, and a rubber belt was wrapped around the edge of the Lazy Susan and the motor. This turned out to be extremely troublesome because the belt had a tendency to slip up or down the motor wheel as the system ran for an extended amount of time. As a result, we decided it would be simpler to change the location of the motor and place it in direct contact with the platform.

           The circuitry for the automated drink mixer consisted of four separate parts: the push-button menu, the IR sensor and comparator, valve control, and the bidirectional motor drive. The details of the electronics of each of these four subsystems can be seen below:

  • Push-Button Menu
    • This was the source of user input. Five push buttons were soldered to a board and placed near the front of our base as described above. The buttons were wired to pins B.0, B.,2, B.4, B.6, and B.7. Each pin is connected to an internal pull-up resistor. When the corresponding button is pressed, the input is shorted to ground and goes low. A circuit diagram for the subsystem can be seen here:

  • Valve Control
    • A valve is activated by outputting 5V from the corresponding output on PORTC to the gate of a BUZ73 power transistor. When this occurs, the drain is connected to the source which is at ground, allowing current to flow from the 12V power supply through the solenoid. A back-biased diode and 100 μF capacitor are placed in parallel with each valve to dissipate any negative voltages generated when the inductive solenoids are deactivated. Ports C.0, C.1, C.4, C.6, and C.7 were used to contol the valves. A diagram of the valve control circuitry can be seen here:

  • Bi-Directional Motor Drive
    • The bi-directional functionality of our motor was implemented with a Texas Instruments L293D Dual-H Bridge Integrated Circuit, and the circuit itself was modeled after the example from the datasheet. Ports D.0 and D.1 were used as the enable bits to turn on and control the direction of the motor. The pin layout of the chip, as well as the motor drive circuitry can be seen here:

  • IR Sensor and Comparator
    • An IR LED is positioned such that it emits directly at the edge of the Lazy Susan. An IR phototransistor receives the reflected light and generates an analog signal corresponding inversely to the intensity of light it receives. The edge of the Lazy Susan is painted white, but has strips of black tape spaced roughly 60 degrees apart around the edge. When the IR emitter shines on a black marking, the intensity of the reflected light decreases and the voltage across the transistor rises. This signal is then fed into an analog comparator that generates a digital signal corresponding to the presence of a black marking. The digital signal is then fed into pin D.2, which triggers an interrupt in the software on any rising edge. The circuit diagram for the subsystem can be seen in here:

Software

            The software for this program uses a state machine to control the order of functions called to move the glass to different positions and dispense mixers. The following is a list of all functions and interrupts and their descriptions:

  • void getorder(void) – This function checks each of the five inputs into PORTB and updates the unsigned character order to reflect the current status of the push button menu.
  • void checkorder(void) – This function is called every 30 milliseconds by the main program in order to update the state machine. This function first calls getorder() and then uses a switch to transition to the next state based on the current state. The current state is stored in an unsigned character PushState, and the possible states are defined as NoPush, MaybePush, Pushed, and MaybeNoPush. If the current state is NoPush and there is an order being placed, the order is stored in a variable maybe and there is a transition to MaybePush; otherwise, the system remains in this idle state polling for an input. MaybePush is used as the debouncing state. If after 30 milliseconds the order still matches maybe, then a legitimate order has been placed. In this case, the corresponding drink function is called to fill the order, and there is a state transition to Pushed. If they don’t match, it is assumed that there was just an error due to noise, and the state machine is reset to NoPush. Once in the Pushed state, the system remains here until order no longer equals maybe, as to avoid triggering multiple orders for a single button press. When the button is released, the system transitions to MaybeNoPush, and the release is debounced in the same manner as the press.
  • ISR (INT0_vect) – This interrupt service routine executes at every rising edge of the comparator input from the IR sensor in order track the position of the glass. It simply increments a character count, which counts the number of spaces the glass has moved.
  • void moveto(float num) – This function is responsible for moving the glass from its current position to a new position specified by num. Each of the six positions around the rotating platform is defined by a different floating point value, and the current position is stored in a floating point variable position. The function implements an algorithm that first calculates the difference between the current position and the desired position. If this difference is positive, the motor is turned counterclockwise until the magnitude of count equals the magnitude of the difference. Else, the motor is turned clockwise until the magnitude of count equals the magnitude of the difference.
  • void dispense(void) – This is a general function called every time any mixer needs to be dispensed. It uses position to determine which valve the glass is under, and simply opens it for a predetermined amount of time and then closes it. For the larger mixers (coke, sprite, and tea), 1/4th of a glass is dispensed at each function call. For the smaller mixers (grenadine and lime juice), only a “dash” of the ingredient is added.

When the main program starts, it initializes the hardware inputs and outputs, defines the INT0 interrupt, and initializes key state variables. It then enables the ISR and begins polling for a menu input. Once an input is received, the state machine debounces the input, and if it is valid, it fills the order. If not, it returns to its idle state. To fill an order, the software uses a combination of calls to movoto() and dispense(). Once the order is filled and the glass is back in the start position, the state machine waits to debounce the release of the push-button. Once the release is validated, the system again enters its initial idle state. The code for this project in its entirety can be found in Appendix A. A diagram of the full state machine can be seen here:

Results

            Overall, our design was successfully implemented, and the system was able to make all the drinks that we programmed into the software. Futhermore, the system is both simple and straightforward to use. The user just places a glass on the marked circle on the Lazy Susan, and presses the button corresponding to their desired beverage. The rest of the process consists of waiting and admiring the drink mixer as it prepares their tasty beverage. In testing, we found the following average times for the automated drink mixer to prepare the corresponding beverages:

  • Cherry Coke – 20.47s
  • Coke & Lime – 23.66s
  • Coke & Sprite – 21.33s
  • Arnold Palmer – 25.11s
  • Shirley Temple – 22.15s

Additionally, we found the mean number of successful runs between errors to be 20. Our three primary error modes were as follows:

  • A missed count by the IR sensor
    • This error mode was caused by the loosening of the central screw connecting the Lazy Susan to the base, that would occur as the mixer ran several times. When the screw loosens, the rotating platform begins to tilt slightly, until IR sensor is no longer pointing directly at the edge of the platform.
  • An extra count by the IR sensor
    • This error occurred few and far between, and would happen only when the motor was changing directions. When the glass arrives at a new position, the IR feedback loop is supposed to stop the motor immediately, and the signal from the comparator should remain high throughout the dispensing period, so that when it starts moving again, a position count is not triggered until the next marker causes a rising edge. However, in the situation where the desired position marker passes slightly beyond the IR sensor before the motor stops, the comparator input goes low before liquid is dispensed. Once the motor begins turning in the opposite direction, the system will recount the current position marker when it should not. This error was noticed mostly in the development of our system and was successfully mitigated, if not removed entirely, from the final product by increasing the width of the position markers.
  • Motor losing contact with the lazy susan
    • This error was caused by the fact that our motor is not fixed to the base. Instead, it rests in a slot and must be rotated into contact with the Lazy Susan before use. This failure mode could be removed entirely if the motor position was fixed with adhesive.

Because the IR sensor and emitter are position close to the platform, we did not find interference to be an issue. Our design also included a certain degree of safety to prevent against catostrophic failures, like mixers being dispensed while the glass is not in position and liquid spilling onto any electronics. First, the IR feedback loop provided enough accuracy that the glass was never far enough out of position for the despensing liquid to “miss”. In addition, if the motor did happen to slip, the IR sensor would never detect the next marker, so it is impossible for dispensing to occur prematurely. Second, bottle stoppers were used at the end of each valve to direct liquid flow in a small, well-aimed stream without splatter. Last, a delay period was placed after each call to dispense(), so that the glass never started to move during the switching time of the valve.

            The system is robust enough that reprogramming the software for new drink orders could be easily done, and the number of mixers could be easily expanded given a larger physical structure. One issue that our final design did not fully overcome is the fact that there is a small amount of leakage from the solenoid valves and bottle stoppers, especially when a carbonated ingredient is used. This was an issue throughout our entire process, but in the end we were able to minimize leakage by extensive re-assembly of the gaskets inside our valves.

Conclusions

            In terms of functional requirements, our final design met all of our desired characteristics. We were repeatedly able to mix all 5 drinks on our menu without having to manually adjust the system, and created a dynamic system, instead of just dispensing mixers into a static glass. As mentioned above, we do not feel that any part of our system is unique enough to warrant any intellectual property applications or concerns.; nor are there any legal concerns, given that all mixers used for this project were non-alcoholic.

            As far as ethical considerations are concerned, we believe that we abide by all 10 of the principles listed in the IEEE Code of Ethics. All of the contributing ideas that were borrowed from other’s work have been acknowledged in this document, and can be found listed as references in Appendix D, and no part of this project was used for the purpose of making money. Furthermore, all of the results found in this document are known to be true to the best of our knowledge, and have not been forged. In terms of safety, it is possible that the automated drink mixer might be used for non-intended functions, such as making alcoholic cocktails. However, if the user is in possession of alcohol and desires to abuse our system with it, we must assume that they are of age, and an adult who is capable of making their own decisions. Finally, all known system shortcomings have been discussed thoroughly and honestly in this document.

            Given more time and resources, there are certainly more features that we would have liked to implement to improve the user experience. First and foremost, using higher quality valves that did not leak would be the major improvement, since this problem requires the most amount of maintenance to mitigate. Next, creating a touch screen display and interface to enhance the menu would make the final product much more appealing for use in the actual service industry. Last, the improvement and inclusion of more visually pleasing aesthetics for the system would make the design appear more complete. Flashing LED’s and so on would make the experience of using this fun machine even more novel. If such a device were perfected and made to work consistently over long periods of use, we beleive that it could definitely serve both a functional and commercial purpose at any restaurant or bar.

Appendix A – Code

//**********************************************************
// ECE4760 Final Project – Automated Drink Mixer
//**********************************************************

#define F_CPU 16000000UL
#include <inttypes.h>
#include <avr/io.h>
#include <stdio.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <math.h>

#define begin {
#define end }

//position definitions and variables
#define start 1
#define coke 2
#define grenadine 3
#define sprite 4
#define lemon 5
#define tea 6
#define restart 7

float position;
volatile char count;
volatile char last;

//state machine definitions and variables
#define NoPush 1
#define MaybePush 2
#define Pushed 3
#define MaybeNoPush 4

unsigned char PushState;
unsigned char order;
unsigned char maybe;

//**********************************************************
// external interrupt ISR
ISR (INT0_vect) {
count++;
}

//**********************************************************
//dispense drink and refill compartment
void dispense(void)
begin
if(position == 2)
begin
PORTC = 0x01;
_delay_ms(2700);
PORTC = 0x00;
if(last) _delay_ms(2000);
end
else if(position == 3)
begin
PORTC = 0x02;
_delay_ms(2000);
PORTC = 0x00;
if(last) _delay_ms(2000);
end
else if(position == 4)
begin
PORTC = 0x10;
_delay_ms(2000);
PORTC = 0x00;
if(last) _delay_ms(2000);
end
else if(position == 5)
begin
PORTC = 0x40;
_delay_ms(1000);
PORTC = 0x00;
if(last) _delay_ms(2000);
end
else if(position == 6)
begin
PORTC = 0x80;
_delay_ms(3000);
PORTC = 0x00;
if(last) _delay_ms(2000);
end
end

//**********************************************************
//move glass to new position
void moveto(float num)
begin
float diff;
diff = position – num;
position = num;
count = 0;

            //if the difference is positive, rotate counterclockwise
if(signbit(diff) == 0)
begin
PORTD = 0x02;
while (count < diff);
PORTD = 0x00;
end

            //otherwise, rotate clockwise
else
begin
diff = -1 * diff;
PORTD = 0x01;
while (count < diff);
PORTD = 0x00;
end
end

//**********************************************************
//drink 1
void cherrycoke(void)
begin
moveto(coke);
last = 0;
dispense();
dispense();
dispense();
last = 1;
dispense();
moveto(grenadine);
dispense();
moveto(start);
end

//**********************************************************
//drink 2
void cokelime(void)
begin
moveto(coke);
last = 0;
dispense();
dispense();
dispense();
last = 1;
dispense();
moveto(lemon);
dispense();
moveto(restart);
position = start;
end

//**********************************************************
//drink 3
void spoke(void)
begin
moveto(coke);
last = 0;
dispense();
last = 1;
dispense();
moveto(sprite);
last = 0;
dispense();
last = 1;
dispense();
moveto(start);
end

//**********************************************************
//drink 4
void arnold_palmer(void)
begin
moveto(lemon);
last = 1;
dispense();
moveto(tea);
last = 0;
dispense();
dispense();
dispense();
last = 1;
dispense();
moveto(restart);
position = start;
end

//**********************************************************
//drink 5
void shirley_temple(void)
begin
moveto(sprite);
last = 0;
dispense();
dispense();
dispense();
last = 1;
dispense();
moveto(grenadine);
dispense();
moveto(start);
end

//**********************************************************
//get the appropriate drink order from PORTB
void getorder(void)
begin
if (~PINB & (1<<PINB0)) order=1;
else if (~PINB & (1<<PINB2)) order=2;
else if (~PINB & (1<<PINB4)) order=3;
else if (~PINB & (1<<PINB6)) order=4;
else if (~PINB & (1<<PINB7)) order=5;
else order=0;
end

//**********************************************************
//update the state machine
void checkorder(void)
begin
getorder();
switch (PushState)
begin
case NoPush:
if(order != 0) {maybe=order; PushState=MaybePush;}
break;
case MaybePush:
if (order == maybe)
begin
if(order == 1) cherrycoke();
else if(order == 2) cokelime();
else if(order == 3) spoke();
else if(order == 4) arnold_palmer();
else if(order == 5) shirley_temple();
PushState=Pushed;
end
else PushState=NoPush;
break;
case Pushed:
if (order != maybe) PushState=MaybeNoPush;
break;
case MaybeNoPush:
if (order == maybe) PushState=Pushed;
else PushState=NoPush;
break;
end
end

//**********************************************************

int main(void)
begin
DDRB=0x00; //Push-button menu inputs
PORTB=0xFF;
DDRC=0xFF; //Valve outputs
PORTC=0x00;
DDRD=0x03; //Motor control outptus and IR sensor input
PORTD=0x00;

            //set up INT0
EIMSK = 1<<INT0; // turn on int0
EICRA = 3;       // rising edge

            //initialize position
position = start;

            //initialize state machine
PushState = NoPush;

            //enable interrupts
sei();

            //poll for drink order every 30msec
while(1)
begin
checkorder();
_delay_ms(30);
end
end

Source: Automated Drink Mixer


About The Author

Muhammad Bilal

I am a highly skilled and motivated individual with a Master's degree in Computer Science. I have extensive experience in technical writing and a deep understanding of SEO practices.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top