#include <LiquidCrystal_I2C.h>
#define I2C_ADDR 0x27
#define LCD_COLUMNS 20
#define LCD_LINES 4
LiquidCrystal_I2C lcd(I2C_ADDR, LCD_COLUMNS, LCD_LINES);
#include "Wire.h"
///// TEMPERATURE STUFF
#include <DHT.h>;
#define DHTPIN 9 // what pin we're connected to
#define DHTTYPE DHT22 // DHT 22 (AM2302)
DHT dht(DHTPIN, DHTTYPE); //// Initialize DHT sensor for normal 16mhz Arduino
#include "time.h"
unsigned long time_last_pump = 0;
////// PUMP AND DRYER STUFF
#define humidityPin 6 // channel 2 on relay
#define heatPin 7 // channel 1 on relay
#define pumpPin 5 // channel 3 on relay
#define max_temp 130
int potpin = 0; // analog pin used to connect the potentiometer
int max_temp_exceeded = 0;
int max_sensor_fails = 0;
int heater_status = 0; // Used to minimize turning pin on and off
int pump_status = 0; // Used to minimize turning pin on and off
int zz_temp = 0;
////////// FUNCTION CODE START
float get_temperature() {
float temp;
temp = dht.readTemperature() * 9/5 + 32;
// safety shutoff
// check if sensor is working, if not shut down the heat
if (isnan(temp)) {
//Serial.println("**** is nan");
max_sensor_fails+=1;
//Serial.println("**** max fails: " + String(max_sensor_fails));
// if can't get a reading more than five times then it's probably broken and shut the heat off permanently
if (max_sensor_fails > 5) {
temp = max_temp + 1;
//Serial.println("**** more than five fails: temp is now: " + String(temp));
}
else {
temp = 107; // turn the heat off if not getting a reading
//Serial.println("**** max fail setting temp to 107 to shut things down temporarily");
return temp;
}
}
else {
// has worked before so reset the fails
max_sensor_fails = 0;
//Serial.println("**** resetting max sensor fails");
}
if (temp > max_temp) {
//Serial.println("**** max temp exceeded, shutting heat down permanently");
max_temp_exceeded = 1;
digitalWrite(heatPin, LOW);
}
///// ERASE THIS SECTION AFTER TESTING /////// START
if (heater_status == 1) {
zz_temp = zz_temp + 2.5;
temp = temp + zz_temp;
}
else {
temp = temp + zz_temp;
zz_temp = zz_temp - 2.5;
}
Serial.println("temperature is: " + String(temp));
///// ERASE THIS SECTION AFTER TESTING /////// END
return temp;
}
float get_humidity() {
float hum;
hum = dht.readHumidity();
if (isnan(hum)) {
hum = 0;
}
Serial.println("humidity is: " + String(hum));
return hum;
}
// number of days Arduino has been running
int today() {
unsigned long time_now = millis();
time_now = time_now * 1000 * 60;
int d = round(time_now/1000/60/60/24);
return d;
}
int get_days_to_hatch() {
int tday = today();
// For chickens
int days = 21 - tday;
// For ducks
//int days = 28 - tday;
return days;
}
void turn_heat_on() {
if (max_temp_exceeded == 0) {
if (heater_status == 0) {
digitalWrite(heatPin, HIGH);
heater_status = 1;
}
}
}
void turn_heat_off() {
digitalWrite(heatPin, LOW);
heater_status = 0;
}
void turn_humidity_on() {
digitalWrite(humidityPin, HIGH);
}
void turn_humidity_off() {
digitalWrite(humidityPin, LOW);
}
void turn_pump_on() {
if (pump_status == 0) {
pump_status = 1;
Serial.println("pump turned on");
digitalWrite(pumpPin, HIGH);
}
}
void turn_pump_off() {
if (pump_status == 1) {
pump_status = 0;
Serial.println("pump turned off");
digitalWrite(pumpPin, LOW);
}
}
void adjust_temperature() {
//Serial.println("adjusting temperature");
float temp = get_temperature();
//if (temp <= 89.1) { // for duckling just to get warm
if (temp <= 98.5) { // 2022-03-21 for ducks and chickens
//Serial.println("turning heat on");
turn_heat_on();
}
else {
//Serial.println("turning heat off");
if (temp > 100.5) {
turn_heat_off();
}
}
//Serial.println("temperature adjusted");
}
void print_water_level(int levl) {
char s[40];
snprintf_P(s, sizeof(s), PSTR("Water Level:%i"), levl);
print_display(s);
}
int get_water_level() {
int levl;
levl = analogRead(potpin); // reads the value of the potentiometer (value between 0 and 1023)
levl = map(levl, 0, 1023, 0, 100); // scale it to use it with the servo (value between 0 and 180)
return levl;
}
void adjust_water_level() {
const int max_level = 80;
const int min_level = 5;
int level;
int full_status = 0;
level = get_water_level();
if (level < 5) {
turn_pump_on();
lcd.clear();
while (full_status == 0) {
delay(100);
level = get_water_level();
print_water_level(level);
if (level > max_level) {
turn_pump_off();
delay(1000);
full_status = 1;
}
}
}
}
void adjust_humidity() {
// Source: https://modernfarmer.com/2015/04/how-to-incubate-chicken-eggs/
int upper_h = 200;
int lower_h = 200;
bool egg_is_duck = false;
//Serial.println("adjusting humidity");
// get the number of days arduino has been on
int d = today();
d = 21; // duck temp day to keep humidity high due to power outage. remove this line later
//Serial.println("day is " + String(d));
// set desired humidity limits
if (egg_is_duck == true) {
if (d <=25) {
lower_h = 55;
upper_h = 65;
}
else {
lower_h = 75;
upper_h = 80;
}
}
// chicken humidity settings
else {
if (d <=18) {
lower_h = 40;
upper_h = 50;
}
else {
lower_h = 65;
upper_h = 75;
}
}
float humidity = get_humidity();
if (humidity < lower_h) {
//Serial.println("turning humidity on");
turn_humidity_on();
}
else {
if (humidity > upper_h) {
// Serial.println("turning humidity off");
turn_humidity_off();
}
}
}
void morse_flash(int flash_count, int dlay) {
int count;
if (flash_count == 0) {
digitalWrite(13, HIGH);
zdelay(2000);
digitalWrite(13, LOW);
zdelay(500);
}
else {
for(count = 1; count <= flash_count; ++count)
{
digitalWrite(13, HIGH);
zdelay(dlay);
digitalWrite(13, LOW);
zdelay(dlay);
}
}
}
void print_morse(int t, int h) {
int hund, tenn, onne;
// indicate starting
morse_flash(20, 100);
zdelay(1000);
// indicate temperature (t is 10 times what it should be because of display issues for the display that no longer works)
hund = t/1000;
tenn = t % 1000 / 100;
onne = t % 100 / 10;
morse_flash(hund, 500);
zdelay(1500);
morse_flash(tenn, 500);
zdelay(1500);
morse_flash(onne, 500);
zdelay(1500);
// indicate temperature done
morse_flash(5, 100);
zdelay(1000);
// indicate humidity
hund = h/100;
tenn = h % 100 / 10;
onne = h % 100 % 10;
morse_flash(hund, 500);
zdelay(1500);
morse_flash(tenn, 500);
zdelay(1500);
morse_flash(onne, 500);
zdelay(1500);
}
void heat_safety_check() {
// Turn off the heat and turn on the humidifier if temperature exceeds maximum then shut down.
}
void print_temp_humid() {
//Serial.println("### in print_temp_humid");
char s[40];
float flt_temp = get_temperature();
int int_temp;
float flt_humid = get_humidity();
int int_humid;
int_temp = round(10*flt_temp);
int_humid = round(flt_humid);
static char str_temp[15];
static char str_hum[15];
dtostrf(flt_temp,5, 1, str_temp);
dtostrf(flt_humid,5, 1, str_hum);
strcpy(s, "Temp:");
strcat(s, str_temp);
strcat(s, " Hum:");
strcat(s, str_hum);
lcd.clear();
// Print Temperature and Humidity
print_display(s);
print_morse(int_temp, int_humid);
}
void print_days_to_hatch() {
char s[40];
// Print days to hatch
int d2hatch = get_days_to_hatch();
lcd.clear();
if (d2hatch <= 3) {
if (d2hatch <=0) {
snprintf_P(s, sizeof(s), PSTR("Jour d'eclore!"));
}
else {
snprintf_P(s, sizeof(s), PSTR("%i jours a eclore. Retirer durotateur"), d2hatch);
}
print_display(s);
zdelay(4000);
}
else {
snprintf_P(s, sizeof(s), PSTR("%i jours a eclore"), d2hatch);
print_display(s);
}
}
void print_display(char *s) {
// Print something
lcd.setCursor(0, 0);
lcd.print(s);
}
// new delay that doesn't hang other processes
void zdelay(int milliseconds) {
unsigned long start_millis = millis();
int ii;
//while (millis() - start_millis < milliseconds) {
ii = 5; // just something to do while counting
//}
}
///////////// FUNCTION CODE END
void setup() {
char s[40];
// Init
lcd.init();
lcd.backlight();
pinMode(humidityPin, OUTPUT);
pinMode(heatPin, OUTPUT);
pinMode(13, OUTPUT);
Serial.begin(115200); //Only needed for Serial.println
zdelay(1000);
snprintf_P(s, sizeof(s), PSTR("Bonjourzz Mme. H2 & Classe K!"));
print_display(s);
zdelay(2000);
////// TEMPERATURE STUFF
dht.begin();
lcd.clear();
}
void loop() {
//snprintf_P(s, sizeof(s), PSTR("Slide:%i"), val);
//lcd.clear();
//print_display(s);
//delay(15);
print_days_to_hatch();
delay(1000); // 100 miliseconds
adjust_temperature();
adjust_water_level();
heat_safety_check();
adjust_humidity();
print_temp_humid();
delay(2000); // 100 miliseconds
}