Blynkubator

* Update some code bugs on 3/16/16

About 3 years ago I started to incubate eggs in my homemade incubator (glorified dorm refrigerator.) I had extremely good success, but wanted to take it to the next level. I needed an app. I built vb.net apps to talk to the incubator and send me notifications, but I wanted full control. Blynk gave me exactly what I was looking for. I debated marketing it, but if it were not for open-source I never would have got this far.

Fig 1. Incubator (295 quail eggs) heated via a 75 watt bulb. Second heat hookup programmed and available, but not shown here. Humidity controlled via a MOSFET and a fan.


Fig. 2 Cam system with stepper motor to eliminate the over-rotation, and reduce strain on the motor.

Fig 3. PCB origanally designed with buttons on the board, but eliminated with Blynk. More room for sensors now!

Multiple sensors attached and more to come. Terminal being used as a menu instead of buttons to make best use of real-estate . Any chance Blynk could reduce the size of the email and push notification widgets?

Biggest challenge with the project was getting the stepper motor to run without using delays. The link below is what helped the most with getting steppers and Blynk to agree. Blynk.run() in other loops

Below is my code. I apologize for the lack of comments. It needs cleaned up as well, but check it out and let me know if you can think of any improvements.

#include <BlynkSimpleSerial.h>
#define BLYNK_PRINT Serial
#include <LiquidCrystal_I2C.h>    //LCD Library
#include <Wire.h>                 //Wire Library for I2C LCD
#include "DHT.h"                //Humidity Library
#include <OneWire.h>              //Library for one wire measurement (TEMP)
#include <DallasTemperature.h>    //Temperature Library
#include <SimpleTimer.h>          //Timer Rotation Library


//**********DEFINE PINS****************************
#define DHTPIN 4
int Bt3 = 5;   
int Bt2 = 6; 
int Bt1 = 7;
#define DIR_PIN 8
#define STEP_PIN 9                          //Stepper Driver Direction Pin
int transis=10;                             //Transistor Fan Control
int ssr1=11;                                //Relay Control 1
#define ONE_WIRE_BUS 12                     //Temperature Probes
int ssr2=13;                                //Relay Control 2
#define DHTTYPE DHT22

OneWire oneWire(ONE_WIRE_BUS);              //Setup a oneWire instance to communicate with Temperature Probe
DallasTemperature sensors(&oneWire);        //Pass oneWire reference to Dallas Temperature Library
DHT dht(DHTPIN, DHTTYPE);

char auth[] = "auth code";

float temps=99.5;                // the initial temperature setpoint on startup
float humids=60;                 // the initial humidity setpoint on startup
float dtr=20;                    // the total number of days to rotate (20 default)
float rpd=6;                     // the number of rotation scheduled per day (6 default)********************************************************************************************************************************
unsigned long msdelay;           // the delay time between rotations in ms
float temp1;                     // the temperature from dallas temp 1
float temp2;                     // the temperature from dallas temp 2
float temph;                     // the temperature value from the temperature probe
float humid;                     // the humidity
long rotatetime;
int nextturn;
int remain;                    // the total time remaining until rotations stop
const int numReadings = 10;      // the total number of reading that go into the average temp
float readings[numReadings];     // the readings from the analog input
float readings2[numReadings];
float total = 0;                 // the running total
float total2 = 0;
float average = 0;               // the average
float average2 = 0;
int index = 0;                   // the index of the current reading
int index2 = 0;
int turns=0;                     // the total number of rotations completed thus far
boolean homestate = false;                   // the location of Stepper Motor
int POWER;   
int POWER2; 
int menub;
int rotating=0;
int termlevel=0;  
int manrote=0;              
WidgetTerminal terminal(V1);
SimpleTimer sensortimer;
WidgetLCD lcdb(V0);
WidgetLED led1(V13);
WidgetLED led2(V14);
WidgetLED led3(V15);


void setup() {
  Serial.begin(9600);            //Start Serial Port
  Blynk.begin(auth);
  sensors.begin();               //Start Temp Sensors 
  pinMode(A0, OUTPUT);           //Defines as Output
  pinMode(Bt1,INPUT);             //Defines as Input
  pinMode(Bt2,INPUT);             //Defines as Input
  pinMode(Bt3,INPUT);             //Defines as Input
  pinMode(transis,OUTPUT);       //Defines as Output
  pinMode(ssr1, OUTPUT);         //Defines as Output
  pinMode(ssr2, OUTPUT);         //Defines as Output
  pinMode(DIR_PIN, OUTPUT); 
  pinMode(STEP_PIN, OUTPUT);

msdelay = 86400000/rpd; //Calculates the number of milliseconds delay for rotations based on the times per day set
rotatetime=millis()+ msdelay;            //Timer that will run rotate Subroutine every "msdelay" milliseconds
for (int thisReading = 0; thisReading < numReadings; thisReading++)  //initialize all the readings to 0: 
readings[thisReading] = 0;                                           //sets reading to zero
digitalWrite (transis,LOW);

dht.begin();

rotate(-800, .02);

sensortimer.setInterval(2500L, sensorchecks);
terminalmenu();              //**************************************************************
}


