/**********************************************************************************************************************
  ███╗   ███╗ █████╗ ██████╗ ███████╗    ██████╗ ██╗   ██╗
  ████╗ ████║██╔══██╗██╔══██╗██╔════╝    ██╔══██╗╚██╗ ██╔╝
  ██╔████╔██║███████║██║  ██║█████╗      ██████╔╝ ╚████╔╝ 
  ██║╚██╔╝██║██╔══██║██║  ██║██╔══╝      ██╔══██╗  ╚██╔╝  
  ██║ ╚═╝ ██║██║  ██║██████╔╝███████╗    ██████╔╝   ██║   
  ╚═╝     ╚═╝╚═╝  ╚═╝╚═════╝ ╚══════╝    ╚═════╝    ╚═╝   

  ██████╗  ██████╗ ██████╗  █████╗ ███╗   ███╗███████╗████████╗    ██╗███╗   ██╗██████╗ ██████╗  ██████╗ ███╗   ███╗
  ██╔══██╗██╔═══██╗██╔══██╗██╔══██╗████╗ ████║██╔════╝╚══██╔══╝    ██║████╗  ██║██╔══██╗██╔══██╗██╔═══██╗████╗ ████║
  ██████╔╝██║   ██║██████╔╝███████║██╔████╔██║█████╗     ██║       ██║██╔██╗ ██║██████╔╝██████╔╝██║   ██║██╔████╔██║
  ██╔═══╝ ██║   ██║██╔══██╗██╔══██║██║╚██╔╝██║██╔══╝     ██║       ██║██║╚██╗██║██╔═══╝ ██╔══██╗██║   ██║██║╚██╔╝██║
  ██║     ╚██████╔╝██║  ██║██║  ██║██║ ╚═╝ ██║███████╗   ██║       ██║██║ ╚████║██║     ██║  ██║╚██████╔╝██║ ╚═╝ ██║
  ╚═╝      ╚═════╝ ╚═╝  ╚═╝╚═╝  ╚═╝╚═╝     ╚═╝╚══════╝   ╚═╝       ╚═╝╚═╝  ╚═══╝╚═╝     ╚═╝  ╚═╝ ╚═════╝ ╚═╝     ╚═╝
***********************************************************************************************************************/

#define BLYNK_TEMPLATE_ID "TMPL6cu1h1f-4"
#define BLYNK_TEMPLATE_NAME "iot pet feeder"
#define BLYNK_AUTH_TOKEN "Q0ktURLm3vWrFBPkk7tPvvjAhDwaDY9Y"
#define BLYNK_FIRMWARE_VERSION    "0.1.0"
#define BLYNK_PRINT Serial // Defines the object that is used for printing
//#define BLYNK_DEBUG        // Optional, this enables more detailed prints

#include <SPI.h>                //นำเข้าไลบรารี่ SPI
#include <Arduino.h>            //นำเข้าไลบรารี่ Arduino
#include <WiFi.h>               //นำเข้าไลบรารี่ WiFi
#include <WiFiClient.h>       
#include <BlynkSimpleEsp32.h>   //นำเข้าไลบรารี่ Blynk
#include <HardwareSerial.h>     //นำเข้าไลบรารี่ HardwareSerial เพื่อใช้งาน Serial port ในการส่งข้อมูล
#include "soc/rtc.h"

#define V_FOOD1 V0
#define V_FOOD2 V1
#define V_FOOD3 V2
#define V_TIME1 V3
#define V_TIME2 V4
#define V_TIME3 V5
#define V_WEIGHT V6
#define V_STEPPER V7

/* ไลบรารี่สำหรับLoadcell */
#include "HX711.h"
const int LOADCELL_DOUT_PIN = 16;
const int LOADCELL_SCK_PIN = 17;
HX711 LoadCell;
//REPLACE WITH YOUR CALIBRATION FACTOR
#define CALIBRATION_FACTOR -471.497

/* ไลบรารี่สำหรับจอแสดงผล LCD I2C */
#include <Wire.h>                   // LCD I2C
#include <LiquidCrystal_I2C.h>      // LCD I2C
LiquidCrystal_I2C lcd(0x27,20,4);   // LCD I2C 0x27

/* ไลบรารี่สำหรับจอServo */
#include <ESP32Servo.h>

Servo servo;

