Created
November 30, 2017 15:35
-
-
Save mai1015/b103249f3fdaf766a7996dbec9575397 to your computer and use it in GitHub Desktop.
AWPM
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// include the library code: | |
#include <LiquidCrystal.h> | |
#include <Wire.h> | |
// | |
#define BUTTON_PIN 7 | |
#define RELAY_PIN 13 | |
#define B_PIN 9 | |
#define FILL_TIME 30 //second | |
// VARIABLE | |
#define DURATION 15 | |
#define WATER_AMOUNT 3000 | |
#define ACH_AMOUNT 3000 | |
#define ONCE_AMOUNT 300 | |
#define PRE_TIME 30 //min | |
#define ONCE_TIME 10 //min | |
// init | |
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2; | |
LiquidCrystal lcd(rs, en, d4, d5, d6, d7); | |
// 0 off, 1 strat, 2 night mode, 3 debug | |
const String modetext[]= { | |
"OFF MODE", | |
"NORMAL MODE", | |
"NIGHT MODE", | |
"FORCE MODE", | |
"DEBUG MODE" | |
}; | |
int mode = -5; | |
//button | |
unsigned long lastButtonTime = 0; | |
int lastButtonState = LOW; | |
int bottonState = LOW; | |
//variable | |
int amount = WATER_AMOUNT; | |
int achieve = ACH_AMOUNT; | |
int remind = PRE_TIME; | |
unsigned long previousMillis = 0; | |
unsigned long current = 0; | |
int angle = 0; | |
bool drinked = true; | |
bool beeper = false; | |
unsigned long beeping = 0; | |
void setup() { | |
// init | |
pinMode(BUTTON_PIN, INPUT); | |
pinMode(RELAY_PIN, OUTPUT); | |
pinMode(B_PIN, OUTPUT); | |
Serial.begin(9600); | |
// set up the LCD's number of columns and rows: | |
lcd.begin(16, 2); | |
// Print a message to the LCD. | |
lcd.print("Welcome to AWPM"); | |
lcd.setCursor(0,1); | |
lcd.print(" Set your goal"); | |
// lcd.setCursor(0,1); | |
// lcd.print(" Setup amount"); | |
delay(2000); | |
lcd.clear(); | |
//printMode(lcd,mode); | |
} | |
void initMode() { | |
bottonState = digitalRead(BUTTON_PIN); | |
current = millis(); | |
if (mode == -5 || mode == -2) { | |
lcd.setCursor(0,0); | |
lcd.print(" HOLD TO INCR "); | |
lcd.setCursor(0,1); | |
lcd.print(" PRESS TO DECR "); | |
if (bottonState == HIGH) { | |
if (mode == -5) | |
mode = -4; | |
else | |
mode = -1; | |
} | |
return; | |
} | |
if (mode == -4) { | |
lcd.setCursor(0,0); | |
lcd.print(" TWICE TO SAVE "); | |
lcd.setCursor(0,1); | |
printState(lcd, String(achieve) + " ml", true); | |
if (bottonState == HIGH && lastButtonState == HIGH && current - previousMillis > 0.5*1000) { | |
achieve += 100; | |
delay(100); | |
} else if (bottonState == HIGH && lastButtonState == LOW) { | |
if (current - previousMillis < 0.3*1000) { | |
achieve += 100; | |
printState(lcd, String(achieve) + " ml", true); | |
mode = -3; | |
delay(1 * 1000); | |
} else { | |
if (achieve > 0) | |
achieve -= 100; | |
} | |
delay(20); | |
previousMillis = millis(); | |
} | |
lastButtonState = bottonState; | |
delay(20); | |
return; | |
} | |
if (mode == -3) { | |
lcd.setCursor(0,0); | |
lcd.print("SET UP REMINDER "); | |
lcd.setCursor(0,1); | |
lcd.print(" PRESS TO NEXT "); | |
if (bottonState == HIGH) { | |
mode = -2; | |
} | |
return; | |
} | |
if (mode == -1) { | |
lcd.setCursor(0,0); | |
lcd.print(" TWICE TO SET "); | |
lcd.setCursor(0,1); | |
printState(lcd, String(remind) + " minutes", true); | |
if (bottonState == HIGH && lastButtonState == HIGH && current - previousMillis > 0.5*1000) { | |
if (remind <=50) | |
remind += ONCE_TIME; | |
delay(100); | |
} else if (bottonState == HIGH && lastButtonState == LOW) { | |
if (current - previousMillis < 0.3*1000) { | |
remind += ONCE_TIME; | |
printState(lcd, String(remind) + " minutes", true); | |
mode = 0; | |
delay(1 * 1000); | |
} else { | |
if (remind > 0) | |
remind -= ONCE_TIME; | |
} | |
delay(20); | |
previousMillis = millis(); | |
} | |
lastButtonState = bottonState; | |
delay(20); | |
return; | |
} | |
} | |
void loop() { | |
bottonState = digitalRead(BUTTON_PIN); | |
current = millis(); | |
// Setup Mode | |
if (mode < 0) { | |
initMode(); | |
delay(20); | |
return; | |
} | |
// Wait | |
if (bottonState == HIGH && lastButtonState == HIGH && mode == 1) { | |
if (current - lastButtonTime > 5 * 1000) { | |
lastButtonTime = millis(); | |
lastButtonState = bottonState; | |
} | |
if (current - lastButtonTime > 3 * 1000 && current - lastButtonTime < 5 * 1000) { | |
printState(lcd, "REFILLING WATER", true); | |
watering(FILL_TIME); | |
previousMillis = millis(); | |
lastButtonTime = millis(); | |
lastButtonState = LOW; | |
amount -= ONCE_AMOUNT; | |
achieve -= ONCE_AMOUNT; | |
} | |
delay(50); | |
return; | |
} | |
// Check button and switch mode | |
if (bottonState == LOW && lastButtonState == HIGH) { | |
// refill successful | |
if (amount < ONCE_AMOUNT) { | |
mode = 1; | |
amount = WATER_AMOUNT; | |
beeper(false); | |
return; | |
} | |
if (achieve <= 0) { | |
mode = -5; | |
return; | |
} | |
// drink mode | |
if (drinked == false) { | |
printMode(lcd,mode); | |
drinked = true; | |
previousMillis = current; | |
} else { | |
if (mode < 4) { | |
mode++; | |
} else { | |
mode = 0; | |
} | |
printMode(lcd,mode); | |
// init | |
previousMillis = millis(); | |
//mode 1 | |
drinked = true; | |
} | |
delay(50); | |
} | |
lastButtonState = bottonState; | |
// Work flow | |
if (amount < ONCE_AMOUNT) { | |
lcd.setCursor(0,0); | |
lcd.print(" PLEASE REFILL "); | |
lcd.setCursor(0,1); | |
lcd.print("PRESS TO RESETUP"); | |
beeper(); | |
return; | |
} | |
if (achieve <=0) { | |
lcd.setCursor(0,0); | |
lcd.print(" YOU DID IT "); | |
lcd.setCursor(0,1); | |
lcd.print(" ACHIEVED GOAL! "); | |
return; | |
} | |
// start modes | |
current = millis(); | |
switch (mode) { | |
case 1: // NORMAL MODE | |
if (!drinked) { | |
if (current - previousMillis > DURATION * 1000) { | |
beeper(true); | |
unsigned long time = ((current - previousMillis) / 1000); | |
printState(lcd, "Over " + getTimeBySecond(time), true); | |
} else { | |
printState(lcd, "Time to drink"); | |
beeper(); | |
} | |
} else if ((current - previousMillis)/1000 > (remind)) { | |
drinked = false; | |
printState(lcd, "Time to drink"); | |
// TODO: make servo do 300 ml | |
amount -= ONCE_AMOUNT; | |
achieve -= ONCE_AMOUNT; | |
//angle = 180; | |
watering(FILL_TIME); | |
//delay(2 * 1000); | |
previousMillis = millis(); | |
} else { | |
printState(lcd, String(amount) + " ml left " + getTimeBySecond((current-previousMillis)/1000) , true); | |
} | |
break; | |
case 2: // NIGHT MODE | |
printState(lcd, " NOT DISTURB"); | |
break; | |
case 3: | |
if ((current - previousMillis)/1000 > (remind * 60)) { | |
printState(lcd, "Time to drink"); | |
// TODO: make servo do 300 ml | |
amount -= ONCE_AMOUNT; | |
achieve -= ONCE_AMOUNT; | |
//angle = 180; | |
watering(FILL_TIME); | |
//delay(2 * 1000); | |
digitalWrite(B_PIN, HIGH); | |
delay(2*1000); | |
digitalWrite(B_PIN, LOW); | |
previousMillis = millis(); | |
//printState(lcd, ""); | |
} else { | |
printState(lcd, String(amount) + " ml left", true); | |
} | |
break; | |
case 4: // DEBUG MODE | |
printMode(lcd, mode); | |
printState(lcd, String(millis() / 1000) + ";" + String(getTimeBySecond(((remind * 60)-(current-previousMillis)/1000)))); | |
delay(200); | |
break; | |
default: | |
lcd.setCursor(0, 1); | |
lcd.print("Press to switch "); | |
} | |
} | |
void printMode(LiquidCrystal lc, int mode) { | |
lc.clear(); | |
lc.print(modetext[mode]); | |
} | |
void printState(LiquidCrystal lc, String text, bool clear = false) { | |
lc.setCursor(0, 1); | |
Serial.println(text); | |
lc.print(text); | |
if (clear) { | |
byte length = text.length(); | |
for(byte i = length; i < 16; i++){ | |
lcd.write(' '); | |
} | |
} | |
} | |
void beeper(bool turnoff = false) { | |
if (turnoff) { | |
beeper = false; | |
digitalWrite(B_PIN, beeper); | |
} | |
if (current - beeping > 1 * 1000) { | |
beeper = !beeper; | |
digitalWrite(B_PIN,beeper?HIGH:LOW); | |
beeping = millis(); | |
} | |
} | |
String getTimeBySecond(unsigned long t) { | |
int h = 0, m = 0, s = 0; | |
if (t > 60) { | |
s = t % 60; | |
m = t / 60; | |
if (m > 60) { | |
h = m / 60; | |
m = m % 60; | |
return String(h) + "h" + String(m) + "m" + String(s) + "s"; | |
} | |
return String(m) + "m" + String(s) + "s"; | |
} | |
return String(t) + "s"; | |
} | |
void watering(int time) { | |
Serial.println("sending"); | |
// Wire.beginTransmission(ADDR); | |
// if (time != -1) { | |
// Wire.write(time); | |
// } | |
// Wire.write(angle); | |
// Wire.endTransmission(); | |
digitalWrite(RELAY_PIN, HIGH); | |
delay(time*1000); | |
digitalWrite(RELAY_PIN, LOW); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment