1
2
3
4
5
60
61
62
63
64
65
66
67
68#define HALL_SENSOR_BACKUP_VALUE 300
69
70
71
72#define FEEDER_STOP_DELAY 100
73
74
75#define LCD_BACKLIGHT_ON_TIME 30000
76
77
78#define MENU_TIMEOUT_VALUE 7000
79
80
81
82
83#include <LiquidCrystal_I2C.h>
84
85#include <Button.h>
86
87#include <DS3232RTC.h>
88
89#include <Time.h>
90
91#include <Wire.h>
92#include <EEPROM.h>
93
94
95
96
97
98
99
100
101
102
103#define HALL_SENSOR_PIN 3
104
105#define BUTTON_BACK_PIN 4
106#define BUTTON_UP_PIN 5
107#define BUTTON_DOWN_PIN 6
108#define BUTTON_SELECT_PIN 7
109#define BUTTON_CANCEL1_PIN 8
110#define BUTTON_CANCEL2_PIN 9
111#define BUTTON_MANUAL_PIN 10
112
113#define LED_CANCEL1_PIN A0
114#define LED_CANCEL2_PIN A1
115#define LED_SUCCESS1_PIN A2
116#define LED_SUCCESS2_PIN A3
117
118
119#define SERVO_OUTPUT_PIN 12
120
121
122#define LED_HALL_SENSOR_PIN 13
123
124
125LiquidCrystal_I2C lcd(0x3F, 16, 2);
126
127
128
129
130#define DEBOUNCE_MS 20
131
132#define REPEAT_FIRST 1000
133
134#define REPEAT_INCR 200
135
136#define PULLUP true
137#define INVERT true
138
139
140Button buttonSelect (BUTTON_SELECT_PIN, PULLUP, INVERT, DEBOUNCE_MS);
141Button buttonUp (BUTTON_UP_PIN, PULLUP, INVERT, DEBOUNCE_MS);
142Button buttonDown (BUTTON_DOWN_PIN, PULLUP, INVERT, DEBOUNCE_MS);
143Button buttonBack (BUTTON_BACK_PIN, PULLUP, INVERT, DEBOUNCE_MS);
144Button buttonCancel1 (BUTTON_CANCEL1_PIN, PULLUP, INVERT, DEBOUNCE_MS);
145Button buttonCancel2 (BUTTON_CANCEL2_PIN, PULLUP, INVERT, DEBOUNCE_MS);
146Button buttonManual (BUTTON_MANUAL_PIN, PULLUP, INVERT, DEBOUNCE_MS);
147
148
149int count;
150
151
152int lastCount = -1;
153
154unsigned long rpt = REPEAT_FIRST;
155
156
157unsigned long timeoutValue = 0;
158
159
160boolean manualCancelFeed1 = false;
161boolean manualCancelFeed2 = false;
162
163
164boolean manualFeed = false;
165
166
167int feedAmount1 = 1;
168int feedAmount2 = 1;
169bool feederSuccess = false;
170
171
172int portions = 0;
173int turns = 0;
174
175
176enum {btnSELECT, btnUP, btnDOWN, btnBACK, btnCANCEL1, btnCANCEL2, btnMANUAL, trigTIMEOUT};
177
178
179enum STATES
180{
181 MAIN,
182 MENU_EDIT_FEEDTIME1,
183 MENU_EDIT_FEEDTIME2,
184 MENU_EDIT_FEEDAMOUNT,
185 MENU_EDIT_TIME,
186 MENU_EDIT_DATE,
187 MENU_EDIT_SETTINGS,
188
189 EDIT_FEED_TIME1_HOUR,
190 EDIT_FEED_TIME1_MINUTE,
191 EDIT_FEED_TIME1_ON_OFF,
192
193 EDIT_FEED_TIME2_HOUR,
194 EDIT_FEED_TIME2_MINUTE,
195 EDIT_FEED_TIME2_ON_OFF,
196
197 EDIT_FEED_AMOUNT1,
198 EDIT_FEED_AMOUNT2,
199
200 EDIT_HOUR,
201 EDIT_MINUTE,
202
203 EDIT_DAY,
204 EDIT_MONTH,
205 EDIT_YEAR,
206
207 EDIT_SERVO_STOP_DELAY,
208 EDIT_SERVO_BACKUP_DELAY,
209};
210
211STATES state;
212
213int8_t userInput;
214int8_t trigger;
215
216int Second;
217int Minute;
218int Hour;
219int Day;
220int Month;
221int Year;
222
223int8_t DoW;
224String day_of_week;
225unsigned char address, data;
226
227int testt = 0;
228
229int feed_time1_hour;
230int feed_time1_minute;
231bool feed_time1_active = false;
232bool alarm1Activated = false;
233
234int feed_time2_hour;
235int feed_time2_minute;
236bool feed_time2_active = false;
237bool alarm2Activated = false;
238
239
240
241uint32_t blink_interval = 500;
242uint32_t blink_previousMillis = 0;
243uint32_t blink_currentMillis = 0;
244boolean blink_state = false;
245
246
247uint32_t spinningWheel_interval = 170;
248uint32_t spinningWheel_previousMillis = 0;
249uint32_t spinningWheel_currentMillis = 0;
250int spinningWheelSymbol = 0;
251
252
253
254
255uint32_t hallSensorBackup_interval = HALL_SENSOR_BACKUP_VALUE;
256uint32_t hallSensorBackup_currentMillis = 0;
257boolean hallSensorFail = false;
258
259
260uint32_t lcdBacklight_interval = LCD_BACKLIGHT_ON_TIME;
261uint32_t lcdBacklight_currentMillis = 0;
262
263boolean RTC_error = true;
264boolean long_press_button = false;
265
266
267byte bell_symbol_Char[8] = {
268 B00100,
269 B01110,
270 B01110,
271 B01110,
272 B11111,
273 B00100,
274 B00000,
275 B00000
276};
277
278byte inverted_one_Char[8] = {
279 0b11111,
280 0b11011,
281 0b10011,
282 0b11011,
283 0b11011,
284 0b11011,
285 0b10001,
286 0b11111
287};
288
289byte inverted_two_Char[8] = {
290 0b11111,
291 0b11011,
292 0b10101,
293 0b11101,
294 0b11011,
295 0b10111,
296 0b10001,
297 0b11111
298};
299
300byte arrow_up_Char[8] = {
301 0b00100,
302 0b01110,
303 0b11111,
304 0b01110,
305 0b01110,
306 0b01110,
307 0b01110,
308 0b00000
309};
310
311byte arrow_down_Char[8] = {
312 0b00000,
313 0b01110,
314 0b01110,
315 0b01110,
316 0b01110,
317 0b11111,
318 0b01110,
319 0b00100
320};
321
322byte inverted_p_Char[8] = {
323 0b11111,
324 0b10001,
325 0b10101,
326 0b10001,
327 0b10111,
328 0b10111,
329 0b11111,
330 0b00000
331};
332
333byte backslash_Char[8] = {
334 0b00000,
335 0b10000,
336 0b01000,
337 0b00100,
338 0b00010,
339 0b00001,
340 0b00000,
341 0b00000
342};
343
344byte thickDash_Char[8] = {
345 0b00000,
346 0b00000,
347 0b11111,
348 0b11111,
349 0b11111,
350 0b00000,
351 0b00000,
352 0b00000
353};
354
355volatile boolean hallSensorActivated = false;
356
357
358void HallSensorIsr()
359{
360 hallSensorActivated = true;
361
362 digitalWrite(LED_HALL_SENSOR_PIN, HIGH);
363}
364
365
366
367void HallSensorIsr();
368void setup();
369void loop();
370void change_states();
371void check_inputs();
372void transition(int trigger);
373void check_alarm();
374void check_manual_feed();
375void display_menu_option_set_feedtime1();
376void display_menu_option_set_feedtime2();
377void display_menu_option_set_feed_amount();
378void display_menu_option_set_time();
379void display_menu_option_set_date();
380void midnight_reset();
381void display_time();
382void displayFeedingAmouts();
383void displayFeedingTimes();
384void set_feedAmount();
385void set_time();
386void set_date();
387void set_feeding1_time();
388void set_feeding2_time();
389void get_time();
390void get_date();
391void write_time();
392void write_date();
393void write_feeding_time1();
394void write_feeding_time2();
395void write_feedamount();
396void get_feedamount();
397void get_feed_time1();
398void get_feed_time2();
399void check_RTC();
400byte decToBcd(byte val);
401byte bcdToDec(byte val);
402void leading_zero(int digits);
403void blinkFunction();
404void displaySpinningWheel();
405void startFeederServo();
406void stopFeederServo();
407void activateFeeder(int portions);
408void check_LcdBacklight();
409void lcd_backlight_ON();
410void ledsAndLcdDisplayStartup();
411void hallSensorCheck();
412#line 355
413
414
415
416void setup()
417{
418
419 lcd.begin();
420
421 lcd_backlight_ON();
422
423
424 Wire.begin();
425
426
427 pinMode(HALL_SENSOR_PIN, INPUT_PULLUP);
428 pinMode(LED_HALL_SENSOR_PIN, OUTPUT);
429 pinMode(SERVO_OUTPUT_PIN, OUTPUT);
430 pinMode(LED_CANCEL1_PIN, OUTPUT);
431 pinMode(LED_CANCEL2_PIN, OUTPUT);
432 pinMode(LED_SUCCESS1_PIN, OUTPUT);
433 pinMode(LED_SUCCESS2_PIN, OUTPUT);
434
435
436 digitalWrite(LED_CANCEL1_PIN, LOW);
437 digitalWrite(LED_CANCEL2_PIN, LOW);
438 digitalWrite(LED_SUCCESS1_PIN, LOW);
439 digitalWrite(LED_SUCCESS2_PIN, LOW);
440 digitalWrite(LED_HALL_SENSOR_PIN, LOW);
441
442 lcd.createChar(0, thickDash_Char);
443 lcd.createChar(1, bell_symbol_Char);
444 lcd.createChar(2, backslash_Char);
445 lcd.createChar(3, inverted_p_Char);
446 lcd.createChar(4, inverted_one_Char);
447 lcd.createChar(5, inverted_two_Char);
448 lcd.createChar(6, arrow_up_Char);
449 lcd.createChar(7, arrow_down_Char);
450
451
452 stopFeederServo();
453
454 Wire.begin();
455
456
457 setSyncProvider(RTC.get);
458
459 setSyncInterval(60);
460
461
462 RTC.squareWave(SQWAVE_NONE);
463
464
465
466
467 attachInterrupt(INT1, HallSensorIsr, FALLING);
468
469
470 ledsAndLcdDisplayStartup();
471
472
473 state = MAIN;
474
475
476 get_feed_time1();
477 get_feed_time2();
478
479}
480
481
482
483
484
485
486void loop()
487{
488
489 change_states();
490
491
492 check_inputs();
493
494
495 check_alarm();
496
497
498 check_manual_feed();
499
500
501 midnight_reset();
502
503
504 check_RTC();
505
506
507 hallSensorCheck();
508
509
510 check_LcdBacklight();
511
512}
513
514
515
516
517
518
519
520
521
522
523
524void change_states()
525{
526
527 switch (state)
528 {
529
530 case MAIN:
531 display_time();
532 displayFeedingAmouts();
533 displayFeedingTimes();
534 break;
535
536 case MENU_EDIT_FEEDTIME1:
537 display_menu_option_set_feedtime1();
538 break;
539
540 case MENU_EDIT_FEEDTIME2:
541 display_menu_option_set_feedtime2();
542 break;
543
544 case MENU_EDIT_FEEDAMOUNT:
545 display_menu_option_set_feed_amount();
546 break;
547
548 case MENU_EDIT_TIME:
549 display_menu_option_set_time();
550 break;
551
552 case MENU_EDIT_DATE:
553 display_menu_option_set_date();
554 break;
555
556
557 case EDIT_FEED_TIME1_HOUR:
558 set_feeding1_time();
559 break;
560
561 case EDIT_FEED_TIME1_MINUTE:
562 set_feeding1_time();
563 break;
564
565 case EDIT_FEED_TIME1_ON_OFF:
566 set_feeding1_time();
567 break;
568
569
570 case EDIT_FEED_TIME2_HOUR:
571 set_feeding2_time();
572 break;
573
574 case EDIT_FEED_TIME2_MINUTE:
575 set_feeding2_time();
576 break;
577
578 case EDIT_FEED_TIME2_ON_OFF:
579 set_feeding2_time();
580 break;
581
582
583 case EDIT_FEED_AMOUNT1:
584 set_feedAmount();
585 break;
586
587 case EDIT_FEED_AMOUNT2:
588 set_feedAmount();
589 break;
590
591
592 case EDIT_HOUR:
593 set_time();
594 break;
595
596 case EDIT_MINUTE:
597 set_time();
598 break;
599
600 case EDIT_DAY:
601 set_date();
602 break;
603
604 case EDIT_MONTH:
605 set_date();
606 break;
607
608 case EDIT_YEAR:
609 set_date();
610 break;
611
612 }
613}
614
615
616
617
618
619void check_inputs()
620{
621
622 if ( millis() - timeoutValue > MENU_TIMEOUT_VALUE )
623 {
624 userInput = trigTIMEOUT;
625 transition(userInput);
626 }
627
628
629 buttonSelect.read();
630 buttonUp.read();
631 buttonDown.read();
632 buttonBack.read();
633 buttonManual.read();
634 buttonCancel1.read();
635 buttonCancel2.read();
636
637
638 switch (buttonCancel1.wasPressed())
639 {
640 case 1:
641
642 manualCancelFeed1 = !manualCancelFeed1;
643
644 lcd_backlight_ON();
645
646
647 if (manualCancelFeed1 == 1)
648 {
649 lcd.clear();
650 lcd.setCursor(0, 0);
651
652 lcd.print("Upcoming Feed #1");
653 lcd.setCursor(0, 1);
654 lcd.print("cancelled once ");
655 delay(2000);
656 lcd.clear();
657 }
658 else if (manualCancelFeed1 == 0)
659 {
660 lcd.clear();
661 lcd.setCursor(0, 0);
662
663 lcd.print("Upcoming Feed #1");
664 lcd.setCursor(0, 1);
665 lcd.print("canceling undone");
666 delay(2000);
667 lcd.clear();
668 }
669 break;
670 }
671
672
673 switch (buttonCancel2.wasPressed())
674 {
675 case 1:
676
677 manualCancelFeed2 = !manualCancelFeed2;
678
679 lcd_backlight_ON();
680
681 if (manualCancelFeed2 == 1)
682 {
683 lcd.clear();
684 lcd.setCursor(0, 0);
685
686 lcd.print("Upcoming Feed #2");
687 lcd.setCursor(0, 1);
688 lcd.print("cancelled once ");
689 delay(2000);
690 lcd.clear();
691 }
692 else if (manualCancelFeed2 == 0)
693 {
694 lcd.clear();
695 lcd.setCursor(0, 0);
696
697 lcd.print("Upcoming Feed #2");
698 lcd.setCursor(0, 1);
699 lcd.print("canceling undone");
700 delay(2000);
701 lcd.clear();
702 }
703 break;
704 }
705
706
707 switch (buttonManual.wasPressed())
708 {
709 case 1:
710 manualFeed = true;
711
712 lcd_backlight_ON();
713 break;
714 }
715
716
717 switch (buttonSelect.wasPressed())
718 {
719 case 1:
720 userInput = btnSELECT;
721
722 lcd_backlight_ON();
723 transition(userInput);
724 break;
725 }
726
727 switch (buttonUp.wasPressed())
728 {
729 case 1:
730 userInput = btnUP;
731 transition(userInput);
732
733 lcd_backlight_ON();
734 break;
735 }
736
737 switch (buttonUp.wasReleased())
738 {
739 case 1:
740 long_press_button = false;
741 rpt = REPEAT_FIRST;
742 break;
743 }
744 switch (buttonUp.pressedFor(rpt))
745 {
746 case 1:
747
748 rpt += REPEAT_INCR;
749 long_press_button = true;
750 userInput = btnUP;
751 transition(userInput);
752 break;
753 }
754
755 switch (buttonDown.wasPressed())
756 {
757 case 1:
758 userInput = btnDOWN;
759 transition(userInput);
760
761 lcd_backlight_ON();
762 break;
763 }
764
765 switch (buttonDown.wasReleased())
766 {
767 case 1:
768 long_press_button = false;
769 rpt = REPEAT_FIRST;
770 break;
771 }
772 switch (buttonDown.pressedFor(rpt))
773 {
774 case 1:
775
776 rpt += REPEAT_INCR;
777 long_press_button = true;
778 userInput = btnDOWN;
779 transition(userInput);
780 break;
781 }
782
783 switch (buttonBack.wasPressed())
784 {
785 case 1:
786 userInput = btnBACK;
787 transition(userInput);
788
789 lcd_backlight_ON();
790 break;
791 }
792
793}
794
795
796
797
798
799void transition(int trigger)
800{
801 switch (state)
802 {
803
804 case MAIN:
805
806
807 timeoutValue = millis();
808
809 if (trigger == btnSELECT)
810 {
811 lcd.clear();
812 state = MENU_EDIT_FEEDTIME1;
813 }
814 else if (trigger == btnBACK)
815 {
816
817
818 }
819 break;
820
821 case MENU_EDIT_FEEDTIME1:
822
823
824 timeoutValue = millis();
825
826 if (trigger == trigTIMEOUT)
827 {
828 lcd.clear();
829 state = MAIN;
830 }
831
832
833 if (trigger == btnUP)
834 {
835
836 }
837 else if (trigger == btnDOWN)
838 {
839 lcd.clear();
840 state = MENU_EDIT_FEEDTIME2;
841 }
842 if (trigger == btnSELECT)
843 {
844 lcd.clear();
845 state = EDIT_FEED_TIME1_HOUR;
846 }
847 if (trigger == btnBACK)
848 {
849 lcd.clear();
850 state = MAIN;
851 }
852 break;
853
854 case MENU_EDIT_FEEDTIME2:
855
856
857 timeoutValue = millis();
858
859 if (trigger == trigTIMEOUT)
860 {
861 lcd.clear();
862 state = MAIN;
863 }
864
865
866 if (trigger == btnUP)
867 {
868 lcd.clear();
869 state = MENU_EDIT_FEEDTIME1;
870 }
871 else if (trigger == btnDOWN)
872 {
873 lcd.clear();
874 state = MENU_EDIT_FEEDAMOUNT;
875 }
876 if (trigger == btnSELECT)
877 {
878 lcd.clear();
879 state = EDIT_FEED_TIME2_HOUR;
880 }
881 if (trigger == btnBACK)
882 {
883 lcd.clear();
884 state = MAIN;
885 }
886 break;
887
888 case MENU_EDIT_FEEDAMOUNT:
889
890
891 timeoutValue = millis();
892
893 if (trigger == trigTIMEOUT)
894 {
895 lcd.clear();
896 state = MAIN;
897 }
898
899
900 if (trigger == btnUP)
901 {
902 lcd.clear();
903 state = MENU_EDIT_FEEDTIME2;
904 }
905 else if (trigger == btnDOWN)
906 {
907 lcd.clear();
908 state = MENU_EDIT_TIME;
909 }
910 if (trigger == btnSELECT)
911 {
912 lcd.clear();
913 state = EDIT_FEED_AMOUNT1;
914 }
915 if (trigger == btnBACK)
916 {
917 lcd.clear();
918 state = MAIN;
919 }
920 break;
921
922 case MENU_EDIT_TIME:
923
924
925 timeoutValue = millis();
926
927 if (trigger == trigTIMEOUT)
928 {
929 lcd.clear();
930 state = MAIN;
931 }
932
933
934 if (trigger == btnUP)
935 {
936 lcd.clear();
937 state = MENU_EDIT_FEEDTIME2;
938 }
939 if (trigger == btnDOWN)
940 {
941 lcd.clear();
942 state = MENU_EDIT_DATE;
943 }
944 if (trigger == btnSELECT)
945 {
946 lcd.clear();
947 state = EDIT_HOUR;
948 }
949 if (trigger == btnBACK)
950 {
951 lcd.clear();
952 state = MAIN;
953 }
954 break;
955
956 case MENU_EDIT_DATE:
957
958
959 timeoutValue = millis();
960
961 if (trigger == trigTIMEOUT)
962 {
963 lcd.clear();
964 state = MAIN;
965 }
966
967
968 if (trigger == btnUP)
969 {
970 lcd.clear();
971 state = MENU_EDIT_TIME;
972 }
973 else if (trigger == btnDOWN)
974 {
975
976 }
977 if (trigger == btnSELECT)
978 {
979 lcd.clear();
980 state = EDIT_DAY;
981 }
982 if (trigger == btnBACK)
983 {
984 lcd.clear();
985 state = MAIN;
986 }
987 break;
988
989
990 case EDIT_FEED_TIME1_HOUR:
991
992 timeoutValue = millis();
993
994 if (trigger == trigTIMEOUT)
995 {
996 lcd.clear();
997 state = MAIN;
998 }
999
1000
1001 if (trigger == btnUP)
1002 {
1003 feed_time1_hour++;
1004 if (feed_time1_hour > 23) feed_time1_hour = 0;
1005 }
1006 else if (trigger == btnDOWN)
1007 {
1008 feed_time1_hour--;
1009 if (feed_time1_hour < 0) feed_time1_hour = 23;
1010 }
1011 if (trigger == btnSELECT)
1012 {
1013 state = EDIT_FEED_TIME1_MINUTE;
1014 }
1015 break;
1016
1017 case EDIT_FEED_TIME1_MINUTE:
1018
1019 timeoutValue = millis();
1020
1021 if (trigger == trigTIMEOUT)
1022 {
1023 lcd.clear();
1024 state = MAIN;
1025 }
1026
1027
1028 if (trigger == btnUP)
1029 {
1030 feed_time1_minute++;
1031 if (feed_time1_minute > 59) feed_time1_minute = 0;
1032 }
1033 else if (trigger == btnDOWN)
1034 {
1035 feed_time1_minute--;
1036 if (feed_time1_minute < 0) feed_time1_minute = 59;
1037 }
1038 if (trigger == btnSELECT)
1039 {
1040 state = EDIT_FEED_TIME1_ON_OFF;
1041 }
1042 if (trigger == btnBACK)
1043 {
1044 state = EDIT_FEED_TIME1_HOUR;
1045 }
1046 break;
1047
1048 case EDIT_FEED_TIME1_ON_OFF:
1049
1050 timeoutValue = millis();
1051
1052 if (trigger == trigTIMEOUT)
1053 {
1054 lcd.clear();
1055 state = MAIN;
1056 }
1057
1058
1059 if (trigger == btnUP)
1060 {
1061 feed_time1_active = true;
1062 }
1063 else if (trigger == btnDOWN)
1064 {
1065 feed_time1_active = false;
1066 }
1067 if (trigger == btnBACK)
1068 {
1069 state = EDIT_FEED_TIME1_MINUTE;
1070 }
1071 if (trigger == btnSELECT)
1072 {
1073
1074 write_feeding_time1();
1075
1076 if (feed_time1_active == false)
1077 {
1078 manualCancelFeed1 = false;
1079 }
1080 lcd.clear();
1081 lcd.setCursor(0, 0);
1082
1083 lcd.print("*Settings saved*");
1084 delay(1000);
1085 lcd.clear();
1086 state = MAIN;
1087 }
1088
1089 break;
1090
1091 case EDIT_FEED_TIME2_HOUR:
1092
1093 timeoutValue = millis();
1094
1095 if (trigger == trigTIMEOUT)
1096 {
1097 lcd.clear();
1098 state = MAIN;
1099 }
1100
1101
1102 if (trigger == btnUP)
1103 {
1104 feed_time2_hour++;
1105 if (feed_time2_hour > 23) feed_time2_hour = 0;
1106 }
1107 else if (trigger == btnDOWN)
1108 {
1109 feed_time2_hour--;
1110 if (feed_time2_hour < 0) feed_time2_hour = 23;
1111 }
1112 if (trigger == btnSELECT)
1113 {
1114 state = EDIT_FEED_TIME2_MINUTE;
1115 }
1116 break;
1117
1118 case EDIT_FEED_TIME2_MINUTE:
1119
1120 timeoutValue = millis();
1121
1122 if (trigger == trigTIMEOUT)
1123 {
1124 lcd.clear();
1125 state = MAIN;
1126 }
1127
1128
1129 if (trigger == btnUP)
1130 {
1131 feed_time2_minute++;
1132 if (feed_time2_minute > 59) feed_time2_minute = 0;
1133 }
1134 else if (trigger == btnDOWN)
1135 {
1136 feed_time2_minute--;
1137 if (feed_time2_minute < 0) feed_time2_minute = 59;
1138 }
1139 if (trigger == btnSELECT)
1140 {
1141 state = EDIT_FEED_TIME2_ON_OFF;
1142 }
1143 if (trigger == btnBACK)
1144 {
1145 state = EDIT_FEED_TIME2_HOUR;
1146 }
1147 break;
1148
1149 case EDIT_FEED_TIME2_ON_OFF:
1150
1151 timeoutValue = millis();
1152
1153 if (trigger == trigTIMEOUT)
1154 {
1155 lcd.clear();
1156 state = MAIN;
1157 }
1158
1159
1160 if (trigger == btnUP)
1161 {
1162 feed_time2_active = true;
1163 }
1164 else if (trigger == btnDOWN)
1165 {
1166 feed_time2_active = false;
1167 }
1168 if (trigger == btnBACK)
1169 {
1170 state = EDIT_FEED_TIME2_MINUTE;
1171 }
1172 if (trigger == btnSELECT)
1173 {
1174
1175 write_feeding_time2();
1176
1177 if (feed_time2_active == false)
1178 {
1179 manualCancelFeed2 = false;
1180 }
1181 lcd.clear();
1182 lcd.setCursor(0, 0);
1183
1184 lcd.print("*Settings saved*");
1185 delay(1000);
1186 lcd.clear();
1187 state = MAIN;
1188 }
1189 break;
1190
1191 case EDIT_FEED_AMOUNT1:
1192
1193
1194 timeoutValue = millis();
1195
1196 if (trigger == trigTIMEOUT)
1197 {
1198 lcd.clear();
1199 state = MAIN;
1200 }
1201
1202
1203 if (trigger == btnUP)
1204 {
1205 feedAmount1++;
1206 if (feedAmount1 > 9) feedAmount1 = 1;
1207 }
1208 else if (trigger == btnDOWN)
1209 {
1210 feedAmount1--;
1211 if (feedAmount1 < 1) feedAmount1 = 9;
1212 }
1213 if (trigger == btnSELECT)
1214 {
1215 state = EDIT_FEED_AMOUNT2;
1216 }
1217 break;
1218
1219 case EDIT_FEED_AMOUNT2:
1220
1221
1222 timeoutValue = millis();
1223
1224 if (trigger == trigTIMEOUT)
1225 {
1226 lcd.clear();
1227 state = MAIN;
1228 }
1229
1230
1231 if (trigger == btnUP)
1232 {
1233 feedAmount2++;
1234 if (feedAmount2 > 9) feedAmount2 = 1;
1235 }
1236 else if (trigger == btnDOWN)
1237 {
1238 feedAmount2--;
1239 if (feedAmount2 < 1) feedAmount2 = 9;
1240 }
1241 if (trigger == btnSELECT)
1242 {
1243 write_feedamount();
1244 lcd.clear();
1245 lcd.setCursor(0, 0);
1246
1247 lcd.print("*Settings saved*");
1248 delay(1000);
1249
1250 lcd.clear();
1251 state = MAIN;
1252 }
1253 break;
1254
1255 case EDIT_HOUR:
1256
1257
1258 timeoutValue = millis();
1259
1260 if (trigger == trigTIMEOUT)
1261 {
1262 lcd.clear();
1263 state = MAIN;
1264 }
1265
1266
1267 if (trigger == btnUP)
1268 {
1269 Hour++;
1270 if (Hour > 23) Hour = 0;
1271 }
1272 else if (trigger == btnDOWN)
1273 {
1274 Hour--;
1275 if (Hour < 0) Hour = 23;
1276 }
1277 if (trigger == btnSELECT)
1278 {
1279 state = EDIT_MINUTE;
1280 }
1281 break;
1282
1283
1284 case EDIT_MINUTE:
1285
1286
1287 timeoutValue = millis();
1288
1289 if (trigger == trigTIMEOUT)
1290 {
1291 lcd.clear();
1292 state = MAIN;
1293 }
1294
1295
1296 if (trigger == btnUP)
1297 {
1298 Minute++;
1299 if (Minute > 59) Minute = 0;
1300 }
1301 else if (trigger == btnDOWN)
1302 {
1303 Minute--;
1304 if (Minute < 0) Minute = 59;
1305 }
1306
1307 if (trigger == btnBACK)
1308 {
1309 state = EDIT_HOUR;
1310 }
1311 if (trigger == btnSELECT)
1312 {
1313 write_time();
1314 lcd.clear();
1315 lcd.setCursor(0, 0);
1316
1317 lcd.print("*Settings saved*");
1318 delay(1000);
1319
1320 lcd.clear();
1321 state = MAIN;
1322 }
1323 break;
1324
1325
1326 case EDIT_DAY:
1327
1328 timeoutValue = millis();
1329
1330 if (trigger == trigTIMEOUT)
1331 {
1332 lcd.clear();
1333 state = MAIN;
1334 }
1335
1336
1337 if (trigger == btnUP)
1338 {
1339 Day++;
1340 if (Day > 31) Day = 1;
1341 }
1342 else if (trigger == btnDOWN)
1343 {
1344 Day--;
1345 if (Day < 1) Day = 31;
1346 }
1347 if (trigger == btnSELECT)
1348 {
1349 state = EDIT_MONTH;
1350 }
1351 break;
1352
1353 case EDIT_MONTH:
1354
1355 timeoutValue = millis();
1356
1357 if (trigger == trigTIMEOUT)
1358 {
1359 lcd.clear();
1360 state = MAIN;
1361 }
1362
1363
1364 if (trigger == btnUP)
1365 {
1366 Month++;
1367 if (Month > 12) Month = 1;
1368 }
1369 else if (trigger == btnDOWN)
1370 {
1371 Month--;
1372 if (Month < 1) Month = 12;
1373 }
1374 if (trigger == btnSELECT)
1375 {
1376
1377
1378 state = EDIT_YEAR;
1379 }
1380 if (trigger == btnBACK)
1381 {
1382 state = EDIT_DAY;
1383 }
1384 break;
1385
1386 case EDIT_YEAR:
1387
1388 timeoutValue = millis();
1389
1390 if (trigger == trigTIMEOUT)
1391 {
1392 lcd.clear();
1393 state = MAIN;
1394 }
1395
1396
1397 if (trigger == btnUP)
1398 {
1399 Year++;
1400 if (Year > 50) Year = 18;
1401 }
1402 else if (trigger == btnDOWN)
1403 {
1404 Year--;
1405 if (Year < 18) Year = 50;
1406 }
1407 if (trigger == btnBACK)
1408 {
1409 state = EDIT_MONTH;
1410 }
1411 if (trigger == btnSELECT)
1412 {
1413 write_date();
1414 lcd.clear();
1415 lcd.setCursor(0, 0);
1416
1417 lcd.print("*Settings saved*");
1418 delay(1000);
1419 lcd.clear();
1420 state = MAIN;
1421 }
1422 break;
1423 }
1424}
1425
1426
1427
1428
1429
1430
1431
1432
1433void check_alarm()
1434{
1435
1436 if (Second == 0)
1437 {
1438
1439
1440
1441 if ( (Hour == feed_time1_hour) && (Minute == feed_time1_minute) )
1442 {
1443
1444 alarm1Activated = true;
1445
1446
1447
1448 if ( (feed_time1_active == true) && (manualCancelFeed1 == false) )
1449 {
1450 lcd.clear();
1451 lcd.setCursor(0, 0);
1452
1453 lcd.print("*** Feed #1 ****");
1454
1455 lcd.setCursor(1, 1);
1456 lcd.print("/");
1457 lcd.print(feedAmount1);
1458 lcd.print(" portions");
1459
1460
1461
1462 activateFeeder(feedAmount1);
1463
1464
1465
1466 if (hallSensorFail == false)
1467 {
1468
1469 digitalWrite(LED_SUCCESS1_PIN, HIGH);
1470 }
1471 else
1472 {
1473
1474 digitalWrite(LED_SUCCESS1_PIN, LOW);
1475 }
1476 }
1477 }
1478
1479
1480
1481
1482 if ( (Hour == feed_time2_hour) && (Minute == feed_time2_minute) )
1483 {
1484
1485 alarm2Activated = true;
1486
1487
1488
1489 if ( (feed_time2_active == true) && (manualCancelFeed2 == false) )
1490 {
1491 lcd.clear();
1492 lcd.setCursor(0, 0);
1493
1494 lcd.print("*** Feed #2 ****");
1495
1496 lcd.setCursor(1, 1);
1497 lcd.print("/");
1498 lcd.print(feedAmount2);
1499 lcd.print(" portions");
1500
1501
1502
1503 activateFeeder(feedAmount2);
1504
1505
1506
1507 if (hallSensorFail == false)
1508 {
1509
1510 digitalWrite(LED_SUCCESS2_PIN, HIGH);
1511 }
1512 else
1513 {
1514
1515 digitalWrite(LED_SUCCESS2_PIN, LOW);
1516 }
1517
1518 }
1519 }
1520
1521 }
1522
1523
1524 else
1525 {
1526
1527
1528 if (alarm1Activated == true)
1529 {
1530
1531 alarm1Activated = false;
1532 manualCancelFeed1 = false;
1533 }
1534
1535
1536 if (alarm2Activated == true)
1537 {
1538
1539 alarm2Activated = false;
1540 manualCancelFeed2 = false;
1541 }
1542 }
1543}
1544
1545
1546
1547void check_manual_feed()
1548{
1549 if (manualFeed == true)
1550 {
1551
1552 lcd.clear();
1553 lcd.setCursor(0, 0);
1554
1555 lcd.print(" Manual feeding ");
1556 lcd.setCursor(2, 1);
1557 lcd.print("portion");
1558
1559
1560 activateFeeder(1);
1561
1562
1563
1564 manualFeed = false;
1565 }
1566}
1567
1568
1569void display_menu_option_set_feedtime1()
1570{
1571
1572
1573
1574 digitalWrite(LED_CANCEL1_PIN, LOW);
1575 digitalWrite(LED_CANCEL2_PIN, LOW);
1576
1577
1578 lcd.setCursor(0, 0);
1579
1580 lcd.write(0);
1581 lcd.print("MENU");
1582
1583 for (int dash = 1; dash <= 9; dash++)
1584 {
1585 lcd.write(0);
1586 }
1587
1588
1589 lcd.setCursor(15, 1);
1590
1591 lcd.write(7);
1592
1593
1594 lcd.setCursor(0, 1);
1595
1596 lcd.print("Feedingtime #1 ");
1597}
1598
1599
1600void display_menu_option_set_feedtime2()
1601{
1602
1603 lcd.setCursor(0, 0);
1604
1605 lcd.write(0);
1606 lcd.print("MENU");
1607
1608 for (int dash = 1; dash <= 9; dash++)
1609 {
1610 lcd.write(0);
1611 }
1612
1613
1614 lcd.setCursor(15, 0);
1615
1616 lcd.write(6);
1617 lcd.setCursor(15, 1);
1618
1619 lcd.write(7);
1620
1621
1622 lcd.setCursor(0, 1);
1623 lcd.print("Feedingtime #2 ");
1624
1625}
1626
1627
1628void display_menu_option_set_feed_amount()
1629{
1630
1631 lcd.setCursor(0, 0);
1632
1633 lcd.write(0);
1634 lcd.print("MENU");
1635
1636 for (int dash = 1; dash <= 9; dash++)
1637 {
1638 lcd.write(0);
1639 }
1640
1641
1642 lcd.setCursor(15, 0);
1643
1644 lcd.write(6);
1645 lcd.setCursor(15, 1);
1646
1647 lcd.write(7);
1648
1649
1650 lcd.setCursor(0, 1);
1651
1652 lcd.print("Feed portions ");
1653
1654}
1655
1656
1657void display_menu_option_set_time()
1658{
1659
1660 lcd.setCursor(0, 0);
1661
1662 lcd.write(0);
1663 lcd.print("MENU");
1664
1665 for (int dash = 1; dash <= 9; dash++)
1666 {
1667 lcd.write(0);
1668 }
1669
1670
1671 lcd.setCursor(15, 0);
1672
1673 lcd.write(6);
1674 lcd.setCursor(15, 1);
1675
1676 lcd.write(7);
1677
1678
1679 lcd.setCursor(0, 1);
1680
1681 lcd.print("Set the time ");
1682}
1683
1684
1685void display_menu_option_set_date()
1686{
1687
1688 lcd.setCursor(0, 0);
1689
1690 lcd.write(0);
1691 lcd.print("MENU");
1692
1693 for (int dash = 1; dash <= 9; dash++)
1694 {
1695 lcd.write(0);
1696 }
1697
1698
1699 lcd.setCursor(15, 0);
1700
1701 lcd.write(6);
1702 lcd.setCursor(15, 1);
1703
1704
1705
1706 lcd.setCursor(0, 1);
1707
1708 lcd.print("Set the date ");
1709}
1710
1711
1712
1713void midnight_reset()
1714{
1715
1716 if ( (Hour == 0) && (Minute == 0) )
1717 {
1718
1719 hallSensorFail = false;
1720
1721
1722 digitalWrite(LED_SUCCESS1_PIN, LOW);
1723 digitalWrite(LED_SUCCESS2_PIN, LOW);
1724
1725
1726
1727
1728 }
1729}
1730
1731
1732void display_time()
1733{
1734
1735 get_time();
1736 get_date();
1737
1738 lcd.setCursor(11, 0);
1739 leading_zero(Hour);
1740 lcd.print(":");
1741 leading_zero(Minute);
1742 lcd.setCursor(14, 1);
1743 leading_zero(Second);
1744}
1745
1746
1747void displayFeedingAmouts()
1748{
1749
1750 get_feedamount();
1751
1752 lcd.setCursor(8, 0);
1753 lcd.write(3);
1754 lcd.print(feedAmount1);
1755 lcd.setCursor(8, 1);
1756 lcd.write(3);
1757 lcd.print(feedAmount2);
1758}
1759
1760
1761void displayFeedingTimes()
1762{
1763
1764
1765
1766
1767 lcd.setCursor(0, 0);
1768 lcd.write(4);
1769
1770
1771 lcd.setCursor(6, 0);
1772 if (feed_time1_active == true)
1773 {
1774 if (manualCancelFeed1 == true)
1775 {
1776
1777 if (blink_state == 0)
1778 {
1779
1780 lcd.write(1);
1781
1782 digitalWrite(LED_CANCEL1_PIN, HIGH);
1783 }
1784 else
1785 {
1786
1787 lcd.print(" ");
1788
1789 digitalWrite(LED_CANCEL1_PIN, LOW);
1790 }
1791 }
1792 else
1793 {
1794
1795 lcd.write(1);
1796
1797 digitalWrite(LED_CANCEL1_PIN, LOW);
1798 }
1799 }
1800
1801 else
1802 {
1803
1804 lcd.print(" ");
1805
1806 digitalWrite(LED_CANCEL1_PIN, LOW);
1807 }
1808
1809
1810 lcd.setCursor(1, 0);
1811 leading_zero(feed_time1_hour);
1812 lcd.print(":");
1813 leading_zero(feed_time1_minute);
1814
1815
1816
1817
1818
1819 lcd.setCursor(0, 1);
1820 lcd.write(5);
1821
1822
1823 lcd.setCursor(6, 1);
1824 if (feed_time2_active == true)
1825 {
1826 if (manualCancelFeed2 == true)
1827 {
1828
1829 if (blink_state == 0)
1830 {
1831
1832 lcd.write(1);
1833
1834 digitalWrite(LED_CANCEL2_PIN, HIGH);
1835 }
1836 else
1837 {
1838
1839 lcd.print(" ");
1840
1841 digitalWrite(LED_CANCEL2_PIN, LOW);
1842 }
1843 }
1844 else
1845 {
1846
1847 lcd.write(1);
1848
1849 digitalWrite(LED_CANCEL2_PIN, LOW);
1850 }
1851 }
1852
1853 else
1854 {
1855
1856 lcd.print(" ");
1857
1858 digitalWrite(LED_CANCEL2_PIN, LOW);
1859 }
1860
1861
1862 lcd.setCursor(1, 1);
1863 leading_zero(feed_time2_hour);
1864 lcd.print(":");
1865 leading_zero(feed_time2_minute);
1866
1867
1868 blinkFunction();
1869}
1870
1871
1872void set_feedAmount()
1873{
1874 lcd.setCursor(0, 0);
1875
1876 lcd.write(0);
1877
1878 lcd.print("SET PORTIONS ");
1879
1880 for (int dash = 1; dash <= 3; dash++)
1881 {
1882 lcd.write(0);
1883 }
1884
1885 switch (state)
1886 {
1887
1888 case EDIT_FEED_AMOUNT1:
1889
1890 lcd.setCursor(0, 1);
1891 lcd.print("Feed1:");
1892 if (long_press_button == false)
1893 {
1894 if (blink_state == 0)
1895 {
1896 lcd.setCursor(6, 1);
1897 lcd.print(feedAmount1);
1898 }
1899 else
1900 {
1901 lcd.setCursor(6, 1);
1902 lcd.print(" ");
1903 }
1904 }
1905 else
1906 {
1907 lcd.setCursor(6, 1);
1908 lcd.print(feedAmount1);
1909 }
1910
1911 lcd.setCursor(9, 1);
1912 lcd.print("Feed2:");
1913 lcd.print(feedAmount2);
1914 break;
1915
1916 case EDIT_FEED_AMOUNT2:
1917
1918 lcd.setCursor(0, 1);
1919 lcd.print("Feed1:");
1920 lcd.print(feedAmount1);
1921
1922 if (long_press_button == false)
1923 {
1924 if (blink_state == 0)
1925 {
1926 lcd.setCursor(15, 1);
1927 lcd.print(feedAmount2);
1928 }
1929 else
1930 {
1931 lcd.setCursor(15, 1);
1932 lcd.print(" ");
1933 }
1934 }
1935 else
1936 {
1937 lcd.setCursor(15, 1);
1938 lcd.print(feedAmount2);
1939 }
1940 break;
1941 }
1942
1943
1944 blinkFunction();
1945}
1946
1947void set_time()
1948{
1949 lcd.setCursor(0, 0);
1950
1951 lcd.write(0);
1952
1953 lcd.print("SET THE TIME ");
1954 for (int dash = 1; dash <= 3; dash++)
1955 {
1956 lcd.write(0);
1957 }
1958
1959 switch (state)
1960 {
1961
1962 case EDIT_HOUR:
1963 if (long_press_button == false)
1964 {
1965 if (blink_state == 0)
1966 {
1967 lcd.setCursor(4, 1);
1968 leading_zero(Hour);
1969 }
1970 else
1971 {
1972 lcd.setCursor(4, 1);
1973 lcd.print(" ");
1974 }
1975 }
1976 else
1977 {
1978 lcd.setCursor(4, 1);
1979 leading_zero(Hour);
1980 }
1981 lcd.print(":");
1982 leading_zero(Minute);
1983 break;
1984
1985 case EDIT_MINUTE:
1986 lcd.setCursor(4, 1);
1987 leading_zero(Hour);
1988 lcd.print(":");
1989 if (long_press_button == false)
1990 {
1991 if (blink_state == 0) {
1992 lcd.setCursor(7, 1);
1993 leading_zero(Minute);
1994 }
1995 else
1996 {
1997 lcd.setCursor(7, 1);
1998 lcd.print(" ");
1999 }
2000 }
2001 else
2002 {
2003 lcd.setCursor(7, 1);
2004 leading_zero(Minute);
2005 }
2006 break;
2007 }
2008
2009
2010 blinkFunction();
2011}
2012
2013
2014void set_date()
2015{
2016 lcd.setCursor(0, 0);
2017
2018 lcd.write(0);
2019
2020 lcd.print("SET THE TIME ");
2021 for (int dash = 1; dash <= 3; dash++)
2022 {
2023 lcd.write(0);
2024 }
2025
2026 switch (state)
2027 {
2028 case EDIT_DAY:
2029 if (long_press_button == false)
2030 {
2031 if (blink_state == 0)
2032 {
2033 lcd.setCursor(4, 1);
2034 leading_zero(Day);
2035 }
2036 else
2037 {
2038 lcd.setCursor(4, 1);
2039 lcd.print(" ");
2040 }
2041 }
2042 else
2043 {
2044 lcd.setCursor(4, 1);
2045 leading_zero(Day);
2046 }
2047 lcd.print("/");
2048 leading_zero(Month);
2049 lcd.print("/");
2050 leading_zero(Year);
2051 break;
2052
2053 case EDIT_MONTH:
2054 lcd.setCursor(4, 1);
2055 leading_zero(Day);
2056 lcd.print("/");
2057 if (long_press_button == false)
2058 {
2059 if (blink_state == 0)
2060 {
2061 lcd.setCursor(7, 1);
2062 leading_zero(Month);
2063 }
2064 else
2065 {
2066 lcd.setCursor(7, 1);
2067 lcd.print(" ");
2068 }
2069 }
2070 else
2071 {
2072 lcd.setCursor(7, 1);
2073 leading_zero(Month);
2074 }
2075
2076 lcd.print("/");
2077 leading_zero(Year);
2078 break;
2079
2080 case EDIT_YEAR:
2081
2082 lcd.setCursor(4, 1);
2083 leading_zero(Day);
2084 lcd.print("/");
2085 leading_zero(Month);
2086 lcd.print("/");
2087 if (long_press_button == false)
2088 {
2089 if (blink_state == 0)
2090 {
2091 lcd.setCursor(10, 1);
2092 leading_zero(Year);
2093 }
2094 else
2095 {
2096 lcd.setCursor(10, 1);
2097 lcd.print(" ");
2098 }
2099 }
2100 else
2101 {
2102 lcd.setCursor(10, 1);
2103 leading_zero(Year);
2104 }
2105 break;
2106 }
2107
2108
2109 blinkFunction();
2110}
2111
2112
2113void set_feeding1_time()
2114{
2115 lcd.setCursor(0, 0);
2116
2117 lcd.write(0);
2118
2119 lcd.print("FEEDING TIME 1");
2120
2121 lcd.write(0);
2122
2123 if (feed_time1_active == true)
2124 {
2125 lcd.setCursor(8, 1);
2126 lcd.print("ENABLED ");
2127 } else
2128 {
2129 lcd.setCursor(8, 1);
2130 lcd.print("DISABLED");
2131 }
2132
2133 switch (state)
2134 {
2135
2136 case EDIT_FEED_TIME1_HOUR:
2137 if (long_press_button == false)
2138 {
2139 if (blink_state == 0)
2140 {
2141 lcd.setCursor(1, 1);
2142 leading_zero(feed_time1_hour);
2143 }
2144 else
2145 {
2146 lcd.setCursor(1, 1);
2147 lcd.print(" ");
2148 }
2149 }
2150 else
2151 {
2152 lcd.setCursor(1, 1);
2153 leading_zero(feed_time1_hour);
2154 }
2155 lcd.print(":");
2156 leading_zero(feed_time1_minute);
2157 break;
2158
2159 case EDIT_FEED_TIME1_MINUTE:
2160 lcd.setCursor(1, 1);
2161 leading_zero(feed_time1_hour);
2162 lcd.print(":");
2163 if (long_press_button == false)
2164 {
2165 if (blink_state == 0)
2166 {
2167 lcd.setCursor(4, 1);
2168 leading_zero(feed_time1_minute);
2169 }
2170 else
2171 {
2172 lcd.setCursor(4, 1);
2173 lcd.print(" ");
2174 }
2175 }
2176 else
2177 {
2178 lcd.setCursor(4, 1);
2179 leading_zero(feed_time1_minute);
2180 }
2181 break;
2182
2183 case EDIT_FEED_TIME1_ON_OFF:
2184 lcd.setCursor(4, 1);
2185 leading_zero(feed_time1_minute);
2186
2187 if (feed_time1_active == true)
2188 {
2189 if (blink_state == 0)
2190 {
2191 lcd.setCursor(8, 1);
2192 lcd.print("ENABLED ");
2193 }
2194 else
2195 {
2196 lcd.setCursor(8, 1);
2197 lcd.print(" ");
2198 }
2199 }
2200 else
2201 {
2202 if (blink_state == 0)
2203 {
2204 lcd.setCursor(8, 1);
2205 lcd.print("DISABLED");
2206 }
2207 else
2208 {
2209 lcd.setCursor(8, 1);
2210 lcd.print(" ");
2211 }
2212 }
2213 break;
2214 }
2215
2216
2217 blinkFunction();
2218}
2219
2220
2221void set_feeding2_time()
2222{
2223 lcd.setCursor(0, 0);
2224
2225 lcd.write(0);
2226
2227 lcd.print("FEEDING TIME 2");
2228
2229 lcd.write(0);
2230
2231
2232 if (feed_time2_active == true)
2233 {
2234 lcd.setCursor(8, 1);
2235 lcd.print("ENABLED ");
2236 } else
2237 {
2238 lcd.setCursor(8, 1);
2239 lcd.print("DISABLED");
2240 }
2241
2242 switch (state)
2243 {
2244
2245 case EDIT_FEED_TIME2_HOUR:
2246 if (long_press_button == false)
2247 {
2248 if (blink_state == 0)
2249 {
2250 lcd.setCursor(1, 1);
2251 leading_zero(feed_time2_hour);
2252 }
2253 else
2254 {
2255 lcd.setCursor(1, 1);
2256 lcd.print(" ");
2257 }
2258 }
2259 else
2260 {
2261 lcd.setCursor(1, 1);
2262 leading_zero(feed_time2_hour);
2263 }
2264 lcd.print(":");
2265 leading_zero(feed_time2_minute);
2266 break;
2267
2268 case EDIT_FEED_TIME2_MINUTE:
2269 lcd.setCursor(1, 1);
2270 leading_zero(feed_time2_hour);
2271 lcd.print(":");
2272 if (long_press_button == false)
2273 {
2274 if (blink_state == 0)
2275 {
2276 lcd.setCursor(4, 1);
2277 leading_zero(feed_time2_minute);
2278 }
2279 else
2280 {
2281 lcd.setCursor(4, 1);
2282 lcd.print(" ");
2283 }
2284 }
2285 else
2286 {
2287 lcd.setCursor(4, 1);
2288 leading_zero(feed_time2_minute);
2289 }
2290 break;
2291
2292 case EDIT_FEED_TIME2_ON_OFF:
2293 lcd.setCursor(4, 1);
2294 leading_zero(feed_time2_minute);
2295
2296 if (feed_time2_active == true)
2297 {
2298 if (blink_state == 0)
2299 {
2300 lcd.setCursor(8, 1);
2301 lcd.print("ENABLED ");
2302 }
2303 else
2304 {
2305 lcd.setCursor(8, 1);
2306 lcd.print(" ");
2307 }
2308 }
2309 else
2310 {
2311 if (blink_state == 0)
2312 {
2313 lcd.setCursor(8, 1);
2314 lcd.print("DISABLED");
2315 }
2316 else
2317 {
2318 lcd.setCursor(8, 1);
2319 lcd.print(" ");
2320 }
2321 }
2322 break;
2323 }
2324
2325
2326 blinkFunction();
2327}
2328
2329
2330void get_time()
2331{
2332 Wire.beginTransmission(0x68);
2333
2334 Wire.write(0);
2335 Wire.endTransmission();
2336
2337 Wire.requestFrom(0x68, 3);
2338 Second = bcdToDec(Wire.read() & 0x7f);
2339 Minute = bcdToDec(Wire.read() );
2340 Hour = bcdToDec(Wire.read() & 0x3f);
2341}
2342
2343
2344void get_date()
2345{
2346 Wire.beginTransmission(0x68);
2347
2348 Wire.write(4);
2349 Wire.endTransmission();
2350
2351
2352 Wire.requestFrom(0x68, 3);
2353 Day = bcdToDec(Wire.read());
2354 Month = bcdToDec(Wire.read());
2355 Year = bcdToDec(Wire.read());
2356}
2357
2358
2359void write_time()
2360{
2361 Wire.beginTransmission(0x68);
2362 Wire.write(0x00);
2363 Second = 0;
2364 Wire.write(decToBcd(Second));
2365 Wire.write(decToBcd(Minute));
2366 Wire.write(decToBcd(Hour));
2367 Wire.write(0x00);
2368 Wire.endTransmission();
2369}
2370
2371
2372void write_date()
2373{
2374 Wire.beginTransmission(0x68);
2375 Wire.write(4);
2376
2377 Wire.write(decToBcd(Day));
2378 Wire.write(decToBcd(Month));
2379 Wire.write(decToBcd(Year));
2380 Wire.endTransmission();
2381}
2382
2383
2384void write_feeding_time1()
2385{
2386
2387 EEPROM.write(0, feed_time1_hour);
2388 EEPROM.write(1, feed_time1_minute);
2389 EEPROM.write(2, feed_time1_active);
2390}
2391
2392
2393void write_feeding_time2()
2394{
2395
2396 EEPROM.write(3, feed_time2_hour);
2397 EEPROM.write(4, feed_time2_minute);
2398 EEPROM.write(5, feed_time2_active);
2399}
2400
2401
2402void write_feedamount()
2403{
2404
2405 EEPROM.write(6, feedAmount1);
2406 EEPROM.write(7, feedAmount2);
2407}
2408
2409
2410void get_feedamount()
2411{
2412
2413 feedAmount1 = EEPROM.read(6);
2414 if (feedAmount1 > 9) feedAmount1 = 0;
2415 feedAmount2 = EEPROM.read(7);
2416 if (feedAmount2 > 9) feedAmount2 = 0;
2417}
2418
2419
2420void get_feed_time1()
2421{
2422
2423 feed_time1_hour = EEPROM.read(0);
2424 if (feed_time1_hour > 23) feed_time1_hour = 0;
2425 feed_time1_minute = EEPROM.read(1);
2426 if (feed_time1_minute > 59) feed_time1_minute = 0;
2427 feed_time1_active = EEPROM.read(2);
2428}
2429
2430
2431void get_feed_time2()
2432{
2433
2434 feed_time2_hour = EEPROM.read(3);
2435 if (feed_time2_hour > 23) feed_time2_hour = 0;
2436 feed_time2_minute = EEPROM.read(4);
2437 if (feed_time2_minute > 59) feed_time2_minute = 0;
2438 feed_time2_active = EEPROM.read(5);
2439}
2440
2441
2442
2443void check_RTC()
2444{
2445 if (timeStatus() != timeSet)
2446
2447 RTC_error = true;
2448 else
2449
2450 RTC_error = false;
2451}
2452
2453
2454
2455byte decToBcd(byte val)
2456{
2457 return ( (val / 10 * 16) + (val % 10) );
2458}
2459
2460
2461
2462byte bcdToDec(byte val)
2463{
2464 return ( (val / 16 * 10) + (val % 16) );
2465}
2466
2467
2468void leading_zero(int digits)
2469{
2470
2471 if (digits < 10)
2472 {
2473 lcd.print("0");
2474 }
2475
2476 lcd.print(digits);
2477
2478}
2479
2480
2481void blinkFunction()
2482{
2483
2484 blink_currentMillis = millis();
2485 if (blink_currentMillis - blink_previousMillis > blink_interval)
2486 {
2487
2488 blink_previousMillis = blink_currentMillis;
2489
2490 blink_state = !blink_state;
2491 }
2492}
2493
2494void displaySpinningWheel()
2495{
2496
2497
2498 lcd.setCursor(15, 1);
2499 switch (spinningWheelSymbol)
2500 {
2501 case 1:
2502 lcd.print("|");
2503 break;
2504 case 2:
2505 lcd.print("/");
2506 break;
2507 case 3:
2508 lcd.print("-");
2509 break;
2510 case 4:
2511
2512
2513 lcd.write(2);
2514 break;
2515 case 5:
2516
2517 spinningWheelSymbol = 1;
2518 break;
2519 }
2520
2521
2522 spinningWheel_currentMillis = millis();
2523 if (spinningWheel_currentMillis - spinningWheel_previousMillis
2524 > spinningWheel_interval)
2525 {
2526
2527 spinningWheel_previousMillis = spinningWheel_currentMillis;
2528
2529 spinningWheelSymbol += 1;
2530 }
2531}
2532
2533void startFeederServo()
2534{
2535 digitalWrite(SERVO_OUTPUT_PIN, HIGH);
2536
2537
2538 delayMicroseconds(950);
2539 digitalWrite(SERVO_OUTPUT_PIN, LOW);
2540 delay(20);
2541}
2542
2543
2544void stopFeederServo()
2545{
2546 digitalWrite(SERVO_OUTPUT_PIN, HIGH);
2547
2548 delayMicroseconds(1490);
2549 digitalWrite(SERVO_OUTPUT_PIN, LOW);
2550 delay(20);
2551}
2552
2553
2554void activateFeeder(int portions)
2555{
2556
2557
2558 turns = 1;
2559 int rotationTime = 0;
2560
2561
2562 spinningWheelSymbol = 1;
2563
2564
2565 hallSensorBackup_currentMillis = millis();
2566
2567
2568
2569
2570 while (turns <= portions)
2571 {
2572
2573
2574 lcd.setCursor(0, 1);
2575 lcd.print(turns);
2576
2577
2578 displaySpinningWheel();
2579
2580
2581 startFeederServo();
2582
2583
2584
2585 if ( hallSensorActivated == true
2586 ||
2587 millis() - hallSensorBackup_currentMillis > hallSensorBackup_interval )
2588 {
2589
2590 rotationTime = millis() - hallSensorBackup_currentMillis;
2591
2592
2593
2594
2595
2596 if (hallSensorActivated == false)
2597 {
2598 hallSensorFail = true;
2599 }
2600
2601
2602 hallSensorActivated = false;
2603 hallSensorBackup_currentMillis = millis();
2604
2605
2606 buttonBack.read();
2607 if (buttonBack.wasPressed())
2608 {
2609
2610 hallSensorActivated = false;
2611
2612 break;
2613 }
2614
2615
2616 turns += 1;
2617
2618
2619
2620 digitalWrite(LED_HALL_SENSOR_PIN, LOW);
2621
2622 }
2623 }
2624
2625
2626
2627
2628 lcd.setCursor(15, 1);
2629 lcd.print(" ");
2630
2631 delay(FEEDER_STOP_DELAY);
2632
2633 stopFeederServo();
2634
2635
2636 lcd.clear();
2637 lcd.setCursor(0, 0);
2638
2639 lcd.print("* Feeding done *");
2640
2641
2642
2643
2644 if (manualFeed == true)
2645 {
2646 lcd.setCursor(0, 1);
2647 lcd.print("1 rotation=");
2648 lcd.print(rotationTime);
2649 lcd.print("ms");
2650 }
2651 delay(2000);
2652 lcd.clear();
2653}
2654
2655
2656void check_LcdBacklight()
2657{
2658 if ( millis() - lcdBacklight_currentMillis > LCD_BACKLIGHT_ON_TIME)
2659 {
2660 lcd.noBacklight();
2661 }
2662}
2663
2664
2665void lcd_backlight_ON()
2666{
2667
2668 lcdBacklight_currentMillis = millis();
2669
2670 lcd.backlight();
2671}
2672
2673void ledsAndLcdDisplayStartup()
2674{
2675
2676 digitalWrite(LED_CANCEL1_PIN, HIGH);
2677 digitalWrite(LED_CANCEL2_PIN, HIGH);
2678 digitalWrite(LED_SUCCESS1_PIN, HIGH);
2679 digitalWrite(LED_SUCCESS2_PIN, HIGH);
2680 digitalWrite(LED_HALL_SENSOR_PIN, HIGH);
2681
2682
2683 lcd.clear();
2684 for (int p = 0; p <= 15; p++)
2685 {
2686
2687 lcd.setCursor(p, 0);
2688 lcd.write(255);
2689
2690 lcd.setCursor(15 - p, 1);
2691 lcd.write(255);
2692 delay(50);
2693 }
2694 lcd.clear();
2695
2696 for (int p = 0; p <= 15; p++)
2697 {
2698
2699 lcd.setCursor(15 - p, 0);
2700 lcd.write(255);
2701
2702 lcd.setCursor(p, 1);
2703 lcd.write(255);
2704 delay(50);
2705 }
2706
2707
2708 lcd.clear();
2709 lcd.setCursor(0, 0);
2710
2711 lcd.print("Pet Feed-O-Matic");
2712 lcd.setCursor(0, 1);
2713 lcd.print("v1.1_UK 20-02-18");
2714 delay(5000);
2715 lcd.clear();
2716
2717
2718 lcd.clear();
2719 digitalWrite(LED_CANCEL1_PIN, LOW);
2720 digitalWrite(LED_CANCEL2_PIN, LOW);
2721 digitalWrite(LED_SUCCESS1_PIN, LOW);
2722 digitalWrite(LED_SUCCESS2_PIN, LOW);
2723 digitalWrite(LED_HALL_SENSOR_PIN, LOW);
2724
2725}
2726
2727void hallSensorCheck()
2728{
2729 if (hallSensorFail == true)
2730 {
2731
2732 if (blink_state == 0)
2733 {
2734
2735 digitalWrite(LED_HALL_SENSOR_PIN, HIGH);
2736 }
2737 else
2738 {
2739
2740 digitalWrite(LED_HALL_SENSOR_PIN, LOW);
2741 }
2742
2743 blinkFunction();
2744 }
2745}
2746
fzzzz
2 months ago
Hello, I’m doing this project for school and I’m wondering if it would be possible to do it without a sensor. Like would it still work but not be accurate? If it’s not 100% accurate it’s fine.