Egg Incubator

Hi all,
here is my project.
The atmega328 controls a 24v lamp (pwm), a 12v pc fan (pwm) and reads a SHT1x temp/hum sensor. A standard laptop power supply is used.
One button and one potentiometer menu system (thanx tronixstuff) is used for user input.
Internal logger for calculating average temp and hum (last hour, taking samples every 10min)
User can set:
-temp levels

  • lamp intensity (in digital steps)
  • fan rpm (in digital steps)
  • calculate avg temp
  • calculate avg hum

here is the circuit

and the box

left to do:

  • incorporate a step motor and control
  • find a way (hardware) to produce humidity, and control

my software knowledge is limited so feel free to correct my sketch,
although it works fine, i am sure i have redundant code.

cant wait to here your thoughts

here is the sketch

// include the library code needed
#include <LiquidCrystal.h>
#include <SHT1x.h>

// initialize the lcd with the numbers of the interface pins
LiquidCrystal lcd(12, 13, 7, 4, 8, 19);

//initialize the SHT1x sensor
#define dataPin  1                             //data connection to pin 1
#define clockPin 11                            //clock connection to pin 11 
SHT1x sht1x(dataPin, clockPin);                //instantiate SHT1x sensor

// constants will not change
const int fanpin = 9;                         //fan connected to digital pin 9 
const int lampin = 10;                        //lamp connected to pin 10
    //const int buttonplus = 2;               //button spare with interupt!
const int dialpin = A1;                       //potentiometer at analog 1
const int button_menu = 3;                    //button for menu at pin 3
//variables will change
int i=0;                                     //used for taking samples, logger  
int fanval = 400;                            //to store the value of the potentiometer
int tempval_min = 60;                        //to store the min value for the lamp pwm   
int tempval_max = 180;                       //to store the max value for the lamp pwm 
int tempval_avg = 100;                       //to store the avg value for the lamp pwm 
int tempval = 100;                           //to store the value for the lamp pwm 
int stepval = 0;                             //to store the value for stepping lights 
float fan_step;                              //to store the value for stepping fan 
float valplus = 35.7;                        //variable to store max allowed temp
float valminus = 35.2;                       //variable to store min allowed temp
float temp_c;                                //float number to measure temperature with library
float humidity;                              //float number to measure humidity with library
float new_temp_minus;                        //for calculation of min temp after user input
float new_temp_plus;                         //for calculation of max temp after user input
float diff;                                  //for calculation of temp limits after user input
float valplus_final;                         //for calculation of max temp after user input
float valminus_final;                        //for calculation of min temp after user input
float temp_data[] = {0,0,0,0,0,0};           //array to store temp samples, logger
float hum_data[] = {0,0,0,0,0,0};            //array to store hum samples, logger 
float sum_temp = 0;                          //for calculation of all samples taken, logger
float avg_temp = 0;                          //for calculation and display, logger
float sum_hum = 0;                           //for calculation of all samples taken, logger
float avg_hum = 0;                           //for calculation and display, logger

// the following variables are long's because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long prevMils_1 = 0;                            //used for the delay loop, TO NOT USE delay()
long prevMils_2 = 0;                            //used for the delay loop, TO NOT USE delay()
long interval_1 = 5000;                         //delay for check and adjust temp, 5sec
long interval_2 = 600000;                       //delay for taking samples, 10 min, display last hour avg


void setup()
{
  pinMode(fanpin, OUTPUT);                //set pin 9 as output
  pinMode(lampin, OUTPUT);                //set pin 10 as output
  pinMode(button_menu, INPUT);            //set pin 3 as input
  //pinMode(buttonplus, INPUT);           //set pin 2 as input
  
  
  lcd.begin(16, 2);                       // set up the LCD's number of rows and columns
  lcd.clear();
  lcd.print("ReklaDance");                // display a message to the LCD
  delay(500);                      
  lcd.setCursor(0, 1);                    // set the cursor to column 0, line 1
  lcd.print("     Electronics");          // display a message to the LCD.
  delay(3000);
  lcd.clear();
  lcd.print("Setting up...");             // display a message to the LCD
  delay(1000);                      
  lcd.setCursor(0, 1);                    // set the cursor to column 0, line 1
  lcd.print("Ready Nikolas!");            // display a message to the LCD.
  delay(500);
}

