Machine week!

1 2 3 4 5 6 7 8 9 10 11 12 13 14

A drinking machine

Drinking machine model

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.

Machine schematic with valves
Valve design

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.

Taking apart the valve to see the rotating mechanism inside the valve

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.

Joint iteration
Glued joint (rejected because we would lose the valve to future projects

After testing all these different connections from valve to servo, we ended up designing a cap for the most robust and least destructive joint.

Laser cut joint prototype from valve to servo arm
All the joints

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.

Testing if the servos works with the 90 degree rotation I programmed my board to do. They are all aligned! (After carefully aligning and then re-aligning some.)
Testing the entire mechanism before we dry-fit it
~~ Interlude: Assembling the whole machine ~~
All four dispensers assembled
All four dispensers (detail)
Water test with all the other parts integrated--functional dispensers! Yay!
Calibrating with Rafa to make sure all the servos have the correct rotation

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);
    
  }
}