Robotic Juice Bar
Want to impress all of your friends with a robot that makes drinks for you? In the PLTW course Principles of Engineering taught by Ms. Berbawy, I built a project that can do just that! My project was inspired by DIY Machine's Arduino Robotic Bartender - 3D Printable & Bluetooth.
Supplies
Machines Needed
- 3D-Printer
- Drill/Driver
- Tabletop Saw (Optional)
- Soldering Iron
Electronics
- Contact Switch (x1)
- Arduino Uno (x1)
- Arduino Motor Shield (x1)
- Breadboard (30 Rows)
- Spool of Electrical Wire
- 270 Ohm Resistor (x1)
- Solder
Hardware
- Stepper Motor (x2)
- Stepper Motor w/ Rod Inclusion (x2)
- Linear Bearing (x3)
- Drink Dispenser (x1)
- Timing Belt and Pulley (x1)
- 1M Steel Rod (x1)
- M3 x 35 Screw (x6)
- M4 x 35 Screw (x2)
- M4 x 50 Screw (x4)
- M4 Wood Screw (Length varies) (x21)
- M3 Wood Screw (Length Varies) (x2)
- Table (Must be at least 1.1 x 0.7 M in length)
- Wood Backing (0.8 x 0.6 M)
- Spool of Filament
3D Printing Parts
Before assembly, there are 7 different 3-D printed parts we need. To follow this step, you'll need to have the following required components:
- PETG Filament (I highly suggest a durable filament)
- Build volume of at least 150L x 250W x 75H mm
*I used the Prusa MK3S+ for the majority of my components, but this can be different as long as you meet the build plate size requirements
*Note that each part only needs to be printed once except for Linear Bearing Foot 1, which requires 2 prints
Assemble the Raft
- Align the bottom and top of the Sliding Base with one another
- Insert the feet for the linear bearings in their respective locations, aligned with holes
- Use the M4x50 screws to attach two linear bearings to feet 1
- Use the M4x35 screws to attach the third linear bearing to foot 2
- Align the stepper motors with rod inclusion to their respective locations, attach them with the M3x35 screws
Attach the Table Ends
Notes Before Proceeding:
It's important to continually check before drilling any new holes into the table during this step. Once you've attached one of the table ends, use the linear rods to see if your holes still line up perfectly.
- Measure out 1M in length, aligned with the center of the table
- Measure out 0.4 M in width, starting from the back of the table
- Mark holes and attach Table Ends using M4 Wood Screws. (The length of the screw may vary depending on how thick the table is, so aim to have the screw be halfway into the tabletop without poking out the bottom of it)
- Slide both Smooth Linear Rods through the Table Ends until they're flush with the Table Ends on both sides
- Drill a 10 mm hole behind Table End #1, spacing will vary depending on how long the table is
- Attach the stepper motor to Table End #1
- Slide the Raft onto the Linear Rods
Attach Drag Chain + Contact Switch
- Attach Drag Chain to Raft and align the other end with the middle of the table.
- Drill an 8 mm hole at the end of the Drag Chain, screw the Drag Chain into the table using M3 Wood Screws
- Attach Contact Switch to Table End #1 using a ziptie
- Thread the Threaded Disc onto the rods, keeping both ends on the same latitude
Attaching the Pulley Belt
- Take the Pulley Belt and thread it through the bottom of the Raft, around the stepper motor, and around Table End #2
- Measure out the belt so both ends are able to wrap around the top of the Raft, cut more than is necessary. Once it's cut, wrap the belt around the circular connecting points at the top of the Raft, using a paper clip to hold the belt firm against itself
*When finished, the belt should feel tight and capable of moving through manual movements of the Stepper Motor on Table End #1. If it's not, continue to make adjustments by cutting the belt shorter.
The Backing
Notes Before Proceeding:
This part is the most difficult, as the backing must be perfectly aligned so that the optics are able to dispense using the Threaded Disc. I cut the backing myself out of spare wood, but you could get the wood in a variety of different ways.
- Attach the Drink Dispenser to the backing, aligned with the top of the wall using M4 Wood Screws. My backing was 1/2 inch thickness, but change the length to fit your backing
- Align backing with the Raft, making sure that the optics are aligned with the Threaded Disc
- Use L-Brackets and M4 Wood Screws to attach the backing to the table. Additionally, the piece of wood I used and brackets weren't fully perpendicular so I used washers for correction
Electronics
- Align the Arduino Board and Breadboard to the back right hand corner of the table, mimicking Table End #1's location
- Merge the Stepper Motors with Rod Inclusion to one another, connecting their respective points with the second driver
- Thread the wires for the third stepper motor through the hole drilled in Step 3 and bring them under the table till they reach the Arduino. Attach the wire to their respective points on the first driver
- Solder wires onto the contact switch (Top=Blue, Middle=Gray, Bottom=Green) and thread the wires under the table through the hole made in step 4. Connect them to their respective points on the breadboard, then afterwards on the Arduino as seen in the photo above
Downloads
Coding
- Connect your laptop to the Arduino, and upload the code below using Arduino IDE
*Some of the values vary between motors, so change the values in the code below. I used a separate stepper motor with blue tape attached to the end to test values such as motor speed and delays. Once you're ready to run the code, plug the power supply into the Arduino and an outlet nearby. As soon as the robot is powered, it will begin to home itself.
int drinkMatrix[6][3] = {
};
//The below is for the contact switch.
const int buttonPin = 2; // the pin that the pushbutton is attached to
int buttonState = 0; // current state of the button
int lastButtonState = 0; // previous state of the button
//The below is for the stepper motors
#include <AFMotor.h>
AF_Stepper motor1(48, 1);
AF_Stepper motor2(48, 2);
//---------------------
//The below are for running the machine:
int raftFound = false;
int drinkRequested = false;
//---------------------
void setup() {
// for the contact switch
// initialize the button pin as a input:
pinMode(buttonPin, INPUT);
// initialize the LED as an output:
pinMode(LED_BUILTIN, OUTPUT);
// initialize serial communication:
Serial.begin(9600);
//--------------------------------
// For the stepper motors
motor1.setSpeed(550);
motor2.setSpeed(190);
//--------------------------------
}
void loop(){
//Lets find the location of the float:
if (raftFound == false){
Serial.println("Raft location not known yet");
setColor(255, 0, 0); // red
delay(1000);
Serial.print("Looking for the raft...");
buttonState = digitalRead(buttonPin); // read the pushbutton input pin:
//move the stepper until the contact switch is triggered
while(buttonState == LOW && raftFound == false){
motor1.step(10, FORWARD, SINGLE);
buttonState = digitalRead(buttonPin);
}
raftFound = true;
Serial.println("ahh! There it is. :)");
motor1.release();
setColor(0, 255, 0); // blue
delay(700); // Delay a little bit to calm everything down
}
//working through the dispensing instructions until drink is complete and paddle is at last optic position:
if (drinkRequested == true){
for (int optic = 0; optic < opticCount; optic++) {
//Move to pump
motor1.step((drinkMatrix[optic][0] * 10), BACKWARD, SINGLE); //move the paddle according to instruciton, x10 to allow us to compress serial data transfer length
motor1.release(); // let the motor's magnets relax
//dispense what is required then resume moving to the next position:
while(drinkMatrix[optic][2] > 0 && raftFound == true){
delay(500);
motor2.step(500, BACKWARD, DOUBLE);
delay((drinkMatrix[optic][1]) * 100);
motor2.step(500, FORWARD, DOUBLE);
motor2.release();
drinkMatrix[optic][2] = drinkMatrix[optic][2]-1;
delay(500);
}
}
//Drink complete
Serial.println("Drinks ready, enjoy.");
setColor(0, 0, 255); // green
drinkRequested = false;
raftFound=false;
}
while(drinkRequested == false){
delay(200);
if (Serial.available()) {
for (int optic = 0; optic < opticCount; optic++){
for (int parameter = 0; parameter < parameterCount; parameter++){
for (int parameterMeasure = 0; parameterMeasure < parameterSize; parameterMeasure++){
if (Serial.available()) {
serialNumber = Serial.read(); /* load the number from serial buffer */
serialNumber = serialNumber - 48; /* convert number to text number */
numberCollector = numberCollector * 10 + serialNumber; /*store and build the number*/
} else {
delay(250);
serialNumber = Serial.read(); /* load the number from serial buffer */
serialNumber = serialNumber - 48; /* convert number to text number */
numberCollector = numberCollector * 10 + serialNumber; /*store and build the number*/
}
}
drinkMatrix[optic][parameter] = numberCollector; /* store the value in the array */
numberCollector = 0; /* Prepare variable for next number */
serialNumber = Serial.read(); /* to clear the comma from the buffer */
}
}
CheckArray();
Serial.println("Done loading");
drinkRequested = true;
}
}
}
void CheckArray(){
//print out the array to check it:
for(int i = 0; i < opticCount; i++) {
for(int j = 0; j < 3; j++) {
Serial.print(drinkMatrix[i][j]);
Serial.print(",");
}
Serial.println();
}
}
Testing Optic Values
To operate the robot, you need to open the Serial Monitor Tab in the Arduino IDE software. Commands are sent through CSV, which tell the motor how far it should turn. The values I used for the locations are:
50,10,01,50,06,01,50,50,00,57,00,00,50,50,02,50,50,00.
The values are in groups of 3. The value for finding the distance needed to travel to your optics is the first value in those groupings, and varies depending on the placement of your optics as well as the stepper motor's performance. Run different CSV values in increments of 5-10, until you've found one that aligns with the center of each optic.
Downloads
Final Product
You're done! Thank you for working on this project with me, and email me about any questions, comments, or concerns.