int servoPin = 19; // Pin connected to the servo
int currentAngle = 174; // Initial angle
int minAngle = 0; // Minimum angle (in degrees)
int maxAngle = 180; // Maximum angle (in degrees)
int angle_s = 174; // Angle for 's' command
int angle_d = 150; // Angle for 'd' command
int repeatCount = 30; // Number of times to repeat the sequence
int feed_angle = 174; // Initial angle
int clean_angle = 150; // Angle for 'd' command

/* ไลบรารี่สำหรับ Stepper Motor*/
#include <AccelStepper.h>
#define stepPin   13    //stepPin
#define dirPin    12    //dirPin
#define enPin     14    //enPin
#define STEPS_PER_REV     200 // Steps per revolution of your stepper motor
#define RPM               120  // Desired revolutions per minute
bool stepperEnabled = false;
AccelStepper stepper(AccelStepper::DRIVER, stepPin, dirPin);

/* ประกาศขาสำหรับ Relay */
#define Relay 32

/* ประกาศขาสำหรับ Switch */
#define SW  15// Switch pin
int count = 0;

/* ไลบรารี่สำหรับบันทึกข้อมูลลง EEPROM */
#include <Preferences.h>            //EEPROM
Preferences pref;                   //EEPROM

/* ประกาศขาสำหรับ Rotary Encoder Switch */
#define encoder_outputA 27
#define encoder_outputB 26
#define encoder_sw 25
int encoder_swState = 0;
int encoder_counter = 0; 
int encoder_currenceState;
int encoder_lastState;
bool encoder_choice = false;

/* ไลบรารี่สำหรับโมดูล RTC */
#include "RTClib.h"                 //RTC I2C
RTC_DS3231 rtc;                     //RTC I2C

/* Void */
void rotary();          //Rotary Switch
void monitor();         //การแสดงผลของจอ LCD
void main_feeder();     //ระบบการให้อาหาร
void pref_eeprom();     //บันทึกข้อมูลลง EEPROM
void blynk_connected();

void cleanFunction();
void tareLoadCell();
void selectFood();
void feeding();
void stepper_motor();

char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; //แปลงเป็นสัปดาห์

/* ตัวแปรเก็บค่าสำหรับบันทึกลงใน EEPROM */
int food1,food2,food3;                 //get data form blynk ปริมาณอาหาร
int mem_food1,mem_food2,mem_food3;     //EEPROM data
String time1,time2,time3;                //get data form blynk เวลาให้อาหารสัตว์
String mem_time1,mem_time2,mem_time3;    //EEPROM data

bool bool_tare = false;
bool bool_feeding = false;

/* ตัวแปรสำหรับเก็บค่า Millis */
unsigned long timer_page      = millis();
unsigned long timer_feeder    = millis();
unsigned long timer_rotary    = millis();
unsigned long timer_clean     = millis();
unsigned long timer_stepper   = millis();

/* boolean เก็บค่าเวลาเมื่อถึงเวลาทำความสะอาดและให้อาหาร */
bool bool_time1,bool_time2,bool_time3;
bool clean_feeder,clean_status;
bool clean_activate,tare_activate,feed_activate,food1_activate,food2_activate,food3_activate;
int value_food;

char auth[] = BLYNK_AUTH_TOKEN;
/* เก็บข้อมูลตัวแปร ไวไฟ และรหัส */
String send_ssid;
String send_pass;

char ssid[] = "Wokwi-GUEST";
char pass[] = "";

float Weight;
float blynk_weight;

