//--------------------------------------------
// Libraries
// Please refer to Arduino official website
//--------------------------------------------
#include <LiquidCrystal.h>
#include <Wire.h>
#include <EEPROM.h>
#include <stdio.h>
/*
Neopixel library by adafruit
For more refer to adafruit website
*/
#include <Adafruit_NeoPixel.h>
//--------------------------------------------
// Define firmware version
//--------------------------------------------
#define FW_VERSION "V0.1"
//--------------------------------------------
// Assign GPIO
//--------------------------------------------
const int fan = 9;
const int uvLed = 10;
const int whiteLed = 11;
const int ws2812B = A3;
//--------------------------------------------
// Input Button GPIO
//--------------------------------------------
const int setButton = A0;
const int upButton = A1;
const int downButton = 0;
const int okButton = 8;
const int confirmButton = 1;
//--------------------------------------------
// Global variables
//--------------------------------------------
int8_t currentButtonState[4]; //Array to current button state
int8_t lastButtonState[4]={1,1,1,1}; //Array to last button state
#define LED_COUNT 3 // Define no. of pixel leds
#define ON 1
#define OFF 0
static int8_t flag = 0;
bool configONTime = false;
bool configOFFTime = false;
//--------------------------------------------
// RTC device address
//--------------------------------------------
#define RTC_ADDR 0x68
//--------------------------------------------
// Lcd pins
//--------------------------------------------
const int rs = 7, en = 6, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
//--------------------------------------------
// Declare NeoPixel strip object
//--------------------------------------------
Adafruit_NeoPixel pixel(LED_COUNT, ws2812B, NEO_GRB + NEO_KHZ800);
//--------------------------------------------
// Structure for timer related operations
//--------------------------------------------
struct Timer{
int onTimeHour;
int onTimeMinute;
int offTimeHour;
int offTimeMinute;
int cycles;
int _onTimeHour;
int _onTimeMinute;
int _offTimeHour;
int _offTimeMinute;
int8_t uv;
int8_t wLed;
char rgb;
int8_t _fan;
int8_t _cycles;
int8_t setTimeFlag;
// int8_t _cycles;
};
Timer timer;
//--------------------------------------------
// Structure for menu related operations
//--------------------------------------------
struct Menu
{
int8_t page ;
int8_t counter;
};
Menu menu;
//--------------------------------------------
// Function prototypes
//--------------------------------------------
bool buttonPressed(const int button);
void readDataFromEEPROM();
void lcdDisplayZero(int8_t v1, int8_t v2);
void lcdDisplay(int8_t number);
int bcdToDec(int value);
void configRTC(int hr, int min);
//--------------------------------------------
// Timer Initalisation
// Timer interrupt
// Timer : Timer 1
// Prescalar :
// Mode :
//--------------------------------------------
void timer1Init()
{
noInterrupts();
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
TCCR1B |= (1 << WGM12);
TIMSK1 |= (1 << OCIE1A);
OCR1A = 15624;
TCCR1B|= (1 << CS10) | (1 << CS12) ;
interrupts();
}
//--------------------------------------------
// Interrupt ISR routine
//--------------------------------------------
ISR(TIMER1_COMPA_vect)
{
flag++; //Increment value of variable everytime when isr is executed
}
void setup()
{
// timer.setTimeFlag = 0;
timer.rgb = 'R';
//--------------------------------------------
// Configure GPIO mode
//--------------------------------------------
pinMode(fan, OUTPUT);
pinMode(uvLed, OUTPUT);
pinMode(whiteLed, OUTPUT);
pinMode(ws2812B, OUTPUT);
pinMode(setButton,INPUT);
pinMode(upButton,INPUT);
pinMode(downButton,INPUT);
pinMode(okButton,INPUT);
pinMode(confirmButton, INPUT);
//--------------------------------------------
// Define no. of lcd rows & columns
//--------------------------------------------
lcd.begin(16, 2);
lcd.setCursor(4,0); //Set cursor position ex 4th column, 0-1st line
lcd.print("Welcome"); //Print welcome msg
lcd.setCursor(6,1);
lcd.print(FW_VERSION); // Print firmware version
delay(2000); //Delay for 2 seconds
pixel.begin(); //Initialize pixel object
Wire.begin(); //Initialize two wire interface registers
configRTC(1,0); //Set RTC time
readDataFromEEPROM(); // Read data from eeprom after device power up
// On power read these parameters & store to temp buffers:
// time on & off, cycles, uv,whiteled,fan,rgb led .
}
void loop()
{
if(flag == 60 && timer._cycles > 0)
{
flag = 0;
int tempMinute;
int tempHour ;
Wire.begin();
Wire.beginTransmission(0x68);
Wire.write(1);
Wire.endTransmission();
Wire.requestFrom(0x68,7);
tempMinute = bcdToDec(Wire.read());
tempHour = bcdToDec(Wire.read());
Wire.endTransmission();
if(tempMinute == timer._onTimeMinute && tempHour == timer._onTimeHour)
{
lcd.setCursor(0,1);
lcd.print("on time");
digitalWrite(fan, timer._fan); //fan
digitalWrite(uvLed, timer.uv); //UV led
digitalWrite(whiteLed,timer.wLed); // white led
if(timer.rgb == 'R')
{
pixel.setPixelColor(1,255,0,0);
}
else if(timer.rgb == 'G')
{
pixel.setPixelColor(1,255,0,0);
}
else
{
pixel.setPixelColor(1,255,0,0);
}
pixel.show();
}
if(tempHour == timer.offTimeHour && tempMinute == timer.offTimeMinute)
{
timer._cycles--;
lcd.setCursor(0,1);
lcd.print("off time");
digitalWrite(fan, LOW); //fan
digitalWrite(uvLed, LOW); //UV led
digitalWrite(whiteLed,LOW); // white led
pixel.setPixelColor(1,0,0,0);
pixel.show();
}
}
else
{
if(buttonPressed(setButton) == true )
{
menu.page++;
switch(menu.page)
{
case 1: lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Set ON time:");
configONTime = true;
configOFFTime = false;
menu.counter = 0;
break;
case 2: lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Set OFF time:");
lcd.setCursor(0,1);
configOFFTime = true;
configONTime = false;
menu.counter = 0;
menu.page=0;
break;
}
}
else if( (buttonPressed(okButton) == true))
{
if(configONTime == true)
{
menu.counter++;
switch (menu.counter)
{
case 1:
lcd.setCursor(0,1);
lcd.print(" ");
if(timer._onTimeHour < 10)
{
lcd.setCursor(0,1);
lcdDisplayZero(0, timer._onTimeHour);
lcd.print(':');
}
else
{
lcd.setCursor(0,1);
lcd.print(timer._onTimeHour);
lcd.print(':');
}
if(timer._onTimeMinute < 10)
{
lcd.setCursor(3,1);
lcdDisplayZero(0, timer._onTimeMinute);
}
else
{
lcd.setCursor(3,1);
lcd.print(timer._onTimeMinute);
}
lcd.setCursor(15,1);
lcd.print('H');
timer.setTimeFlag = 1;
break;
case 2:
if(timer._onTimeMinute < 10)
{
lcd.setCursor(3,1);
lcdDisplayZero(0, timer._onTimeMinute);
}
else
{
lcd.setCursor(3,1);
lcd.print(timer._onTimeMinute);
}
lcd.setCursor(15,1);
lcd.print('M');
timer.setTimeFlag = 2;
// menu.counter = 0;
break;
case 3: //set uv
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Set UV:");
lcd.setCursor(8,0);
if(timer.uv == ON)
{
lcd.print("ON");
}
else
{
lcd.print("OFF");
}
timer.setTimeFlag = 99;
break;
case 4: //set rgb
//lcd.clear();
lcd.setCursor(0,1);
lcd.print("Set RGB:");
lcd.setCursor(9,1);
lcd.print(timer.rgb);
timer.setTimeFlag = 100;
break;
case 5: // set White led
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Set White led:");
lcd.setCursor(0,0);
timer.setTimeFlag = 102;
break;
case 6: //set cycles
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Set cycles:");
lcd.print(timer._cycles);
timer.setTimeFlag = 101;
break;
case 7: //set cycles
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Set fan:");
lcd.print(timer._cycles);
timer.setTimeFlag = 103;
// menu.counter =0;
break;
}
}
else if(configOFFTime == true)
{
menu.counter++;
if(menu.counter == 1)
{
lcd.setCursor(0,1);
lcd.print(" ");
if(timer._offTimeHour < 10)
{
lcd.setCursor(0,1);
lcdDisplayZero(0, timer._offTimeHour);
lcd.print(':');
}
else
{
lcd.setCursor(0,1);
lcd.print(timer._offTimeHour);
lcd.print(':');
}
if(timer._offTimeMinute < 10)
{
lcd.setCursor(3,1);
lcdDisplayZero(0, timer._offTimeMinute);
}
else
{
lcd.setCursor(3,1);
lcd.print(timer._offTimeMinute);
}
lcd.setCursor(15,1);
lcd.print('H');
timer.setTimeFlag = 3;
}
else if(menu.counter == 2)
{
if(timer._offTimeMinute < 10)
{
lcd.setCursor(3,1);
lcdDisplayZero(0, timer._offTimeMinute);
}
else
{
lcd.setCursor(3,1);
lcd.print(timer._offTimeMinute);
}
lcd.setCursor(15,1);
lcd.print('M');
timer.setTimeFlag = 4;
menu.counter = 0;
}
}
}
else if( buttonPressed(upButton) == true)
{
switch (timer.setTimeFlag)
{
case 1 :
if(timer._onTimeHour >= 23)
{
timer._onTimeHour = 0;
lcd.setCursor(0,1);
lcdDisplayZero(0,timer._onTimeHour);
}
else
{
timer._onTimeHour++;
if(timer._onTimeHour < 10)
{
lcd.setCursor(0,1);
lcdDisplayZero(0,timer._onTimeHour);
}
else
{
lcd.setCursor(0,1);
lcd.print(timer._onTimeHour);
}
}
break;
case 2:
if(timer._onTimeMinute >= 59)
{
timer._onTimeMinute = 0;
lcd.setCursor(3,1);
lcdDisplayZero(0,timer._onTimeMinute);
}
else
{
timer._onTimeMinute++;
if(timer._onTimeMinute < 10)
{
lcd.setCursor(3,1);
lcdDisplayZero(0,timer._onTimeMinute);
}
else
{
lcd.setCursor(3,1);
lcd.print(timer._onTimeMinute);
}
}
break;
case 3:
if(timer._offTimeHour >= 23)
{
timer._offTimeHour = 0;
lcd.setCursor(0,1);
lcdDisplayZero(0,timer._offTimeHour);
}
else
{
timer._offTimeHour++;
if(timer._offTimeHour < 10)
{
lcd.setCursor(0,1);
lcdDisplayZero(0,timer._offTimeHour);
}
else
{
lcd.setCursor(0,1);
lcd.print(timer._offTimeHour);
}
}
break;
case 4:
if(timer._offTimeMinute >= 59)
{
timer._offTimeMinute = 0;
lcd.setCursor(3,1);
//lcd.print(timer._onTimeMinute);
lcdDisplayZero(0,timer._offTimeMinute);
}
else
{
timer._offTimeMinute++;
if(timer._offTimeMinute < 10)
{
lcd.setCursor(3,1);
lcdDisplayZero(0,timer._offTimeMinute);
}
else
{
lcd.setCursor(3,1);
lcd.print(timer._offTimeMinute);
}
}
break;
case 99: if(timer.uv == ON)
{
timer.uv = OFF;
lcd.setCursor(8,0);
lcd.print(" ");
lcd.setCursor(8,0);
lcd.print("OFF");
}
else
{
timer.uv = ON;
lcd.setCursor(8,0);
lcd.print(" ");
lcd.setCursor(8,0);
lcd.print("ON");
}
break;
case 100: lcd.setCursor(9,1);
if(timer.rgb == 'R')
{
timer.rgb = 'G';
lcd.print('G');
}
else if(timer.rgb == 'G')
{
timer.rgb = 'B';
lcd.print(timer.rgb);
}
else if(timer.rgb == 'B')
{
timer.rgb = 'R';
lcd.print(timer.rgb);
}
break;
case 101: timer._cycles ++;
lcd.setCursor(11,0);
lcd.print(" ");
lcd.setCursor(11,0);
lcd.print(timer._cycles);
break;
case 102:
if(timer.wLed == ON)
{
timer.wLed = OFF;
lcd.setCursor(0,1);
lcd.print(" ");
lcd.setCursor(0,1);
lcd.print("OFF");
}
else
{
timer.wLed = ON;
lcd.setCursor(0,1);
lcd.print(" ");
lcd.setCursor(0,1);
lcd.print("ON");
}
break;
case 103:
if(timer._fan == ON)
{
timer._fan = OFF;
lcd.setCursor(8,0);
lcd.print(" ");
lcd.setCursor(8,0);
lcd.print("OFF");
}
else
{
timer._fan = ON;
lcd.setCursor(8,0);
lcd.print(" ");
lcd.setCursor(8,0);
lcd.print("ON");
}
break;
}
}
else if( buttonPressed(downButton) == true)
{
switch (timer.setTimeFlag)
{
case 1:
if(timer._onTimeHour <=0)
{
timer._onTimeHour = 23;
lcd.setCursor(0,1);
lcd.print(timer._onTimeHour);
}
else
{
timer._onTimeHour--;
if(timer._onTimeHour < 10)
{
lcd.setCursor(0,1);
lcdDisplayZero(0,timer._onTimeHour);
// lcd.print(timer._onTimeHour);
}
else
{
lcd.setCursor(0,1);
lcd.print(timer._onTimeHour);
}
}
break;
case 2:
if(timer._onTimeMinute <= 0)
{
timer._onTimeMinute = 59;
lcd.setCursor(3,1);
lcd.print(timer._onTimeMinute);
}
else
{
timer._onTimeMinute--;
if(timer._onTimeMinute < 10)
{
lcd.setCursor(3,1);
lcdDisplayZero(0,timer._onTimeMinute);
}
else
{
lcd.setCursor(3,1);
lcd.print(timer._onTimeMinute);
}
}
break;
case 3:
if(timer._offTimeHour <=0)
{
timer._offTimeHour = 23;
lcd.setCursor(0,1);
lcd.print(timer._offTimeHour);
}
else
{
timer._offTimeHour--;
if(timer._offTimeHour < 10)
{
lcd.setCursor(0,1);
lcdDisplayZero(0,timer._offTimeHour);
}
else
{
lcd.setCursor(0,1);
lcd.print(timer._offTimeHour);
}
}
break;
case 4:
if(timer._offTimeMinute <= 0)
{
timer._offTimeMinute = 59;
lcd.setCursor(3,1);
lcd.print(timer._offTimeMinute);
}
else
{
timer._offTimeMinute--;
if(timer._offTimeMinute < 10)
{
lcd.setCursor(3,1);
lcdDisplayZero(0,timer._offTimeMinute);
}
else
{
lcd.setCursor(3,1);
lcd.print(timer._offTimeMinute);
}
}
break;
case 101: timer._cycles --;
if(timer._cycles <=0)
{
timer._cycles=0;
}
lcd.setCursor(11,0);
lcd.print(" ");
lcd.setCursor(11,0);
lcd.print(timer._cycles);
break;
}
}
else if(buttonPressed(confirmButton) == true)
{
/*
Write to EEPROM entered by user
*/
EEPROM.write(0, timer._onTimeHour);
EEPROM.write(1, timer._onTimeMinute);
EEPROM.write(2, timer._offTimeHour);
EEPROM.write(3, timer._offTimeMinute);
EEPROM.write(4, timer.uv);
EEPROM.write(5, timer.rgb);
EEPROM.write(6, timer._cycles);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Parameters saved");
delay(1000);
readDataFromEEPROM();
timer1Init(); // Start timer
}
}
}
//--------------------------------------------
// Function to read button state
// Current configuration : When button is pressed
// the input goes low , when this is detected
// function returns as true else false
// True: button press detected
// False : No button press detected
// Uses state change of gpio to avoid debounce
//--------------------------------------------
bool buttonPressed(const int button)
{
bool state=false;
currentButtonState[button] = digitalRead(button);
if( (currentButtonState[button] == LOW) && (lastButtonState[button] == HIGH))
{
state = true;
}
lastButtonState[button] = currentButtonState[button];
return state;
}
//--------------------------------------------
// Function to convert decimal to bcd
//--------------------------------------------
int decToBcd(int value)
{
return ((value / 10 * 16) + (value % 10));
}
//--------------------------------------------
// Function to convert bcd to decimal
//--------------------------------------------
int bcdToDec(int value)
{
return ((value / 16 * 10) + (value % 16));
}
//--------------------------------------------
// Function to set RTC hour & min
//--------------------------------------------
void configRTC(int hr, int min)
{
Wire.beginTransmission(0x68);
Wire.write(decToBcd(0));
Wire.write(decToBcd(0));
Wire.write(decToBcd(min));
Wire.write(decToBcd(hr));
Wire.endTransmission();
}
//--------------------------------------------
// Function to read data from EEPROM
//--------------------------------------------
void readDataFromEEPROM()
{
timer.onTimeHour = EEPROM.read(0);
timer.onTimeMinute = EEPROM.read(1);
timer.offTimeHour = EEPROM.read(2);
timer.offTimeMinute = EEPROM.read(3);
timer.cycles = EEPROM.read(6);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("ON ");
lcd.setCursor(3,0);
lcd.print(' ');
lcd.setCursor(3,0);
(timer.onTimeHour < 10) ? lcdDisplayZero(0,timer.onTimeHour) : lcdDisplay(timer.onTimeHour);
lcd.print(':');
lcd.setCursor(6,0);
(timer.onTimeMinute < 10) ? lcdDisplayZero(0,timer.onTimeMinute) : lcdDisplay(timer.onTimeMinute);
// lcd.setCursor(10,0);
// lcd.print(tempCycle);
lcd.setCursor(0,1);
lcd.print("OFF ");
lcd.setCursor(4,1);
(timer.offTimeHour < 10) ? lcdDisplayZero(0,timer.offTimeHour) : lcdDisplay(timer.offTimeHour);
lcd.print(':');
lcd.setCursor(7,1);
(timer.offTimeMinute < 10) ? lcdDisplayZero(0,timer.offTimeMinute) : lcdDisplay(timer.offTimeMinute);
}
void lcdDisplayZero(int8_t v1, int8_t v2)
{
lcd.print(v1);
lcd.print(v2);
}
void lcdDisplay(int8_t number)
{
lcd.print(number);
}