void loop()
{
    
  //turn fan on
  analogWrite(fanpin, fanval / 4);       // analogRead value go from 0 to 1023, analogWrite value from 0 to 255

  //turn lamp on 
  analogWrite(lampin, tempval);           //about 45% duty cycle, at startup        
  
  // Read values from the sensor
  temp_c = sht1x.readTemperatureC();
  humidity = sht1x.readHumidity();
  
  valplus_final = new_temp_plus + diff;        //calculation of the final value   
  valminus_final = new_temp_minus;             //exageration
  
  // read the state of the menu button 
   if (digitalRead(button_menu) == HIGH) 
   {
    delay(200);
    displaymenu();                             //call to the menu routine
   }
   
  //use local variable for not using the delay() function
  unsigned long curMils_1 = millis();             //check to see if the difference between the current time and 
  if (curMils_1 - prevMils_1 > interval_1) {      //last time you checked is bigger than the interval set
    prevMils_1 = curMils_1;                       //save the last time you checked
    
      //loop to set the temperature betweem user input 
      if (temp_c<valminus_final)                  //check if temp is lower than,say 37.2
      {
        tempval=tempval_max;                      //set to about 100% duty cycle for pwm lamp
      }
      else if(temp_c>valplus_final)               //check if temp is higher than, say 37.7
      {
        tempval=tempval_min;                      //set to about 50% duty cycle for pwm lamp
      }  
      else                                        //temp is between, say 37.2 and 37.7
      {
        tempval=tempval_avg;                      //set to about 75% duty cycle for pwm lamp
      }
    }
    
    //use local variable for not using the delay() function
  unsigned long curMils_2 = millis();             //check to see if the difference between the current time and 
  if (curMils_2 - prevMils_2 > interval_2) {      //last time you checked is bigger than the interval set
    prevMils_2 = curMils_2;                       //save the last time you checked
  
  //LOGGER, without the need of any external hardware
  if (i<=5)                                       //loop for taking samples
      {
      temp_data[i] = 0;                           //set all samples for temperature to zero
      hum_data[i] = 0;                            //set all samples for humidity to zero
      delay(100);
      temp_data[i] = temp_c;                      //6 samples for temperature
      hum_data[i] = humidity;                     //6 samples for humidity
      i = i++;
      }
      if (i>5)                                    //loop to make sure that we wont
      {                                           //write any sample outside the specified array
        i=0;
      }
    }
    
  //display the values
  lcd.clear();
  lcd.setCursor(0, 0);                            // set the cursor to column 0, line 0
  lcd.print("T:");                                // display the temperature to the lcd
  lcd.print(temp_c, 1);               
  lcd.print("C");  
  lcd.print("    ");
  lcd.print(valminus_final, 0);                  //display the user input temp levels
  lcd.print("-");
  lcd.print(valplus_final, 0);
  lcd.setCursor(0, 1);                           // set the cursor to column 0, line 1 
  lcd.print("H:");                               // display the humidity to the lcd
  lcd.print(humidity);                  
  lcd.print("%");  
  lcd.print("   L");                             //display the user input light step
  lcd.print(stepval);
  lcd.print("-F");                               //display the user input fan step
  lcd.print(fan_step);
}

and the rest

// rangemax is the number of values in your range, e.g. if you want 0~9, set rangemax to be '10'
// dialpin is the analog pin number connected to the potentiometer to read
int readdial(int rangemax, int dialpin)
{
int kv=0;                                       //used for calculation
int kr=0;                                       //used for calculation
int kb=0;                                       //used for calculation
float a=0;                                      //used for calculation
float rd=0;                                     //used for calculation
rd=1023/rangemax;
kb=analogRead(dialpin);                         // read potentiometer connected to analog pin 1
a=kb/rd;
kr=int(a);
if (kr>rangemax)
{
kr=rangemax;
}
return kr;
}