//-----------------------------------------------------------------------------------------------------------//
void setup() {
  // rtc_cpu_freq_config_t config;
  // rtc_clk_cpu_freq_get_config(&config);
  // rtc_clk_cpu_freq_to_config(RTC_CPU_FREQ_80M, &config);
  // rtc_clk_cpu_freq_set_config_fast(&config);

  /* Initial Servo pin */
  servo.attach(servoPin);
  servo.write(currentAngle); // Initialize servo to initial angle

  /* Initial Relay Pin */
  pinMode(Relay,OUTPUT);

  count = 0;

  /* Initial Feed protocal */
  clean_activate  = true;
  tare_activate   = false;
  feed_activate   = false;
  food1_activate  = false;
  food2_activate  = false;
  food3_activate  = false;

  /* Initial Loadcell */
  LoadCell.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN);
  LoadCell.set_scale(CALIBRATION_FACTOR);

  encoder_counter = 1;
  // encoder_bt.begin(encoder_bt_pin);
  pinMode(encoder_outputA,INPUT);
  pinMode(encoder_outputB,INPUT);
  pinMode(encoder_sw,INPUT);
  //pinMode(encoder_sw,INPUT_PULLUP);

  lcd.backlight();
  lcd.init(); //LCD Begin
  Wire.begin(); //I2C
  Serial.begin(115200); //Serial Rate

  WiFi.begin(ssid, pass);

  /* Stepper Motor */
  pinMode(SW, INPUT_PULLUP);
  pinMode(enPin, OUTPUT);
  digitalWrite(enPin, HIGH); // Disable stepper motor initially
  stepper.setMaxSpeed(RPM * STEPS_PER_REV);
  stepper.setAcceleration(1000); // You can adjust the acceleration value as needed
  stepper.setSpeed(RPM * STEPS_PER_REV);

  /* Pref Setup */
  pref.begin("food_state", false);  //Given namespace name from an NVS partition
  
  //WiFi.begin(ssid, pass);
  Blynk.config(auth);

  lcd.setCursor(0,0);
  lcd.print("IoT Cat Feeder");
  lcd.setCursor(0,1);
  lcd.print("Version 1.4.1");
  lcd.setCursor(0,2);
  lcd.print("Poramet Inprom");
  lcd.setCursor(0,3);
  lcd.print("SID : 6531280024");
  delay(2000);
  lcd.clear();

  LoadCell.tare();

}
//-----------------------------------------------------------------------------------------------------------//
void loop() {

  if (SW == LOW) {
    count++;
    delay(200); // Debouncing delay
  }
    if (count == 2) {
    count = 0;
  }

  if (Serial.available() > 0) {
    char command = Serial.read(); // Read the command from Serial Monitor

    if (command == 's') {
      servo.write(angle_s);
      currentAngle = angle_s; // Update current angle
      Serial.println("Angle set to 174.");
    } else if (command == 'd') {
      servo.write(angle_d);
      currentAngle = angle_d; // Update current angle
      Serial.println("Angle set to 150.");
    } else {
      Serial.println("Invalid command. Use 's' to set angle to 174, 'd' to set angle to 150, 'a' to execute sequence or input angle (0-180).");
    }
  }

  if (digitalRead(SW) == LOW) { // If switch is pressed
    Serial.println("Stepper On");
    stepperEnabled = true;
  }
  else{
    stepperEnabled = false;
  }

  if (stepperEnabled) {
    digitalWrite(enPin, LOW); // Enable stepper motor
    digitalWrite(dirPin, HIGH); // Set direction (clockwise)
    
    // Step the motor
    for (int i = 0; i < STEPS_PER_REV; i++) {
      digitalWrite(stepPin, HIGH);
      delayMicroseconds(500); // Adjust delay for desired speed
      digitalWrite(stepPin, LOW);
      delayMicroseconds(500); // Adjust delay for desired speed
    }
  }

  rotary();
  monitor();
  main_feeder();
  pref_eeprom();  //เก็บข้อมูลลง EEPROM
  blynk_connected();

  servo.write(feed_angle);
  

  if (WiFi.status() == WL_CONNECTED)
  {
  Blynk.run();
  }
}
//-----------------------------------------------------------------------------------------------------------//

BLYNK_WRITE(V_STEPPER)
{   
  int value = param.asInt(); // Get value as integer
  if(value == 1){
    stepper_motor();
  }
  else{

  }
}


/*-----------------------------------*/
BLYNK_WRITE(V_FOOD1) {   //รับค่าจาก Blynk
  food1 = param.asInt();
  pref.putInt("FOOD1",food1);
}
BLYNK_WRITE(V_FOOD2) {   //รับค่าจาก Blynk
  food2 = param.asInt();
  pref.putInt("FOOD2",food2);
}
BLYNK_WRITE(V_FOOD3) {   //รับค่าจาก Blynk
  food3 = param.asInt();
  pref.putInt("FOOD3",food3);
}
/*-----------------------------------*/
BLYNK_WRITE(V_TIME1) {   //รับค่าจาก Blynk
  time1 = param.asString();
  pref.putString("Time1",time1);
}
BLYNK_WRITE(V_TIME2) {   //รับค่าจาก Blynk
  time2 = param.asString();
  pref.putString("Time2",time2);
}
BLYNK_WRITE(V_TIME3) {   //รับค่าจาก Blynk
  time3 = param.asString();
  pref.putString("Time3",time3);
}
/*-----------------------------------*/
BLYNK_WRITE(V_TARE) {   //รับค่าจาก Blynk
  bool_tare = param.asString();
  //pref.putString("Bool_Tare",bool_tare);
}

