For Machine Week, our group decided to make a bartenting machine that we documented from start to end here. I was in charge of designing, fabricating, and troubleshooting the control of the drink dispenser with Jung and Emily--and later also jumped on their programming.
The basic idea was to hold the bottles & the dispensers vertically above the motor's axis. The first task at hand was the choice of the dispensing mechanism: We were choosing between a pressurized solenoid valve and servo-driven options, and we landed on using a simple valve & rotating its handle with a servo so that we could also separate the parts later.
We then tested several ways of attaching to the servo arms, either by removing the valve cap of by keeping it so that we can reuse the valves later.
After testing all these different connections from valve to servo, we ended up designing a cap for the most robust and least destructive joint.
And then we assembled the dispensers! First, however, we had to adjust the tight design a little bit and decided to use zip ties to secure the servos and valves in place, because screwing them in was way too difficult. I already had a working board, so throughout this testing process we could use that, change the PWM speed and angles, and check each board individually before integrating it into the machine.
Jung and Rafa then carefully calibrated each servo's PWM to make sure they are not over-rotated, and I jumped on the programming team to set up the servo (& also stepper) code. They all opened & closed (with green light indicating open, red light closed) in a linear order with a delay proportional to the volume released / desired:
// Dry-run for single-time demo
bool dryrun = true;
// steppers
const int stepper_forward = 11; // stepper_pin_forward
const int stepper_backward = 12; // stepper_pin_backward
// servos
int servo_pins[] = {5, 4, 3, 2};
int mixer_pin = 6;
// delays
const int start_to_first_delay = 10000;
const int inbetween_bottle_delay = 10000;
const int mixing_delay = 123;
const int total_move_back_delay = 5000;
// volumes
const float total_volume_glass = 200; //ml
// potentiometer readings
const float drip_rate = 12.5/1000; //ml / ms
// button controls
int pot_pins[] = {A0, A1, A2, A3};
int pot_pins_size = 4;
int valve_delays[4];
const int button_start_pin = 7;
const int delay_time = 2000;
void setup() {
// Taking out stepper because the motor fried upon the second run! :(
// pinMode(stepper_forward, OUTPUT);
// pinMode(stepper_backward, OUTPUT);
for(int i = 0; i < pot_pins_size; i++) {
pinMode(servo_pins[i], OUTPUT);
}
pinMode(button_start_pin, INPUT);
Serial.begin(9600);
}
void loop() {
if (dryrun == true){
dryrun = false;
// if button is pressed read all analog ins and set the delays accordingly
float pt_readings[4];
float pt_readings_sum = 0;
for(int i = 0; i < pot_pins_size; i++) {
// Ideally, these readings would have been from the potentiometer
// pt_readings[i] = analogRead(pot_pins[i]);
pt_readings_sum += pt_readings[i];
}
float servo_delays[4];
for(int i = 0; i < pot_pins_size; i++) {
servo_delays[i] = pt_readings[i] / pt_readings_sum * total_volume_glass / drip_rate;
}
// Move to first bottle
// Again, stepper not working
// digitalWrite(stepper_forward, HIGH);
delay(start_to_first_delay);
// digitalWrite(stepper_forward, LOW);
// Fill and move
for(int i = 0; i < pot_pins_size; i++) {
// Open and close valve
digitalWrite(servo_pins[i], HIGH);
delay(servo_delays[i]);
digitalWrite(servo_pins[i], LOW);
// Move to next bottle
if (i< pot_pins_size-1) {
// digitalWrite(stepper_forward, HIGH);
delay(inbetween_bottle_delay);
// digitalWrite(stepper_forward, LOW);
}
}
// Mix drink
// digitalWrite(mixer_pin, HIGH);
// delay(mixing_delay);
// digitalWrite(mixer_pin, LOW);
}
}