284 lines
7.2 KiB
C++
284 lines
7.2 KiB
C++
#include <Wire.h>
|
|
#include <LiquidCrystal_I2C.h>
|
|
#include <ESP8266WiFi.h>
|
|
#include <RTClib.h>
|
|
#include <ThingerESP8266.h>
|
|
#include <WiFiUdp.h>
|
|
#include <NTPClient.h>
|
|
#include <Servo.h>
|
|
|
|
// WiFi Credentials
|
|
const char* ssid = "IANION";
|
|
const char* password = "ianryanian";
|
|
|
|
// Thinger.io Credentials
|
|
#define USERNAME "iannion"
|
|
#define DEVICE_ID "yono3"
|
|
#define DEVICE_CREDENTIAL "H3GFa2M7cN&wYxbk"
|
|
|
|
RTC_DS3231 rtc;
|
|
LiquidCrystal_I2C lcd(0x27, 20, 4);
|
|
|
|
volatile int flow_frequency = 0;
|
|
float vol = 0.0, l_minute;
|
|
const unsigned char flowsensor = 13;
|
|
const unsigned char buttonPin1 = 14;
|
|
const unsigned char buttonPin2 = 12;
|
|
const unsigned char buttonPin3 = 2;
|
|
const unsigned char buttonPin4 = 16;
|
|
unsigned long currentTime;
|
|
unsigned long cloopTime;
|
|
float volume_per_pulse = 0.004;
|
|
float cost_per_liter = 5.07;
|
|
float total_cost = 0.0;
|
|
|
|
Servo servo;
|
|
const int servoPin = 3;
|
|
|
|
const int posisiBuka = 0;
|
|
const int posisiTutup = 180;
|
|
|
|
const unsigned long delayBuka = 1000;
|
|
const unsigned long delayTutup = 2000;
|
|
|
|
int limitSet2Counter = 0;
|
|
int limitSet3Counter = 0;
|
|
bool kranDitutup = true;
|
|
|
|
ThingerESP8266 thing(USERNAME, DEVICE_ID, DEVICE_CREDENTIAL);
|
|
|
|
WiFiUDP ntpUDP;
|
|
NTPClient timeClient(ntpUDP, "pool.ntp.org", 25200, 60000);
|
|
|
|
unsigned long lastThingerUpdateTime = 0;
|
|
const unsigned long thingerUpdateInterval = 60000; // Update every 60 seconds
|
|
|
|
void IRAM_ATTR flow() {
|
|
static unsigned long last_interrupt_time = 0;
|
|
unsigned long interrupt_time = millis();
|
|
if (interrupt_time - last_interrupt_time > 10) {
|
|
flow_frequency++;
|
|
}
|
|
last_interrupt_time = interrupt_time;
|
|
}
|
|
|
|
void setup() {
|
|
Serial.begin(115200);
|
|
lcd.init();
|
|
lcd.backlight();
|
|
pinMode(flowsensor, INPUT);
|
|
digitalWrite(flowsensor, HIGH);
|
|
pinMode(buttonPin1, INPUT_PULLUP);
|
|
pinMode(buttonPin2, INPUT_PULLUP);
|
|
pinMode(buttonPin3, INPUT_PULLUP);
|
|
pinMode(buttonPin4, INPUT_PULLUP);
|
|
servo.attach(servoPin);
|
|
|
|
WiFi.begin(ssid, password);
|
|
while (WiFi.status() != WL_CONNECTED) {
|
|
delay(1000);
|
|
Serial.println("Connecting to WiFi...");
|
|
}
|
|
Serial.println("Connected to WiFi");
|
|
|
|
timeClient.begin();
|
|
timeClient.update();
|
|
|
|
unsigned long epochTime = timeClient.getEpochTime();
|
|
if (!rtc.begin()) {
|
|
Serial.println("Couldn't find RTC");
|
|
while (1);
|
|
}
|
|
|
|
if (rtc.lostPower()) {
|
|
Serial.println("RTC lost power, set time...");
|
|
rtc.adjust(DateTime(epochTime));
|
|
}
|
|
|
|
attachInterrupt(digitalPinToInterrupt(flowsensor), flow, RISING);
|
|
currentTime = millis();
|
|
cloopTime = currentTime;
|
|
|
|
thing.add_wifi(ssid, password);
|
|
|
|
thing["meyala"] >> [] (pson & out) {
|
|
out["flow_rate"] = String(l_minute);
|
|
out["volume"] = String(vol);
|
|
out["total_cost"] = String(total_cost);
|
|
};
|
|
|
|
thing["current_time"] >> [](pson& out) {
|
|
DateTime now = rtc.now();
|
|
char buffer[30];
|
|
snprintf(buffer, sizeof(buffer), "%02d/%02d/%d %02d:%02d", now.day(), now.month(), now.year(), now.hour(), now.minute());
|
|
out = String(buffer);
|
|
};
|
|
}
|
|
|
|
void tutupKatup() {
|
|
if (!kranDitutup) {
|
|
Serial.println("Menutup katup...");
|
|
servo.write(posisiTutup);
|
|
delay(delayTutup); // Delay untuk memastikan servo memiliki waktu untuk bergerak
|
|
kranDitutup = true;
|
|
}
|
|
}
|
|
|
|
void bukaKatup() {
|
|
if (kranDitutup) {
|
|
Serial.println("Membuka katup...");
|
|
servo.write(posisiBuka);
|
|
delay(delayBuka); // Delay untuk memastikan servo memiliki waktu untuk bergerak
|
|
kranDitutup = false;
|
|
}
|
|
}
|
|
|
|
bool kirimDataKeThinger() {
|
|
pson data;
|
|
data["flow_rate"] = l_minute;
|
|
data["volume"] = vol;
|
|
data["total_cost"] = total_cost;
|
|
bool success = thing.write_bucket("meyala", data);
|
|
if (!success) {
|
|
Serial.println("Gagal mengirim data ke Thinger.io");
|
|
}
|
|
return success;
|
|
}
|
|
|
|
void resetData() {
|
|
vol = 0;
|
|
total_cost = 0.0;
|
|
limitSet2Counter = 0;
|
|
limitSet3Counter = 0;
|
|
|
|
Serial.println("Semua pembacaan sensor direset");
|
|
|
|
// Update Thinger.io dengan nilai reset
|
|
kirimDataKeThinger();
|
|
|
|
// Perbarui tampilan LCD
|
|
lcd.setCursor(0, 1);
|
|
lcd.print("Flow :0 L/M ");
|
|
lcd.setCursor(0, 2);
|
|
lcd.print("Volume :0 mL ");
|
|
lcd.setCursor(0, 3);
|
|
lcd.print("Cost :Rp 0.00 ");
|
|
}
|
|
|
|
void loop() {
|
|
DateTime now = rtc.now();
|
|
timeClient.update();
|
|
unsigned long epochTime = timeClient.getEpochTime();
|
|
rtc.adjust(DateTime(epochTime));
|
|
|
|
lcd.setCursor(0, 0);
|
|
if (now.day() < 10) lcd.print('0');
|
|
lcd.print(now.day());
|
|
lcd.print('/');
|
|
if (now.month() < 10) lcd.print('0');
|
|
lcd.print(now.month());
|
|
lcd.print('/');
|
|
lcd.print(now.year());
|
|
|
|
lcd.print(' ');
|
|
if (now.hour() < 10) lcd.print('0');
|
|
lcd.print(now.hour());
|
|
lcd.print(':');
|
|
if (now.minute() < 10) lcd.print('0');
|
|
lcd.print(now.minute());
|
|
|
|
currentTime = millis();
|
|
if (currentTime >= (cloopTime + 1000)) {
|
|
cloopTime = currentTime;
|
|
if (flow_frequency != 0) {
|
|
l_minute = (flow_frequency * volume_per_pulse * 60);
|
|
Serial.print("Flow: ");
|
|
Serial.print(l_minute);
|
|
Serial.println(" L/M");
|
|
lcd.setCursor(0, 1);
|
|
lcd.print("Flow :");
|
|
lcd.print(l_minute);
|
|
lcd.print(" L/M ");
|
|
|
|
vol += l_minute / 60;
|
|
total_cost += (l_minute / 60) * cost_per_liter;
|
|
Serial.print("Volume: ");
|
|
Serial.print(vol);
|
|
Serial.println(" L");
|
|
Serial.print("Volume: ");
|
|
Serial.print(vol * 1000);
|
|
Serial.println(" mL");
|
|
lcd.setCursor(0, 2);
|
|
lcd.print("Volume :");
|
|
lcd.print(int(vol * 1000));
|
|
lcd.print(" mL ");
|
|
|
|
Serial.print("Cost: Rp ");
|
|
Serial.print(total_cost, 2);
|
|
Serial.println();
|
|
lcd.setCursor(0, 3);
|
|
lcd.print("Cost :Rp ");
|
|
lcd.print(total_cost, 2);
|
|
lcd.print(" ");
|
|
|
|
if (limitSet2Counter > 0 && vol >= (2.0 * limitSet2Counter)) { // Batasan kelipatan 2 liter
|
|
Serial.println("Batas aliran tercapai: " + String(2.0 * limitSet2Counter) + " liter!");
|
|
thing.call_endpoint("Notifikasi_Harian"); // kirim notifikasi dengan endpoint
|
|
tutupKatup();
|
|
}
|
|
|
|
if (limitSet3Counter > 0 && vol >= (3.0 * limitSet3Counter)) { // Batasan kelipatan 3 liter
|
|
Serial.println("Batas aliran tercapai: " + String(3.0 * limitSet3Counter) + " liter!");
|
|
thing.call_endpoint("Notifikasi_Harian3"); // kirim notifikasi dengan endpoint
|
|
tutupKatup();
|
|
}
|
|
|
|
flow_frequency = 0;
|
|
} else {
|
|
Serial.println("Flow: 0 L/M");
|
|
lcd.setCursor(0, 1);
|
|
lcd.print("Flow :0 L/M ");
|
|
}
|
|
}
|
|
|
|
if (digitalRead(buttonPin1) == LOW) {
|
|
limitSet2Counter++;
|
|
limitSet3Counter = 0; // Reset counter untuk batasan 3 liter
|
|
Serial.println("Batas aliran ditetapkan untuk 2 liter kelipatan " + String(limitSet2Counter));
|
|
lcd.setCursor(0, 3);
|
|
lcd.print("Limit :2 L ");
|
|
delay(500);
|
|
bukaKatup();
|
|
}
|
|
|
|
if (digitalRead(buttonPin2) == LOW) {
|
|
limitSet3Counter++;
|
|
limitSet2Counter = 0; // Reset counter untuk batasan 2 liter
|
|
Serial.println("Batas aliran ditetapkan untuk 3 liter kelipatan " + String(limitSet3Counter));
|
|
lcd.setCursor(0, 3);
|
|
lcd.print("Limit :3 L ");
|
|
delay(500);
|
|
bukaKatup();
|
|
}
|
|
|
|
if (digitalRead(buttonPin3) == LOW) {
|
|
resetData();
|
|
delay(500);
|
|
}
|
|
|
|
if (digitalRead(buttonPin4) == LOW) {
|
|
if (kranDitutup) {
|
|
bukaKatup();
|
|
}
|
|
}
|
|
|
|
if (currentTime - lastThingerUpdateTime >= thingerUpdateInterval) {
|
|
lastThingerUpdateTime = currentTime;
|
|
kirimDataKeThinger();
|
|
}
|
|
|
|
thing.handle();
|
|
|
|
delay(10);
|
|
}
|