void pref_eeprom() {   //นำข้อมูลเก็บลงใน EEPROM
  mem_food1 = pref.getInt("FOOD1",0);
  mem_food2 = pref.getInt("FOOD2",0);
  mem_food3 = pref.getInt("FOOD3",0);
  mem_time1 = pref.getString("Time1",String());
  mem_time2 = pref.getString("Time2",String());
  mem_time3 = pref.getString("Time3",String());
}

void blynk_connected() {
}

void monitor() {

  //เช็คโมดูล
  if (!rtc.begin()) {  //RTC I2C Check
    Serial.println("Couldn't find RTC");
  }

  /* ตัวแปรแปลงเวลาจากวินาทีเป็น ชั่วโมง นาที */
  int int_time1 = mem_time1.toInt();
  int int_time2 = mem_time2.toInt();
  int int_time3 = mem_time3.toInt();
  int time1_hours, time1_minutes;
  int time2_hours, time2_minutes;
  int time3_hours, time3_minutes;
  time1_hours   = int_time1/3600;
  time1_minutes = (int_time1 % 3600) / 60; 
  time2_hours   = int_time2/3600;
  time2_minutes = (int_time2 % 3600) / 60;
  time3_hours   = int_time3/3600;
  time3_minutes = (int_time3 % 3600) / 60;
  DateTime now  = rtc.now(); //RTC I2C

  bool time1_incoming,time2_incoming,time3_incoming;
  int time1_compare,time2_compare,time3_compare;
  if(time1_hours - now.hour() >= 0){
    time1_compare = time1_hours - now.hour();
    //Serial.println((String)"Time 1 : Incoming" +time1_compare);
  }
  else if(time1_hours - now.hour() < 0){
    //Serial.println((String)"Time 1 : Past");
    time1_incoming = false;
    time1_compare = 99;
  }
  if(time2_hours - now.hour() >= 0){
    time2_compare = time2_hours - now.hour();
    //Serial.println((String)"Time 2 : Incoming" +time2_compare);
  }
  else if(time2_hours - now.hour() < 0){
    //Serial.println((String)"Time 2 : Past");
    time2_incoming = false;
    time2_compare = 99;
  }
  if(time3_hours - now.hour() >= 0){
    time3_compare = time3_hours - now.hour();
    //Serial.println((String)"Time 3 : Incoming" +time3_compare);
  }
  else if(time3_hours - now.hour() < 0){
    //Serial.println((String)"Time 3 : Past");
    time3_incoming = false;
    time3_compare = 99;
  }
  if(time1_compare < time2_compare && time1_compare <time3_compare){
    time1_incoming = true;
  }
  else if(time2_compare < time1_compare && time2_compare < time3_compare){
    time2_incoming = true;
  }
  else if(time3_compare < time1_compare && time3_compare < time2_compare){
    time3_incoming = true;
  }

  //เปรียบเทียบเวลาที่ส่งมาจาก Blynk กับ RTC
  if(now.hour() == time1_hours && now.minute() == time1_minutes && now.second() == 0){
    // DEBUG_PRINT(String("Time 1"));
    bool_time1  = true;
  }
  else{
    bool_time1  = false;
  }
  if(now.hour() == time2_hours && now.minute() == time2_minutes && now.second() == 0){
    // DEBUG_PRINT(String("Time 2"));
    bool_time2  = true;
  }
    else{
    bool_time2  = false;
  }
  if(now.hour() == time3_hours && now.minute() == time3_minutes && now.second() == 0){
    // DEBUG_PRINT(String("Time 3"));
    bool_time3  = true;
  }
    else{
    bool_time3  = false;
  }

  if (millis() - timer_page >=100) {  //Status
    //Serial.println((String)"Position: "+encoder_counter);
    /* Main Display */
    if (count == 0) {  
      lcd.setCursor(19,3);
      lcd.print("1");
      bool isconnected = Blynk.connected();
      if (isconnected == false) {
        //lcd.clear();
        lcd.setCursor(0,0);
        lcd.print("                ");
        lcd.setCursor(0,0);
        lcd.print("Status : Offline");
        //Serial.println("Blynk Not Connected");
      }
      if (isconnected == true) {
        //lcd.clear();
        lcd.setCursor(0,0);
        lcd.print("                  "); 
        lcd.setCursor(0,0);
        lcd.print("Status : Online");
        //Serial.println("Blynk Connected");
      }
      lcd.setCursor(0,1);
      lcd.print(now.hour(), DEC);    //hour ชั่วโมง
      lcd.print(":");
      lcd.print(now.minute(), DEC);  //minute นาที
      lcd.print(":");
      lcd.print(now.second(), DEC);  //secound วินาที
      lcd.print("  ");
      lcd.setCursor(9,1);
      lcd.print(now.day(), DEC);
      lcd.print("/");
      lcd.print(now.month(), DEC);
      lcd.print("/");
      lcd.print(now.year(), DEC);
      
      if(time1_incoming == true && bool_time1 == false){
        lcd.setCursor(0,2);
        lcd.print("                   ");
        lcd.setCursor(0,2);
        lcd.print((String)"Time 1 : "+time1_hours +":" +time1_minutes);
        lcd.setCursor(0,3);
        lcd.print("                ");
        lcd.setCursor(0,3);
        lcd.print((String)"Food Value : "+mem_food1 +"g");
          
      }
      else if(time2_incoming == true && bool_time2 == false){
        lcd.setCursor(0,2);
        lcd.print("                   ");
        lcd.setCursor(0,2);
        lcd.print((String)"Time 2 : "+time2_hours +":" +time2_minutes);
        lcd.setCursor(0,3);
        lcd.print("                   ");
        lcd.setCursor(0,3);
        lcd.print((String)"Food Value : "+mem_food2 +"g");
      }
      else if(time3_incoming == true && bool_time3 == false){
        lcd.setCursor(0,2);
        lcd.print("                ");
        lcd.setCursor(0,2);
        lcd.print((String)"Time 3 : "+time3_hours +":" +time3_minutes);
        lcd.setCursor(0,3);
        lcd.print("                ");
        lcd.setCursor(0,3);
        lcd.print((String)"Food Value : "+mem_food3 +"g");
      }

      if(time1_incoming == true && bool_time1 == true){
        lcd.setCursor(0,2);
        lcd.print("                   ");
        lcd.setCursor(0,2);
        lcd.print((String)"Feeding : ");
        lcd.setCursor(0,3);
        lcd.print("                ");
        lcd.setCursor(0,3);
        lcd.print((String)"Food Value : "+mem_food1 +"g");
          
      }
      else if(time2_incoming == true && bool_time2 == true){
        lcd.setCursor(0,2);
        lcd.print("                   ");
        lcd.setCursor(0,2);
        lcd.print((String)"Feeding : ");
        lcd.setCursor(0,3);
        lcd.print("                   ");
        lcd.setCursor(0,3);
        lcd.print((String)"Food Value : "+mem_food2 +"g");
      }
      else if(time3_incoming == true && bool_time3 == true){
        lcd.setCursor(0,2);
        lcd.print("                ");
        lcd.setCursor(0,2);
        lcd.print((String)"Feeding : ");
        lcd.setCursor(0,3);
        lcd.print("                ");
        lcd.setCursor(0,3);
        lcd.print((String)"Food Value : "+mem_food3 +"g");
      }
    }
    if (count == 1) {
      lcd.setCursor(0,0);
      lcd.print("Feed Time      Value");

      lcd.setCursor(0,1);
      lcd.print("*");
      lcd.setCursor(1,1);
      lcd.print("Feed1 : ");
      lcd.setCursor(9,1);
      lcd.print(time1_hours);
      lcd.setCursor(11,1);
      lcd.print(":");
      lcd.setCursor(12,1);
      lcd.print(time1_minutes);
      lcd.setCursor(16,1);
      lcd.print((String)mem_food1 +"g");

      lcd.setCursor(0,2);
      lcd.print("*");
      lcd.setCursor(1,2);
      lcd.print("Feed2 : ");
      lcd.setCursor(9,2);
      lcd.print(time2_hours);
      lcd.setCursor(11,2);
      lcd.print(":");
      lcd.setCursor(12,2);
      lcd.print(time2_minutes);
      lcd.setCursor(16,2);
      lcd.print((String)mem_food2 +"g");

      lcd.setCursor(0,3);
      lcd.print("*");
      lcd.setCursor(1,3);
      lcd.print("Feed3 : ");
      lcd.setCursor(9,3);
      lcd.print(time3_hours);
      lcd.setCursor(11,3);
      lcd.print(":");
      lcd.setCursor(12,3);
      lcd.print(time3_minutes);
      lcd.setCursor(16,3);
      lcd.print((String)mem_food3 +"g");
    }

    if (encoder_counter == 3 && encoder_choice == true) { //Edit Display
      lcd.setCursor(1,0);
      lcd.print("Food1 :");
      lcd.setCursor(1,1);
      lcd.print("Food2 :");
      lcd.setCursor(0,2);
      lcd.print("Food3 :");
    }
  timer_page += 100;
  timer_page = millis();
  }
}

