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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. #include <Arduino.h>
  2. #include "Keymatrix.h"
  3. #include "SerialLCD.h"
  4. #include "Statemachine.h"
  5. #include "GPIOBank.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. GPIOBank valves(5);
  13. int valve_pins[5] = { 9, 10, 11, 12, 13 };
  14. GPIOBank pumps(3);
  15. int pump_pins[5] = { 14, 15, 16 };
  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. valves.setPinNumbers(valve_pins);
  96. valves.setOutput();
  97. pumps.setPinNumbers(pump_pins);
  98. pumps.setOutput();
  99. Serial.println("Setting up LCD, please wait");
  100. delay(1000); // give LCD some time to boot
  101. lcd.init();
  102. #ifdef DEBUG_WAIT_FOR_SERIAL_CONN
  103. lcd.write(0, "Waiting for serial");
  104. lcd.write(1, "connection on debug");
  105. lcd.write(2, "USB port...");
  106. while (!Serial);
  107. lcd.clear();
  108. #endif
  109. Serial.println("Ready, starting main loop");
  110. sm.begin();
  111. }
  112. void blink_lcd(int n, int wait = 200) {
  113. for (int i = 0; i < n; i++) {
  114. lcd.setBacklight(0);
  115. delay(wait);
  116. lcd.setBacklight(255);
  117. if (i < (n - 1))
  118. delay(wait);
  119. }
  120. }
  121. void loop() {
  122. keys.scan();
  123. while (keys.hasEvent()) {
  124. auto ke = keys.getEvent();
  125. if (ke.getType() == Keymatrix::Event::button_down) {
  126. last_input_time = millis();
  127. if (!backlight_state) {
  128. backlight_state = true;
  129. lcd.setBacklight(255);
  130. // swallow input when used to activate light
  131. continue;
  132. }
  133. int n = ke.getNum();
  134. Serial.print("Got keypad input: \"");
  135. if (n < 0) {
  136. Serial.print((n == -1) ? '*' : '#');
  137. } else {
  138. Serial.print(n);
  139. if (doing_multi_input) {
  140. char s[2] = { (char)(n + '0'), '\0' };
  141. lcd.write(s);
  142. }
  143. }
  144. Serial.println("\"");
  145. blink_lcd(1, 100);
  146. sm.input(n);
  147. }
  148. }
  149. #ifdef DEBUG_ENABLE_KEYPAD_INPUT_ON_SERIAL
  150. if (Serial.available() > 0) {
  151. last_input_time = millis();
  152. if (!backlight_state) {
  153. backlight_state = true;
  154. lcd.setBacklight(255);
  155. }
  156. int c = Serial.read();
  157. if (c == '*') {
  158. Serial.write(c);
  159. Serial.write('\n');
  160. if (doing_multi_input) {
  161. char s[2] = { (char)(c), '\0' };
  162. lcd.write(s);
  163. }
  164. sm.input(-1);
  165. } else if (c == '#') {
  166. Serial.write(c);
  167. Serial.write('\n');
  168. if (doing_multi_input) {
  169. char s[2] = { (char)(c), '\0' };
  170. lcd.write(s);
  171. }
  172. sm.input(-2);
  173. } else if (c == '\n') {
  174. Serial.write('#');
  175. Serial.write('\n');
  176. if (doing_multi_input) {
  177. char s[2] = { '#', '\0' };
  178. lcd.write(s);
  179. }
  180. sm.input(-2);
  181. } else if (c == '\b') {
  182. Serial.write(c);
  183. sm.input(-1);
  184. } else if ((c >= '0') && (c <= '9')) {
  185. Serial.write(c);
  186. if (!doing_multi_input) {
  187. Serial.write('\n');
  188. }
  189. if (doing_multi_input) {
  190. char s[2] = { (char)(c), '\0' };
  191. lcd.write(s);
  192. }
  193. sm.input(c - '0');
  194. }
  195. }
  196. #endif
  197. sm.act();
  198. if (backlight_state && (millis() >= (last_input_time + DISPLAY_BACKLIGHT_TIMEOUT))) {
  199. backlight_state = false;
  200. lcd.setBacklight(0);
  201. }
  202. }