IOT Automated Fish Feeder project with NodeMCU and Real time clock module

  I have made a fish feeder previously where I used: 


1. NodeMCU 

2. RTC DS 3231

3. Servo motor

And the fish feeder worked through a website, the website was accessible through HTTP localhost. The fish feeder was connected to a local database and the ui was completely hosted through the NodeMCU. It was unlimited hosting and free of cost!

Here are two codes, one of server side automation and another of full automations.:

full code.ino:

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <EEPROM.h>

#include "Wire.h"
#include <Servo.h>

#define DS1307_ADDRESS 0x68
byte zero = 0x00;

#define servo_pin D5
#define EEPROM_SIZE 512

int homePage = 0;
int dispenseFoodDelay = 100, writeDegrees = 90, foodDispenseState = true;
Servo myservo;

template< typename T, size_t N > size_t ArraySize (T (&) [N]) {
  return N;
}

/* Put your SSID & Password */
String ssid = "NodeMCU";  // Enter SSID here
String password = "12345678";  //Enter Password here

int ssidAddr = 1, passAdds = 2;

String timeList[50] = {"MyTime1", "Mytime2"};



void setDateTime(int hr, int mnt) {

  byte second =      30; //0-59
  byte minute =      mnt; //0-59
  byte hour =        hr; //0-23
  byte weekDay =     3; //1-7
  byte monthDay =    31; //1-31
  byte month =       10; //1-12
  byte year  =       22; //0-99

  Wire.beginTransmission(DS1307_ADDRESS);
  Wire.write(zero); //stop Oscillator

  Wire.write(decToBcd(second));
  Wire.write(decToBcd(minute));
  Wire.write(decToBcd(hour));
  Wire.write(decToBcd(weekDay));
  Wire.write(decToBcd(monthDay));
  Wire.write(decToBcd(month));
  Wire.write(decToBcd(year));

  Wire.write(zero); //start

  Wire.endTransmission();
}

byte decToBcd(byte val) {
  // Convert normal decimal numbers to binary coded decimal
  return ( (val / 10 * 16) + (val % 10) );
}

byte bcdToDec(byte val)  {
  // Convert binary coded decimal to normal decimal numbers
  return ( (val / 16 * 10) + (val % 16) );
}

void printDate() {

  // Reset the register pointer
  Wire.beginTransmission(DS1307_ADDRESS);
  Wire.write(zero);
  Wire.endTransmission();

  Wire.requestFrom(DS1307_ADDRESS, 7);

  int second = bcdToDec(Wire.read());
  int minute = bcdToDec(Wire.read());
  int hour = bcdToDec(Wire.read() & 0b111111); //24 hour time
  int weekDay = bcdToDec(Wire.read()); //0-6 -> sunday - Saturday
  int monthDay = bcdToDec(Wire.read());
  int month = bcdToDec(Wire.read());
  int year = bcdToDec(Wire.read());

  //print the date EG   3/1/11 23:59:59

  //
  Serial.print(month);
  Serial.print("/");
  Serial.print(monthDay);
  Serial.print("/");
  Serial.print(year);
  Serial.print("     ");
  Serial.print(hour);
  Serial.print(":");
  Serial.print(minute);
  Serial.print(":");
  Serial.println(second);

  if(minute == 165)
  {
    ESP.restart();
  }

  for (int i = 0; i < getArraySize(timeList, ArraySize(timeList)); i++)
  {
    int alarmHour = timeList[i].substring(0, 2).toInt();
    int alarmMinute = timeList[i].substring(3, 6).toInt();
    if (alarmHour == hour)
    {
      if (alarmMinute == minute)
      {
        Serial.println("Ringing");
        if (second == 0)
        {
          dispenseFood();
        }
      }
    }
  }
}

void dispenseFood()
{
  myservo.write(180);
  delay(dispenseFoodDelay);
  myservo.write(0);
  Serial.println("Servo");
  delay(1000);
}

String convertArray(String arr[], int n)
{
  String rsltStr = "";
  for (int i = 0; i < n; i++)
  {
    if (arr[i] != "")
    {
      rsltStr += arr[i] + ",";
    }
  }
  return (rsltStr);
}