void main_feeder() {
  //
  //Serial.println((String)"Weight : "+LoadCell.get_units());
  if(bool_time1){
    food1_activate = true;
  }
  else{
  }
  if(bool_time2){
    food2_activate = true;
  }
  else{
  }
  if(bool_time3){
    food3_activate = true;
  }
  else{
  }

  /*Check Feeding*/
  if(bool_time1 || bool_time2 || bool_time3 ){
    bool_feeding = true;
  }
  else{}

  //servo.write(174);
  if(bool_feeding == true){
    feed_activate = true;
    while (feed_activate)
    {
      Serial.println("Feeddddddd");
      lcd.clear();
      cleanFunction();
      delay(200);
      selectFood();
      delay(200);
      feeding();
      stepper.stop();
      delay(200);
      feed_activate   = false;
      food1_activate  = false;
      food2_activate  = false;
      food3_activate  = false;
      encoder_counter = 1;
      bool_feeding    = false;
    }
    
  }

}

void rotary(){
  encoder_currenceState = digitalRead(encoder_outputA);
  if (encoder_currenceState != encoder_lastState){     
    if (digitalRead(encoder_outputB) != encoder_currenceState) { 
      encoder_counter ++;
      lcd.clear();
    }
    else{
      encoder_counter --;
      lcd.clear();
    }
  }
  encoder_lastState = encoder_currenceState;


  if (encoder_counter >= 3){
    encoder_counter = 1;
  }
  else if (encoder_counter <= 0){
    encoder_counter = 2;
  }
}

