/**
Arduino Gardening Simulation
This is a "gardening simulation" for a homework project. The program is set up so a reference temperature
and humidity can be set. The program takes temperature and humidity readings (simulated by DHT22) and
tries to optimise to these reference values with simulated actuators. For high temperature it tries to ventilate
(green servo), for low temp. it tries to heat (red led) and for low humidity it tries to water (red servo).
The program only starts when switch is on and turns off with the switch. (It will not turn off during
initialisation phase.) With the yellow button you can turn on the LCD and read
the set and actual temperature and humidity.
*/
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
#include <DHT.h>
#include <Servo.h>
// LCD definition
#define LCD_ADDR 0x27
#define LCD_COLUMNS 16
#define LCD_ROWS 2
//DHT definition
#define DHTPIN 12
#define DHTTYPE DHT22
//Servo definition
Servo valve;
Servo cooling_fan;
const byte valve_pin = 9;
const byte fan_pin = 8;
// LED definitions
const byte green = 18;
const byte red = 17;
//Switch and button definitions
const byte start_switch = 19;
bool start_switch_state = 0;
const byte LCD_button = 2;
bool LCD_button_state = 0;
// Keypad setup
const byte KEYPAD_ROWS = 4;
const byte KEYPAD_COLS = 3;
byte rowPins[KEYPAD_ROWS] = {A11, A10, A9, A8};
byte colPins[KEYPAD_COLS] = {A2, A1, A0};
char keys[KEYPAD_ROWS][KEYPAD_COLS] = {
{'1', '2', '3'},
{'4', '5', '6'},
{'7', '8', '9'},
{'*', '0', '#'}
};
DHT dht(DHTPIN, DHTTYPE);
LiquidCrystal_I2C lcd(LCD_ADDR, LCD_COLUMNS, LCD_ROWS);
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, KEYPAD_ROWS, KEYPAD_COLS);
//variables setup
int set_temp = 0; //Temperature set to 0
int set_hum = 0; //Humidity set to 0
bool initiate = 1; //Initialization turned on
int k = 0; //Counting variable
float hum = 0; //Humidity reading (needs to be float)
float temp = 0; //Temperature reading (needs to be float)
int hum_int = 0; //Humidity reading for LCD
int temp_int = 0; //Temperature reading for LCD
int valve_pos = 90; //Valve servo position
int fan_pos = 90; //Fan servo position
bool reset_set = 0; //Reset variable
void setup() {
// PinMode Setup
pinMode(green, OUTPUT);
pinMode(red, OUTPUT);
pinMode(LCD_button, INPUT_PULLUP);
pinMode(start_switch, INPUT);
//LCD Setup
lcd.begin(16, 2);
lcd.init();
//Baud rate
Serial.begin(9600);
//DHT setup
dht.begin();
//Interrupt setup
attachInterrupt(digitalPinToInterrupt(LCD_button), interrupt_LCD_button, FALLING);
//Servo setup
valve.attach(valve_pin);
valve.write(valve_pos);
cooling_fan.attach(fan_pin);
cooling_fan.write(fan_pos);
}
void loop()
{
start_switch_state = digitalRead(start_switch); // turn on-off with switch
while (start_switch_state)
{
reset_set = 1;
digitalWrite(green, HIGH);
//Initialization start
while (initiate)
{
k = 0;
lcd.backlight();
lcd.clear();
lcd.setCursor(4, 0);
lcd.print("WELCOME!");
lcd.setCursor(0, 1);
lcd.print("PRESS * TO CONT");
while (k == 0)
{
char key = keypad.getKey();
if (key == '*')
{
k++;
}
}
//SET TEMPERATURE START
redo:
int k = 0;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("SET TEMPERATURE!");
lcd.setCursor(8, 1);
lcd.print("C.DEG.");
while (k == 0)
{
char key = keypad.getKey();
if (key != NO_KEY)
{
set_temp = (key - 48) * 10;
lcd.setCursor(5, 1);
lcd.print(key);
k++;
while (k == 1)
{
char key = keypad.getKey();
if (key != NO_KEY)
{
set_temp = set_temp + (key - 48);
lcd.setCursor(6, 1);
lcd.print(key);
k++;
while (k == 2)
{
char key = keypad.getKey();
if (key == '*')
{
k++;
}
}
}
}
}
}
//SET TEMPERATURE END
//SET HUMIDITY START
k = 0;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("SET HUMIDITY!");
lcd.setCursor(8, 1);
lcd.print("%");
while (k == 0)
{
char key = keypad.getKey();
if (key != NO_KEY)
{
set_hum = (key - 48) * 10;
lcd.setCursor(5, 1);
lcd.print(key);
k++;
while (k == 1)
{
char key = keypad.getKey();
if (key != NO_KEY)
{
set_hum = set_hum + (key - 48);
lcd.setCursor(6, 1);
lcd.print(key);
k++;
while (k == 2)
{
char key = keypad.getKey();
if (key == '*')
{
k++;
}
}
}
}
}
}
//SET HUMIDITY END
// CONFIRMATION START
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("SET TO:");
lcd.setCursor(8, 0);
lcd.print(set_temp);
lcd.setCursor(10, 0);
lcd.print("C");
lcd.setCursor(12, 0);
lcd.print(set_hum);
lcd.setCursor(14, 0);
lcd.print("%");
lcd.setCursor(0, 1);
lcd.print("* CONF # REDO");
k = 0;
while (k == 0)
{
char key = keypad.getKey();
if (key != NO_KEY)
{
if (key == '*') // IN CASE OF * ARM THE DEVICE
{
k++;
lcd.clear();
lcd.setCursor(5, 0);
lcd.print("ARMED");
}
else if (key == '#') //IN CASE OF # RESTART WITH GOTO
{
goto redo;
}
}
};
//CONFIRMATION END
initiate = 0; //Initialization turned off
start_switch_state = digitalRead(start_switch);
if (start_switch_state == 0)
{
goto turn_off;
};
delay(3000);
lcd.clear();
lcd.noBacklight(); //LCD turn off
};
//DHT read cycle
hum = dht.readHumidity();
temp = dht.readTemperature();
//Data convert for LCD
hum_int = (int)hum;
temp_int = (int)temp;
//Data evaluation start
//Temperature actuation
switch (temp_check(set_temp, temp_int))
{
case 1: //hotter than should be
digitalWrite(red, LOW);
cooling_fan.write (0);
break;
case 2: //colder than should be
digitalWrite(red, HIGH);
cooling_fan.write (90);
break;
case 0: //optimal temperature
digitalWrite(red, LOW);
cooling_fan.write (90);
};
//Humidity actuation
switch (hum_check(set_hum, hum_int))
{
case 1: //more humid than should be
valve.write (90);
break;
case 2: //less humid than should be
valve.write (0);
break;
case 0: //optimal humidity
valve.write (90);
};
if (LCD_button_state)
{
LCD_data();
LCD_button_state = 0;
};
start_switch_state = digitalRead(start_switch);
if (start_switch_state == 0)
{
goto turn_off;
}
delay(2000); //data read every 2 secs
}
turn_off:
if (reset_set)
{
reset();
}
}
void interrupt_LCD_button()
{
LCD_button_state = 1;
}
void LCD_data()
{
lcd.backlight();
lcd.clear();
//SHOW SET TEMP/HUM
lcd.setCursor(0, 0);
lcd.print("SET: ");
lcd.setCursor(5, 0);
lcd.print(set_temp);
lcd.setCursor(8, 0);
lcd.print("C ");
lcd.setCursor(11, 0);
lcd.print(set_hum);
lcd.setCursor(13, 0);
lcd.print("%");
//SHOW ACTUAL TEMP/HUM
lcd.setCursor(0, 1);
lcd.print("ACT: ");
lcd.setCursor(5, 1);
lcd.print(temp_int);
lcd.setCursor(8, 1);
lcd.print("C ");
lcd.setCursor(11, 1);
lcd.print(hum_int);
lcd.setCursor(13, 1);
lcd.print("%");
delay(5000);
lcd.clear();
lcd.noBacklight();
}
int temp_check(int set_temp, int temp_int)
{
if (temp_int > set_temp + 2)
{
return 1;
}
else if (temp_int < set_temp - 2)
{
return 2;
}
else
{
return 0;
}
}
int hum_check(int set_hum, int hum_int)
{
if (hum_int > set_hum + 3)
{
return 1;
}
else if (hum_int < set_hum - 3)
{
return 2;
}
else
{
return 0;
}
}
void reset()
{
lcd.backlight();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("SHUTTING DOWN");
valve.write(valve_pos);
cooling_fan.write(fan_pos);
digitalWrite(red, LOW);
digitalWrite(green, LOW);
reset_set = 0;
initiate = 1;
delay(2000);
lcd.clear();
lcd.noBacklight();
}