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

3 months ago
  1. #include <Wire.h>
  2. #include <LiquidCrystal_I2C.h>
  3. #include <LcdBarGraphX.h>
  4. #include <FastLED.h>
  5. // --- LEDS ---
  6. #define LED_TYPE WS2811
  7. #define COLOR_ORDER RGB
  8. #define MASTER_BRIGHTNESS 200
  9. #define DATA_PIN_A 11 // update pin numbers for data lines as needed
  10. #define DATA_PIN_B 10
  11. #define DATA_PIN_C 8
  12. #define DATA_PIN_D 9
  13. #define NUM_LEDS_A 22 // adjust number of pixels as needed
  14. #define NUM_LEDS_B 12
  15. #define NUM_LEDS_C 12
  16. #define NUM_LEDS_D 22
  17. CRGB ledsA[NUM_LEDS_A];
  18. CRGB ledsB[NUM_LEDS_B];
  19. CRGB ledsC[NUM_LEDS_C];
  20. CRGB ledsD[NUM_LEDS_D];
  21. static uint8_t hueA=123;
  22. // --- Robot Functionality ---
  23. // Initialize LCD
  24. LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
  25. LcdBarGraphX bar(&lcd, 20, 0, 3); // -- Second line at column 0
  26. // Define ports
  27. int poti_port=A0;
  28. int poti_value=0;
  29. int amount=0;
  30. int poti_last_value;
  31. int poti_read;
  32. int poti_new_value;
  33. int button_port=12;
  34. int button_pressed=0;
  35. int relay_port=13;
  36. bool relay_status=false;
  37. bool pump_running=false;
  38. char state='i';
  39. int led_bottle = 1;
  40. int led_pump = 2;
  41. int led_glass= 3;
  42. unsigned long previousMillis=0;
  43. unsigned long currentMillis=0;
  44. // 500ml/min mean 120ms per ml
  45. int ms_per_ml=132;
  46. int ml_pumped=0;
  47. void setup()
  48. {
  49. // --- Robot Functionality ---
  50. pinMode(button_port, INPUT);
  51. pinMode(relay_port, OUTPUT);
  52. //Initialize lcd
  53. lcd.begin(20,4);
  54. // Standard Set text
  55. lcd.setCursor ( 0, 0 );
  56. lcd.print(" * * Cockstar * * ");
  57. lcd.setCursor ( 0, 1 );
  58. lcd.print("Starting... ");
  59. Serial.begin(9600);
  60. // --- LEDS ---
  61. delay(2500); //power up delay
  62. FastLED.addLeds<LED_TYPE, DATA_PIN_A, COLOR_ORDER>(ledsA, NUM_LEDS_A);
  63. FastLED.addLeds<LED_TYPE, DATA_PIN_B, COLOR_ORDER>(ledsB, NUM_LEDS_B);
  64. FastLED.addLeds<LED_TYPE, DATA_PIN_C, COLOR_ORDER>(ledsC, NUM_LEDS_C);
  65. FastLED.addLeds<LED_TYPE, DATA_PIN_D, COLOR_ORDER>(ledsD, NUM_LEDS_D);
  66. FastLED.setBrightness(MASTER_BRIGHTNESS);
  67. FastLED.clear();
  68. }
  69. void loop()
  70. {
  71. // --- Robot Functionality ---
  72. // Read status of poti
  73. poti_read =analogRead(A0);
  74. //
  75. poti_new_value=map(poti_read,0,1023,0,101);
  76. if(poti_value != poti_new_value && poti_last_value != poti_new_value) {
  77. poti_last_value=poti_value;
  78. poti_value=poti_new_value;
  79. }
  80. // Read status of button
  81. int button_pressed=digitalRead(button_port);
  82. Serial.println(button_pressed);
  83. // Reset title
  84. lcd.setCursor ( 0, 0 );
  85. lcd.print(" * * Cockstar * * ");
  86. // States:
  87. // i: idle
  88. // w: waiting
  89. // r: Running
  90. // f: Finished
  91. // lcd.print(" ");
  92. switch(state){
  93. case 'i':
  94. // Idle
  95. lcd.setCursor ( 0, 1 );
  96. lcd.print("Ready. Place glass. ");
  97. pump_running=false;
  98. previousMillis=millis();
  99. // Print bar graph only if pump running
  100. if(poti_value>0){
  101. bar.drawValue(ml_pumped,poti_value);
  102. } else {
  103. lcd.print(" ");
  104. }
  105. if(button_pressed){
  106. state='w';
  107. }
  108. break;
  109. case 'w':
  110. // Waiting until glass is finally placed
  111. lcd.setCursor ( 0, 1 );
  112. lcd.print("Wait... ");
  113. lcd.print(" ");
  114. if(!button_pressed){
  115. state='i';
  116. }
  117. // wait 500ms
  118. if(millis()-previousMillis>500) {
  119. state='r';
  120. previousMillis=millis();
  121. }
  122. break;
  123. case 'r':
  124. // Pump is running
  125. pump_running=true;
  126. if(!button_pressed){
  127. state='i';
  128. }
  129. // Run pump only when poti at least 1ml
  130. if(poti_value > 0){
  131. // If poti is over 100ml, run forever
  132. if(poti_value > 100) {
  133. lcd.setCursor ( 0, 1 );
  134. lcd.print("Pump running. ");
  135. } else {
  136. // Else, normal mode limited by poti_value
  137. lcd.setCursor ( 0, 1 );
  138. lcd.print("Filling glass. ");
  139. ml_pumped=int((millis()-previousMillis)/ms_per_ml);
  140. if(ml_pumped >= poti_value) {
  141. pump_running=false;
  142. state='f';
  143. previousMillis=millis();
  144. }
  145. lcd.setCursor ( 0, 3 );
  146. // Print bar graph only if pump running
  147. if(poti_value>0){
  148. bar.drawValue(ml_pumped,poti_value);
  149. } else {
  150. lcd.print(" ");
  151. }
  152. }
  153. } else {
  154. lcd.setCursor ( 0, 1 );
  155. lcd.print("Pump deactivated. ");
  156. pump_running=false;
  157. }
  158. break;
  159. case 'f':
  160. // Glass filled
  161. lcd.setCursor ( 0, 1 );
  162. lcd.print("Ready, remove glass.");
  163. if(!button_pressed){
  164. state='i';
  165. }
  166. break;
  167. }
  168. // Update pump status
  169. if(pump_running) {
  170. digitalWrite(relay_port, 1);
  171. } else {
  172. digitalWrite(relay_port, 0);
  173. }
  174. // Update fluid amount
  175. //lcd.setCursor ( 0, 2 );
  176. //lcd.print(" ");
  177. lcd.setCursor ( 0, 2 );
  178. if(poti_value==0) {
  179. lcd.print("Amount: None ");
  180. } else {
  181. if(poti_value>100) {
  182. lcd.print("Amount: Infinite ");
  183. } else {
  184. lcd.print(String("Amount: ") + poti_value + "ml ");
  185. }
  186. }
  187. // --- LEDS ---
  188. EVERY_N_MILLISECONDS(50) {
  189. //static uint8_t hueA;
  190. fill_solid(ledsA, NUM_LEDS_A, CHSV(hueA, 255, 255));
  191. hueA++;
  192. }
  193. //------code for the second strip, ledsB here------
  194. // Putting the ledsB pattern inside this EVERY_N section allows
  195. // the speed for just this strip to be individually adjusted.
  196. // This will run every 500 milliseconds.
  197. // Use ledsB in this section, such as ledsB[i], and NUM_LEDS_B
  198. // with for loops so it uses the correct length of strip B.
  199. // For example:
  200. // EVERY_N_MILLISECONDS(20) {
  201. // }
  202. //------code for ledsC pattern------
  203. // This strip can run a similar or different pattern, and have
  204. // it's own timing. This will run every 35 milliseconds.
  205. // Use ledsC[i] and NUM_LEDS_C in this section.
  206. EVERY_N_MILLISECONDS(20) {
  207. static uint8_t hueC;
  208. static uint8_t brightnessC;
  209. static uint8_t countC;
  210. //fill_solid(ledsC, NUM_LEDS_B, CHSV(hueB, 255, 255));
  211. //hueB++;
  212. if(state=='f'){
  213. fill_solid(ledsC, NUM_LEDS_C, CHSV(255, 0, brightnessC));
  214. countC++;
  215. if(countC==10){
  216. countC=0;
  217. if(brightnessC<10){
  218. brightnessC=255;
  219. } else {
  220. brightnessC=0;
  221. }
  222. }
  223. } else {
  224. fill_solid(ledsC, NUM_LEDS_C, CHSV(hueC, 255, 255));
  225. }
  226. hueC++;
  227. }
  228. //------code for ledsLogo pattern------
  229. // This strip can also do it's own individual thing.
  230. // Use ledsD and NUM_LEDS_D in this section.
  231. EVERY_N_MILLISECONDS(20) {
  232. fill_rainbow( ledsD, NUM_LEDS_D, millis()/5, 12);
  233. }
  234. // Update the display for all strips.
  235. FastLED.show();
  236. }