int getArraySize(String myArr[], int n)
{
  int counter = 0;
  for (int i = 0; i < n; i++)
  {
    if (myArr[i] != "")
    {
      counter++;
    }
  }
  return (counter);
}
String resultArray[50];
void convertToArray(String csv)
{
  for (int i = 0; i < ArraySize(resultArray); i++)
  {
    resultArray[i] = "";
  }
  csv = csv + ",";
  String prt = "";
  char prtArr[csv.length()];
  csv.toCharArray(prtArr, csv.length());
  for (int i = 0; i < csv.length(); i++)
  {
    if (prtArr[i] != ',')
    {
      prt += prtArr[i];
    }
    else
    {
      Serial.println(prt);
      resultArray[getArraySize(resultArray, ArraySize(resultArray))] = prt;
      prt = "";
    }
  }
}

ESP8266WebServer server(80);


void setup()
{
  Serial.begin(115200);
  Wire.begin();
  myservo.attach(D5);
  myservo.write(0);
  Serial.println("loopstart");
  EEPROM.begin(EEPROM_SIZE);
  ssid = read_String(70);
  password = read_String(110);
  WiFi.softAP(ssid, password);
  delay(100);
  convertToArray(read_String(140));

  for (int i = 0; i < ArraySize(resultArray); i++)
  {
    timeList[i] = resultArray[i];
  }

  server.on("/", handle_Redirection);
  server.on("/home", handle_OnConnect);
  server.on("/saved", handle_onSave);
  server.on("/add", handle_onAdd);
  server.on("/remove", handle_onRemove);

  server.begin();
  Serial.println("HTTP server started");
  pinMode(D6, OUTPUT);
  pinMode(D7, OUTPUT);
  digitalWrite(D7, LOW);
  digitalWrite(D6, HIGH);
  delay(2000);
  setDateTime(21,36);
  printDate();
}
void loop() {
  server.handleClient();
  printDate();
}

void handle_OnConnect() {
  homePage = 0;
  Serial.println("New Client!");
  server.send(200, "text/html", SendHTML());
}
void handle_Redirection()
{
  homePage = 1;
  server.send(200, "text/html", SendHTML());
}

void handle_onSave()
{
  Serial.println("Data Saved!");
  String mySSID = server.arg("ssid");
  String myPass = server.arg("pass");
  if (mySSID == ssid && myPass == password)
  {
    server.send(200, "text/html", SendHTML());
  }
  else
  {
    writeString(70, mySSID);
    writeString(110, myPass);
    ssid = mySSID;
    password = myPass;
    server.send(200, "text/html", passChanged());
    delay(2000);

    WiFi.softAPdisconnect(true);
    WiFi.softAP(ssid, password);

    homePage = 1;
    server.send(200, "text/html", SendHTML());
  }

}

String passChanged()
{
  return ("<h1 style='color:red'>Device Name and Password has been changed, please re-connect the Device WIFI!<h1>");
}

void handle_onAdd()
{
  homePage = 1;
  Serial.println("Time Added!");
  String addedTime = server.arg("time");
  timeList[getArraySize(timeList, ArraySize(timeList))] = addedTime;
  writeString(140, convertArray(timeList, ArraySize(timeList)));
  Serial.println(timeList[getArraySize(timeList, ArraySize(timeList)) - 1]);
  server.send(200, "text/html", SendHTML());
}

void handle_onRemove()
{
  homePage = 1;
  Serial.println("Time Removed!");
  String removedTime = server.arg("id");
  int timeId = removedTime.toInt();
  timeList[timeId] = "";
  writeString(140, convertArray(timeList, ArraySize(timeList)));
  convertToArray(read_String(140));

  for (int i = 0; i < ArraySize(resultArray); i++)
  {
    timeList[i] = resultArray[i];
  }
  server.send(200, "text/html", SendHTML());
}

void writeString(int add, String data)
{
  int _size = data.length();
  int i;
  for (i = 0; i < _size; i++)
  {
    EEPROM.write(add + i, data[i]);
  }
  EEPROM.write(add + _size, '\0'); //Add termination null character for String Data
  EEPROM.commit();
}


String read_String(int add)
{
  int i;
  char data[100]; //Max 100 Bytes
  int len = 0;
  unsigned char k;
  k = EEPROM.read(add);
  while (k != '\0' && len < 500) //Read until null character
  {
    k = EEPROM.read(add + len);
    data[len] = k;
    len++;
  }
  data[len] = '\0';
  return String(data);
}


String getTimesHTML()
{
  String myTestStr = "";
  String myArrStr = "";
  for (int i = 0; i < ArraySize(timeList); i++)
  {
    if (timeList[i] != "")
    {
      myTestStr = timeList[i];
      myTestStr.replace("x", ":");
      myArrStr += "<button class='removeBtn' id='delete" + String(i) + "'>" + myTestStr + " &nbsp;&nbsp;&nbsp;<b id='crossTxt'>X</b></button></p>\n";
    }
  }
  return (myArrStr);
}