// display the menu options, selectable by using the knob  
void displaymenu()
{
delay(300);                                     // for debounce
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Turn knob slowly");                  //print msg
lcd.setCursor(0,1);
lcd.print("to select option");
delay(2000);
while (digitalRead(button_menu)==LOW)           //until user presses button stay in this loop
{
if (readdial(7,1)==0) {                         //from readdial, we get 7 menu options
lcd.clear();                                    //option 1
lcd.setCursor(0,0);
lcd.print("Set Temperature");                   
}
else if (readdial(7,1)==1) {                    //option 2
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Set Fan RPM");
}
else if (readdial(7,1)==2) {                    //option 3
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Set Lamp PWM");
}
else if (readdial(7,1)==3) {                    //option 4
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Calc Average");
lcd.setCursor(0, 1);                    
lcd.print("Temperature?");
}
else if (readdial(7,1)==4) {                    //option 5
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Calc Average");
lcd.setCursor(0, 1);                    
lcd.print("Humidity?");
}
else if (readdial(7,1)==5) {                    //option 6
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Set Temperature");
lcd.setCursor(0, 1);                    
lcd.print("Difference");
}
else if (readdial(7,1)==6) {                    //option 7
lcd.clear();
lcd.setCursor(0,0);
lcd.print(" exit menu ");
}
delay(100); // stop screen flicker
}
switch(readdial(7,1))
{
case 0:
set_temp();                                   //call the routine for setting temperature levels 
break;
case 1:
set_rpm();                                    //call the routine for setting fan steps
break;
case 2:
set_step();                                   //call the routine for setting light steps
break;
case 3:
calc_avg_temp();                              //call the routine to calculate average temp
break;
case 4:
calc_avg_hum();                               //call the routine to calculate average humidity
break;
case 5:
set_temp_dif();                               //call the routine for setting temp difference
break;
}
}

//All 7 routines for the menu system
//Setting temperature levels from 35-36 to 44-45 (10 menu options)
void set_temp()
{
  delay(300);
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Set Temp. Range");
  while (digitalRead(button_menu)==LOW)
  {
    if      (readdial(10,1)==0)               //from readdial, we get 10 menu options
    {
      new_temp_plus = valplus;                //from 35-36
      new_temp_minus = valminus;
      lcd.setCursor(0, 1);                    
      lcd.print("From ");
      lcd.print(new_temp_minus, 0);
      lcd.print(" to ");
      lcd.print(new_temp_plus, 0);
      delay(100);
    }
    else if (readdial(10,1)==1)                //from 36-37
    {
      new_temp_plus = valplus +1;
      new_temp_minus = valminus + 1;
      lcd.setCursor(0, 1);                    
      lcd.print("From ");
      lcd.print(new_temp_minus, 0);
      lcd.print(" to ");
      lcd.print(new_temp_plus, 0);
      delay(100);
    }
    else if (readdial(10,1)==2)               //from 37-38
    {
      new_temp_plus = valplus + 2;
      new_temp_minus = valminus + 2;
      lcd.setCursor(0, 1);                    
      lcd.print("From ");
      lcd.print(new_temp_minus, 0);
      lcd.print(" to ");
      lcd.print(new_temp_plus, 0);
      delay(100);
    }
    else if (readdial(10,1)==3)               //from 38-39
    {
      new_temp_plus = valplus + 3;
      new_temp_minus = valminus + 3;
      lcd.setCursor(0, 1);                    
      lcd.print("From ");
      lcd.print(new_temp_minus, 0);
      lcd.print(" to ");
      lcd.print(new_temp_plus, 0);
      delay(100);
    }
    else if (readdial(10,1)==4)               //from 39-40
    {
      new_temp_plus = valplus + 4;
      new_temp_minus = valminus + 4;
      lcd.setCursor(0, 1);                    
      lcd.print("From ");
      lcd.print(new_temp_minus, 0);
      lcd.print(" to ");
      lcd.print(new_temp_plus, 0);
      delay(100);
    }
    else if (readdial(10,1)==5)              //from 40-41
    {
      new_temp_plus = valplus + 5;
      new_temp_minus = valminus + 5;
      lcd.setCursor(0, 1);                    
      lcd.print("From ");
      lcd.print(new_temp_minus, 0);
      lcd.print(" to ");
      lcd.print(new_temp_plus, 0);
      delay(100);
    }
    else if (readdial(10,1)==6)              //from 41-42
    {
      new_temp_plus = valplus + 6;
      new_temp_minus = valminus + 6;
      lcd.setCursor(0, 1);                    
      lcd.print("From ");
      lcd.print(new_temp_minus, 0);
      lcd.print(" to ");
      lcd.print(new_temp_plus, 0);
      delay(100);
    }
    else if (readdial(10,1)==7)             //from 42-43
    {
      new_temp_plus = valplus + 7;
      new_temp_minus = valminus + 7;
      lcd.setCursor(0, 1);                    
      lcd.print("From ");
      lcd.print(new_temp_minus, 0);
      lcd.print(" to ");
      lcd.print(new_temp_plus, 0);
      delay(100);
    }
    else if (readdial(10,1)==8)            //from 43-44
    {
      new_temp_plus = valplus + 8;
      new_temp_minus = valminus + 8;
      lcd.setCursor(0, 1);                    
      lcd.print("From ");
      lcd.print(new_temp_minus, 0);
      lcd.print(" to ");
      lcd.print(new_temp_plus, 0);
      delay(100);
    }
    else if (readdial(10,1)==9)           //from 44-45
    {
      new_temp_plus = valplus + 9;
      new_temp_minus = valminus + 9;
      lcd.setCursor(0, 1);                    
      lcd.print("From ");
      lcd.print(new_temp_minus, 0);
      lcd.print(" to ");
      lcd.print(new_temp_plus, 0);
      delay(100);
    }
  }
}

