#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include "OneButton.h"
#include <Servo.h>
#include "pitches.h"
#define NOTE_B0 31
#define NOTE_C1 33
#define NOTE_CS1 35
#define NOTE_D1 37
#define NOTE_DS1 39
#define NOTE_E1 41
#define NOTE_F1 44
#define NOTE_FS1 46
#define NOTE_G1 49
#define NOTE_GS1 52
#define NOTE_A1 55
#define NOTE_AS1 58
#define NOTE_B1 62
#define NOTE_C2 65
#define NOTE_CS2 69
#define NOTE_D2 73
#define NOTE_DS2 78
#define NOTE_E2 82
#define NOTE_F2 87
#define NOTE_FS2 93
#define NOTE_G2 98
#define NOTE_GS2 104
#define NOTE_A2 110
#define NOTE_AS2 117
#define NOTE_B2 123
#define NOTE_C3 131
#define NOTE_CS3 139
#define NOTE_D3 147
#define NOTE_DS3 156
#define NOTE_E3 165
#define NOTE_F3 175
#define NOTE_FS3 185
#define NOTE_G3 196
#define NOTE_GS3 208
#define NOTE_A3 220
#define NOTE_AS3 233
#define NOTE_B3 247
#define NOTE_C4 262
#define NOTE_CS4 277
#define NOTE_D4 294
#define NOTE_DS4 311
#define NOTE_E4 330
#define NOTE_F4 349
#define NOTE_FS4 370
#define NOTE_G4 392
#define NOTE_GS4 415
#define NOTE_A4 440
#define NOTE_AS4 466
#define NOTE_B4 494
#define NOTE_C5 523
#define NOTE_CS5 554
#define NOTE_D5 587
#define NOTE_DS5 622
#define NOTE_E5 659
#define NOTE_F5 698
#define NOTE_FS5 740
#define NOTE_G5 784
#define NOTE_GS5 831
#define NOTE_A5 880
#define NOTE_AS5 932
#define NOTE_B5 988
#define NOTE_C6 1047
#define NOTE_CS6 1109
#define NOTE_D6 1175
#define NOTE_DS6 1245
#define NOTE_E6 1319
#define NOTE_F6 1397
#define NOTE_FS6 1480
#define NOTE_G6 1568
#define NOTE_GS6 1661
#define NOTE_A6 1760
#define NOTE_AS6 1865
#define NOTE_B6 1976
#define NOTE_C7 2093
#define NOTE_CS7 2217
#define NOTE_D7 2349
#define NOTE_DS7 2489
#define NOTE_E7 2637
#define NOTE_F7 2794
#define NOTE_FS7 2960
#define NOTE_G7 3136
#define NOTE_GS7 3322
#define NOTE_A7 3520
#define NOTE_AS7 3729
#define NOTE_B7 3951
#define NOTE_C8 4186
#define NOTE_CS8 4435
#define NOTE_D8 4699
#define NOTE_DS8 4978
#define NOTE_SUSTAIN 200
// Setup a new OneButton on pin A1.
OneButton btn(4, true);
#define sAudioPin 11
LiquidCrystal_I2C lcd(0x27, 20, 4); // Set the LCD I2C address
#define Start 6 // start stop button
int setHours = 0;
int setMinutes = 0;
int setSeconds = 5;
int hours = 0;
int minutes = 0;
int seconds = 0;
boolean timeState = false;
#define encoderPinA 2 // right
#define encoderPinB 3 // left
#define encoderButton 5 // switch
int HMS = 1;
int encoderPos = 0; // a counter for the dial
unsigned int lastReportedPos = 1; // change management
static boolean rotating = false; // debounce management
boolean A_set = false;
boolean B_set = false;
int mode = 0; // 0: timer mode, 1: setting mode
int timeMode = 0;
Servo myservo;
void setup() {
pinMode(Start, INPUT_PULLUP);
pinMode(encoderPinA, INPUT_PULLUP); //enabling pullups
pinMode(encoderPinB, INPUT_PULLUP);
pinMode(encoderButton, INPUT_PULLUP);
attachInterrupt(0, doEncoderA, CHANGE); //pin 2
attachInterrupt(1, doEncoderB, CHANGE); //pin 3
Serial.begin(115200); // output
myservo.attach(3);
myservo.write(0);
lcd.begin(16, 2); // initialize the lcd for 16 chars 2 lines, turn on backlight
// lcd.clear();
// lcd.setCursor(0, 0);
// lcd.print("COUNT DOWN TIMER");
// lcd.setCursor(4, 1);
// lcd.print("00:00:00");
// link the button 1 functions.
btn.attachClick(onBtnClicked);
// button1.attachDoubleClick(doubleclick1);
// button1.attachLongPressStart(longPressStart1);
btn.attachLongPressStop(onBtnLongPress);
// button1.attachDuringLongPress(longPress1);
Serial.println("setup done");
// Start
resetTimer();
// startCountdownTimer();
}
void setTimeMode(int mode) {
switch (mode) {
case 0:
setHours = 0;
setMinutes = 0;
setSeconds = 15;
// hours = 0;
// minutes = 0;
// seconds = 15;
break;
case 1:
setHours = 1;
setMinutes = 0;
setSeconds = 0;
// hours = 1;
// minutes = 0;
// seconds = 0;
break;
case 2:
setHours = 3;
setMinutes = 0;
setSeconds = 0;
// hours = 3;
// minutes = 0;
// seconds = 0;
break;
case 3:
setHours = 6;
setMinutes = 0;
setSeconds = 0;
// hours = 6;
// minutes = 0;
// seconds = 0;
break;
}
resetTimer();
}
void displayTimeMode(int mode) {
if (timeMode == 0) {
drawText(5, "MODE 1", 4, "00:00:15");
singleSound();
}
else if (timeMode == 1) {
drawText(5, "MODE 2", 4, "01:00:00");
singleSound();
singleSound();
}
else if (timeMode == 2) {
drawText(5, "MODE 3", 4, "03:00:00");
singleSound();
singleSound();
singleSound();
}
else {
drawText(5, "MODE 4", 4, "06:00:00");
singleSound();
singleSound();
singleSound();
singleSound();
}
}
void onBtnClicked() {
Serial.println("clicked");
switch (mode) {
case 0:
// startCountdownTimer();
feeding();
break;
case 1:
timeMode = (timeMode + 1) % 4;
displayTimeMode(timeMode);
break;
default:
break;
}
}
void onBtnLongPress() {
Serial.println("long press");
if (mode == 1) {
// Set current mode
doubleSound();
Serial.print("Time mode: ");
Serial.println(timeMode);
setTimeMode(timeMode);
mode = 0;
// startCountdownTimer();
return;
}
// Go to setting mode
longSound();
mode = 1;
drawText(4, "SETTING", 0, "");
delay(1500);
displayTimeMode(timeMode);
}
void resetTimer() {
hours = setHours;
minutes = setMinutes;
seconds = setSeconds;
Serial.print(hours);
Serial.print(":");
Serial.print(minutes);
Serial.print(":");
Serial.println(seconds);
drawText(0, " WILL FEED IN ", 0, "");
renderTime();
}
void feeding() {
winSound();
drawText(0, "FEEDING .....", 4, "MLEMMMM");
myservo.write(180);
delay(3000);
myservo.write(0);
delay(3000);
// reset timer
resetTimer();
mode = 0;
}
void doubleSound() {
tone(11, 500, 100);
delay(200);
tone(11, 500, 100);
delay(200);
}
void longSound() {
tone(11, 500, 500);
delay(500);
}
void singleSound() {
tone(11, 500, 100);
delay(200);
}
void winSound() {
for (uint8_t nLoop = 0; nLoop < 2; nLoop ++)
{
tone(sAudioPin, NOTE_A5);
delay(NOTE_SUSTAIN);
tone(sAudioPin, NOTE_B5);
delay(NOTE_SUSTAIN);
tone(sAudioPin, NOTE_C5);
delay(NOTE_SUSTAIN);
tone(sAudioPin, NOTE_B5);
delay(NOTE_SUSTAIN);
tone(sAudioPin, NOTE_C5);
delay(NOTE_SUSTAIN);
tone(sAudioPin, NOTE_D5);
delay(NOTE_SUSTAIN);
tone(sAudioPin, NOTE_C5);
delay(NOTE_SUSTAIN);
tone(sAudioPin, NOTE_D5);
delay(NOTE_SUSTAIN);
tone(sAudioPin, NOTE_E5);
delay(NOTE_SUSTAIN);
tone(sAudioPin, NOTE_D5);
delay(NOTE_SUSTAIN);
tone(sAudioPin, NOTE_E5);
delay(NOTE_SUSTAIN);
tone(sAudioPin, NOTE_E5);
delay(NOTE_SUSTAIN);
}
noTone(sAudioPin);
}
void failSound() {
tone(sAudioPin, NOTE_G4);
delay(250);
tone(sAudioPin, NOTE_C4);
delay(500);
noTone(sAudioPin);
}
void tickTimer() {
Serial.println("tick timer");
// timeState = true;
//delay(1000);
// while (timeState == true) {
if (minutes == 0 && hours >= 1) {
minutes = 60;
hours = hours - 1;
}
if (seconds == 0 && minutes >= 1) {
seconds = 60;
minutes = minutes - 1;
}
else if (minutes == 0 && hours == 0 && seconds == 0) { //count down alarm
mode = 2;
feeding();
return;
// while (timeState == true) {
// tone(11, 600, 250);
// delay(250);
// tone(11, 800, 250);
// delay(250);
// if (digitalRead(Start) == LOW) { // turn alarm off
// timeState = false;
// seconds = 1;
// lcd.clear();
// lcd.setCursor(0, 0);
// lcd.print("COUNT DOWN TIMER");
// lcd.setCursor(4, 1);
// lcd.print("00:00:00");
// break;
// }
// }
}
// delay(992); // delay for keping time master setting
seconds = seconds - 1;
renderTime();
// if (digitalRead(Start) == LOW) {
// delay(1000);
// timeState = false;
// break;
// }
// }
}
void renderTime() {
lcd.setCursor(4, 1);
if (hours <= 9)
{
lcd.print("0");
}
lcd.print(hours);
lcd.print(":");
if (minutes <= 9)
{
lcd.print("0");
}
lcd.print(minutes);
lcd.print(":");
if (seconds <= 9)
{
lcd.print("0");
}
lcd.print(seconds);
}
void drawText(int p1, String t1, int p2, String t2) {
lcd.clear();
lcd.setCursor(p1, 0);
lcd.print(t1);
lcd.setCursor(p2, 1);
lcd.print(t2);
}
unsigned int previous = millis();
void loop() {
btn.tick();
if (mode == 0) {
if (millis() - previous > 1000)
{
previous = millis();
tickTimer();
//Just nothing here. It does nothing here.
}
} else if (mode == 1) {
}
}
// Interrupt on A changing state
void doEncoderA() {
// debounce
if ( rotating ) delay (1); // wait a little until the bouncing is done
// Test transition, did things really change?
if ( digitalRead(encoderPinA) != A_set ) { // debounce once more
A_set = !A_set;
// adjust counter + if A leads B
if ( A_set && !B_set )
encoderPos = 1;
rotating = false; // no more debouncing until loop() hits again
}
}
// Interrupt on B changing state
void doEncoderB() {
if ( rotating ) delay (1);
if ( digitalRead(encoderPinB) != B_set ) {
B_set = !B_set;
// adjust counter - 1 if B leads A
if ( B_set && !A_set )
encoderPos = -1;
rotating = false;
}
}