Server UI Host.ino:

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <EEPROM.h>

#include "Wire.h"
#include <Servo.h>

#define DS1307_ADDRESS 0x68
byte zero = 0x00;

#define servo_pin D5
#define EEPROM_SIZE 512

int homePage = 0;
int dispenseFoodDelay = 100, writeDegrees = 90, foodDispenseState = true;
Servo myservo;

template< typename T, size_t N > size_t ArraySize (T (&) [N]) {
  return N;
}

/* Put your SSID & Password */
String ssid = "NodeMCU";  // Enter SSID here
String password = "12345678";  //Enter Password here

int ssidAddr = 1, passAdds = 2;

String timeList[50] = {"MyTime1", "Mytime2"};



void setDateTime(int hr, int mnt) {

  byte second =      30; //0-59
  byte minute =      mnt; //0-59
  byte hour =        hr; //0-23
  byte weekDay =     3; //1-7
  byte monthDay =    31; //1-31
  byte month =       10; //1-12
  byte year  =       22; //0-99

  Wire.beginTransmission(DS1307_ADDRESS);
  Wire.write(zero); //stop Oscillator

  Wire.write(decToBcd(second));
  Wire.write(decToBcd(minute));
  Wire.write(decToBcd(hour));
  Wire.write(decToBcd(weekDay));
  Wire.write(decToBcd(monthDay));
  Wire.write(decToBcd(month));
  Wire.write(decToBcd(year));

  Wire.write(zero); //start

  Wire.endTransmission();
}

byte decToBcd(byte val) {
  // Convert normal decimal numbers to binary coded decimal
  return ( (val / 10 * 16) + (val % 10) );
}

byte bcdToDec(byte val)  {
  // Convert binary coded decimal to normal decimal numbers
  return ( (val / 16 * 10) + (val % 16) );
}

void printDate() {

  // Reset the register pointer
  Wire.beginTransmission(DS1307_ADDRESS);
  Wire.write(zero);
  Wire.endTransmission();

  Wire.requestFrom(DS1307_ADDRESS, 7);

  int second = bcdToDec(Wire.read());
  int minute = bcdToDec(Wire.read());
  int hour = bcdToDec(Wire.read() & 0b111111); //24 hour time
  int weekDay = bcdToDec(Wire.read()); //0-6 -> sunday - Saturday
  int monthDay = bcdToDec(Wire.read());
  int month = bcdToDec(Wire.read());
  int year = bcdToDec(Wire.read());

  //print the date EG   3/1/11 23:59:59

  //
  Serial.print(month);
  Serial.print("/");
  Serial.print(monthDay);
  Serial.print("/");
  Serial.print(year);
  Serial.print("     ");
  Serial.print(hour);
  Serial.print(":");
  Serial.print(minute);
  Serial.print(":");
  Serial.println(second);

  if(minute == 165)
  {
    ESP.restart();
  }

  for (int i = 0; i < getArraySize(timeList, ArraySize(timeList)); i++)
  {
    int alarmHour = timeList[i].substring(0, 2).toInt();
    int alarmMinute = timeList[i].substring(3, 6).toInt();
    if (alarmHour == hour)
    {
      if (alarmMinute == minute)
      {
        Serial.println("Ringing");
        if (second == 0)
        {
          dispenseFood();
        }
      }
    }
  }
}

void dispenseFood()
{
  myservo.write(180);
  delay(dispenseFoodDelay);
  myservo.write(0);
  Serial.println("Servo");
  delay(1000);
}

String convertArray(String arr[], int n)
{
  String rsltStr = "";
  for (int i = 0; i < n; i++)
  {
    if (arr[i] != "")
    {
      rsltStr += arr[i] + ",";
    }
  }
  return (rsltStr);
}

int getArraySize(String myArr[], int n)
{
  int counter = 0;
  for (int i = 0; i < n; i++)
  {
    if (myArr[i] != "")
    {
      counter++;
    }
  }
  return (counter);
}
String resultArray[50];
void convertToArray(String csv)
{
  for (int i = 0; i < ArraySize(resultArray); i++)
  {
    resultArray[i] = "";
  }
  csv = csv + ",";
  String prt = "";
  char prtArr[csv.length()];
  csv.toCharArray(prtArr, csv.length());
  for (int i = 0; i < csv.length(); i++)
  {
    if (prtArr[i] != ',')
    {
      prt += prtArr[i];
    }
    else
    {
      Serial.println(prt);
      resultArray[getArraySize(resultArray, ArraySize(resultArray))] = prt;
      prt = "";
    }
  }
}

