bangnaga

Anco Feeder IOT-EKASA

Oct 14th, 2024 (edited)
282
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Arduino 30.06 KB | None | 0 0
  1. #include <Wire.h>
  2. #include <LiquidCrystal_I2C.h>
  3. #include <ESP32Servo.h>
  4. #include <ezButton.h>
  5. #include <TaskScheduler.h>
  6. #include <WiFi.h>
  7. #include <PubSubClient.h>
  8. #include <ArduinoJson.h>
  9. #include <Preferences.h>
  10.  
  11. Preferences preferences;
  12.  
  13. byte iup[] = {B00000, B00100, B01010, B10001, B00100, B01010, B10001, B00000};
  14. byte idown[] = {B00000, B10001, B01010, B00100, B10001, B01010, B00100, B00000};
  15. byte istop[] = {B00000, B11111, B11111, B11111, B11111, B11111, B00000, B00000};
  16. byte ifeedStart[] = {B11111, B11111, B01110, B01110, B00000, B00100, B00000, B00100};
  17. byte ifeedStop[] = {B11111, B10001, B01010, B01110, B00000, B00000, B00000, B00000};
  18. byte ilimitUp[] = {B00100, B01110, B10101, B00100, B11111, B11111, B00000, B00000};
  19. byte ilimitDown[] = {B00100, B00100, B00100, B00100, B00100, B00100, B11111, B11111};
  20. byte isignalOn[] = {B00001, B00011, B00111, B01111, B11111, B11111, B00000, B00000};
  21. byte isignalOff[] = {B10100, B01000, B10101, B00011, B00011, B00111, B01111, B11111};
  22.  
  23. // Inisialisasi LCD (alamat I2C, jumlah kolom, jumlah baris)
  24. const int lcdColumns = 16;
  25. const int lcdRows = 2;
  26. LiquidCrystal_I2C lcd(0x27, lcdColumns, lcdRows);
  27.  
  28. // Variabel untuk deteksi long press pada tombol stop
  29. unsigned long stopButtonPressStartTime = 0;
  30. bool isStopButtonLongPressed = false;
  31. const unsigned long LONG_PRESS_DURATION = 3000; // 3 detik
  32.  
  33.  
  34. // MQTT dan WiFi credentials
  35. const char* ssid = "IOT-EKASA";
  36. const char* password = "iot-ekasa";
  37. const char* mqtt_broker = "server.local";
  38. const int mqtt_port = 1883;
  39. const char* mqttUser = "";
  40. const char* mqttPassword = "";
  41.  
  42. // MQTT topic
  43. const char* mqttTopicSetOtomatis = "setOtomatis";
  44. const char* mqttTopicKontrol = "kontrol";
  45.  
  46. // WiFi dan MQTT Client
  47. WiFiClient espClient;
  48. PubSubClient client(espClient);
  49.  
  50.  
  51.  
  52.  
  53. // Deklarasi Fungsi
  54. void wifi_connect();
  55. void mqtt_connect();
  56. void mqttCallback(char* topic, byte* payload, unsigned int length);
  57.  
  58. void updateTimeLeft();
  59. void checkButtons();
  60. void stopAll();
  61. void startProcess(const char *status, unsigned long duration);
  62. void setIconUp();
  63. void setIconDown();
  64. void setIconStop();
  65. bool checkTimeElapsed(unsigned long duration);
  66. void checkLimitSwitch();
  67. void checkConnections();
  68.  
  69. // Scheduler dan Tugas
  70. Scheduler runner;
  71. Task taskUpdateTime(500, TASK_FOREVER, &updateTimeLeft);
  72. Task taskCheckButtons(100, TASK_FOREVER, &checkButtons);
  73. Task taskCheckLimitSwitch(50, TASK_FOREVER, &checkLimitSwitch);
  74. Task taskCheckConnections(1000, TASK_FOREVER, &checkConnections); // Setiap 1000 ms (1 detik)
  75.  
  76. // Variabel
  77. Servo myServo;
  78. int servoPin = 4;
  79. const int relay1 = 32;
  80. const int relay2 = 33;
  81. const int limitSwitchPin = 5;
  82. // Tambahkan variabel global untuk menyimpan status sebelumnya
  83. bool previousRemoteMode = false;
  84.  
  85. bool standbyActive = false;
  86. unsigned long standbyStartTime = 0;
  87. const unsigned long standbyDuration = 5000; // 5 detik
  88.  
  89. // Tombol dan LED
  90. const int selectorButtonPin = 25;  // Selector mode (Manual / Otomatis)
  91. const int ledPin = 26;  // LED untuk indikasi mode
  92.  
  93.  
  94.  
  95.  
  96. // Tombol menggunakan ezButton
  97. ezButton buttonCW(13);  // Tombol UP
  98. ezButton buttonCCW(12); // Tombol DOWN
  99. ezButton buttonServo(27);
  100. ezButton btnEmergencyStop(14);
  101.  
  102.  
  103.  
  104. unsigned long durasiServo = 5;
  105. unsigned long durasiTurun = 5;
  106. unsigned long durasiRendam = 1;  // Dalam menit
  107. unsigned long startTime = 0;
  108.  
  109. bool servoActive = false;
  110. bool turunActive = false;
  111. bool rendamActive = false;
  112. bool upActive = false;
  113. bool processActive = false;
  114. bool isManualMode = true;  // Default: Mode Manual
  115. bool remoteMode = false;  // Default: Remote mode = false (Manual Mode)
  116.  
  117. // Variabel debounce untuk Selector Mode
  118. unsigned long lastDebounceTimeSelector = 0;
  119. const unsigned long debounceDelaySelector = 500;
  120.  
  121. void setup() {
  122.   Serial.begin(115200);
  123.   lcd.init();
  124.   lcd.backlight();
  125.   lcd.createChar(0, ifeedStart);
  126.   lcd.createChar(1, ifeedStop);
  127.   lcd.createChar(2, iup);
  128.   lcd.createChar(3, idown);
  129.   lcd.createChar(4, istop);
  130.   lcd.createChar(5, ilimitUp);
  131.   lcd.createChar(6, ilimitDown);
  132.   lcd.createChar(7, isignalOn);
  133.  
  134.   // Setup tombol dengan debounce
  135.   buttonCW.setDebounceTime(50);
  136.   buttonCCW.setDebounceTime(50);
  137.   buttonServo.setDebounceTime(50);
  138.   btnEmergencyStop.setDebounceTime(50);
  139.  
  140.   pinMode(limitSwitchPin, INPUT_PULLUP);
  141.   pinMode(relay1, OUTPUT);
  142.   pinMode(relay2, OUTPUT);
  143.   pinMode(selectorButtonPin, INPUT_PULLUP);  // Selector Mode
  144.   pinMode(ledPin, OUTPUT);  // LED Indikator
  145.  
  146.   digitalWrite(relay1, LOW);
  147.   digitalWrite(relay2, LOW);
  148.   myServo.attach(servoPin, 500, 2400);
  149.   myServo.write(0);
  150.  
  151.   // Setup TaskScheduler
  152.   runner.init();
  153.   runner.addTask(taskUpdateTime);
  154.   runner.addTask(taskCheckButtons);
  155.   runner.addTask(taskCheckLimitSwitch);
  156.   runner.addTask(taskCheckConnections);
  157.   taskUpdateTime.enable();
  158.   taskCheckButtons.enable();
  159.   taskCheckLimitSwitch.enable();
  160.   taskCheckConnections.enable();
  161.   setSignalOff();
  162.  
  163. //  clearKeterangan();
  164. //  wifi_connect();
  165. //  mqtt_connect();
  166.  
  167. // Inisialisasi Preferences
  168.   preferences.begin("config", false); // Namespace "config", read-write mode
  169.  
  170.   // Baca durasiServo, durasiTurun, durasiRendam dari Preferences
  171.   durasiServo = preferences.getUInt("durasiServo", 5); // Default 5 detik
  172.   durasiTurun = preferences.getUInt("durasiTurun", 5); // Default 5 detik
  173.   durasiRendam = preferences.getUInt("durasiRendam", 1); // Default 1 menit
  174.  
  175.   Serial.println("Durasi Servo: " + String(durasiServo) + " detik");
  176.   Serial.println("Durasi Turun: " + String(durasiTurun) + " detik");
  177.   Serial.println("Durasi Rendam: " + String(durasiRendam) + " menit");
  178.   // Tampilkan informasi timer pertama kali
  179.   displayInfoTimer();
  180.  
  181.      
  182.    if (digitalRead(limitSwitchPin) == LOW) {
  183. //    lcd.clear();
  184.     clearKeterangan();
  185.     lcd.setCursor(2, 0);
  186.     lcd.print("Anco diatas");
  187.     lcd.setCursor(2, 1);
  188.     lcd.print("Standby ...");
  189.    
  190.    
  191.    
  192.   }else{
  193. //    lcd.clear();
  194.     clearKeterangan();
  195.     setLimitUp();
  196.     lcd.setCursor(2, 0);
  197.     lcd.print("Set Posisi!");
  198.     lcd.setCursor(2, 1);
  199.     lcd.print("Ready");    
  200.   }
  201.  
  202.   delay(1000);
  203.  
  204.    // Pengecekan Selector Mode (Remote Mode)
  205.   if (digitalRead(selectorButtonPin) == LOW) {
  206.     remoteMode = true;  // Aktifkan Remote Mode
  207.     digitalWrite(ledPin, HIGH);  // Nyalakan LED
  208.     lcd.setCursor(14, 0);
  209.     lcd.print("|R");
  210.     delay(500);  // Debounce sederhana
  211.   } else {
  212.     remoteMode = false;  // Nonaktifkan Remote Mode (Manual Mode)
  213.     digitalWrite(ledPin, LOW);  // Matikan LED
  214.     lcd.setCursor(14, 0);
  215.     lcd.print("|M");
  216.   }
  217.   delay (1000);
  218. }
  219.  
  220. void loop() {
  221.   runner.execute();  // Jalankan scheduler
  222.   client.loop();  // MQTT loop
  223.  }
  224.  
  225. // Fungsi untuk memperbarui waktu tersisa
  226. void updateTimeLeft() {
  227.   if (processActive) {
  228.     unsigned long elapsedTime = (millis() - startTime) / 1000;
  229.     unsigned long timeLeft = 0;
  230.  
  231.     if (servoActive) {
  232.       timeLeft = max(0UL, durasiServo - elapsedTime);
  233.     } else if (turunActive) {
  234.       timeLeft = max(0UL, durasiTurun - elapsedTime);
  235.     } else if (rendamActive) {
  236.       timeLeft = max(0UL, (durasiRendam * 60) - elapsedTime);
  237.     }
  238.  
  239.     unsigned long hours = timeLeft / 3600;
  240.     unsigned long minutes = (timeLeft % 3600) / 60;
  241.     unsigned long seconds = timeLeft % 60;
  242.  
  243.     lcd.setCursor(2, 1);
  244.     lcd.print("Time: ");
  245.     if (hours < 10) lcd.print('0');
  246.     lcd.print(hours);
  247.     lcd.print(':');
  248.     if (minutes < 10) lcd.print('0');
  249.     lcd.print(minutes);
  250.     lcd.print(':');
  251.     if (seconds < 10) lcd.print('0');
  252.     lcd.print(seconds);
  253.   }
  254. }
  255.  
  256. //// Fungsi untuk memantau tombol
  257. //void checkButtons() {
  258. //  buttonCW.loop();
  259. //  buttonCCW.loop();
  260. //  buttonServo.loop();
  261. //  btnEmergencyStop.loop();
  262. //
  263. //
  264. //  // Pengecekan Selector Mode (Remote Mode)
  265. //  if (digitalRead(selectorButtonPin) == LOW) {
  266. //    remoteMode = true;  // Aktifkan Remote Mode
  267. //    digitalWrite(ledPin, HIGH);  // Nyalakan LED
  268. //    lcd.setCursor(14, 0);
  269. //    lcd.print("|R");
  270. //    delay(500);  // Debounce sederhana
  271. //  } else {
  272. //    remoteMode = false;  // Nonaktifkan Remote Mode (Manual Mode)
  273. //    digitalWrite(ledPin, LOW);  // Matikan LED
  274. //    lcd.setCursor(14, 0);
  275. //    lcd.print("|M");
  276. //    disconnectWiFi();
  277. //  }
  278. //  
  279. //  if (btnEmergencyStop.isPressed()) {
  280. //    stopAll();
  281. //  }
  282. //
  283. //  if (buttonServo.isPressed() && !processActive) {
  284. //    processActive = true;
  285. //    servoActive = true;
  286. //    startProcess("Feeding", durasiServo);
  287. //    setFeedStart();
  288. //    myServo.write(90);
  289. //  }
  290. //
  291. //  if (servoActive && checkTimeElapsed(durasiServo)) {
  292. //    clearKeterangan();
  293. //    setFeedStop();
  294. //    myServo.write(0);
  295. //    lcd.setCursor(2, 0);
  296. //    lcd.print("Stop Feed");
  297. //    lcd.setCursor(2, 1);
  298. //    lcd.print("Standby ...(5s)");
  299. //    delay(5000);
  300. //    servoActive = false;
  301. //    turunActive = true;
  302. ////    lcd.clear();
  303. //    clearKeterangan();
  304. //    startProcess("Turun", durasiTurun);
  305. //    setIconDown();
  306. //    digitalWrite(relay1, LOW);
  307. //    digitalWrite(relay2, HIGH);
  308. //  }
  309. //
  310. //  if (turunActive && checkTimeElapsed(durasiTurun)) {
  311. //    turunActive = false;
  312. //    rendamActive = true;
  313. //    
  314. //    startProcess("Rendam", durasiRendam * 60);
  315. //    setIconStop();
  316. //    digitalWrite(relay1, LOW);
  317. //    digitalWrite(relay2, LOW);
  318. //  }
  319. //
  320. //  if (rendamActive && checkTimeElapsed(durasiRendam * 60)) {
  321. //    rendamActive = false;
  322. //    upActive = true;
  323. //    setIconUp();
  324. ////    startProcess("Anco Naik", 0);
  325. //    clearKeterangan();
  326. //    lcd.setCursor(2, 0);
  327. //    lcd.print("Angkat Anco");
  328. //    lcd.setCursor(2, 1);
  329. //    lcd.print("Motor Up");
  330. //    digitalWrite(relay1, HIGH);
  331. //    digitalWrite(relay2, LOW);
  332. //  }
  333. //if (!remoteMode) {  // Kontrol Manual
  334. //  if (buttonCW.isPressed()) {
  335. //    clearKeterangan();
  336. //    lcd.setCursor(2, 0);
  337. //    lcd.print("Instruksi:");
  338. //    lcd.setCursor(2, 1);
  339. //    lcd.print("Anco Naik");
  340. //    setIconUp();
  341. //    upActive = true;
  342. //    digitalWrite(relay1, HIGH);
  343. //    digitalWrite(relay2, LOW);
  344. //  }
  345. //
  346. //  if (buttonCCW.isPressed()) {
  347. //    clearKeterangan();
  348. //    lcd.setCursor(2, 0);
  349. //    lcd.print("Instruksi:");
  350. //    lcd.setCursor(2, 1);
  351. //    lcd.print("Anco Turun");
  352. //    setIconDown();
  353. //    digitalWrite(relay1, LOW);
  354. //    digitalWrite(relay2, HIGH);
  355. //    }
  356. //  }
  357. //}
  358.  
  359.  
  360. //void checkButtons() {
  361. //  buttonCW.loop();
  362. //  buttonCCW.loop();
  363. //  buttonServo.loop();
  364. //  btnEmergencyStop.loop();
  365. //
  366. //  unsigned long currentMillis = millis();
  367. //
  368. //  // Pengecekan Selector Mode (Remote Mode) dengan debounce non-blocking
  369. //  bool currentSelectorState = (digitalRead(selectorButtonPin) == LOW);
  370. //  if (currentSelectorState != previousRemoteMode) {
  371. //    if (currentMillis - lastDebounceTimeSelector > debounceDelaySelector) {
  372. //      if (currentSelectorState) {
  373. //        // Mode berubah ke Remote Mode
  374. //        remoteMode = true;
  375. //        digitalWrite(ledPin, HIGH);  // Nyalakan LED
  376. //        lcd.setCursor(14, 0);
  377. //        lcd.print("|R ");
  378. //        setSignalOn(); // Update ikon koneksi
  379. //        Serial.println("Mode: Remote");
  380. //      } else {
  381. //        // Mode berubah ke Manual Mode
  382. //        remoteMode = false;
  383. //        digitalWrite(ledPin, LOW);  // Matikan LED
  384. //        lcd.setCursor(14, 0);
  385. //        lcd.print("|M ");
  386. //        disconnectWiFi(); // Putuskan koneksi WiFi dan MQTT
  387. //        Serial.println("Mode: Manual");
  388. //      }
  389. //      lastDebounceTimeSelector = currentMillis;
  390. //    }
  391. //  }
  392. //  previousRemoteMode = currentSelectorState;
  393. //
  394. //  // Pengecekan tombol Emergency Stop
  395. //  if (btnEmergencyStop.isPressed()) {
  396. //    stopAll();
  397. //  }
  398. //
  399. //  // Pengecekan tombol Servo
  400. //  if (buttonServo.isPressed() && !processActive && !remoteMode) {
  401. //    processActive = true;
  402. //    servoActive = true;
  403. //    startProcess("Feeding", durasiServo);
  404. //    setFeedStart();
  405. //    myServo.write(90);
  406. //    Serial.println("Proses manual dimulai.");
  407. //  }
  408. //
  409. //  // Pengecekan durasi Servo
  410. //  if (servoActive && checkTimeElapsed(durasiServo)) {
  411. //    clearKeterangan();
  412. //    setFeedStop();
  413. //    myServo.write(0);
  414. //    lcd.setCursor(2, 0);
  415. //    lcd.print("Stop Feed");
  416. //    lcd.setCursor(2, 1);
  417. //    lcd.print("Standby ...(5s)");
  418. //
  419. //    // Mulai Standby tanpa delay
  420. //    standbyActive = true;
  421. //    standbyStartTime = millis();
  422. //    servoActive = false;
  423. //  }
  424. //
  425. //  // Pengecekan Standby
  426. //  if (standbyActive && (millis() - standbyStartTime >= standbyDuration)) {
  427. //    standbyActive = false;
  428. //    turunActive = true;
  429. //    clearKeterangan();
  430. //    startProcess("Turun", durasiTurun);
  431. //    setIconDown();
  432. //    digitalWrite(relay1, LOW);
  433. //    digitalWrite(relay2, HIGH);
  434. //    Serial.println("Proses turun dimulai setelah standby.");
  435. //  }
  436. //
  437. //  // Pengecekan durasi Turun
  438. //  if (turunActive && checkTimeElapsed(durasiTurun)) {
  439. //    turunActive = false;
  440. //    rendamActive = true;
  441. //
  442. //    startProcess("Rendam Anco", durasiRendam * 60);
  443. //    setIconStop();
  444. //    digitalWrite(relay1, LOW);
  445. //    digitalWrite(relay2, LOW);
  446. //    Serial.println("Proses rendam dimulai.");
  447. //  }
  448. //
  449. //  // Pengecekan durasi Rendam
  450. //  if (rendamActive && checkTimeElapsed(durasiRendam * 60)) {
  451. //    rendamActive = false;
  452. //    upActive = true;
  453. //    setIconUp();
  454. //    clearKeterangan();
  455. //    lcd.setCursor(2, 0);
  456. //    lcd.print("Angkat Anco");
  457. //    lcd.setCursor(2, 1);
  458. //    lcd.print("Motor Up");
  459. //    digitalWrite(relay1, HIGH);
  460. //    digitalWrite(relay2, LOW);
  461. //    Serial.println("Proses angkat anco dimulai.");
  462. //  }
  463. //
  464. //  // Kontrol Manual
  465. //  if (!remoteMode) {  // Kontrol Manual
  466. //    if (buttonCW.isPressed()) {
  467. //      clearKeterangan();
  468. //      lcd.setCursor(2, 0);
  469. //      lcd.print("Instruksi:");
  470. //      lcd.setCursor(2, 1);
  471. //      lcd.print("Anco Naik");
  472. //      setIconUp();
  473. //      upActive = true;
  474. //      digitalWrite(relay1, HIGH);
  475. //      digitalWrite(relay2, LOW);
  476. //    }
  477. //
  478. //    if (buttonCCW.isPressed()) {
  479. //      clearKeterangan();
  480. //      lcd.setCursor(2, 0);
  481. //      lcd.print("Instruksi:");
  482. //      lcd.setCursor(2, 1);
  483. //      lcd.print("Anco Turun");
  484. //      setIconDown();
  485. //      digitalWrite(relay1, LOW);
  486. //      digitalWrite(relay2, HIGH);
  487. //    }
  488. //  }
  489. //}
  490.  
  491. void checkButtons() {
  492.   buttonCW.loop();
  493.   buttonCCW.loop();
  494.   buttonServo.loop();
  495.   btnEmergencyStop.loop();
  496.  
  497.   unsigned long currentMillis = millis();
  498.  
  499.   // Pengecekan Selector Mode (Remote Mode) dengan debounce non-blocking
  500.   bool currentSelectorState = (digitalRead(selectorButtonPin) == LOW);
  501.   if (currentSelectorState != previousRemoteMode) {
  502.     if (currentMillis - lastDebounceTimeSelector > debounceDelaySelector) {
  503.       if (currentSelectorState) {
  504.         // Mode berubah ke Remote Mode
  505.         remoteMode = true;
  506.         digitalWrite(ledPin, HIGH);  // Nyalakan LED
  507.         lcd.setCursor(14, 0);
  508.         lcd.print("|R ");
  509.         setSignalOn(); // Update ikon koneksi
  510.         Serial.println("Mode: Remote");
  511.       } else {
  512.         // Mode berubah ke Manual Mode
  513.         remoteMode = false;
  514.         digitalWrite(ledPin, LOW);  // Matikan LED
  515.         lcd.setCursor(14, 0);
  516.         lcd.print("|M ");
  517.         disconnectWiFi(); // Putuskan koneksi WiFi dan MQTT
  518.         Serial.println("Mode: Manual");
  519.       }
  520.       lastDebounceTimeSelector = currentMillis;
  521.     }
  522.   }
  523.   previousRemoteMode = currentSelectorState;
  524.  
  525.   // Pengecekan tombol Emergency Stop dengan deteksi long press
  526.   if (btnEmergencyStop.isPressed()) {
  527.     if (stopButtonPressStartTime == 0) {
  528.       // Tombol baru saja ditekan
  529.       stopButtonPressStartTime = currentMillis;
  530.       isStopButtonLongPressed = false;
  531.       Serial.println("Emergency Stop button pressed.");
  532.     } else {
  533.       // Tombol sedang ditekan
  534.       if (!isStopButtonLongPressed && (currentMillis - stopButtonPressStartTime >= LONG_PRESS_DURATION)) {
  535.         // Long press terdeteksi
  536.         isStopButtonLongPressed = true;
  537.         displayInfoTimer();
  538.         Serial.println("Emergency Stop button long pressed. Displaying Info Timer.");
  539.       }
  540.     }
  541.   } else {
  542.     if (stopButtonPressStartTime != 0) {
  543.       // Tombol dilepas
  544.       if (!isStopButtonLongPressed) {
  545.         // Ini adalah short press
  546.         stopAll();
  547.         Serial.println("Emergency Stop button short pressed. Stopping all processes.");
  548.       }
  549.       // Reset variabel deteksi
  550.       stopButtonPressStartTime = 0;
  551.       isStopButtonLongPressed = false;
  552.  
  553.       // Tampilkan informasi timer setelah tombol dilepas
  554.       displayInfoTimer();
  555.     }
  556.   }
  557.  
  558.   // Pengecekan tombol Servo
  559.   if (buttonServo.isPressed() && !processActive && !remoteMode) {
  560.     processActive = true;
  561.     servoActive = true;
  562.     startProcess("Feeding", durasiServo);
  563.     setFeedStart();
  564.     myServo.write(90);
  565.     Serial.println("Proses manual dimulai.");
  566.   }
  567.  
  568.   // Pengecekan durasi Servo
  569.   if (servoActive && checkTimeElapsed(durasiServo)) {
  570.     clearKeterangan();
  571.     setFeedStop();
  572.     myServo.write(0);
  573.     lcd.setCursor(2, 0);
  574.     lcd.print("Stop Feed");
  575.     lcd.setCursor(2, 1);
  576.     lcd.print("Standby ...(5s)");
  577.  
  578.     // Mulai Standby tanpa delay
  579.     standbyActive = true;
  580.     standbyStartTime = millis();
  581.     servoActive = false;
  582.   }
  583.  
  584.   // Pengecekan Standby
  585.   if (standbyActive && (millis() - standbyStartTime >= standbyDuration)) {
  586.     standbyActive = false;
  587.     turunActive = true;
  588.     clearKeterangan();
  589.     startProcess("Turun", durasiTurun);
  590.     setIconDown();
  591.     digitalWrite(relay1, LOW);
  592.     digitalWrite(relay2, HIGH);
  593.     Serial.println("Proses turun dimulai setelah standby.");
  594.   }
  595.  
  596.   // Pengecekan durasi Turun
  597.   if (turunActive && checkTimeElapsed(durasiTurun)) {
  598.     turunActive = false;
  599.     rendamActive = true;
  600.  
  601.     startProcess("Rendam Anco", durasiRendam * 60);
  602.     setIconStop();
  603.     digitalWrite(relay1, LOW);
  604.     digitalWrite(relay2, LOW);
  605.     Serial.println("Proses rendam dimulai.");
  606.   }
  607.  
  608.   // Pengecekan durasi Rendam
  609.   if (rendamActive && checkTimeElapsed(durasiRendam * 60)) {
  610.     rendamActive = false;
  611.     upActive = true;
  612.     setIconUp();
  613.     clearKeterangan();
  614.     lcd.setCursor(2, 0);
  615.     lcd.print("Angkat Anco");
  616.     lcd.setCursor(2, 1);
  617.     lcd.print("Motor Up");
  618.     digitalWrite(relay1, HIGH);
  619.     digitalWrite(relay2, LOW);
  620.     Serial.println("Proses angkat anco dimulai.");
  621.   }
  622.  
  623.   // Kontrol Manual
  624.   if (!remoteMode) {  // Kontrol Manual
  625.     if (buttonCW.isPressed()) {
  626.       clearKeterangan();
  627.       lcd.setCursor(2, 0);
  628.       lcd.print("Instruksi:");
  629.       lcd.setCursor(2, 1);
  630.       lcd.print("Anco Naik");
  631.       setIconUp();
  632.       upActive = true;
  633.       digitalWrite(relay1, HIGH);
  634.       digitalWrite(relay2, LOW);
  635.     }
  636.  
  637.     if (buttonCCW.isPressed()) {
  638.       clearKeterangan();
  639.       lcd.setCursor(2, 0);
  640.       lcd.print("Instruksi:");
  641.       lcd.setCursor(2, 1);
  642.       lcd.print("Anco Turun");
  643.       setIconDown();
  644.       digitalWrite(relay1, LOW);
  645.       digitalWrite(relay2, HIGH);
  646.     }
  647.   }
  648. }
  649.  
  650.  
  651.  
  652.  
  653. // Fungsi pengecekan limit switch saat UP
  654. void checkLimitSwitch() {
  655.   if (upActive && digitalRead(limitSwitchPin) == LOW) {
  656.     stopAll();
  657.     setLimitUp();
  658.     clearKeterangan();
  659.     lcd.setCursor(2, 0);
  660.     lcd.print("Anco di atas");
  661.     lcd.setCursor(2, 1);
  662.     lcd.print("Standby ...");
  663.    
  664.   }
  665. }
  666.  
  667. // Fungsi untuk memulai proses
  668. void startProcess(const char *status, unsigned long duration) {
  669. //  lcd.clear();
  670.   clearKeterangan();
  671.   startTime = millis();
  672.   lcd.setCursor(2, 0);
  673.   lcd.print(status);
  674. }
  675.  
  676. // Fungsi untuk menghentikan semua proses
  677. void stopAll() {
  678.   digitalWrite(relay1, LOW);
  679.   digitalWrite(relay2, LOW);
  680.   myServo.write(0);
  681.   servoActive = false;
  682.   turunActive = false;
  683.   rendamActive = false;
  684.   upActive = false;
  685.   processActive = false;
  686. //  lcd.clear();
  687.   clearKeterangan();
  688.   lcd.setCursor(2, 0);
  689.   lcd.print("Instruksi:");
  690.   lcd.setCursor(2, 1);
  691.   lcd.print("Motor Stop");
  692.   setIconStop();
  693. }
  694.  
  695. //// Fungsi untuk kontrol tampilan UP
  696. //void setUp() {
  697. //  lcd.clear();
  698. //  lcd.setCursor(0, 0);
  699. //  lcd.print("UP");
  700. //}
  701. //
  702. //// Fungsi untuk kontrol tampilan DOWN
  703. //void setDown() {
  704. //  lcd.clear();
  705. //  lcd.setCursor(0, 0);
  706. //  lcd.print("DOWN");
  707. //}
  708.  
  709. // Fungsi untuk mengecek apakah waktu habis
  710. bool checkTimeElapsed(unsigned long duration) {
  711.   return millis() - startTime >= duration * 1000;
  712. }
  713.  
  714.  
  715.  // Fungsi koneksi WiFi
  716.   void wifi_connect() {
  717.     Serial.print("Connecting to WiFi...");
  718. //    lcd.clear();
  719.     setSignalOff();
  720.     clearKeterangan();
  721.     lcd.setCursor(2, 0);
  722.     lcd.print("WiFi status:");
  723.     lcd.setCursor(2, 1);
  724.     lcd.print("Connecting...");
  725.    
  726.     WiFi.begin(ssid, password);
  727.     while (WiFi.status() != WL_CONNECTED) {
  728.       delay(500);
  729.       Serial.print(".");
  730.     }
  731.  
  732.     Serial.println("Connected to WiFi");
  733. //    lcd.clear();
  734.     clearKeterangan();
  735.     lcd.setCursor(2, 0);
  736.     lcd.print("Wifi Connected");
  737.     lcd.setCursor(2, 1);
  738.     lcd.print(WiFi.localIP());
  739.     setSignalOn();
  740.     delay(1000);
  741.    
  742.   }
  743.  
  744.   // Fungsi koneksi MQTT
  745.   void mqtt_connect() {
  746.     client.setServer(mqtt_broker, mqtt_port);
  747.     client.setCallback(mqttCallback);
  748.  
  749.     while (!client.connected()) {
  750.       Serial.print("Connecting to MQTT...");
  751.       if (client.connect("ESP32Client", mqttUser, mqttPassword)) {
  752.         Serial.println("connected");
  753. //        lcd.clear();
  754.         clearKeterangan();
  755.         lcd.setCursor(2, 0);
  756.         lcd.print("Server Con:");
  757.         lcd.setCursor(2, 1);
  758.         lcd.print("Connected");
  759.         setSignalOn();
  760.         client.subscribe(mqttTopicSetOtomatis);
  761.         client.subscribe(mqttTopicKontrol);
  762.       } else {
  763.         Serial.print("failed with state ");
  764.         Serial.println(client.state());
  765. //        lcd.clear();
  766.         clearKeterangan();
  767.         lcd.setCursor(2, 0);
  768.         lcd.print("Net status:");
  769.         lcd.setCursor(2, 1);
  770.         lcd.print("Disconected");
  771.         setSignalOff();
  772.         delay(2000);
  773.       }
  774.     }
  775.   }
  776.  
  777. //// Callback MQTT untuk menerima pesan
  778. //void mqttCallback(char* topic, byte* payload, unsigned int length) {
  779. //  String message;
  780. //  for (int i = 0; i < length; i++) {
  781. //    message += (char)payload[i];
  782. //  }
  783. //
  784. //  Serial.print("Message received: ");
  785. //  Serial.println(message);
  786. //   // Parsing JSON payload
  787. //  DynamicJsonDocument doc(1024);
  788. //  DeserializationError error = deserializeJson(doc, payload, length);
  789. //  if (error) {
  790. //    Serial.print("deserializeJson() failed: ");
  791. //    Serial.println(error.f_str());
  792. //    return;
  793. //  }
  794. //  String instruksi = doc["instruksi"];
  795. //  durasiServo = doc["durasiServo"].as<unsigned long>();
  796. //  durasiTurun = doc["durasiTurun"].as<unsigned long>();
  797. //  durasiRendam = doc["durasiRendam"].as<unsigned long>();
  798. //
  799. //  if (instruksi == "otomatis") {
  800. //    if (!processActive) {
  801. //      processActive = true;
  802. //      servoActive = true;
  803. //      startProcess("Feeding", durasiServo);
  804. //      setFeedStart();
  805. //      myServo.write(90);
  806. //      Serial.println("Proses otomatis dimulai.");
  807. //    }
  808. //  }
  809. //  
  810. //  if (String(topic) == mqttTopicKontrol) {
  811. //    if (message == "naik") {
  812. //      digitalWrite(relay1, HIGH);
  813. //      digitalWrite(relay2, LOW);
  814. ////      lcd.clear();
  815. //      clearKeterangan();
  816. //      lcd.setCursor(2, 0);
  817. //      lcd.print("Instruksi:");
  818. //      lcd.setCursor(2, 1);
  819. //      lcd.print("Anco Naik");
  820. //      setIconUp();
  821. //    } else if (message == "turun") {
  822. //      digitalWrite(relay1, LOW);
  823. //      digitalWrite(relay2, HIGH);
  824. ////      lcd.clear();
  825. //      clearKeterangan();
  826. //      lcd.setCursor(2, 0);
  827. //      lcd.print("Instruksi:");
  828. //      lcd.setCursor(2, 1);
  829. //      lcd.print("Anco Turun");
  830. //      setIconUp();
  831. //    } else if (message == "stop") {
  832. //      stopAll();
  833. ////      lcd.clear();
  834. //      clearKeterangan();
  835. //      lcd.setCursor(2, 0);
  836. //      lcd.print("Instruksi:");
  837. //      lcd.setCursor(2, 1);
  838. //      lcd.print("Motor Stop");
  839. //      setIconStop();
  840. //    }
  841. //  }
  842. //}
  843.  
  844. // Callback MQTT untuk menerima pesan
  845. void mqttCallback(char* topic, byte* payload, unsigned int length) {
  846.   String message;
  847.   for (int i = 0; i < length; i++) {
  848.     message += (char)payload[i];
  849.   }
  850.  
  851.   Serial.print("Message received on topic [");
  852.   Serial.print(topic);
  853.   Serial.print("]: ");
  854.   Serial.println(message);
  855.  
  856.   // Penanganan untuk topik "setOtomatis" dengan format JSON
  857.   if (String(topic) == mqttTopicSetOtomatis) {
  858.     // Parsing JSON payload
  859.     DynamicJsonDocument doc(1024);
  860.     DeserializationError error = deserializeJson(doc, payload, length);
  861.     if (error) {
  862.       Serial.print("deserializeJson() failed: ");
  863.       Serial.println(error.f_str());
  864.       return;
  865.     }
  866.  
  867.     String instruksi = doc["instruksi"];
  868.     durasiServo = doc["durasiServo"].as<unsigned long>();
  869.     durasiTurun = doc["durasiTurun"].as<unsigned long>();
  870.     durasiRendam = doc["durasiRendam"].as<unsigned long>();
  871.  
  872.  // Simpan nilai baru ke Preferences
  873.     preferences.putUInt("durasiServo", durasiServo);
  874.     preferences.putUInt("durasiTurun", durasiTurun);
  875.     preferences.putUInt("durasiRendam", durasiRendam);
  876.  
  877.     Serial.println("Durasi Servo diperbarui: " + String(durasiServo) + " detik");
  878.     Serial.println("Durasi Turun diperbarui: " + String(durasiTurun) + " detik");
  879.     Serial.println("Durasi Rendam diperbarui: " + String(durasiRendam) + " menit");
  880.  
  881.  
  882.     if (instruksi == "otomatis") {
  883.       if (!processActive) {
  884.         processActive = true;
  885.         servoActive = true;
  886.         startProcess("Feeding", durasiServo);
  887.         setFeedStart();
  888.         myServo.write(90);
  889.         Serial.println("Proses otomatis dimulai.");
  890.       }
  891.     }
  892.   }
  893.   // Penanganan untuk topik "kontrol" dengan perintah sederhana
  894.   else if (String(topic) == mqttTopicKontrol) {
  895.     if (message == "naik") {
  896.       digitalWrite(relay1, HIGH);
  897.       digitalWrite(relay2, LOW);
  898.       clearKeterangan();
  899.       lcd.setCursor(2, 0);
  900.       lcd.print("Instruksi:");
  901.       lcd.setCursor(2, 1);
  902.       lcd.print("Anco Naik");
  903.       setIconUp();
  904.       Serial.println("Instruksi: Anco Naik");
  905.     }
  906.     else if (message == "turun") {
  907.       digitalWrite(relay1, LOW);
  908.       digitalWrite(relay2, HIGH);
  909.       clearKeterangan();
  910.       lcd.setCursor(2, 0);
  911.       lcd.print("Instruksi:");
  912.       lcd.setCursor(2, 1);
  913.       lcd.print("Anco Turun");
  914.       setIconDown(); // Perbaiki dari setIconUp() ke setIconDown()
  915.       Serial.println("Instruksi: Anco Turun");
  916.     }
  917.     else if (message == "stop") {
  918.       stopAll();
  919.       clearKeterangan();
  920.       lcd.setCursor(2, 0);
  921.       lcd.print("Instruksi:");
  922.       lcd.setCursor(2, 1);
  923.       lcd.print("Motor Stop");
  924.       setIconStop();
  925.       Serial.println("Instruksi: Motor Stop");
  926.     }
  927.   }
  928. }
  929.  
  930.  
  931.  
  932. void setFeedStart() {
  933.   lcd.setCursor(0, 1);
  934.   lcd.write(byte(0));
  935. }
  936.  
  937. void setFeedStop() {
  938.   lcd.setCursor(0, 1);
  939.   lcd.write(byte(1));
  940. }
  941.  
  942. void setIconUp() {
  943.   lcd.setCursor(0, 1);
  944.   lcd.write(byte(2));
  945. //  lcd.setCursor(2, 1);
  946. //  lcd.print("Anco Naik");
  947. }
  948.  
  949. void setIconDown() {
  950.   lcd.setCursor(0, 1);
  951.   lcd.write(byte(3));
  952. //  lcd.setCursor(2, 1);
  953. //  lcd.print("Anco Turun");
  954. }
  955.  
  956. void setIconStop() {
  957.   lcd.setCursor(0, 1);
  958.   lcd.write(byte(4));
  959. }
  960.  
  961. void setLimitUp() {
  962.   lcd.setCursor(0, 1);
  963.   lcd.write(byte(5));  
  964. }
  965.  
  966. void setLimitDown() {
  967.   lcd.setCursor(0, 1);
  968.   lcd.write(byte(6));    
  969. }
  970.  
  971. void setSignalOn() {
  972. //  lcd.setCursor(0, 0);
  973. //  lcd.write(byte(7));  
  974.   lcd.createChar(7, isignalOn);  // Kembalikan karakter asli ke slot 7
  975.   lcd.setCursor(0, 0);
  976.   lcd.write(byte(7));
  977. }
  978.  
  979. void setSignalOff() {
  980. //  lcd.setCursor(0, 0);
  981. //  lcd.print("x");  
  982.   lcd.createChar(7, isignalOff);  // Kembalikan karakter asli ke slot 7
  983.   lcd.setCursor(0, 0);
  984.   lcd.write(byte(7));
  985. }
  986.  
  987. // Fungsi untuk membersihkan area tertentu pada LCD
  988. void clearLCDArea(byte row, byte startCol, byte endCol) {
  989.   // Pastikan baris dan kolom berada dalam rentang yang valid
  990.   if (row >= lcdRows) return;
  991.   if (startCol >= lcdColumns) return;
  992.   if (endCol >= lcdColumns) endCol = lcdColumns - 1;
  993.  
  994.   // Set kursor ke posisi awal
  995.   lcd.setCursor(startCol, row);
  996.  
  997.   // Hitung jumlah spasi yang perlu ditulis
  998.   byte numSpaces = endCol - startCol + 1;
  999.  
  1000.   // Tulis spasi sebanyak yang diperlukan
  1001.   for (byte i = 0; i < numSpaces; i++) {
  1002.     lcd.print(" ");
  1003.   }
  1004. }
  1005.  
  1006. void clearKeterangan(){
  1007.  // Bersihkan kembali area tertentu
  1008.   clearLCDArea(0, 2, lcdColumns - 1); // Baris 0, kolom 2-15
  1009.   clearLCDArea(1, 2, lcdColumns - 1); // Baris 1, kolom 2-15
  1010. }
  1011.  
  1012. void checkConnections() {
  1013.   if (!remoteMode) {
  1014.     // Jika tidak dalam remoteMode, tidak perlu memeriksa koneksi
  1015.     return;
  1016.   }
  1017.   bool wifiConnected = (WiFi.status() == WL_CONNECTED);
  1018.   bool mqttConnected = client.connected();
  1019.  
  1020.   // Jika WiFi terputus, coba reconnect
  1021.   if (!wifiConnected) {
  1022.     Serial.println("WiFi disconnected. Attempting to reconnect...");
  1023.     setSignalOff(); // Update ikon LCD untuk menunjukkan status terputus
  1024.     wifi_connect(); // Coba reconnect WiFi
  1025.   }
  1026.  
  1027.   // Jika MQTT terputus, coba reconnect
  1028.   if (wifiConnected && !mqttConnected) {
  1029.     Serial.println("MQTT disconnected. Attempting to reconnect...");
  1030.     setSignalOff(); // Update ikon LCD untuk menunjukkan status terputus
  1031.     mqtt_connect(); // Coba reconnect MQTT
  1032.   }
  1033.  
  1034.   // Jika kedua koneksi terhubung, update ikon LCD
  1035.   if (wifiConnected && mqttConnected) {
  1036.     setSignalOn();
  1037.   } else {
  1038.     setSignalOff();
  1039.   }
  1040. }
  1041.  
  1042.  
  1043. void disconnectWiFi() {
  1044.   if (WiFi.status() == WL_CONNECTED) {
  1045.     WiFi.disconnect(true); // Memutuskan koneksi dan menghapus SSID/password
  1046.     Serial.println("WiFi disconnected.");
  1047.     // Perbarui LCD jika perlu
  1048.     clearKeterangan();
  1049.     lcd.setCursor(2, 0);
  1050.     lcd.print("Net status:");
  1051.     lcd.setCursor(2, 1);
  1052.     lcd.print("Disconnected");
  1053.     setSignalOff();
  1054.   }
  1055. }
  1056.  
  1057.  
  1058. // Fungsi untuk menampilkan informasi timer pada LCD
  1059. void displayInfoTimer() {
  1060.   clearKeterangan();
  1061. // Baris Pertama: "Motor Stop"
  1062. // clearLCDArea(0, 0, lcdColumns - 1); // Bersihkan seluruh baris pertama
  1063.   lcd.setCursor(2, 0);
  1064.   lcd.print("Motor Stop");
  1065.  
  1066. // Baris Kedua: "F: 5s T:5s R:1m"
  1067. // clearLCDArea(1, 0, lcdColumns - 1); // Bersihkan seluruh baris kedua
  1068.   lcd.setCursor(2, 1);
  1069.   lcd.print("F:" + String(durasiServo) + "s ");
  1070.   lcd.print("T:" + String(durasiTurun) + "s ");
  1071.   lcd.print("R:" + String(durasiRendam) + "m");
  1072. }
  1073.  
Tags: feeder Anco
Advertisement