DIY fertilizer mixer and plant watering machine https://www.xythobuz.de/giessomat.html
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.

main.cpp 5.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. #include <Arduino.h>
  2. #include "Keymatrix.h"
  3. #include "SerialLCD.h"
  4. #include "Statemachine.h"
  5. #include "Plants.h"
  6. //#define DEBUG_WAIT_FOR_SERIAL_CONN
  7. #define DEBUG_ENABLE_LCD_OUTPUT_ON_SERIAL
  8. #define DEBUG_ENABLE_KEYPAD_INPUT_ON_SERIAL
  9. SerialLCD lcd(9);
  10. Keymatrix keys(4, 3);
  11. int keymatrix_pins[4 + 3] = { 5, 6, 7, 8, 2, 3, 4 };
  12. Plants plants(5, 3, 2);
  13. int valve_pins[5] = { 10, 11, 12, 13, 14 };
  14. int pump_pins[3] = { 15, 16, 17 };
  15. int switch_pins[2] = { 18, 19 };
  16. #define DISPLAY_BACKLIGHT_TIMEOUT (5UL * 60UL * 1000UL)
  17. unsigned long last_input_time = 0;
  18. bool backlight_state = true;
  19. bool doing_multi_input = false;
  20. void write_to_all(const char *a, const char *b,
  21. const char *c, const char *d, int num_input) {
  22. lcd.clear();
  23. if (num_input >= 0) {
  24. lcd.write(0, a);
  25. if (num_input >= 1) {
  26. lcd.write(1, b);
  27. }
  28. if (num_input >= 2) {
  29. lcd.write(2, c);
  30. }
  31. if (num_input >= 3) {
  32. lcd.write(3, d);
  33. }
  34. lcd.cursor(3);
  35. doing_multi_input = true;
  36. } else {
  37. lcd.write(0, a);
  38. lcd.write(1, b);
  39. lcd.write(2, c);
  40. lcd.write(3, d);
  41. lcd.cursor(0);
  42. doing_multi_input = false;
  43. }
  44. #ifdef DEBUG_ENABLE_LCD_OUTPUT_ON_SERIAL
  45. int la = strlen(a);
  46. int lb = strlen(b);
  47. int lc = strlen(c);
  48. int ld = strlen(d);
  49. Serial.println();
  50. Serial.println(" ----------------------");
  51. Serial.print("| ");
  52. Serial.print(a);
  53. if (la < 20) {
  54. for (int i = 0; i < (20 - la); i++) {
  55. Serial.print(' ');
  56. }
  57. }
  58. Serial.println(" |");
  59. Serial.print("| ");
  60. Serial.print(b);
  61. if (lb < 20) {
  62. for (int i = 0; i < (20 - lb); i++) {
  63. Serial.print(' ');
  64. }
  65. }
  66. Serial.println(" |");
  67. Serial.print("| ");
  68. Serial.print(c);
  69. if (lc < 20) {
  70. for (int i = 0; i < (20 - lc); i++) {
  71. Serial.print(' ');
  72. }
  73. }
  74. Serial.println(" |");
  75. Serial.print("| ");
  76. Serial.print(d);
  77. if (ld < 20) {
  78. for (int i = 0; i < (20 - ld); i++) {
  79. Serial.print(' ');
  80. }
  81. }
  82. Serial.println(" |");
  83. Serial.println(" ----------------------");
  84. Serial.println("Please provide keypad input:");
  85. #endif
  86. }
  87. void backspace(void) {
  88. lcd.write("\b");
  89. }
  90. Statemachine sm(write_to_all, backspace);
  91. void setup() {
  92. Serial.begin(115200);
  93. Serial.println("Initializing Giess-o-mat");
  94. keys.setPins(keymatrix_pins);
  95. plants.setValvePins(valve_pins);
  96. plants.setPumpPins(pump_pins);
  97. plants.setSwitchPins(switch_pins, true);
  98. Serial.println("Setting up LCD, please wait");
  99. delay(1000); // give LCD some time to boot
  100. lcd.init();
  101. #ifdef DEBUG_WAIT_FOR_SERIAL_CONN
  102. lcd.write(0, "Waiting for serial");
  103. lcd.write(1, "connection on debug");
  104. lcd.write(2, "USB port...");
  105. while (!Serial);
  106. lcd.clear();
  107. #endif
  108. Serial.println("Ready, starting main loop");
  109. sm.begin();
  110. }
  111. void blink_lcd(int n, int wait = 200) {
  112. for (int i = 0; i < n; i++) {
  113. lcd.setBacklight(0);
  114. delay(wait);
  115. lcd.setBacklight(255);
  116. if (i < (n - 1))
  117. delay(wait);
  118. }
  119. }
  120. void loop() {
  121. keys.scan();
  122. while (keys.hasEvent()) {
  123. auto ke = keys.getEvent();
  124. if (ke.getType() == Keymatrix::Event::button_down) {
  125. last_input_time = millis();
  126. if (!backlight_state) {
  127. backlight_state = true;
  128. lcd.setBacklight(255);
  129. // swallow input when used to activate light
  130. continue;
  131. }
  132. int n = ke.getNum();
  133. Serial.print("Got keypad input: \"");
  134. if (n < 0) {
  135. Serial.print((n == -1) ? '*' : '#');
  136. } else {
  137. Serial.print(n);
  138. if (doing_multi_input) {
  139. char s[2] = { (char)(n + '0'), '\0' };
  140. lcd.write(s);
  141. }
  142. }
  143. Serial.println("\"");
  144. blink_lcd(1, 100);
  145. sm.input(n);
  146. }
  147. }
  148. #ifdef DEBUG_ENABLE_KEYPAD_INPUT_ON_SERIAL
  149. if (Serial.available() > 0) {
  150. last_input_time = millis();
  151. if (!backlight_state) {
  152. backlight_state = true;
  153. lcd.setBacklight(255);
  154. }
  155. int c = Serial.read();
  156. if (c == '*') {
  157. Serial.write(c);
  158. Serial.write('\n');
  159. if (doing_multi_input) {
  160. char s[2] = { (char)(c), '\0' };
  161. lcd.write(s);
  162. }
  163. sm.input(-1);
  164. } else if (c == '#') {
  165. Serial.write(c);
  166. Serial.write('\n');
  167. if (doing_multi_input) {
  168. char s[2] = { (char)(c), '\0' };
  169. lcd.write(s);
  170. }
  171. sm.input(-2);
  172. } else if (c == '\n') {
  173. Serial.write('#');
  174. Serial.write('\n');
  175. if (doing_multi_input) {
  176. char s[2] = { '#', '\0' };
  177. lcd.write(s);
  178. }
  179. sm.input(-2);
  180. } else if (c == '\b') {
  181. Serial.write(c);
  182. sm.input(-1);
  183. } else if ((c >= '0') && (c <= '9')) {
  184. Serial.write(c);
  185. if (!doing_multi_input) {
  186. Serial.write('\n');
  187. }
  188. if (doing_multi_input) {
  189. char s[2] = { (char)(c), '\0' };
  190. lcd.write(s);
  191. }
  192. sm.input(c - '0');
  193. }
  194. }
  195. #endif
  196. sm.act();
  197. if (backlight_state && (millis() >= (last_input_time + DISPLAY_BACKLIGHT_TIMEOUT))) {
  198. backlight_state = false;
  199. lcd.setBacklight(0);
  200. }
  201. }