void cleanFunction() {
  lcd.clear();
  lcd.print((String)"Cleanning !! ");
  servo.write(clean_angle);
  delay(500);
  digitalWrite(Relay,HIGH);
  delay(2000);
  digitalWrite(Relay,LOW);
  delay(100);
  // int i;
  // for (i = 0; i < 10; i++) {
  //   lcd.setCursor(0,0);
  //   lcd.print((String)"Cleanning !! "+i);
  //   servo.write(feed_angle);
  //   delay(200);
  //   servo.write(clean_angle);
  //   delay(500);
  // }
}

void tareLoadCell() {
  servo.write(feed_angle);
  lcd.clear();
  LoadCell.tare();
  lcd.print((String)"Tare !! ");
  delay(500);
  lcd.clear();
}

void selectFood() {
  if (food1_activate == true) {
    value_food = mem_food1;
  } else if (food2_activate == true) {
    value_food = mem_food2;
  } else if (food3_activate == true) {
    value_food = mem_food3;
  }
}

void feeding() {
  lcd.clear();
  tareLoadCell();
  float weight = LoadCell.get_units();
  float current_weight = weight;
  float real_weight;
  delay(200);
  while (real_weight <= value_food) {
    servo.write(feed_angle);
    lcd.setCursor(0,0);
    lcd.print("Feeding");
    stepper.runSpeed();
    weight = LoadCell.get_units(); // Update weight reading
    real_weight = -weight - -current_weight;
    blynk_weight = real_weight;
    Blynk.virtualWrite(V_WEIGHT, blynk_weight);
    lcd.setCursor(0,1);
    lcd.print((String)"Feeding : " +real_weight +" g");
  }
  lcd.clear();
}
void stepper_motor(){
    stepper.runSpeed();
}
//-----------------------------------------------------------------------------------------------------------//
A4988
GND5VSDASCLSQWRTCDS1307+
NOCOMNCVCCGNDINLED1PWRRelay Module