//this code is not written by us but by 'Krodal' and we edited to make it useable for our greenhouse
// https://www.instructables.com/id/Real-Time-Clock-DS1302/
// http://playground.arduino.cc/Main/DS1302
// DS1302 RTC
// ----------
//
// Open Source / Public Domain
//
// Version 1
// By arduino.cc user "Krodal".
// June 2012
// Using Arduino 1.0.1
// Version 2
// By arduino.cc user "Krodal"
// March 2013
// Using Arduino 1.0.3, 1.5.2
// The code is no longer compatible with older versions.
// Added bcd2bin, bin2bcd_h, bin2bcd_l
// A few minor changes.
//
//
// Documentation: datasheet
//
// The DS1302 uses a 3-wire interface:
// - bidirectional data.
// - clock
// - chip select
// It is not I2C, not OneWire, and not SPI.
// So the standard libraries can not be used.
// Even the shiftOut() function is not used, since it
// could be too fast (it might be slow enough,
// but that's not certain).
//
// I wrote my own interface code according to the datasheet.
// Any three pins of the Arduino can be used.
// See the first defines below this comment,
// to set your own pins.
//
// The "Chip Enable" pin was called "/Reset" before.
//
// The chip has internal pull-down registers.
// This keeps the chip disabled, even if the pins of
// the Arduino are floating.
//
//
// Range
// -----
// seconds : 00-59
// minutes : 00-59
// hour : 1-12 or 0-23
// date : 1-31
// month : 1-12
// day : 1-7
// year : 00-99
//
//
// Burst mode
// ----------
// In burst mode, all the clock data is read at once.
// This is to prevent a rollover of a digit during reading.
// The read data is from an internal buffer.
//
// The burst registers are commands, rather than addresses.
// Clock Data Read in Burst Mode
// Start by writing 0xBF (as the address),
// after that: read clock data
// Clock Data Write in Burst Mode
// Start by writing 0xBE (as the address),
// after that: write clock data
// Ram Data Read in Burst Mode
// Start by writing 0xFF (as the address),
// after that: read ram data
// Ram Data Write in Burst Mode
// Start by writing 0xFE (as the address),
// after that: write ram data
//
//
// Ram
// ---
// The DS1302 has 31 of ram, which can be used to store data.
// The contents will be lost if the Arduino is off,
// and the backup battery gets empty.
// It is better to store data in the EEPROM of the Arduino.
// The burst read or burst write for ram is not implemented
// in this code.
//
//
// Trickle charge
// --------------
// The DS1302 has a build-in trickle charger.
// That can be used for example with a lithium battery
// or a supercap.
// Using the trickle charger has not been implemented
// in this code.
//
// Set your own pins with these defines !
#define DS1302_SCLK_PIN 10 // Arduino pin for the Serial Clock
#define DS1302_IO_PIN 9 // Arduino pin for the Data I/O
#define DS1302_CE_PIN 8 // Arduino pin for the Chip Enable
// Macros to convert the bcd values of the registers to normal
// integer variables.
// The code uses separate variables for the high byte and the low byte
// of the bcd, so these macros handle both bytes separately.
#define bcd2bin(h,l) (((h)*10) + (l))
#define bin2bcd_h(x) ((x)/10)
#define bin2bcd_l(x) ((x)%10)
// Register names.
// Since the highest bit is always '1',
// the registers start at 0x80
// If the register is read, the lowest bit should be '1'.
#define DS1302_SECONDS 0x80
#define DS1302_MINUTES 0x82
#define DS1302_HOURS 0x84
#define DS1302_DATE 0x86
#define DS1302_MONTH 0x88
#define DS1302_DAY 0x8A
#define DS1302_YEAR 0x8C
#define DS1302_ENABLE 0x8E
#define DS1302_TRICKLE 0x90
#define DS1302_CLOCK_BURST 0xBE
#define DS1302_CLOCK_BURST_WRITE 0xBE
#define DS1302_CLOCK_BURST_READ 0xBF
#define DS1302_RAMSTART 0xC0
#define DS1302_RAMEND 0xFC
#define DS1302_RAM_BURST 0xFE
#define DS1302_RAM_BURST_WRITE 0xFE
#define DS1302_RAM_BURST_READ 0xFF
// Defines for the bits, to be able to change
// between bit number and binary definition.
// By using the bit number, using the DS1302
// is like programming an AVR microcontroller.
// But instead of using "(1<<X)", or "_BV(X)",
// the Arduino "bit(X)" is used.
#define DS1302_D0 0
#define DS1302_D1 1
#define DS1302_D2 2
#define DS1302_D3 3
#define DS1302_D4 4
#define DS1302_D5 5
#define DS1302_D6 6
#define DS1302_D7 7
// Bit for reading (bit in address)
#define DS1302_READBIT DS1302_D0 // READBIT=1: read instruction
// Bit for clock (0) or ram (1) area,
// called R/C-bit (bit in address)
#define DS1302_RC DS1302_D6
// Seconds Register
#define DS1302_CH DS1302_D7 // 1 = Clock Halt, 0 = start
// Hour Register
#define DS1302_AM_PM DS1302_D5 // 0 = AM, 1 = PM
#define DS1302_12_24 DS1302_D7 // 0 = 24 hour, 1 = 12 hour
// Enable Register
#define DS1302_WP DS1302_D7 // 1 = Write Protect, 0 = enabled
// Trickle Register
#define DS1302_ROUT0 DS1302_D0
#define DS1302_ROUT1 DS1302_D1
#define DS1302_DS0 DS1302_D2
#define DS1302_DS1 DS1302_D2
#define DS1302_TCS0 DS1302_D4
#define DS1302_TCS1 DS1302_D5
#define DS1302_TCS2 DS1302_D6
#define DS1302_TCS3 DS1302_D7
// Structure for the first 8 registers.
// These 8 bytes can be read at once with
// the 'clock burst' command.
// Note that this structure contains an anonymous union.
// It might cause a problem on other compilers.
typedef struct ds1302_struct
{
uint8_t Seconds:4; // low decimal digit 0-9
uint8_t Seconds10:3; // high decimal digit 0-5
uint8_t CH:1; // CH = Clock Halt
uint8_t Minutes:4;
uint8_t Minutes10:3;
uint8_t reserved1:1;
union
{
struct
{
uint8_t Hour:4;
uint8_t Hour10:2;
uint8_t reserved2:1;
uint8_t hour_12_24:1; // 0 for 24 hour format
} h24;
struct
{
uint8_t Hour:4;
uint8_t Hour10:1;
uint8_t AM_PM:1; // 0 for AM, 1 for PM
uint8_t reserved2:1;
uint8_t hour_12_24:1; // 1 for 12 hour format
} h12;
};
uint8_t Date:4; // Day of month, 1 = first day
uint8_t Date10:2;
uint8_t reserved3:2;
uint8_t Month:4; // Month, 1 = January
uint8_t Month10:1;
uint8_t reserved4:3;
uint8_t Day:3; // Day of week, 1 = first day (any day)
uint8_t reserved5:5;
uint8_t Year:4; // Year, 0 = year 2000
uint8_t Year10:4;
uint8_t reserved6:7;
uint8_t WP:1; // WP = Write Protect
};
//---LiquidCrystalDisplay---
#include <LiquidCrystal.h> //include the LCD library
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2; //define the pins connections to the arduino
LiquidCrystal lcd(rs, en, d4, d5, d6, d7); //declare the pin names for the library
//---InfraredRemote---
#include "IRLibAll.h" //include IR library for infrared function
IRrecvPCI myReceiver(20); //Create a receiver object to listen on pin 20
IRdecode myDecoder; //Create a decoder obj
//---Servo---
#include <Servo.h> //include the servo library
Servo servo1; //declare the first servo a name
Servo servo2; //declare the second servo a name
const int servoVoltage = 17; //power-supply connected to pin 17 of the arduinoboard and pin 1 of the 5v h-bridge
int angle1; //declare a variable for servo 1
int angle2; //declare a variable for servo 2
bool alreadyOpenedWindows = false; //boolean to check whether the windows are allready closed or open
bool actuaterIsOn = false; //boolean to check whether the actuater is allraedy on of off
bool fanIsOn = false; //boolean to check whether the actuater is allraedy on of off
bool ledstripIsOn = false; //boolean to check whether the ledstrip is allready on or off
bool heaterIsOn = false; //boolean to check whether the heater is allready on or off
//---All-OUTPUT-PINS---
//---5-Volt---
const int pinServo = 17; //the power pin of the servos
const int pinWaterSensors = 16; //the power pin of the waterlevel & moisture sernosr
const int pinActuater = 15; //the pin to activate the actuator
const int pinFan = 14; //the power pin for the fan behind the heater
//---12-Volt---
const int pinLedstrip = 23; //the power pin for the ledstrip
const int pinHeater = 24; //the power pin for the heater
//---All-Sensors-pins/variables--------------------------------------------------------------------
//---moisture---
const int pinSoilMoisture0 = A10; //declare wich pin on the arduino board
const int pinSoilMoisture1 = A11; //declare wich pin on the arduino board
//---leakage---
const int pinWaterdrop = A12; //declare wich pin on the arduino board
//---temperature---
const int pinHeaterTemp = A8; //NTC sensorpin 5v --> 10k ohm --> A_ & NTC --> GND
const int pinHouseTemp = A9; //NTC sensorpin 5v --> 10k ohm --> A_ & NTC --> GND
//---light---
const int ldr0 = A5; // goes between GND-->10k resistor-->A12<--ldr<--5v
const int ldr1 = A6; // goes between GND-->10k resistor-->A12<--ldr<--5v
int lightIndex; //the light index ([0=Dark],[1=Dim],[2=Light],[3=Bright],[4=Very Bright])
//---waterlevel---
const int pinWaterlevel[5] = {A0, A1, A2, A3, A4}; //declare the pins to read the watertank
//---Time---variables------------------------------------------------------------------------------
int timeSettingsMenu = 4; //this value is for the settings menu controled by IR
int setValueTime = 0; //this value is used to show edited value of the time controled by IR
//---clock---
int fiveMinHeater = 0;
int previousHour = 25; //this varible[integer] is used to check if there passed an hour by making it 25 it will run for the first time.
int previousQuarter = 0; //this varible[integer] is used to check if there passed a quarter
//---TimeSettings---
int Ssec = 0; //this varible[integer] is for the seconds
int Smin = 1; //this varible[integer] is for the minutes
int Shour = 1; //this varible[integer] is for the hours
int Sdayofweek = 1; //this varible[integer] is for the day of the week
int Sdate = 1; //this varible[integer] is for the date
int Smonth = 1; //this varible[integer] is for the month
int Syear = 2018; //this varible[integer] is for the year
//---WIFI---------------------------------------------------------------------
String dataFromESP; //is used to store the tabel for the ESP
//---Memory-------------------------------------------------------------------
int MRsoilmoisture;
int MRminute;
int MRmenu;
//---Symbols------------------------
byte charHeater[8] = { //symbol of the heater
B01001,
B10010,
B01001,
B10010,
B00000,
B00000,
B11111,
B10101
};
byte charWatertank[8] = { //symbol of the watertank
B11111,
B10001,
B10001,
B10001,
B11111,
B11111,
B11111,
B01110
};
byte charTemperature[8] = { //symbol of the temperature
B01110,
B01010,
B01010,
B01010,
B01110,
B11111,
B11111,
B01110
};
byte charSoilmoisture[] = { //symbol of the soilmoisture
B00100,
B00100,
B01010,
B01010,
B10001,
B10001,
B10001,
B01110
};
void setup() {
//XXX-------------------------------------------------------------------------------------------------------move lcd and serial etc.... to an function and cal that function
lcd.begin(20,4); //define that the display has 4 rows and 20 digits
Serial.begin(9600); //define the baundrate for serial comunication with the laptop
Serial1.begin(115200); //define the baundrate for serial comunication with the ESP
sensorSetup(); //run a function to declare al input/output pins
myReceiver.enableIRIn(); //open the IR port
SerialTime(); //send the time on the greenhouse to the laptop by serial comunication ---optional not necessery
}
void sensorSetup() {
pinMode(pinHeaterTemp, INPUT); //declare NTC sensor pin as input for temperature
pinMode(pinHouseTemp, INPUT); //declare NTC sensor pin as input for temperature
pinMode(ldr0,INPUT); //declare LDR sensor pin as input for light-index
pinMode(ldr1,INPUT); //declare LDR sensor pin as input for light-index
pinMode(pinSoilMoisture0,INPUT); //declare moisture sensor pin as input for soil-moisture
pinMode(pinSoilMoisture1,INPUT); //declare moisture sensor pin as input for soil-moisture
pinMode(pinWaterdrop, INPUT); //declare waterdrop sensor pin as input for leakage
for (int i=0; i<5; i++) { //run a for loop 5 times to declare all the five pins
pinMode(pinWaterlevel[i],INPUT); //declare waterlevel sensor pins as input for waterlevel in the watertank
}
pinMode(pinServo,OUTPUT); //declare the servo pin as output
pinMode(pinWaterSensors,OUTPUT); //declare the waterSensors pin as output
pinMode(pinActuater,OUTPUT); //declare the Actuator pin as output
pinMode(pinFan,OUTPUT); //declare the Fan pin as output
pinMode(pinHeater,OUTPUT); //declare the Heater pin as output
pinMode(pinLedstrip,OUTPUT); //declare the Ledstrip pin as output
digitalWrite(pinHeater, HIGH); // trun heater off otherwise the heater would automatically trun on
digitalWrite(pinLedstrip, HIGH); // trun ledstrip off otherwise the ledstrip would automatically trun on
servo1.attach(28); //servo 1 connected to pin 28
servo2.attach (29); //servo 2 connected to pin 29
openWindows(true); //close the windows
previousQuarter = MINUTE() - 15; //set the Quarter correctly
lcd.createChar(1, charTemperature); //temperature symbol
lcd.createChar(2, charHeater); //heater symbol
lcd.createChar(3, charSoilmoisture);//water drop symbol
lcd.createChar(4, charWatertank); //watertank symbol
MRsoilmoisture = soilMoisture(); //read soilmostur for the first time
}
void loop() {
if (MRmenu != timeSettingsMenu || MRminute != MINUTE()) { //check if the display needs to be refresed
showMenuTimeSettings(); //show menu
sendESP(); //update the webserver
MRmenu = timeSettingsMenu; //reset memory
MRminute = MINUTE(); //reset memory
}
settingsMenuTime(); //change menu & value of edited time
calulator(); //optimize conditions
delay(10); //a tiny delay for proper use
}
// make an function that callculate if the ledstip, heater, etc... should trun on or off
void calulator() {
if (heaterIsOn) {
if (fiveMinHeater + 5 < MINUTE()) { //check for 5 minutes
fiveMinHeater == MINUTE(); //reset 5 minutes
turnOnFan(true); //turn fan on every 5 minutes
delay(5000); //wait 5 seconds
turnOnFan(false); //turn fan off
}
else if (fiveMinHeater > 54 && MINUTE() > 59){
fiveMinHeater == MINUTE(); //reset five minutes
turnOnFan(true); //turn fan on every 5 minutes
delay(5000); //wait 5 seconds
turnOnFan(false); //turn fan off
}
}
if (checkHour()) { //check if we passed an hour
MRsoilmoisture = soilMoisture(); //read soilMoisture only ones in a hour
int Gsoil = MRsoilmoisture; //declare soilmoisture for actuater
if (Gsoil < 65) { //check if moisture if below 65%
//give some water
if (!Leakage()) { //give only water if there is no leakage
turnOnActuater(true); //turn actuater on(give water)
delay(30000); //wait for 30 seconds
turnOnActuater(false); //turn actuater off(stop water)
}
}
}
if (checkQuarter()) { //check if we passed a quarter
Serial.println("quarter");
int Glight = lightSensor();
float Gtemp = Temperature("house");
bool GLeakage = Leakage();
//---Temperature---
if (Temperature("house") < 18) {
turnOnHeater(true); //turn heater on
openWindows(false); //close the windows
}
else if (Temperature("house") < 25) {
turnOnHeater(false); //turn heater off
openWindows(false); //close the windows
}
else {
turnOnHeater(false); //turn heater off
openWindows(true); //open the windows
}
//---Light---
if (HOUR() > 8 && HOUR() < 21) { //check if it is day
if (Glight < 2) { //below averagedaylight
turnOnHeater(false); //turn heater off
turnOnLedstrip(true); //turn ledstrip on
}
else { //its daylight
turnOnLedstrip(false); //trun off
}
}
else { //its night
turnOnLedstrip(false); //trun off
}
sendESP(); //send tabel to esp
}
}
// --------------------------------------------------------
// DS1302_clock_burst_read
//
// This function reads 8 bytes clock data in burst mode
// from the DS1302.
//
// This function may be called as the first function,
// also the pinMode is set.
//
void DS1302_clock_burst_read( uint8_t *p)
{
int i;
_DS1302_start();
// Instead of the address,
// the CLOCK_BURST_READ command is issued
// the I/O-line is released for the data
_DS1302_togglewrite( DS1302_CLOCK_BURST_READ, true);
for( i=0; i<8; i++) {
*p++ = _DS1302_toggleread();
}
_DS1302_stop();
}
// --------------------------------------------------------
// DS1302_clock_burst_write
//
// This function writes 8 bytes clock data in burst mode
// to the DS1302.
//
// This function may be called as the first function,
// also the pinMode is set.
//
void DS1302_clock_burst_write( uint8_t *p)
{
int i;
_DS1302_start();
// Instead of the address,
// the CLOCK_BURST_WRITE command is issued.
// the I/O-line is not released
_DS1302_togglewrite( DS1302_CLOCK_BURST_WRITE, false);
for( i=0; i<8; i++) {
// the I/O-line is not released
_DS1302_togglewrite( *p++, false);
}
_DS1302_stop();
}
// --------------------------------------------------------
// DS1302_read
//
// This function reads a byte from the DS1302
// (clock or ram).
//
// The address could be like "0x80" or "0x81",
// the lowest bit is set anyway.
//
// This function may be called as the first function,
// also the pinMode is set.
//
uint8_t DS1302_read(int address)
{
uint8_t data;
// set lowest bit (read bit) in address
bitSet( address, DS1302_READBIT);
_DS1302_start();
// the I/O-line is released for the data
_DS1302_togglewrite( address, true);
data = _DS1302_toggleread();
_DS1302_stop();
return (data);
}
// --------------------------------------------------------
// DS1302_write
//
// This function writes a byte to the DS1302 (clock or ram).
//
// The address could be like "0x80" or "0x81",
// the lowest bit is cleared anyway.
//
// This function may be called as the first function,
// also the pinMode is set.
//
void DS1302_write( int address, uint8_t data) {
// clear lowest bit (read bit) in address
bitClear( address, DS1302_READBIT);
_DS1302_start();
// don't release the I/O-line
_DS1302_togglewrite( address, false);
// don't release the I/O-line
_DS1302_togglewrite( data, false);
_DS1302_stop();
}
// --------------------------------------------------------
// _DS1302_start
//
// A helper function to setup the start condition.
//
// An 'init' function is not used.
// But now the pinMode is set every time.
// That's not a big deal, and it's valid.
// At startup, the pins of the Arduino are high impedance.
// Since the DS1302 has pull-down resistors,
// the signals are low (inactive) until the DS1302 is used.
void _DS1302_start( void) {
digitalWrite( DS1302_CE_PIN, LOW); // default, not enabled
pinMode( DS1302_CE_PIN, OUTPUT);
digitalWrite( DS1302_SCLK_PIN, LOW); // default, clock low
pinMode( DS1302_SCLK_PIN, OUTPUT);
pinMode( DS1302_IO_PIN, OUTPUT);
digitalWrite( DS1302_CE_PIN, HIGH); // start the session
delayMicroseconds( 4); // tCC = 4us
}
// --------------------------------------------------------
// _DS1302_stop
//
// A helper function to finish the communication.
//
void _DS1302_stop(void)
{
// Set CE low
digitalWrite( DS1302_CE_PIN, LOW);
delayMicroseconds( 4); // tCWH = 4us
}
// --------------------------------------------------------
// _DS1302_toggleread
//
// A helper function for reading a byte with bit toggle
//
// This function assumes that the SCLK is still high.
//
uint8_t _DS1302_toggleread( void)
{
uint8_t i, data;
data = 0;
for( i = 0; i <= 7; i++)
{
// Issue a clock pulse for the next databit.
// If the 'togglewrite' function was used before
// this function, the SCLK is already high.
digitalWrite( DS1302_SCLK_PIN, HIGH);
delayMicroseconds( 1);
// Clock down, data is ready after some time.
digitalWrite( DS1302_SCLK_PIN, LOW);
delayMicroseconds( 1); // tCL=1000ns, tCDD=800ns
// read bit, and set it in place in 'data' variable
bitWrite( data, i, digitalRead( DS1302_IO_PIN));
}
return( data);
}
// --------------------------------------------------------
// _DS1302_togglewrite
//
// A helper function for writing a byte with bit toggle
//
// The 'release' parameter is for a read after this write.
// It will release the I/O-line and will keep the SCLK high.
//
void _DS1302_togglewrite( uint8_t data, uint8_t release)
{
int i;
for( i = 0; i <= 7; i++)
{
// set a bit of the data on the I/O-line
digitalWrite( DS1302_IO_PIN, bitRead(data, i));
delayMicroseconds( 1); // tDC = 200ns
// clock up, data is read by DS1302
digitalWrite( DS1302_SCLK_PIN, HIGH);
delayMicroseconds( 1); // tCH = 1000ns, tCDH = 800ns
if( release && i == 7)
{
// If this write is followed by a read,
// the I/O-line should be released after
// the last bit, before the clock line is made low.
// This is according the datasheet.
// I have seen other programs that don't release
// the I/O-line at this moment,
// and that could cause a shortcut spike
// on the I/O-line.
pinMode( DS1302_IO_PIN, INPUT);
// For Arduino 1.0.3, removing the pull-up is no longer needed.
// Setting the pin as 'INPUT' will already remove the pull-up.
// digitalWrite (DS1302_IO, LOW); // remove any pull-up
}
else
{
digitalWrite( DS1302_SCLK_PIN, LOW);
delayMicroseconds( 1); // tCL=1000ns, tCDD=800ns
}
}
}
// -----------------------------------------------------
int WEEKDAY() { //this function will give you the daynuber of the week
ds1302_struct rtc; //give it the name rtc
char buffer[80]; //buffer s where all the time data will be loaded
DS1302_clock_burst_read( (uint8_t *) &rtc); //read all time data
sprintf( buffer, "%02d", (rtc.Day)); //take only the dayofweek data
int day = atoi(buffer); //store data in: "int day"
return day; //return the data
}
// -----------------------------------------------------
int YEAR() { //this function will give you the year
ds1302_struct rtc; //give it the name rtc
char buffer[80]; //buffer s where all the time data will be loaded
DS1302_clock_burst_read( (uint8_t *) &rtc); //read all time data
sprintf( buffer, "%02d", 2000 + bcd2bin( rtc.Year10, rtc.Year));//take only the year data
int year = atoi(buffer); //store data in: "int year"
return year; //return the data
}
// -----------------------------------------------------
int MONTH() { //this function will give you the month
ds1302_struct rtc; //give it the name rtc
char buffer[80]; //buffer s where all the time data will be loaded
DS1302_clock_burst_read( (uint8_t *) &rtc); //read all time data
sprintf( buffer, "%02d", bcd2bin( rtc.Month10, rtc.Month));//take only the month data
int month = atoi(buffer); //store data in: "int month"
return month; //return the data
}
// -----------------------------------------------------
int DATE() { //this function will give you the date
ds1302_struct rtc; //give it the name rtc
char buffer[80]; //buffer s where all the time data will be loaded
DS1302_clock_burst_read( (uint8_t *) &rtc); //read all time data
sprintf( buffer, "%02d", bcd2bin( rtc.Date10, rtc.Date));//take only the date data
int date = atoi(buffer); //store data in: "int date"
return date; //return the data
}
// -----------------------------------------------------
int HOUR() { //this function will give you the hour
ds1302_struct rtc; //give it the name rtc
char buffer[80]; //buffer s where all the time data will be loaded
DS1302_clock_burst_read( (uint8_t *) &rtc); //read all time data
sprintf( buffer, "%02d", bcd2bin( rtc.h24.Hour10, rtc.h24.Hour));//take only the hour data
int hour = atoi(buffer); //store data in: "int hour"
return hour; //return the data
}
// -----------------------------------------------------
int MINUTE() { //this function will give you the minute
ds1302_struct rtc; //give it the name rtc
char buffer[80]; //buffer s where all the time data will be loaded
DS1302_clock_burst_read( (uint8_t *) &rtc); //read all time data
sprintf( buffer, "%02d", bcd2bin( rtc.Minutes10, rtc.Minutes));//take only the minute data
int minute = atoi(buffer); //store data in: "int minute"
return minute; //return the data
}
// -----------------------------------------------------
int SECOND() { //this function will give you the second
ds1302_struct rtc; //give it the name rtc
char buffer[80]; //buffer s where all the time data will be loaded
DS1302_clock_burst_read( (uint8_t *) &rtc); //read all time data
sprintf( buffer, "%02d", bcd2bin( rtc.Seconds10, rtc.Seconds));//take only the seconds data
int seconds = atoi(buffer); //store data in: "int seconds"
return seconds; //return the data
}
// -----------------------------------------------------
void SerialTime() { //this function will set the all time
ds1302_struct rtc; //give it the name rtc
char buffer[80]; // the code uses 70 characters.
DS1302_clock_burst_read( (uint8_t *) &rtc); // Read all clock data at once (burst mode).
sprintf( buffer, "Time = %02d:%02d:%02d, ", //load for print the time on the SerialMonitor
bcd2bin( rtc.h24.Hour10, rtc.h24.Hour), //load for print hours
bcd2bin( rtc.Minutes10, rtc.Minutes), //load for print minutes
bcd2bin( rtc.Seconds10, rtc.Seconds)); //load for print seconds
Serial.print(buffer); //print the time
sprintf(buffer, "Date(day of month) = %d, Month = %d, " //load for print the date on the SerialMonitor
"Day(day of week) = %d, Year = %d", //load for print the date on the SerialMonitor
bcd2bin( rtc.Date10, rtc.Date), //load for print date
bcd2bin( rtc.Month10, rtc.Month), //load for print month
rtc.Day, //load for print day of week
2000 + bcd2bin( rtc.Year10, rtc.Year)); //load for print month
Serial.println( buffer); //print the date
}
// -----------------------------------------------------
void LoadTime() { //this function will load the time to the time in stettings for Reset
//[S] before variable means settings
Ssec = SECOND(); //run void[second] to set seconds
Smin = MINUTE(); //run void[minute] to set minutes
Shour = HOUR(); //run void[hour] to set hour
Sdayofweek = WEEKDAY(); //run void[weekday] to set day of week
Sdate = DATE(); //run void[date] to set date
Smonth = MONTH(); //run void[month] to set month
Syear = YEAR(); //run void[year] to set year
}
// -----------------------------------------------------
void SetTime(int second, int minute, int hour) { //this function will set[hour|minute|second]
LoadTime(); //run void[LoadTime] set the time of now in the settings
//[S] before variable means settings
Ssec = second; //set variable seconds
Smin = minute; //set variable minutes
Shour = hour; //set variable hours
TimeReset(Ssec,Smin,Shour,Sdayofweek,Sdate,Smonth,Syear);//run the void[Time Setup] to set the time
}
// -----------------------------------------------------
void SetDate(int day, int date, int month, int year) { //this function will set[year|month|date|dayofweek]
LoadTime(); //run void[LoadTime] to avoid wrong time
//[S] before variable means settings
Sdayofweek = day; //set variable dayofweek
Sdate = date; //set variable date
Smonth = month; //set variable month
Syear = year; //set variable year
TimeReset(Ssec,Smin,Shour,Sdayofweek,Sdate,Smonth,Syear);//run the void[Time Setup] to set the time
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void TimeReset(int Qsec,int Qmin,int Qhour,int Qday,int Qdate,int Qmonth, int Qyear) {
ds1302_struct rtc;
Serial.println(F("DS1302 Real Time Clock"));
Serial.println(F("Version 1, March 2018"));
Serial.println(F("Edited by Ximoo"));
// Start by clearing the Write Protect bit
// Otherwise the clock data cannot be written
// The whole register is written,
// but the WP-bit is the only bit in that register.
DS1302_write (DS1302_ENABLE, 0);
// Disable Trickle Charger.
DS1302_write (DS1302_TRICKLE, 0x00);
// Remove the next define,
// after the right date and time are set.
#define SET_DATE_TIME_JUST_ONCE
#ifdef SET_DATE_TIME_JUST_ONCE
// Fill these variables with the date and time.
int seconds, minutes, hours, dayofweek, dayofmonth, month, year;
// Example for april 15, 2013, 10:08, monday is 2nd day of Week.
// Set your own time and date in these variables.
//[S] before variable means settings
seconds = Qsec;
minutes = Qmin;
hours = Qhour;
dayofweek = Qday; // Day of week, any day can be first, counts 1...7
dayofmonth = Qdate; // Day of month, 1...31
month = Qmonth; // month 1...12
year = Qyear;
// Set a time and date
// This also clears the CH (Clock Halt) bit,
// to start the clock.
// Fill the structure with zeros to make
// any unused bits zero
memset ((char *) &rtc, 0, sizeof(rtc));
rtc.Seconds = bin2bcd_l( seconds);
rtc.Seconds10 = bin2bcd_h( seconds);
rtc.CH = 0; // 1 for Clock Halt, 0 to run;
rtc.Minutes = bin2bcd_l( minutes);
rtc.Minutes10 = bin2bcd_h( minutes);
// To use the 12 hour format,
// use it like these four lines:
// rtc.h12.Hour = bin2bcd_l( hours);
// rtc.h12.Hour10 = bin2bcd_h( hours);
// rtc.h12.AM_PM = 0; // AM = 0
// rtc.h12.hour_12_24 = 1; // 1 for 24 hour format
rtc.h24.Hour = bin2bcd_l( hours);
rtc.h24.Hour10 = bin2bcd_h( hours);
rtc.h24.hour_12_24 = 0; // 0 for 24 hour format
rtc.Date = bin2bcd_l( dayofmonth);
rtc.Date10 = bin2bcd_h( dayofmonth);
rtc.Month = bin2bcd_l( month);
rtc.Month10 = bin2bcd_h( month);
rtc.Day = dayofweek;
rtc.Year = bin2bcd_l( year - 2000);
rtc.Year10 = bin2bcd_h( year - 2000);
rtc.WP = 0;
// Write all clock data at once (burst mode).
DS1302_clock_burst_write( (uint8_t *) &rtc);
#endif
}
bool checkHour() { //this function will check if there past a hour (time to read the sensors?)
if (HOUR() != previousHour) { //if the hour is diffrent by the previous check
previousHour = HOUR(); //set the current time for for the next check
return true; //retrun that we are in a new hour [true]
}
else { //if the hour is the same by the previous check
return false; //return that we are in the same hour [false]
}
}
bool checkQuarter() { //this function will check if there past a hour (time to read the sensors?)
if (MINUTE() > previousQuarter) { //check for a new quarter
if (previousQuarter < 15) { //check for a valid quarter
if (MINUTE() < 45) { //it is a new quarter
previousQuarter = MINUTE() + 15; //set the current time for for the next check
if (previousQuarter >= 60) { //check if minute is valid below 60
previousQuarter -= 60; //if not valid - 60
}
return true; //end of function return that we have a new quarter
}
else { //it is not a new quarter
return false; //end ot function return that we dont have a new quarter
}
}
else { //it is a new quarter
previousQuarter = MINUTE() + 15; //set the current time for for the next check
if (previousQuarter >= 60) { //check if minute is valid below 60
previousQuarter -= 60; //if not valid - 60
}
return true; //end of function return that we have a new quarter
}
}
else { //it is not a new quarter
return false; //end ot function return that we dont have a new quarter
}
}
void LCD(int linenumber, int digit, String text){ //new function - declare 3 variables
lcd.setCursor(digit, linenumber); //set the corsor on the right location
lcd.print(text); //print the given text
}
String dayOfWeek(int dayNumber) { //this function will retrun the day of week in the first 3 letters String[text]
String daychar;
switch (dayNumber) { //calculate wich day it is
case 1: //if day of week is [1]
daychar = "Sun"; //day is sunday
break;
case 2: //if day of week is [2]
daychar = "Mon"; //day is monday
break;
case 3: //if day of week is [3]
daychar = "Tue"; //day is tuesday
break;
case 4: //if day of week is [4]
daychar = "Wed"; //day is wednesday
break;
case 5: //if day of week is [5]
daychar = "Thu"; //day is thursday
break;
case 6: //if day of week is [6]
daychar = "Fri"; //day is friday
break;
case 7: //if day of week is [7]
daychar = "Sat"; //day is saterday
break;
default: //if day of week is not valid
daychar = "XXX"; //not a valid day
break;
}
return daychar;
}
void LCDTime() { //function to display the time on the lcd
String Display; //we use this string to store all the text together before we display it
String daychar = dayOfWeek(WEEKDAY()); //run function to get day of week in text
Display = daychar; //preloadLCD day
Display += " " + zeroCheck(DATE()); //preloadLCD date
Display += "-" + zeroCheck(MONTH()); //preloadLCD month
Display += "-" + String(YEAR()); //preloadLCD year
Display += " " + zeroCheck(HOUR()); //preloadLCD hour
Display += ":" + zeroCheck(MINUTE()); //preloadLCD minute
LCD(0,0 ,Display); //set the loaded time on the display
}
String zeroCheck(int value) { //this function is used to set a 0 before the number so it will always return a two digit number parameter value is the number to check
String number; //create a variable to store the number
if (value < 10) { //check if the number is 1 digit
number = "0" + String(value); //add a zero
}
else { //allready is a two digit number
number = String(value); //make ready for return
}
return number; //always return a two digit number
}
float Temperature(String which){ //the parameter which makes claer which temperature sensor you want to measure
float Vin=5.0; //[V] the voltage used for the NTC
float Rt=10000; // Resistor t [ohm] the resitor used in this sensor
float R0=10000; // value of NTC in T0 [ohm]
float T0=298.15; // use T0 in Kelvin [K]
// use the datasheet to get this data.
float T1=273.15; // [K] in datasheet 0º C
float T2=373.15; // [K] in datasheet 100° C
float RT1=35563; // [ohms] resistence in T1
float RT2=549; // [ohms] resistence in T2
//processing/calculating all data
float beta=(log(RT1/RT2))/((1/T1)-(1/T2)); //calc a variable to calculate a variable for the NTC resitor
float Rinf=R0*exp(-beta/T0); //calc a variable to calculate the resitance in the NTC
float VoutA=Vin*((float)(analogRead(pinHeaterTemp))/1024.0); //calc voltage output on the heater NTC
float VoutB=Vin*((float)(analogRead(pinHouseTemp))/1024.0); //calc voltage output on the house NTC
float RoutA=(Rt*VoutA/(Vin-VoutA)); //calc resistance output on the heater NTC
float RoutB=(Rt*VoutB/(Vin-VoutB)); //calc resistance output on the house NTC
float TempKA=(beta/log(RoutA/Rinf)); //[K] calc the temperature in the heater NTC
float TempKB=(beta/log(RoutB/Rinf)); //[K] calc the temperature in the house NTC
float TempCA=TempKA-273.15; //[C] convert the temperature of the heater it to Celcius
float TempCB=TempKB-273.15; //[C] convert it to Celcius
if (which == "house") { //check wich temperature it needs to return [heater] or [house]
return TempCB; //return the temperatur inside the greenhouse
}
else {
return TempCA; //return the temperature around the heater
}
}
int lightSensor() { //return in ([0=Dark],[1=Dim],[2=Light],[3=Bright],[4=Very Bright])
int lightIndex; // the vaiable for the return ([0=Dark],[1=Dim],[2=Light],[3=Bright],[4=Very Bright])
int ldr0Value = analogRead(ldr0) - 150; //the value from the first sensor -150 is a correction cause of sensor failure
int ldr1Value = analogRead(ldr1); //the value from the second sensor
int ldrValue = (ldr0Value + ldr1Value)/2; //calculate the average of the two sensors
float resistorValue = 10.0; //resitance of the LDR in kilo ohms
float voltageValue = ldrValue*0.0048828125; // this calculate the voltage trough the ldr
int lux0 = 500/(resistorValue*((5-voltageValue)/voltageValue)); // this calculate the lux on the ldr
if (lux0 < 10) { //0-10 is dark
lightIndex = 0; //set lightindex [0=Dark]
} else if (lux0 < 200) { //10-200 = dim
lightIndex = 1; //set lightindex [1=Dim]
} else if (lux0 < 400) { //200-400 = light
lightIndex = 2; //set lightindex [2=Light]
} else if (lux0 < 700) { //400-7000 = bright
lightIndex = 3; //set lightindex [3=Bright]
} else { //more than 1000 is very bright
lightIndex = 4; //set lightindex [4=Very Bright]
}
Serial.print("the light intensity: ");
Serial.println(lux0);
return lightIndex; // return ([0=Dark],[1=Dim],[2=Light],[3=Bright],[4=Very Bright])
}
int soilMoisture() {
int soilMoistureProcent; //variable of the soilMoisture in procent
int soilMoistureAverage; //variable for the average of the 2 soilmoisture variables
int soilMoisture0; // variable for the sensorValue [0],[1]
int soilMoisture1; // variable for the sensorValue [0],[1]
digitalWrite(pinWaterSensors,HIGH); //turn on the sensor
delay(2000); //wait two seconds because of start up sensor
soilMoisture0 = analogRead(pinSoilMoisture0); //soilMoisture = read the sensorValue --> between 0 - 1023
soilMoisture1 = analogRead(pinSoilMoisture1); //soilMoisture = read the sensorValue --> between 0 - 1023
digitalWrite(pinWaterSensors, LOW); //turn off the sensor
soilMoistureAverage = (soilMoisture0 + soilMoisture1)/2; //calculate the average the two sensors
soilMoistureProcent = map(soilMoistureAverage, 0, 1023, 99, 0); //calculate to moisture procentage
soilMoistureProcent -= 5; //correction of measurement because of short time period
return soilMoistureProcent; //return the average procentage of the moisture in the soil
}
bool Leakage() { //this function checks for water leakage and returns a [true] or a [false]
if (digitalRead(pinWaterdrop)){ //read the waterdrop sensor if there is a leakage
return true; //return that there is no leakage found
}
else { //there is no leakage
return false; //retrun that there is a leakage found
}
}
int Waterlevel() { //this function will measure how many water is la=eft in the tank
int waterlevel = 0; //create a variable to store the measurement of the sensor
digitalWrite(pinWaterSensors,HIGH); //turn the sensor on
for (int i=0; i<5; i++) { //check all levels
if (analogRead(pinWaterlevel[i]) > 100) { //check if we measure water
waterlevel += 20; //add 20% cause we measured water
}
}
digitalWrite(pinWaterSensors,LOW); //turn sensor water off
return waterlevel; //return how much water is in the tank in procentage
}
//---all functions to turn things on or off
void openWindows(bool openWindows){ //this function is used to open and close the windows
if(!alreadyOpenedWindows && openWindows){ //if windows are closed and has to be open
digitalWrite(servoVoltage, HIGH); //give the servo's their power-supply
delay(100); //wait 100 milliseconds
for (int i = 150; i >= 90; i -= 1){ //close the windows by 1 degree at the time
servo1.write(i+33); //set servo 1 at the angle of degrees as saved in the variable of servo 1
servo2.write(i); //set servo 2 at the angle of degrees as saved in the variable of servo 2
delay(25); //wait 25 milliseconds between every added degree
} //the windows both are closed now
delay(100); //wait 100 milliseconds
digitalWrite(servoVoltage, LOW); //stop the power-supply
Serial.println("should be open");
alreadyOpenedWindows = true; //save that we opend the windows
}
if(alreadyOpenedWindows && !openWindows){ //if the windows are open and has to be closed
digitalWrite(servoVoltage, HIGH); //give the servo's their power-supply
delay(100); //wait 100 milliseconds
for (int i = 90; i <= 150; i += 1){ //open the windows by 1 degrees at the time
servo1.write(i+33); //set servo 1 at the angle of degrees as saved in the variable of servo 1
servo2.write(i); //set servo 2 at the angle of degrees as saved in the variable of servo 2
delay(25); //wait 25 milliseconds between every added degree
} //the windows both are opened now
delay(100); //wait 100 milliseconds
digitalWrite(servoVoltage, LOW); //stop the power-supply
Serial.println("should be closed");
alreadyOpenedWindows = false; //save that we closed the windows
}
}
void turnOnLedstrip(bool trunOn) { //this function is used to turn the ledstrip on and off
if (trunOn && !ledstripIsOn) { //check if the ledstrip is not on and if needs to turn on
digitalWrite(pinLedstrip,LOW); //trun ledstrip on
ledstripIsOn = true; //remember that the ledstrip is on
}
if (!trunOn && ledstripIsOn) { //check if the ledstrip is on and if needs to turn off
digitalWrite(pinLedstrip,HIGH); //trun ledstrip off
ledstripIsOn = false; //remember that the ledstrip is off
}
}
void turnOnHeater(bool trunOn) { //this function is used to turn the heater on and off
if (trunOn && !heaterIsOn) { //check if the heater is not on and if needs to turn on
digitalWrite(pinHeater,LOW); //trun heater on
heaterIsOn = true; //remember that the heater is on
}
if (!trunOn && heaterIsOn) { //check if the heater is on and if needs to turn off
digitalWrite(pinHeater,HIGH); //trun heater off
heaterIsOn = false; //remember that the heater is off
}
}
void turnOnActuater(bool trunOn) { //this function is used to turn the actuater on and off
if (trunOn && !actuaterIsOn) { //check if the actuater is not on and if needs to turn on
digitalWrite(pinActuater,HIGH); //trun actuater on
actuaterIsOn = true; //remember that the actuater is on
}
if (!trunOn && actuaterIsOn) { //check if the actuater is on and if needs to turn off
digitalWrite(pinActuater,LOW); //trun actuater off
actuaterIsOn = false; //remember that the actuater is off
}
}
void turnOnFan(bool trunOn) { //this function is used to turn the fan on and off
if (trunOn && !fanIsOn) { //check if the fan is not on and if needs to turn on
digitalWrite(pinFan,HIGH); //trun fan on
fanIsOn = true; //remember that the fan is on
}
if (!trunOn && fanIsOn) { //check if the fan is on and if needs to turn off
digitalWrite(pinFan,LOW); //trun fan off
fanIsOn = false; //remember that the fan is off
}
}
void settingsMenuTime() { //this function listens to the IR and will manage trough the menu
int menu = timeSettingsMenu; //is used cause of the shorter name
String IRrecieved = IRRecievedSignal(); //read IR sensor and load the siganl (button)
if (IRrecieved == "PWR") { //go to home screen
timeSettingsMenu = 4;
}
if (IRrecieved == "*") { //go to time settings
timeSettingsMenu = 1;
}
if (IRrecieved == "DWN") { //scrol down
if (menu == 1 || menu == 2 || menu == 10 || menu == 11 || menu == 20 || menu == 21 || menu == 22 || menu == 23 || menu == 100 || menu == 110 || menu == 200 || menu == 210 || menu == 220) {
timeSettingsMenu++;
}
}
if (IRrecieved == "UP") { //scrol up
if (menu == 2 || menu == 3 || menu == 11 || menu == 12 || menu == 21 || menu == 22 || menu == 23 || menu == 24 || menu == 101 || menu == 111 || menu == 201 || menu == 211 || menu == 221) {
timeSettingsMenu--;
}
}
if (IRrecieved == "SEL"){
if (menu == 3) { //close the settings menu
//here is shoud close the settings-------------------------------------------------------XX TO-DO
timeSettingsMenu = 4;
}
if (menu == 1 || menu == 2 || menu == 10 || menu == 11 || menu == 20 || menu == 21 || menu == 22 || menu == 23){ //all go forward on the selected sub menu
timeSettingsMenu *= 10;
}
if (menu == 12 || menu == 24 || menu == 101 || menu == 111 || menu == 201 || menu == 211 || menu == 221){ //all go back situations
timeSettingsMenu /= 10;
}
if (menu == 100){ //save hour
setValueTime = constrain(setValueTime, 0 ,60);
SetTime(SECOND(), MINUTE(), setValueTime);
timeSettingsMenu = 1;
}
if (menu == 110){ //save minute
setValueTime = constrain(setValueTime, 0 ,60);
SetTime(0, setValueTime, HOUR());
timeSettingsMenu = 1;
}
if (menu == 200){ //save date
setValueTime = constrain(setValueTime, 0 ,31);
SetDate(WEEKDAY(), setValueTime, MONTH(), YEAR());
timeSettingsMenu = 1;
}
if (menu == 210){ //save month
setValueTime = constrain(setValueTime, 0 ,12);
SetDate(WEEKDAY(), DATE(), setValueTime, YEAR());
timeSettingsMenu = 1;
}
if (menu == 220){ //save year
setValueTime = constrain(setValueTime, 0 ,75);
setValueTime += 2000;
SetDate(WEEKDAY(), DATE(), MONTH(), setValueTime);
timeSettingsMenu = 1;
}
if (menu == 230){ //save day of week
setValueTime = constrain(setValueTime, 1 ,7);
SetDate(setValueTime, DATE(), MONTH(), YEAR());
timeSettingsMenu = 1;
}
setValueTime = 1;
}
if (IRrecieved == "PLS") { //value plus
if (menu == 100 || menu == 101 || menu == 110 || menu == 111 || menu == 200 || menu == 201 || menu == 210 || menu == 211 || menu == 220 || menu == 221|| menu == 230 || menu == 231) {
setValueTime++;
Serial.println("plus");
}
}
if (IRrecieved == "MIN") { //value plus
if (menu == 100 || menu == 101 || menu == 110 || menu == 111 || menu == 200 || menu == 201 || menu == 210 || menu == 211 || menu == 220 || menu == 221|| menu == 230 || menu == 231) {
setValueTime--;
}
}
if (IRrecieved == "MODE") { //go to home screen
timeSettingsMenu = 4;
}
//---Actions---------------------By-IR-remotecontrol---
//those actions work like an toggle if its on turn it of and if its off turn it off
if (IRrecieved == "1") { //check if we recieved the number 1 button of the remotecontrol
if (alreadyOpenedWindows) { //check if the windows are open
openWindows(false); //close the windows
}
else { //the windows are open
openWindows(true);
}
}
if (IRrecieved == "2") { //check if we recieved the number 2 button of the remotecontrol
if (ledstripIsOn) { //check if the ledstrip is on
turnOnLedstrip(false); //turn it off
}
else { //it is not on
turnOnLedstrip(true); //turn it on
}
}
if (IRrecieved == "3") { //check if we recieved the number 3 button of the remotecontrol
if (fanIsOn) { //check if the fan is on
turnOnFan(false); //turn it off
}
else { //it is not on
turnOnFan(true); //turn it on
}
}
if (IRrecieved == "4") { //check if we recieved the number 4 button of the remotecontrol
if (heaterIsOn) { //check if the heater is on
turnOnHeater(false); //turn it off
}
else { //it is not on
turnOnHeater(true); //turn it on
}
}
if (IRrecieved == "5") { //check if we recieved the number 4 button of the remotecontrol
sendESP(); //update the webserver
showMenuTimeSettings(); //show menu
}
}
void showMenuTimeSettings() { //this value is used to switch between the sub menu's of the settings
int menu = timeSettingsMenu;
String displayYear = String(2000 + setValueTime);
String value = String(setValueTime); // covert int to string to show on display
switch(menu) {
//-----------------------------------------------//settings menu
/* example of the display, and how it works. In de following cases, this is all the same!
* case Q:
* lcd.clear(); //clear the screen
* LCD(X,Y ," Text on row 1"); //print the words "Text on row 1"
* LCD(X,Y ,">Text on row 2"); //print the words "Text on row 2" This row is selected
* LCD(X,Y ," Text on row 3"); //print the words "Text on row 3"
* LCD(X,Y ," Text on row 4"); //print the words "Text on row 4"
* break; //End of this case
*
* Q stands for which menu has to be displayed on the screen.
* X stands for the linenumber the text has to be displayed on.
* Y stands for the digit of the linenumber where the text has to be displayed on.
*/
case 1:
lcd.clear();
LCD(0,0 ," Settings");
LCD(1,0 ,">Reset Time"); //selected
LCD(2,0 ," Reset Date");
LCD(3,0 ," Go back");
break;
case 2:
lcd.clear();
LCD(0,0 ," Settings");
LCD(1,0 ," Reset Time");
LCD(2,0 ,">Reset Date"); //selected
LCD(3,0 ," Go back");
break;
case 3:
lcd.clear();
LCD(0,0 ," Settings");
LCD(1,0 ," Reset Time");
LCD(2,0 ," Reset Date");
LCD(3,0 ,">Go back"); //selected
break;
case 4: //home screen
lcd.clear();
LCDTime(); //display time
//lcd.setCursor(digit, linenumber);
lcd.setCursor(0, 1); lcd.write(1); //temp
LCD(1,1," " + String(Temperature("heater")));
lcd.print((char)223); lcd.print("C");
lcd.setCursor(10, 1); lcd.write(2); //heater
if (heaterIsOn) { LCD(1,11," ON"); } //check if heater is on
else { LCD(1,11," OFF"); }
lcd.setCursor(0, 2); lcd.write(3); //soilmoisture
LCD(2,1," " + String(MRsoilmoisture) + "%");
lcd.setCursor(10, 2); lcd.write(4); //watertank
LCD(2,11," " + String(Waterlevel()) + "%");
if (!Leakage()) { LCD(3,0,"Leakage: not found"); } //check for leakage
else { LCD(3,0,"Leakage: WARNING!!!"); }
break;
//--------------------------------------Reset time
case 10: //sub settings
lcd.clear();//clear the screen
LCD(0,0 ," Reset Time");
LCD(1,0 ,">Reset Hour"); //selected
LCD(2,0 ," Reset Minute");
LCD(3,0 ," Go back");
break;
case 11: //sub settings
lcd.clear();//clear the screen
LCD(0,0 ," Reset Time");
LCD(1,0 ," Reset Hour");
LCD(2,0 ,">Reset Minute"); //selected
LCD(3,0 ," Go back");
break;
case 12: //sub settings
lcd.clear();//clear the screen
LCD(0,0 ," Reset Time");
LCD(1,0 ," Reset Hour");
LCD(2,0 ," Reset Minute");
LCD(3,0 ,">Go back"); //selected
break;
//-----------------------------------//Reset date
case 20: //sub settings
lcd.clear();//clear the screen
LCD(0,0 ,">Reset Date"); //selected
LCD(1,0 ," Reset Month");
LCD(2,0 ," Reset Year");
LCD(3,0 ," Reset Day of week");
break;
case 21: //sub settings
lcd.clear();//clear the screen
LCD(0,0 ," Reset Date");
LCD(1,0 ,">Reset Month"); //selected
LCD(2,0 ," Reset Year");
LCD(3,0 ," Reset Day of week");
break;
case 22: //sub settings
lcd.clear();//clear the screen
LCD(0,0 ," Reset Date");
LCD(1,0 ," Reset Month");
LCD(2,0 ,">Reset Year"); //selected
LCD(3,0 ," Reset Day of week");
break;
case 23: //sub settings
lcd.clear();//clear the screen
LCD(0,0 ," Reset Date");
LCD(1,0 ," Reset Month");
LCD(2,0 ," Reset Year");
LCD(3,0 ,">Reset Day of week"); //selected
break;
case 24: //sub settings
lcd.clear();//clear the screen
LCD(0,0 ," Reset Month");
LCD(1,0 ," Reset Year");
LCD(2,0 ," Reset Day of week");
LCD(3,0 ,">Go back"); //selected
break;
//-----------------------------------------//change hour
case 100: //sub settings
lcd.clear();//clear the screen
LCD(0,0 ," Reset Hour");
LCD(1,0 ," Change to: " + value);
LCD(2,0 ,">Save hour"); //selected
LCD(3,0 ," Go back");
break;
case 101: //sub settings
lcd.clear();//clear the screen
LCD(0,0 ," Reset Hour");
LCD(1,0 ," Change to: " + value);
LCD(2,0 ," Save hour");
LCD(3,0 ,">Go back"); //selected
break;
//------------------------------------//change minute
case 110: //sub settings
lcd.clear();//clear the screen
LCD(0,0 ," Reset Minute");
LCD(1,0 ," Change to: " + value);
LCD(2,0 ,">Save minute"); //selected
LCD(3,0 ," Go back");
break;
case 111: //sub settings
lcd.clear();//clear the screen
LCD(0,0 ," Reset Minute");
LCD(1,0 ," Change to: " + value);
LCD(2,0 ," Save minute");
LCD(3,0 ,">Go back"); //selected
break;
//--------------------------------------//change date
case 200: //sub settings
lcd.clear();//clear the screen
LCD(0,0 ," Reset Date");
LCD(1,0 ," Change to: " + value);
LCD(2,0 ,">Save date"); //selected
LCD(3,0 ," Go back");
break;
case 201: //sub settings
lcd.clear();//clear the screen
LCD(0,0 ," Reset Date");
LCD(1,0 ," Change to: " + value);
LCD(2,0 ," Save date");
LCD(3,0 ,">Go back"); //selected
break;
//--------------------------------------//change month
case 210: //sub settings
lcd.clear();//clear the screen
LCD(0,0 ," Reset Month");
LCD(1,0 ," Change to: " + value);
LCD(2,0 ,">Save month"); //selected
LCD(3,0 ," Go back");
break;
case 211: //sub settings
lcd.clear();//clear the screen
LCD(0,0 ," Reset Month");
LCD(1,0 ," Change to: " + value);
LCD(2,0 ," Save month");
LCD(3,0 ,">Go back"); //selected
break;
//--------------------------------------//change year
case 220: //sub settings
lcd.clear();//clear the screen
LCD(0,0 ," Reset Year");
LCD(1,0 ," Change to: " + displayYear);
LCD(2,0 ,">Save year"); //selected
LCD(3,0 ," Go back");
break;
case 221: //sub settings
lcd.clear();//clear the screen
LCD(0,0 ," Reset Year");
LCD(1,0 ," Change to: " + displayYear);
LCD(2,0 ," Save year");
LCD(3,0 ,">Go back"); //selected
break;
//--------------------------------------//change day of week-------------------------------------------------------------------XXX
case 230: //sub settings
lcd.clear();//clear the screen
LCD(0,0 ," Reset Day");
LCD(1,0 ," Change to: " + dayOfWeek(setValueTime));
LCD(2,0 ,">Save day"); //selected
LCD(3,0 ," Go back");
break;
case 231: //sub settings
lcd.clear();//clear the screen
LCD(0,0 ," Reset Day");
LCD(1,0 ," Change to: " + dayOfWeek(setValueTime));
LCD(2,0 ," Save day");
LCD(3,0 ,">Go back"); //selected
break;
//--------------------------------------// if menu went wrong
default: //if somting went wrong show it on display incl the menu[number]
lcd.clear();//clear the screen
LCD(0,0 ," Somthing went wrong");
LCD(1,0 ," menu error: " + String(menu));
LCD(2,0 ," ");
LCD(3,0 ," press POWER to exit"); //selected
break;
}
}
String IRRecievedSignal() {
if (myReceiver.getResults()) { //check if there are results
myDecoder.decode(); //Decode it
String Hexadecimal = "0x" + String(myDecoder.value, HEX); //converts it to Hexadecimal
if(Hexadecimal != "0xffffffff" && Hexadecimal != "0x0"){ //don't print these hexadecimal numbers
Serial.println(IRButtons()); //print the return
myReceiver.enableIRIn();
}
myReceiver.enableIRIn();
return IRButtons();
}
else {
return "nothing";
}
}
String IRButtons(){
if (myDecoder.protocolNum == NEC) { //if NEC-protcol id used
switch(myDecoder.value) { //look for a match with the recieved code
case 0x1ce3f00f: //Hexadecimal number of "PWR" button 1
return "PWR"; break;
case 0x1ce3b24d: //Hexadecimal number of "AP" button 2
return "AP"; break;
case 0x1ce3c837: //Hexadecimal number of "SCN" button 3
return "SCN"; break;
case 0x1ce302fd: //Hexadecimal number of "CLK" button 4
return "CLK"; break;
case 0x1ce3a857: //Hexadecimal number of "MIN" button 5
return "MIN"; break;
case 0x1ce3f20d: //Hexadecimal number of "AF" button 6
return "AF"; break;
case 0x1ce308f7: //Hexadecimal number of "DN" button 7
return "DWN"; break;
case 0x1ce38877: //Hexadecimal number of "SEL" button 8
return "SEL"; break;
case 0x1ce348b7: //Hexadecimal number of "UP" button 9
return "UP"; break;
case 0x1ce3728d: //Hexadecimal number of "PLS" button 10
return "PLS"; break;
case 0x1ce318e7: //Hexadecimal number of "MODE" button 11
return "MODE"; break;
case 0x1ce328d7: //Hexadecimal number of "BND" button 12
return "BND"; break;
case 0x1ce3ca35: //Hexadecimal number of "PTY" button 13
return "PTY"; break;
case 0x1ce38a75: //Hexadecimal number of "TA" button 14
return "TA"; break;
case 0x1ce36897: //Hexadecimal number of "1" button 15
return "1"; break;
case 0x1ce3a25d: //Hexadecimal number of "2" button 16
return "2"; break;
case 0x1ce36a95: //Hexadecimal number of "3" button 17
return "3"; break;
case 0x1ce3ea15: //Hexadecimal number of "4" button 18
return "4"; break;
case 0x1ce3708f: //Hexadecimal number of "5" button 19
return "5"; break;
case 0x1ce30af5: //Hexadecimal number of "6" button 20
return "6"; break;
case 0x1ce3aa55: //Hexadecimal number of "7" button 21
return "7"; break;
case 0x1ce34ab5: //Hexadecimal number of "8" button 22
return "8"; break;
case 0x1ce3906f: //Hexadecimal number of "*" button 23
return "*"; break;
case 0x1ce32ad5: //Hexadecimal number of "9" button 24
return "9"; break;
case 0x1ce3e21d: //Hexadecimal number of "0" button 25
return "0"; break;
case 0x1ce342bd: //Hexadecimal number of "#" button 26
return "#"; break;
case 0x1ce332cd: //Hexadecimal number of "MUTE" button 27
return "MUTE"; break;
case 0x1ce310ef: //Hexadecimal number of "TM" button 28
return "TM"; break;
case 0x1ce312ed: //Hexadecimal number of "TEL" button 29
return "TEL"; break;
case 0x1ce3d22d: //Hexadecimal number of "CLR" button 30
return "CLR"; break;
case 0x0: //When this hexadecimal number appears, return the word "ERROR"
return "ERROR of 0"; break;
case 0xffffffff:
return "ERROR of fff"; break;
default:
return "i dont know this one";
break;
}
}
else {
return "there is nothing";
}
}
String stateChecker(bool check) { //this function reads if a boolean is true and returns if it is on or off in text
if (check) {
return "On";
}
else {
return "Off";
}
}
void sendESP() { //this function will make a table in HTML and send it to the wifi chip
String txtWindows; //string for the state of the windows
String txtLeakage; //string for the state of the leakage sensor
String txtLight; //string for the state of the light conditions
String txtMoisture = String(MRsoilmoisture); //here we read the moisture conditions
if (!alreadyOpenedWindows) { //check if windows are closed
txtWindows = "Closed";
}
else { //windows are not closed
txtWindows = "Open";
}
if (Leakage) { //check for leakage
txtLeakage = "Not found";
}
else { //leakage found
txtLeakage = "Found";
}
switch(lightSensor()) { //calculate the light conditions
case 0:
txtLight = "Dark";
break;
case 1:
txtLight = "Dim";
break;
case 2:
txtLight = "Light";
break;
case 3:
txtLight = "Bright";
break;
case 4:
txtLight = "Very bright";
break;
}
String ESPtime; //Sting for the time we updated the webserver
String daychar = dayOfWeek(WEEKDAY()); //run function to get day of week in text
ESPtime = daychar; //preloadLCD day
ESPtime += " " + zeroCheck(DATE()); //preloadLCD date
ESPtime += "-" + zeroCheck(MONTH()); //preloadLCD month
ESPtime += "-" + String(YEAR()); //preloadLCD year
ESPtime += " " + zeroCheck(HOUR()); //preloadLCD hour
ESPtime += ":" + zeroCheck(MINUTE()); //preloadLCD minute
//----upload--the-table-to-the-wifi-chip-----------------------------------------[HTML]
Serial.println("start sending to esp");//to laptop
Serial1.print(" <table class=\"w3-table w3-bordered\"> ");
Serial1.print(" <thead> ");
Serial1.print(" <tr class=\"w3-theme\"> ");
Serial1.print(" <th>SENSOR</th> ");
Serial1.print(" <th>VALUE</th> ");
Serial1.print(" <th>FUNCTION</th> ");
Serial1.print(" <th>STATE</th> ");
Serial1.print(" </tr> ");
Serial1.print(" </thead> ");
Serial1.print(" <tbody> ");
Serial1.print(" <tr> ");
Serial1.print(" <td>Temperature</td> ");
Serial1.print(" <td>" + String(Temperature("heater")) +"℃</td> ");
Serial1.print(" <td>Heater</td> ");
Serial1.print(" <td>" + stateChecker(heaterIsOn) + "</td> ");
Serial1.print(" </tr> ");
Serial1.print(" <tr > ");
Serial1.print(" <td>Temperature</td> ");
Serial1.print(" <td>" + String(Temperature("house")) + "℃</td> ");
Serial1.print(" <td>Windows</td> ");
Serial1.print(" <td>"+ txtWindows +"</td> ");
Serial1.print(" </tr> ");
Serial1.print(" <tr> ");
Serial1.print(" <td>Light intensity</td> ");
Serial1.print(" <td>"+ txtLight +"</td> ");
Serial1.print(" <td>Ledstrip</td> ");
Serial1.print(" <td>" + stateChecker(ledstripIsOn) + "</td> ");
Serial1.print(" </tr> ");
Serial1.print(" <tr> ");
Serial1.print(" <td>Soil moisture</td> ");
Serial1.print(" <td>" + txtMoisture+ "%</td> ");
Serial1.print(" <td>Actuater</td> ");
Serial1.print(" <td>" + stateChecker(actuaterIsOn) + "</td> ");
Serial1.print(" </tr> ");
Serial1.print(" <tr> ");
Serial1.print(" <td>Watertank</td> ");
Serial1.print(" <td>"+ String(Waterlevel()) +"%</td> ");
Serial1.print(" <td>leakage</td> ");
Serial1.print(" <td>"+ txtLeakage +"</td> ");
Serial1.print(" </tr> ");
Serial1.print(" <tr> ");
Serial1.print(" <td>Last update:</td> ");
Serial1.print(" <td colspan=\"4\" >" + ESPtime + " </td> ");
Serial1.print(" </tr> ");
Serial1.print(" </tbody> ");
Serial1.println(" </table> ");
delay(1000); //this delay will make clear of the end of the table
//----done----
}