void loop() {               
if (rotating!=1){
  sensortimer.run();
  Blynk.run();}
  
  sensors.requestTemperatures();
  temp1 = sensors.getTempCByIndex(1) * 1.8 + 32;           //Calculates tempF (deg F) from tempC
  temp2 = sensors.getTempCByIndex(0) * 1.8 + 32;           //Calculates tempF (deg F) from tempC
  total= total - readings[index];          // subtract the last reading:    
  total2= total2 - readings2[index]; 
  readings[index] = temp1;                 // read from the sensor:  
  readings2[index] = temp2; 
  total= total + readings[index];          // add the reading to the total:
  total2= total2 + readings2[index];
  index = index + 1;                       // advance to the next position in the array:               
  if (index >= numReadings){               // if we're at the end of the array...     
    index = 0;}                              // ...wrap around to the beginning:                
  average = total / numReadings;           // calculate the average:  
  average2 = total2 / numReadings;           // calculate the average: 
timerotate(millis());}

void sensorchecks(){
  humid= dht.readHumidity();
  temph=dht.readTemperature(true);
    if (humid< humids){
      digitalWrite (transis,HIGH);
      led3.on();}
    else {
      digitalWrite (transis,LOW);
      led3.off();}
  if (average > temps + 0.01){
    digitalWrite (ssr1, HIGH);
    POWER=0;
    led1.off();}
  if (average < temps - 0.01){
    digitalWrite (ssr1, LOW);
    POWER=1;
    led1.on();}  
  if (average2 > temps + 0.01){
    digitalWrite (ssr2, HIGH);
    POWER2=0;
    led2.off();}
  if (average2 < temps - 0.01){
    digitalWrite (ssr2, LOW);
    POWER2=1;
    led2.on();}
    remain=(dtr-millis()/86400000);
  displays();
//  Blynk.email("my_email@example.com", "Subject", "Your message goes here");
  }

void timerotate(unsigned long timestamp){
  nextturn=(rotatetime-timestamp)/60000;
  if (timestamp > rotatetime){
   rotates();
   rotatetime=millis()+ msdelay; 
   turns= (turns + 1);}}
   
void rotates(){
   digitalWrite (ssr1, HIGH);
   digitalWrite (ssr2, HIGH);
   if (homestate==true && rpd != 0){
      rotate(-1600, .02);}
   else if (homestate==false && rpd != 0){
      rotate(1600, .02);}
      homestate=!homestate;  
   if (millis() >= dtr*86400000){
         humids=80;}}

void rotate(int steps, float speed){ 
  float ms;
  int dir = (steps > 0)? HIGH:LOW;
  steps = abs(steps);
  digitalWrite(DIR_PIN,dir); 
  float usDelay = (1/speed) * 70;
  for(int i=0; i < steps; i++){
  digitalWrite(STEP_PIN, HIGH); 
  ms=millis()+usDelay/1000;
  while(ms > millis()){}
  Blynk.run();
  digitalWrite(STEP_PIN, LOW);
  ms=millis()+usDelay/1000;
  while(ms > millis()){}
  Blynk.run();}  }

  
  
void displays(){
if(menub==0){
      lcdb.clear();  
      lcdb.print(3, 0, "TEMP1:");
      lcdb.print(10, 0, temp1);
      lcdb.print(0, 1, "HUMIDITY: ");
      lcdb.print(10, 1, humid);
      menub=1;}
else if(menub==1){
      lcdb.clear();
      lcdb.print(3, 0, "TEMP2:");
      lcdb.print(10, 0, temp2);
      lcdb.print(0, 1, "  H TEMP: ");
      lcdb.print(10, 1, temph);
      menub=0;}
      
Blynk.virtualWrite(V2, temp1);
Blynk.virtualWrite(V3, temp2);
Blynk.virtualWrite(V4, temph);
Blynk.virtualWrite(V5, humid);}