ESP8266WebServer server(80);


void setup()
{
  Serial.begin(115200);
  Wire.begin();
  myservo.attach(D5);
  myservo.write(0);
  Serial.println("loopstart");
  EEPROM.begin(EEPROM_SIZE);
  ssid = read_String(70);
  password = read_String(110);
  WiFi.softAP(ssid, password);
  delay(100);
  convertToArray(read_String(140));

  for (int i = 0; i < ArraySize(resultArray); i++)
  {
    timeList[i] = resultArray[i];
  }

  server.on("/", handle_Redirection);
  server.on("/home", handle_OnConnect);
  server.on("/saved", handle_onSave);
  server.on("/add", handle_onAdd);
  server.on("/remove", handle_onRemove);

  server.begin();
  Serial.println("HTTP server started");
  pinMode(D6, OUTPUT);
  pinMode(D7, OUTPUT);
  digitalWrite(D7, LOW);
  digitalWrite(D6, HIGH);
  delay(2000);
  setDateTime(21,36);
  printDate();
}
void loop() {
  server.handleClient();
  printDate();
}

void handle_OnConnect() {
  homePage = 0;
  Serial.println("New Client!");
  server.send(200, "text/html", SendHTML());
}
void handle_Redirection()
{
  homePage = 1;
  server.send(200, "text/html", SendHTML());
}

void handle_onSave()
{
  Serial.println("Data Saved!");
  String mySSID = server.arg("ssid");
  String myPass = server.arg("pass");
  if (mySSID == ssid && myPass == password)
  {
    server.send(200, "text/html", SendHTML());
  }
  else
  {
    writeString(70, mySSID);
    writeString(110, myPass);
    ssid = mySSID;
    password = myPass;
    server.send(200, "text/html", passChanged());
    delay(2000);

    WiFi.softAPdisconnect(true);
    WiFi.softAP(ssid, password);

    homePage = 1;
    server.send(200, "text/html", SendHTML());
  }

}

String passChanged()
{
  return ("<h1 style='color:red'>Device Name and Password has been changed, please re-connect the Device WIFI!<h1>");
}

void handle_onAdd()
{
  homePage = 1;
  Serial.println("Time Added!");
  String addedTime = server.arg("time");
  timeList[getArraySize(timeList, ArraySize(timeList))] = addedTime;
  writeString(140, convertArray(timeList, ArraySize(timeList)));
  Serial.println(timeList[getArraySize(timeList, ArraySize(timeList)) - 1]);
  server.send(200, "text/html", SendHTML());
}

void handle_onRemove()
{
  homePage = 1;
  Serial.println("Time Removed!");
  String removedTime = server.arg("id");
  int timeId = removedTime.toInt();
  timeList[timeId] = "";
  writeString(140, convertArray(timeList, ArraySize(timeList)));
  convertToArray(read_String(140));

  for (int i = 0; i < ArraySize(resultArray); i++)
  {
    timeList[i] = resultArray[i];
  }
  server.send(200, "text/html", SendHTML());
}

void writeString(int add, String data)
{
  int _size = data.length();
  int i;
  for (i = 0; i < _size; i++)
  {
    EEPROM.write(add + i, data[i]);
  }
  EEPROM.write(add + _size, '\0'); //Add termination null character for String Data
  EEPROM.commit();
}


String read_String(int add)
{
  int i;
  char data[100]; //Max 100 Bytes
  int len = 0;
  unsigned char k;
  k = EEPROM.read(add);
  while (k != '\0' && len < 500) //Read until null character
  {
    k = EEPROM.read(add + len);
    data[len] = k;
    len++;
  }
  data[len] = '\0';
  return String(data);
}


String getTimesHTML()
{
  String myTestStr = "";
  String myArrStr = "";
  for (int i = 0; i < ArraySize(timeList); i++)
  {
    if (timeList[i] != "")
    {
      myTestStr = timeList[i];
      myTestStr.replace("x", ":");
      myArrStr += "<button class='removeBtn' id='delete" + String(i) + "'>" + myTestStr + " &nbsp;&nbsp;&nbsp;<b id='crossTxt'>X</b></button></p>\n";
    }
  }
  return (myArrStr);
}


Comments

Popular posts from this blog

Husband's Affair with Step Daughter Ends in Grisly Murder (True Crime Documentary)