#include <LiquidCrystal.h>
/* Display */
LiquidCrystal lcd(12, 11, 10, 9, 8, 7);
byte statusLed = 13;
byte sensorInterrupt = 0;
byte sensorPin = 2;
float calibrationFactor = 4.8; // YF-G1 DN25 1inch Water Flow Sensor
volatile byte pulseCount;
float flowRate;
unsigned int flowMilliLitres;
unsigned long totalMilliLitres;
unsigned long oldTime;
unsigned long current_value=0;
////////////////////////////////
const int btn_enter = 6;
const int btn_up = 5;
const int btn_down = 4;
const int btn_left = 3;
signed long setpoint_value=0;
String v;
char str[17];
char str_num[10];
int mode=0;
unsigned int cursor_loc=1;
unsigned long multiple_value(int v);
void setup()
{
// Initialize a serial connection for reporting values to the host
Serial.begin(9600);
// Set up the status LED line as an output
pinMode(statusLed, OUTPUT);
digitalWrite(statusLed, HIGH); // We have an active-low LED attached
pinMode(sensorPin, INPUT);
digitalWrite(sensorPin, HIGH);
pulseCount = 0;
flowRate = 0.0;
flowMilliLitres = 0;
totalMilliLitres = 0;
oldTime = 0;
// The Hall-effect sensor is connected to pin 2 which uses interrupt 0.
// Configured to trigger on a FALLING state change (transition from HIGH
// state to LOW state)
attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
lcd.begin(16, 2);
//init_icons(lcd);
delay(100);
lcd.clear();
pinMode(btn_enter, INPUT);
pinMode(btn_up, INPUT);
pinMode(btn_down, INPUT);
pinMode(btn_left, INPUT);
}
void loop()
{
if (mode == 0){
setpoint();
}else{
if ((millis() - oldTime) > 1000) // Only process counters once per second
{
detachInterrupt(sensorInterrupt);
flowRate = ((1000.0 / (millis() - oldTime)) * pulseCount) / calibrationFactor; // F = 4.8 * Q => Q = F/4.8 (L/min)
oldTime = millis();
flowMilliLitres = (flowRate / 60) * 1000;
totalMilliLitres += flowMilliLitres;
unsigned int frac;
// Print the flow rate for this second in litres / minute
Serial.print("Flow rate: ");
Serial.print(int(flowRate)); // Print the integer part of the variable
Serial.print("L/min");
Serial.print("t"); // Print tab space
// Print the cumulative total of litres flowed since starting
Serial.print("Output Liquid Quantity: ");
Serial.print(totalMilliLitres);
Serial.println("mL");
Serial.print("t"); // Print tab space
Serial.print(totalMilliLitres / 1000);
Serial.print("L");
// Reset the pulse counter so we can start incrementing again
pulseCount = 0;
// Enable the interrupt again now that we've finished sending output
attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
}
}
}
/*
Insterrupt Service Routine
*/
void pulseCounter()
{
// Increment the pulse counter
pulseCount++;
}
void checkbutton(){
if (digitalRead(btn_up) == 0){
delay(150);
if (digitalRead(btn_up) == 0){
//unsigned long value = pow(10,cursor_loc);
Serial.println(setpoint_value);
Serial.println(multiple_value(cursor_loc));
setpoint_value = (signed long)setpoint_value + (signed long)multiple_value(cursor_loc) ;
Serial.println(setpoint_value);
if (setpoint_value > 99999) setpoint_value=0;
dislay_change_value_setpoint();
}
}
//
if (digitalRead(btn_down) == 0){
delay(150);
if (digitalRead(btn_down) == 0){
//unsigned long value = pow(10,cursor_loc);
setpoint_value = setpoint_value - (signed long)multiple_value(cursor_loc) ;
if (setpoint_value < 0) setpoint_value=0;
dislay_change_value_setpoint();
}
}
//
if (digitalRead(btn_left) == 0){
delay(150);
if (digitalRead(btn_left) == 0) {
cursor_loc++;
if (cursor_loc >=5) cursor_loc =0;
lcd.setCursor(strlen(str_num)-1-cursor_loc, 1);
}
}
//
if (digitalRead(btn_enter) == 0){
delay(150);
if (digitalRead(btn_enter) == 0)
mode=1;
}
}
void setpoint(){
dislay_setpoint();
cursor_loc =0;
lcd.setCursor(strlen(str_num)-1, 1);
lcd.blink();
while(mode ==0){
checkbutton();
}
lcd.noBlink();
mode=1;
start_mode();
}
void start_mode(){
lcd.setCursor(0, 0);
snprintf(str_num, sizeof(str_num), "VOLUME %05ld", current_value);
lcd.print(str_num);
}
void dislay_setpoint(){
lcd.clear();
lcd.setCursor(0, 1);
// int whole = (int)l; // phần nguyên
// int frac = (int)((l - whole) * 10); // làm tròn 1 chữ số
// snprintf(str_num, sizeof(str_num), "SET %3d.%01d", whole, frac); setpoint_value
snprintf(str_num, sizeof(str_num), "SET %05ld", setpoint_value);
lcd.print(str_num);
lcd.setCursor(0, 0);
lcd.print("Setpoint ...");
}
void dislay_change_value_setpoint(){
lcd.setCursor(0, 1);
snprintf(str_num, sizeof(str_num), "SET %05ld", setpoint_value);
lcd.print(str_num);
lcd.setCursor(strlen(str_num)-1-cursor_loc, 1);
}
unsigned long multiple_value(int v){
switch(v){
case 0:
return 1;
case 1:
return 10;
case 2:
return 100;
case 3:
return 1000;
case 4:
return 10000;
default:
return 1;
}
}