BLYNK_WRITE(V1){
  double term= param.asDouble();
  rotating=1;
  int termi=term;
  switch (termlevel){
  case 0: 
    if (termi==1){    
      terminal.println("Range (80-105)");
      terminal.println("Set Temperature: ");
      terminal.flush();
      termlevel=1;}
    else if (termi==2){   
      terminal.println("Range (50-100)");
      terminal.println("Set Humidity: ");
      terminal.flush();
      termlevel=2;} 
    else if (termi==3){    
      terminal.println("Range (0-96)");
      terminal.println("Set Rotations Per Day: ");
      terminal.flush();
      termlevel=3;} 
    else if (termi==4){  
      terminal.println("Range (0-50)");
      terminal.print("Set Days to Rotate: ");
      terminal.flush();
      termlevel=4;}
    else{
      termlevel=0;
      terminalmenu();
    }
    break;
  case 1:
    if (term>=80 && term<=105){
      temps=term;
      termlevel=0;
      terminalmenu();}
    else{invalid();}
    break;
  case 2:
    if (term>=0 && term<=100){
      humids=term;
      termlevel=0;
      terminalmenu();}
    else{invalid();}
   break; 
  case 3:
    if (term>=0 && term<=1200){
      rpd=term;
      msdelay = 86400000/rpd;
      rotatetime=millis()+ msdelay; 
      termlevel=0;
      terminalmenu();}
    else{invalid();} 
   break;
  case 4:
    if (term>=0 && term<=50){
      dtr=term;
      termlevel=0;
      terminalmenu();}
    else{invalid();} 
    break;
  default:
      termlevel=0;
      terminalmenu();
  break;}
  rotating=0;}

void invalid(){
  termlevel=0;
  terminalmenu();
  terminal.println("Invalid Input");}

void terminalmenu(){
  terminal.println("Blynkubator Settings Menu");
  terminal.print("1= Set Temperature: ");
  terminal.println(temps);
  terminal.print("2= Set Humidity: ");
  terminal.println(humids); 
  terminal.print("3= Set Rotations Per Day: ");
  terminal.println(rpd);
  terminal.print("4= Set Days to Rotate: ");
  terminal.println(dtr); 
  terminal.print("  *Days Remaining: ");
  terminal.println(remain); 
  terminal.print("  *Rotation Total: ");
  terminal.print(turns);
  terminal.print("   Next: ");
  terminal.print(nextturn); 
  terminal.println("min");
  termlevel=0;
  terminal.flush();}

Thank you Blynk for the great app and the help.

11 Likes

Wow.
Just wow! :bow: This is fantastic!

Now all we need is a video of cute yellow baby chicks )) :hatching_chick: > :hatched_chick: > :baby_chick:

Thanks for sharing!

The birds should hatch in on the 24th. I will be sure to post a picture.

3 Likes

So awesome! I love this. This is really good stuff. Where tech meets new life. Supercool!

@arduinewb, we posted it on our Facebook and your project became the most popular ever.
Congrats! :clap:

That is awesome. If anyone is interested in more information with respect to the PCB design, programming, incubation, or hardware I would be more than willing to share. Keep up the great work Blynk.

1 Like

Thank you so much!!! I’ve been combing the web for weeks looking for a good DHT/Blynk sketch for Arduino, especially without a wifi module. What’s more is that your sketch appears to me to be a working example of how the Blynk sketch can work with other lines of code for doing other things outside of the Blynk platform which to me is also invaluable. I will try to reverse engineer your sketch to work with the Ethernet and hopefully in a few days I’ll be getting temp and humidity readings from my DHT22.

Thanks again!!!

Eggs finally hatched!!

7 Likes

Congrats! ) Thanks for posting!

Another successful hatch in the Blynkubator…Chukar and Quail

7 Likes

So Cute :smiley: That might be quite useful

Hi very nice project. I am interested to build one. Can u share the design and PCB layout. Thanks in advance. My mail id is athekhan@gmail.com

1 Like

Hows your project now?
still progressive?

Hello, you project is very promising I wish to stimulate similar project and I would be grateful if you could kindly email me more information with respect to the PCB design, programming, incubation, or hardware to guide me in the process. Hoping for your reply. Thanks. Email@ tawfik.osman@ashesi.edu.gh

Hello sir. GOOD DAY ,Im a fan of the app that will everything will make it easy ,Can i have the design of the pcb and the code of it because i want to buil that too ,thank you for you response

@Jognrey21 Please take note of the time date stamps before posting. This is a very old topic, originated back in 2016, so you might have to start from scratch :wink:

You can also send the OP a request via private message… but the OP hasn’t been in this forum for almost a year, so who knows if they get it.