Upload files to "/"
This commit is contained in:
commit
834c67996a
|
@ -0,0 +1,403 @@
|
||||||
|
#define BLYNK_TEMPLATE_ID "TMPL6-koCiZAA"
|
||||||
|
#define BLYNK_TEMPLATE_NAME "Projek TA"
|
||||||
|
#define BLYNK_AUTH_TOKEN "pOhzyHxD1TKgFF-pJ7TZYoS0HOfUyVPK"
|
||||||
|
|
||||||
|
#include <Wire.h>
|
||||||
|
#include <LiquidCrystal_I2C.h>
|
||||||
|
#include <ESP32Servo.h>
|
||||||
|
#include <RTClib.h>
|
||||||
|
#include <WiFi.h>
|
||||||
|
#include <BlynkSimpleEsp32.h>
|
||||||
|
#include <WiFiUdp.h>
|
||||||
|
#include <NTPClient.h>
|
||||||
|
|
||||||
|
#define SERVO_PIN 2
|
||||||
|
#define BUTTON_SERVO_PIN 15
|
||||||
|
#define BUTTON_PENGURAS_PIN 13
|
||||||
|
#define TDS_SENSOR_PIN 34
|
||||||
|
#define BUZZER_PIN 5
|
||||||
|
#define PENGURAS_PIN 26
|
||||||
|
#define PENGISI_PIN 27
|
||||||
|
#define WATERLEVEL_PENGURAS_PIN 32
|
||||||
|
#define WATERLEVEL_PENGISI_PIN 33
|
||||||
|
#define LCD_COLS 16
|
||||||
|
#define LCD_ROWS 2
|
||||||
|
#define TDS_THRESHOLD 300
|
||||||
|
#define PIN_BUTTON_SERVO V0
|
||||||
|
#define PIN_BUTTON_PENGURAS V1
|
||||||
|
#define PIN_TDS_READING V2
|
||||||
|
#define PIN_TIME_MORNING V3
|
||||||
|
#define PIN_TIME_NOON V4
|
||||||
|
#define PIN_TIME_NIGHT V5
|
||||||
|
|
||||||
|
RTC_DS3231 rtc;
|
||||||
|
Servo feeder;
|
||||||
|
LiquidCrystal_I2C lcd(0x27, LCD_COLS, LCD_ROWS);
|
||||||
|
|
||||||
|
unsigned long lastSlideChangeTime = 0;
|
||||||
|
int currentSlide = 0;
|
||||||
|
|
||||||
|
int WaterLevelPengurasStatus;
|
||||||
|
int WaterLevelPengisiStatus;
|
||||||
|
|
||||||
|
const char* ssid = "Safirudin 2";
|
||||||
|
const char* password = "safirudin54321";
|
||||||
|
char auth[] = BLYNK_AUTH_TOKEN;
|
||||||
|
|
||||||
|
bool notificationSent = false;
|
||||||
|
|
||||||
|
WiFiUDP ntpUDP;
|
||||||
|
NTPClient timeClient(ntpUDP, "pool.ntp.org", 7 * 3600, 60000);
|
||||||
|
|
||||||
|
int feedTimeMorningHour;
|
||||||
|
int feedTimeMorningMinute;
|
||||||
|
int feedTimeNoonHour;
|
||||||
|
int feedTimeNoonMinute;
|
||||||
|
int feedTimeNightHour;
|
||||||
|
int feedTimeNightMinute;
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
feeder.attach(SERVO_PIN);
|
||||||
|
pinMode(BUTTON_SERVO_PIN, INPUT_PULLUP);
|
||||||
|
pinMode(BUZZER_PIN, OUTPUT);
|
||||||
|
pinMode(PENGURAS_PIN, OUTPUT);
|
||||||
|
pinMode(PENGISI_PIN, OUTPUT);
|
||||||
|
pinMode(WATERLEVEL_PENGURAS_PIN, INPUT_PULLUP);
|
||||||
|
pinMode(WATERLEVEL_PENGISI_PIN, INPUT_PULLUP);
|
||||||
|
pinMode(BUTTON_PENGURAS_PIN, INPUT_PULLUP);
|
||||||
|
Serial.begin(9600);
|
||||||
|
Wire.begin();
|
||||||
|
|
||||||
|
lcd.init();
|
||||||
|
lcd.backlight();
|
||||||
|
|
||||||
|
connectToWiFi();
|
||||||
|
|
||||||
|
if (!rtc.begin()) {
|
||||||
|
Serial.println("Tidak dapat menemukan RTC");
|
||||||
|
while (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rtc.lostPower()) {
|
||||||
|
Serial.println("RTC kehilangan daya, mengatur waktu!");
|
||||||
|
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
|
||||||
|
}
|
||||||
|
|
||||||
|
timeClient.begin();
|
||||||
|
|
||||||
|
Blynk.begin(auth, ssid, password, "blynk.cloud", 80);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
unsigned long currentTime = millis();
|
||||||
|
bool servoButtonState = digitalRead(BUTTON_SERVO_PIN);
|
||||||
|
bool pengurasButtonState = digitalRead(BUTTON_PENGURAS_PIN);
|
||||||
|
|
||||||
|
Blynk.run();
|
||||||
|
timeClient.update();
|
||||||
|
|
||||||
|
DateTime now = rtc.now();
|
||||||
|
if (abs((long)(now.unixtime() - timeClient.getEpochTime())) > 10) {
|
||||||
|
rtc.adjust(DateTime(timeClient.getEpochTime()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (servoButtonState == LOW) {
|
||||||
|
openFeeder();
|
||||||
|
delay(500);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pengurasButtonState == LOW) {
|
||||||
|
activatePenguras();
|
||||||
|
delay(500);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentTime - lastSlideChangeTime >= 2000) {
|
||||||
|
currentSlide = (currentSlide + 1) % 3;
|
||||||
|
lastSlideChangeTime = currentTime;
|
||||||
|
|
||||||
|
switch (currentSlide) {
|
||||||
|
case 1:
|
||||||
|
showFeederScreen();
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
showNextFeedingTimeScreen();
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
unsigned int tdsValue = readTDS();
|
||||||
|
showTDSReadingScreen(tdsValue);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int tdsValue = readTDS();
|
||||||
|
updateBuzzer(tdsValue);
|
||||||
|
updateRelayAndWaterLevel();
|
||||||
|
|
||||||
|
if (tdsValue > TDS_THRESHOLD && !notificationSent) {
|
||||||
|
sendTDSNotification();
|
||||||
|
notificationSent = true;
|
||||||
|
} else if (tdsValue <= TDS_THRESHOLD) {
|
||||||
|
notificationSent = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkFeedingTime(now.hour(), now.minute(), now.day());
|
||||||
|
|
||||||
|
delay(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkFeedingTime(int currentHour, int currentMinute, int currentDay) {
|
||||||
|
static int lastFedDay = -1;
|
||||||
|
static bool fedMorning = false;
|
||||||
|
static bool fedNoon = false;
|
||||||
|
static bool fedNight = false;
|
||||||
|
|
||||||
|
if (lastFedDay != currentDay) {
|
||||||
|
fedMorning = false;
|
||||||
|
fedNoon = false;
|
||||||
|
fedNight = false;
|
||||||
|
lastFedDay = currentDay;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentHour == feedTimeMorningHour && currentMinute == feedTimeMorningMinute && !fedMorning) {
|
||||||
|
openFeeder();
|
||||||
|
showFeedingStatus();
|
||||||
|
fedMorning = true;
|
||||||
|
} else if (currentHour == feedTimeNoonHour && currentMinute == feedTimeNoonMinute && !fedNoon) {
|
||||||
|
openFeeder();
|
||||||
|
showFeedingStatus();
|
||||||
|
fedNoon = true;
|
||||||
|
} else if (currentHour == feedTimeNightHour && currentMinute == feedTimeNightMinute && !fedNight) {
|
||||||
|
openFeeder();
|
||||||
|
showFeedingStatus();
|
||||||
|
fedNight = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void showWiFiStatus(const char* statusMessage) {
|
||||||
|
lcd.clear();
|
||||||
|
lcd.setCursor(0, 0);
|
||||||
|
lcd.print(statusMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
void connectToWiFi() {
|
||||||
|
showWiFiStatus("Connecting WiFi");
|
||||||
|
Serial.println("Menghubungkan WiFi...");
|
||||||
|
|
||||||
|
WiFi.begin(ssid, password);
|
||||||
|
|
||||||
|
while (WiFi.status() != WL_CONNECTED) {
|
||||||
|
delay(1000);
|
||||||
|
Serial.println("Mencoba terhubung ke WiFi...");
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.println("Tersambung ke jaringan WiFi");
|
||||||
|
Serial.print("Alamat IP: ");
|
||||||
|
Serial.println(WiFi.localIP());
|
||||||
|
showWiFiStatus("Connect to WiFi.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void showFeederScreen() {
|
||||||
|
DateTime now = rtc.now();
|
||||||
|
|
||||||
|
lcd.clear();
|
||||||
|
lcd.setCursor((LCD_COLS - 11) / 2, 0);
|
||||||
|
lcd.print("Ikan Feeder");
|
||||||
|
|
||||||
|
lcd.setCursor((LCD_COLS - 5) / 2, 1);
|
||||||
|
lcd.print(now.hour());
|
||||||
|
lcd.print(":");
|
||||||
|
if (now.minute() < 10) {
|
||||||
|
lcd.print("0");
|
||||||
|
}
|
||||||
|
lcd.print(now.minute());
|
||||||
|
}
|
||||||
|
|
||||||
|
void showNextFeedingTimeScreen() {
|
||||||
|
lcd.clear();
|
||||||
|
lcd.setCursor(0, 0);
|
||||||
|
lcd.print("Pakan Berikutnya:");
|
||||||
|
|
||||||
|
lcd.setCursor(0, 1);
|
||||||
|
DateTime now = rtc.now();
|
||||||
|
|
||||||
|
if (now.hour() < feedTimeMorningHour || (now.hour() == feedTimeMorningHour && now.minute() < feedTimeMorningMinute)) {
|
||||||
|
lcd.print("Pagi ");
|
||||||
|
lcd.print(feedTimeMorningHour);
|
||||||
|
lcd.print(":");
|
||||||
|
if (feedTimeMorningMinute < 10) {
|
||||||
|
lcd.print("0");
|
||||||
|
}
|
||||||
|
lcd.print(feedTimeMorningMinute);
|
||||||
|
} else if (now.hour() < feedTimeNoonHour || (now.hour() == feedTimeNoonHour && now.minute() < feedTimeNoonMinute)) {
|
||||||
|
lcd.print("Siang ");
|
||||||
|
lcd.print(feedTimeNoonHour);
|
||||||
|
lcd.print(":");
|
||||||
|
if (feedTimeNoonMinute < 10) {
|
||||||
|
lcd.print("0");
|
||||||
|
}
|
||||||
|
lcd.print(feedTimeNoonMinute);
|
||||||
|
} else if (now.hour() < feedTimeNightHour || (now.hour() == feedTimeNightHour && now.minute() < feedTimeNightMinute)) {
|
||||||
|
lcd.print("Malam ");
|
||||||
|
lcd.print(feedTimeNightHour);
|
||||||
|
lcd.print(":");
|
||||||
|
if (feedTimeNightMinute < 10) {
|
||||||
|
lcd.print("0");
|
||||||
|
}
|
||||||
|
lcd.print(feedTimeNightMinute);
|
||||||
|
} else {
|
||||||
|
lcd.print("Pagi ");
|
||||||
|
lcd.print(feedTimeMorningHour);
|
||||||
|
lcd.print(":");
|
||||||
|
if (feedTimeMorningMinute < 10) {
|
||||||
|
lcd.print("0");
|
||||||
|
}
|
||||||
|
lcd.print(feedTimeMorningMinute);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void showTDSReadingScreen(unsigned int tdsValue) {
|
||||||
|
String quality;
|
||||||
|
if (tdsValue <= TDS_THRESHOLD) {
|
||||||
|
quality = "Baik";
|
||||||
|
digitalWrite(BUZZER_PIN, LOW);
|
||||||
|
} else {
|
||||||
|
quality = "Buruk";
|
||||||
|
digitalWrite(BUZZER_PIN, HIGH);
|
||||||
|
digitalWrite(PENGURAS_PIN, HIGH);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WaterLevelPengurasStatus == LOW) {
|
||||||
|
digitalWrite(PENGURAS_PIN, LOW);
|
||||||
|
digitalWrite(PENGISI_PIN, HIGH);
|
||||||
|
}
|
||||||
|
if (WaterLevelPengisiStatus == HIGH) {
|
||||||
|
digitalWrite(PENGISI_PIN, LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
lcd.clear();
|
||||||
|
lcd.setCursor(0, 0);
|
||||||
|
lcd.print("TDS : ");
|
||||||
|
lcd.print(tdsValue);
|
||||||
|
lcd.print(" ppm");
|
||||||
|
lcd.setCursor(0, 1);
|
||||||
|
lcd.print("Kualitas : ");
|
||||||
|
lcd.print(quality);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int readTDS() {
|
||||||
|
int sensorValue = analogRead(TDS_SENSOR_PIN);
|
||||||
|
unsigned int tdsValue = map(sensorValue, 0, 1023, 0, 1000);
|
||||||
|
|
||||||
|
WaterLevelPengurasStatus = digitalRead(WATERLEVEL_PENGURAS_PIN);
|
||||||
|
WaterLevelPengisiStatus = digitalRead(WATERLEVEL_PENGISI_PIN);
|
||||||
|
|
||||||
|
sendTDSReadingToBlynk(tdsValue);
|
||||||
|
|
||||||
|
return tdsValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void feedFish() {
|
||||||
|
showFeedingStatus();
|
||||||
|
feeder.write(22);
|
||||||
|
delay(1000);
|
||||||
|
feeder.write(0);
|
||||||
|
delay(500);
|
||||||
|
feeder.write(18);
|
||||||
|
delay(500);
|
||||||
|
feeder.write(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void openFeeder() {
|
||||||
|
feedFish();
|
||||||
|
}
|
||||||
|
|
||||||
|
void showFeedingStatus() {
|
||||||
|
lcd.clear();
|
||||||
|
lcd.setCursor((LCD_COLS - 16) / 2, 0);
|
||||||
|
lcd.print("-Sedang Memberi-");
|
||||||
|
lcd.setCursor((LCD_COLS - 16) / 2, 1);
|
||||||
|
lcd.print("-----Pakan-----");
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateBuzzer(unsigned int tdsValue) {
|
||||||
|
if (tdsValue <= TDS_THRESHOLD) {
|
||||||
|
digitalWrite(BUZZER_PIN, LOW);
|
||||||
|
} else {
|
||||||
|
digitalWrite(BUZZER_PIN, HIGH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateRelayAndWaterLevel() {
|
||||||
|
if (WaterLevelPengurasStatus == LOW) {
|
||||||
|
digitalWrite(PENGURAS_PIN, LOW);
|
||||||
|
digitalWrite(PENGISI_PIN, HIGH);
|
||||||
|
}
|
||||||
|
if (WaterLevelPengisiStatus == HIGH) {
|
||||||
|
digitalWrite(PENGISI_PIN, LOW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void activatePenguras() {
|
||||||
|
digitalWrite(PENGURAS_PIN, HIGH);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendTDSReadingToBlynk(unsigned int tdsValue) {
|
||||||
|
Blynk.virtualWrite(PIN_TDS_READING, tdsValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendTDSNotification() {
|
||||||
|
Blynk.logEvent("notify","Kualitas air akuarium Buruk! Mohon segera cek!");
|
||||||
|
}
|
||||||
|
|
||||||
|
BLYNK_WRITE(PIN_BUTTON_SERVO) {
|
||||||
|
int pinValue = param.asInt();
|
||||||
|
if (pinValue == 1) {
|
||||||
|
openFeeder();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BLYNK_WRITE(PIN_BUTTON_PENGURAS) {
|
||||||
|
int pinValue = param.asInt();
|
||||||
|
if (pinValue == 1) {
|
||||||
|
activatePenguras();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Blynk handlers for time inputs
|
||||||
|
BLYNK_WRITE(PIN_TIME_MORNING) {
|
||||||
|
TimeInputParam t(param);
|
||||||
|
if (t.hasStartTime()) {
|
||||||
|
feedTimeMorningHour = t.getStartHour();
|
||||||
|
feedTimeMorningMinute = t.getStartMinute();
|
||||||
|
Serial.print("Waktu Pagi diatur ke: ");
|
||||||
|
Serial.print(feedTimeMorningHour);
|
||||||
|
Serial.print(":");
|
||||||
|
Serial.println(feedTimeMorningMinute);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BLYNK_WRITE(PIN_TIME_NOON) {
|
||||||
|
TimeInputParam t(param);
|
||||||
|
if (t.hasStartTime()) {
|
||||||
|
feedTimeNoonHour = t.getStartHour();
|
||||||
|
feedTimeNoonMinute = t.getStartMinute();
|
||||||
|
Serial.print("Waktu Siang diatur ke: ");
|
||||||
|
Serial.print(feedTimeNoonHour);
|
||||||
|
Serial.print(":");
|
||||||
|
Serial.println(feedTimeNoonMinute);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BLYNK_WRITE(PIN_TIME_NIGHT) {
|
||||||
|
TimeInputParam t(param);
|
||||||
|
if (t.hasStartTime()) {
|
||||||
|
feedTimeNightHour = t.getStartHour();
|
||||||
|
feedTimeNightMinute = t.getStartMinute();
|
||||||
|
Serial.print("Waktu Malam diatur ke: ");
|
||||||
|
Serial.print(feedTimeNightHour);
|
||||||
|
Serial.print(":");
|
||||||
|
Serial.println(feedTimeNightMinute);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue