Cocktail robot to automatically dose rum for Tschunk.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

309 lines
6.6 KiB

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <LcdBarGraphX.h>
#include <FastLED.h>
// --- LEDS ---
#define LED_TYPE WS2811
#define COLOR_ORDER RGB
#define MASTER_BRIGHTNESS 200
#define DATA_PIN_A 11 // update pin numbers for data lines as needed
#define DATA_PIN_B 10
#define DATA_PIN_C 8
#define DATA_PIN_D 9
#define NUM_LEDS_A 22 // adjust number of pixels as needed
#define NUM_LEDS_B 12
#define NUM_LEDS_C 12
#define NUM_LEDS_D 22
CRGB ledsA[NUM_LEDS_A];
CRGB ledsB[NUM_LEDS_B];
CRGB ledsC[NUM_LEDS_C];
CRGB ledsD[NUM_LEDS_D];
static uint8_t hueA=123;
// --- Robot Functionality ---
// Initialize LCD
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
LcdBarGraphX bar(&lcd, 20, 0, 3); // -- Second line at column 0
// Define ports
int poti_port=A0;
int poti_value=0;
int amount=0;
int poti_last_value;
int poti_read;
int poti_new_value;
int button_port=12;
int button_pressed=0;
int relay_port=13;
bool relay_status=false;
bool pump_running=false;
char state='i';
int led_bottle = 1;
int led_pump = 2;
int led_glass= 3;
unsigned long previousMillis=0;
unsigned long currentMillis=0;
// 500ml/min mean 120ms per ml
int ms_per_ml=132;
int ml_pumped=0;
void setup()
{
// --- Robot Functionality ---
pinMode(button_port, INPUT);
pinMode(relay_port, OUTPUT);
//Initialize lcd
lcd.begin(20,4);
// Standard Set text
lcd.setCursor ( 0, 0 );
lcd.print(" * * Cockstar * * ");
lcd.setCursor ( 0, 1 );
lcd.print("Starting... ");
Serial.begin(9600);
// --- LEDS ---
delay(2500); //power up delay
FastLED.addLeds<LED_TYPE, DATA_PIN_A, COLOR_ORDER>(ledsA, NUM_LEDS_A);
FastLED.addLeds<LED_TYPE, DATA_PIN_B, COLOR_ORDER>(ledsB, NUM_LEDS_B);
FastLED.addLeds<LED_TYPE, DATA_PIN_C, COLOR_ORDER>(ledsC, NUM_LEDS_C);
FastLED.addLeds<LED_TYPE, DATA_PIN_D, COLOR_ORDER>(ledsD, NUM_LEDS_D);
FastLED.setBrightness(MASTER_BRIGHTNESS);
FastLED.clear();
}
void loop()
{
// --- Robot Functionality ---
// Read status of poti
poti_read =analogRead(A0);
//
poti_new_value=map(poti_read,0,1023,0,101);
if(poti_value != poti_new_value && poti_last_value != poti_new_value) {
poti_last_value=poti_value;
poti_value=poti_new_value;
}
// Read status of button
int button_pressed=digitalRead(button_port);
Serial.println(button_pressed);
// Reset title
lcd.setCursor ( 0, 0 );
lcd.print(" * * Cockstar * * ");
// States:
// i: idle
// w: waiting
// r: Running
// f: Finished
// lcd.print(" ");
switch(state){
case 'i':
// Idle
lcd.setCursor ( 0, 1 );
lcd.print("Ready. Place glass. ");
pump_running=false;
previousMillis=millis();
// Print bar graph only if pump running
if(poti_value>0){
bar.drawValue(ml_pumped,poti_value);
} else {
lcd.print(" ");
}
if(button_pressed){
state='w';
}
break;
case 'w':
// Waiting until glass is finally placed
lcd.setCursor ( 0, 1 );
lcd.print("Wait... ");
lcd.print(" ");
if(!button_pressed){
state='i';
}
// wait 500ms
if(millis()-previousMillis>500) {
state='r';
previousMillis=millis();
}
break;
case 'r':
// Pump is running
pump_running=true;
if(!button_pressed){
state='i';
}
// Run pump only when poti at least 1ml
if(poti_value > 0){
// If poti is over 100ml, run forever
if(poti_value > 100) {
lcd.setCursor ( 0, 1 );
lcd.print("Pump running. ");
} else {
// Else, normal mode limited by poti_value
lcd.setCursor ( 0, 1 );
lcd.print("Filling glass. ");
ml_pumped=int((millis()-previousMillis)/ms_per_ml);
if(ml_pumped >= poti_value) {
pump_running=false;
state='f';
previousMillis=millis();
}
lcd.setCursor ( 0, 3 );
// Print bar graph only if pump running
if(poti_value>0){
bar.drawValue(ml_pumped,poti_value);
} else {
lcd.print(" ");
}
}
} else {
lcd.setCursor ( 0, 1 );
lcd.print("Pump deactivated. ");
pump_running=false;
}
break;
case 'f':
// Glass filled
lcd.setCursor ( 0, 1 );
lcd.print("Ready, remove glass.");
if(!button_pressed){
state='i';
}
break;
}
// Update pump status
if(pump_running) {
digitalWrite(relay_port, 1);
} else {
digitalWrite(relay_port, 0);
}
// Update fluid amount
//lcd.setCursor ( 0, 2 );
//lcd.print(" ");
lcd.setCursor ( 0, 2 );
if(poti_value==0) {
lcd.print("Amount: None ");
} else {
if(poti_value>100) {
lcd.print("Amount: Infinite ");
} else {
lcd.print(String("Amount: ") + poti_value + "ml ");
}
}
// --- LEDS ---
EVERY_N_MILLISECONDS(50) {
//static uint8_t hueA;
fill_solid(ledsA, NUM_LEDS_A, CHSV(hueA, 255, 255));
hueA++;
}
//------code for the second strip, ledsB here------
// Putting the ledsB pattern inside this EVERY_N section allows
// the speed for just this strip to be individually adjusted.
// This will run every 500 milliseconds.
// Use ledsB in this section, such as ledsB[i], and NUM_LEDS_B
// with for loops so it uses the correct length of strip B.
// For example:
// EVERY_N_MILLISECONDS(20) {
// }
//------code for ledsC pattern------
// This strip can run a similar or different pattern, and have
// it's own timing. This will run every 35 milliseconds.
// Use ledsC[i] and NUM_LEDS_C in this section.
EVERY_N_MILLISECONDS(20) {
static uint8_t hueC;
static uint8_t brightnessC;
static uint8_t countC;
//fill_solid(ledsC, NUM_LEDS_B, CHSV(hueB, 255, 255));
//hueB++;
if(state=='f'){
fill_solid(ledsC, NUM_LEDS_C, CHSV(255, 0, brightnessC));
countC++;
if(countC==10){
countC=0;
if(brightnessC<10){
brightnessC=255;
} else {
brightnessC=0;
}
}
} else {
fill_solid(ledsC, NUM_LEDS_C, CHSV(hueC, 255, 255));
}
hueC++;
}
//------code for ledsLogo pattern------
// This strip can also do it's own individual thing.
// Use ledsD and NUM_LEDS_D in this section.
EVERY_N_MILLISECONDS(20) {
fill_rainbow( ledsD, NUM_LEDS_D, millis()/5, 12);
}
// Update the display for all strips.
FastLED.show();
}