//Seting the difference for temperature levels
//ex. either 37-38 or 37-39
void set_temp_dif()
{
  delay(300);
  lcd.setCursor(0,0);
  lcd.print("Set Temp. Diff.");
  while (digitalRead(button_menu)==LOW)
  {
    if      (readdial(5,1)==0)                //from readdial, we get 5 menu options
    {                                         //1 degree celcius diff
      diff = readdial(5,1);
      lcd.setCursor(0, 1);                    
      lcd.print("One(1)    degree");          
      delay(100);
    }
     else if (readdial(5,1)==1)               //2 degrees celcius diff
    {
      diff = readdial(5,1);
      lcd.setCursor(0, 1);                    
      lcd.print("Two(2)   degrees");
      
      delay(100);
    }
    else if (readdial(5,1)==2)                //3 degrees celcius diff
    {
      diff = readdial(5,1);
      lcd.setCursor(0, 1);                    
      lcd.print("Three(3) degrees");
      delay(100);
    }
    else if (readdial(5,1)==3)                //4 degrees celcius diff
    {
      diff = readdial(5,1);                   
      lcd.setCursor(0, 1);                    
      lcd.print("Four(4)  degrees");
      delay(100);
    }
    else if (readdial(5,1)==4)               //5 degrees celcius diff
    {
      diff = readdial(5,1);
      lcd.setCursor(0, 1);                    
      lcd.print("Five(5)  degrees");
      delay(100);
    }
  }
}

and the last bit

//Setting the Light Intensity, in 5 steps
void set_step()
{
  delay(300);
  lcd.setCursor(0,0);
  lcd.print("Set Step Light");
  while (digitalRead(button_menu)==LOW)
  {
   if      (readdial(5,1)==0)                 //from readdial, we get 5 menu options
    {
      stepval = readdial(5,1);                //step 0, lowest values
      tempval_min = 40;       
      tempval_max = 120;
      tempval_avg = 60;
      lcd.setCursor(0, 1);                    
      lcd.print("Step 0");
      delay(100);
    }
    else if (readdial(5,1)==1)                //step 1
    {
      stepval = readdial(5,1);
      tempval_min = 50;       
      tempval_max = 150;
      tempval_avg = 80;
      lcd.setCursor(0, 1);                   
      lcd.print("Step 1");
      delay(100);
    }
    else if (readdial(5,1)==2)               //step 2
    {
      stepval = readdial(5,1);
      tempval_min = 60;       
      tempval_max = 180;
      tempval_avg = 100;
      lcd.setCursor(0, 1);                    
      lcd.print("Step 2");
      delay(100);
    }
    else if (readdial(5,1)==3)              //step 3
    {
      stepval = readdial(5,1);
      tempval_min = 70;       
      tempval_max = 210;
      tempval_avg = 120;
      lcd.setCursor(0, 1);                    
      lcd.print("Step 3");
      delay(100);
    }
    else if (readdial(5,1)==4)             //step 4
    {
      stepval = readdial(5,1);
      tempval_min = 100;       
      tempval_max = 240;
      tempval_avg = 180;
      lcd.setCursor(0, 1);                    
      lcd.print("Step 4");
      delay(100);
    }
  }
}

//Setting the fan rpm, in 4 steps
void set_rpm()                                                                  
{                                                
  delay(300);
  lcd.setCursor(0,0);
  lcd.print("Set Fan RPM");
  while (digitalRead(button_menu)==LOW)
  {
   if      (readdial(4,1)==0)                 //from readdial, we get 4 menu options
    {                                         //step 0
      fanval = 200;
      fan_step = readdial(4,1);
      lcd.setCursor(0, 1);                    
      lcd.print("Step 0");    
      delay(100);
    }
    else if (readdial(4,1)==1)               //step 1
    {
      fanval = 350;
      fan_step = readdial(4,1);
      lcd.setCursor(0, 1);                    
      lcd.print("Step 1");
      delay(100);
    }
    else if (readdial(4,1)==2)               //step 2
    {
      fanval = 500;
      fan_step = readdial(4,1);
      lcd.setCursor(0, 1);                    
      lcd.print("Step 2");
      delay(100);
    }
    else if (readdial(4,1)==3)               //step 3
    {
      fanval = 700;
      fan_step = readdial(4,1);
      lcd.setCursor(0, 1);                    
      lcd.print("Step 3");
      delay(100);
    }
  }
}

//Calculating average temperature for LOGGER
void calc_avg_temp()
{
  delay(300);
  sum_temp = 0;                                     //reset the sum
  int c=0;
  for (c=0; c<=5; c++)
    {
      sum_temp = sum_temp + temp_data[c];          //calculate sum of samples taken
      delay(10);
     }
   if (c>5)                                        //loop to make sure that we wont
     {                                             //read any data outside the specified array
       c=0;
      }
   delay(500);
   avg_temp = 0;                                   //reset the average temperature
   delay(100);
   avg_temp = sum_temp/6;                          //calculate average of samples taken
   lcd.clear();
   lcd.setCursor(0,0);
   lcd.print(" Last Hour");                        //display info
   lcd.setCursor(0, 1);
   lcd.print("Avg Temp:");
   lcd.print(avg_temp, 1);
   lcd.print("C");
   delay(3000);
   
}

//Calculate average humidity for LOGGER
void calc_avg_hum()
{
  delay(300);
  sum_hum = 0;                                     //reset the sum
  int d=0;
  for (d=0; d<=5; d++)
    {
      sum_hum = sum_hum + hum_data[d];             //calculate sum of samples taken
      delay(10);
     }
   if (d>5)
     {
       d=0;
      }
   delay(500);
   avg_hum = 0;                                    //reset the average temperature
   delay(100);
   avg_hum = sum_hum/6;                            //calculate average of samples taken
   lcd.clear();
   lcd.setCursor(0,0);
   lcd.print(" Last Hour");                        //display info
   lcd.setCursor(0, 1);
   lcd.print("Avg Hum:");
   lcd.print(avg_hum, 2);
   lcd.print("%");
   delay(3000);
}

/*if we get hardware for producing humidity...

void set_hum() {
}
void set_hum_dif() {
}
*/