Arduino Projects
Arduino
RGB Clock + Micro Weather Station
- Details
Below is the code used for RGB Clock + Micro Weather Station
The library's used in the code can be downloaded library for S65Display, DS1302, DHT11, BMP180, GVIFastWire, WS2812 libraries.
The demo video is shared on YouTube RGB Clock + Micro Weather Station Video Demo
//GROZEA Ion
//www.grozeaion.com
//Open Source, licensed under a Creative Commons Attribution-NonCommercial 3.0 License (http://creativecommons.org/licenses/by-nc/3.0/)
//License Agreement
//
//Copyright (c) 2011 GROZEA Ion (www.grozeaion.com)
//All rights reserved.
//
//Redistribution and use in source and binary forms, with or without modification,
//are permitted provided that the following conditions are met:
//
//* Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
//* Redistributions in binary form must reproduce the above copyright notice, this
// list of conditions and the following disclaimer in the documentation and/or
// other materials provided with the distribution.
//
//* The name of the copyright holder may not be used to endorse or promote
// products derived from this software without specific prior written permission.
//
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS OR
//IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
//MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
//SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
//SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
//OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
//IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
//ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
//POSSIBILITY OF SUCH DAMAGE.
#include <S65Display.h>
#include <DS1302.h>
#include <DHT11.h>
#include <BMP180.h>
#include <GVIFastWire.h>
#include <WS2812.h>
#include <avr/eeprom.h>
#include <avr/pgmspace.h>
S65Display lcd;
DS1302 myClock;
BMP180 PT;
#define Buzzer_On PORTD |= (1<<6)
#define Buzzer_Off PORTD &= ~(1<<6)
#define DHT11pin 3//Digital pin for comunications of DHT11 RH/Temp sensorD2 or D3
void theWrapper(); // must be declared before the lib initialization
DHT11 RH_Sensor;
WS2812 LED; // 60 LEDs ring
//#define WHITE 0xFFFFFFFF//RGB(255,255,255)
//#define BLACK 0x00000000//RGB(0,0,0)
//#define GREY 0xFFFFC618//RGB(195,195,195)
//#define RED 0xFFFFF800//RGB(255,0,0)
//#define GREEN 0x7E0//RGB(0,255,0)
//#define BLUE 0x1F//RGB(0,0,255)
//#define CYAN 0x7FF//RGB(0,255,255)
//#define MAGENTA 0xFFFFF81F//RGB(255,0,255)
//#define YELLOW 0xFFFFFFE0//RGB(255,255,0)
//#define BROWN 0xFFFFA145//RGB(165,42,42)
//#define ORANGE 0xFFFFFD20//RGB(255,165,0)
//#define PINK 0xFFFFFE19//RGB(255,192,203)
#define bgColor 0x00000000//RGB(0,0,0)//Background color
#define nText 0xFFFFFFE0//RGB(0,0,255)//Normal text
#define hText 0xFFFFFFFF//RGB(255,255,255)//Highlight text
#define sText 0x7E0//RGB(0,255,0)//Screen text
//Coorinates
const byte iX = 8;
const byte iY = 12;
//Memory offsets for EEPROM
const byte ROM_TH = 0; //Time Hour 0-24
const byte ROM_TM = 1; //Time Minute 0-59
const byte ROM_TS = 2; //Time Second 0-59
const byte ROM_TY = 3; //Time Year 0-99(2000-2099)
const byte ROM_MM = 4; //Time Month 1-12
const byte ROM_TD = 5; //Time Day 1-31
const byte ROM_WD = 6; //Time Day of week 1-7
const byte ROM_AH = 7; //Alarm Hour 0-23
const byte ROM_AM = 8; //Alarm Minute 0-59
const byte ROM_A1 = 9; //Alarm Start Day 1-7
const byte ROM_A2 = 10; //Alarm End Day 1-7
const byte ROM_HR = 11; //Hot Color RED 0-255
const byte ROM_HG = 12; //Hot Color GREEN 0-255
const byte ROM_HB = 13; //Hot Color BLUE 0-255
const byte ROM_NR = 14; //Normal Color RED 0-255
const byte ROM_NG = 15; //Normal Color GREEN 0-255
const byte ROM_NB = 16; //Normal Color BLUE 0-255
const byte ROM_CR = 17; //Cold Color RED 0-255
const byte ROM_CG = 18; //Cold Color GREEN 0-255
const byte ROM_CB = 19; //Cold Color BLUE 0-255
const byte ROM_HT = 20; //Temperature Alarm High 0-99
const byte ROM_LT = 21; //Temperature Alarm Low 0-99
const byte ROM_HRR = 22; //RH Alarm High 0-99
const byte ROM_LR = 23; //RH Alarm Low 0-99
const byte ROM_ST = 24; //Screen time 0-59
const byte ROM_SE = 25; //Light sensor threshold 0-255
const byte ROM_SC = 26; //Screen contrast 0-255
const byte ROM_BL = 27; //BackLight 1-On 0-Off
const byte ROM_Size = 28; //
//Strings used
const prog_char Str00[] PROGMEM = "GVI Clock";
//Menu names
const prog_char Str01[] PROGMEM = "Time";
const prog_char Str02[] PROGMEM = "Alarm";
const prog_char Str03[] PROGMEM = "Comfort";
const prog_char Str04[] PROGMEM = "Timing";
const prog_char Str05[] PROGMEM = "Colors";
//Time menu
const prog_char Str06[] PROGMEM = "H";
const prog_char Str07[] PROGMEM = "M";
const prog_char Str08[] PROGMEM = "S";
const prog_char Str09[] PROGMEM = "YY";
const prog_char Str10[] PROGMEM = "MM";
const prog_char Str11[] PROGMEM = "DD";
const prog_char Str12[] PROGMEM = "WD";
//Alarm menu
const prog_char Str13[] PROGMEM = "SDay";
const prog_char Str14[] PROGMEM = "EDay";
//Comfort
const prog_char Str15[] PROGMEM = "T Alarm";
const prog_char Str16[] PROGMEM = "RH Alarm";
//Colors
const prog_char Str17[] PROGMEM = "Hot";
const prog_char Str18[] PROGMEM = "Normal";
const prog_char Str19[] PROGMEM = "Cold";
const prog_char Str20[] PROGMEM = "R";
const prog_char Str21[] PROGMEM = "G";
const prog_char Str22[] PROGMEM = "B";
//Timing
const prog_char Str23[] PROGMEM = "Screen T";
const prog_char Str24[] PROGMEM = "Sensitiv";
//
const prog_char Str25[] PROGMEM = "Exit";
//Values
const prog_char Str26[] PROGMEM = "High";
const prog_char Str27[] PROGMEM = "Low";
const prog_char Str28[] PROGMEM = "Contrast";
const prog_char Str29[] PROGMEM = "BkLight";
const prog_char Str30[] PROGMEM = "Save";
//days of week
const prog_char Str31[] PROGMEM = "Sun";
const prog_char Str32[] PROGMEM = "Mon";
const prog_char Str33[] PROGMEM = "Tue";
const prog_char Str34[] PROGMEM = "Wed";
const prog_char Str35[] PROGMEM = "Thu";
const prog_char Str36[] PROGMEM = "Fri";
const prog_char Str37[] PROGMEM = "Sat";
//
const prog_char Str38[] PROGMEM = " No";
const prog_char Str39[] PROGMEM = "Yes";
//
const prog_char Str40[] PROGMEM = "Temp";
const prog_char Str41[] PROGMEM = "C/10";
const prog_char Str42[] PROGMEM = "Pres";
const prog_char Str43[] PROGMEM = "Pa";
const prog_char Str44[] PROGMEM = "RHum";
const prog_char Str45[] PROGMEM = "%";
const prog_char Str46[] PROGMEM = "DewP";
const prog_char Str47[] PROGMEM = "C/100";
PROGMEM const char *Strings[] PROGMEM = {Str00, Str01, Str02, Str03, Str04, Str05, Str06, Str07, Str08, Str09, Str10, Str11, Str12, Str13, Str14, Str15, Str16,
Str17, Str18, Str19, Str20, Str21, Str22, Str23, Str24, Str25, Str26, Str27, Str28, Str29, Str30, Str31, Str32, Str33, Str34, Str35, Str36, Str37, Str38, Str39,
Str40, Str41, Str42, Str43, Str44, Str45, Str46, Str47};
//Menus
void fMenu(byte Param);
void fValue(byte Param);
char* GetPrgStr(byte Idx);
void (*fTarget[])(byte Param) = {fMenu, fValue};
typedef struct MenuItem
{
const byte LabelIdx;//Text to display
void (*fTarget)(byte TargetParam);//Target function
const byte fParam;//Parameter for target function
};
typedef struct Menu
{
MenuItem *Item;
byte Size;
byte Pos;
byte ID;
};
//Main Menu
const byte MainMenuSize = 6;
MenuItem MainMenu[MainMenuSize] = {{1, fMenu, 110}, {2, fMenu, 120}, {3, fMenu, 130}, {4, fMenu, 140}, {5, fMenu, 150}, {25, fMenu, 170}};
//Time Menu
const byte TimeMenuSize = 9;
MenuItem TimeMenu[TimeMenuSize] = {{6, fValue, ROM_TH}, {7, fValue, ROM_TM}, {8, fValue, ROM_TS}, {9, fValue, ROM_TY}, {10, fValue, ROM_MM}, {11, fValue, ROM_TD}, {12, fValue, ROM_WD}, {30, fMenu, 160}, {25, fMenu, 100}};
//Alarm Menu
const byte AlarmMenuSize = 6;
MenuItem AlarmMenu[AlarmMenuSize] = {{6, fValue, ROM_AH}, {7, fValue, ROM_AM}, {13, fValue, ROM_A1}, {14, fValue, ROM_A2}, {30, fMenu, 160}, {25, fMenu, 100}};
//Comfort Menu
const byte ComfortMenuSize = 3;
MenuItem ComfortMenu[ComfortMenuSize] = {{15, fMenu, 131}, {16, fMenu, 132}, {25, fMenu, 100}};
//HighLowTemperature Menu
const byte HLTMenuSize = 4;
MenuItem HLTMenu[HLTMenuSize] = {{26, fValue, ROM_HT}, {27, fValue, ROM_LT}, {30, fMenu, 160}, {25, fMenu, 130}};
//HighLowRH Menu
const byte HLRHMenuSize = 4;
MenuItem HLRHMenu[HLRHMenuSize] = {{33, fValue, ROM_HRR}, {34, fValue, ROM_LR}, {30, fMenu, 160}, {25, fMenu, 130}};//Timing Menu
const byte TimingMenuSize = 6;
MenuItem TimingMenu[TimingMenuSize] = {{23, fValue, ROM_ST}, {24, fValue, ROM_SE}, {28, fValue, ROM_SC}, {29, fValue, ROM_BL}, {30, fMenu, 160}, {25, fMenu, 100}};
//Color Menu
const byte ColorMenuSize = 4;
MenuItem ColorMenu[ColorMenuSize] = {{17, fMenu, 151}, {18, fMenu, 152}, {19, fMenu, 153}, {25, fMenu, 100}};
//ColorHot Menu
const byte ColorXMenuSize = 5;
MenuItem ColorHMenu[ColorXMenuSize] = {{20, fValue, ROM_HR}, {21, fValue, ROM_HG}, {22, fValue, ROM_HB}, {30, fMenu, 160}, {25, fMenu, 150}};
//ColorNormal Menu
MenuItem ColorNMenu[ColorXMenuSize] = {{20, fValue, ROM_NR}, {21, fValue, ROM_NG}, {22, fValue, ROM_NB}, {30, fMenu, 160}, {25, fMenu, 150}};
//ColorCold Menu
MenuItem ColorCMenu[ColorXMenuSize] = {{20, fValue, ROM_CR}, {21, fValue, ROM_CG}, {22, fValue, ROM_CB}, {30, fMenu, 160}, {25, fMenu, 150}};
//
enum {Key_0, Key_M, Key_S, Key_U, Key_D, Key_L, Key_R};
// This variable will keep info about the current menu
Menu CrtMenu;
const byte MAX_VAL[ROM_Size] = {23, 59, 59, 99, 12, 31, 7, 23, 59, 7, 7, 255, 255, 255, 255, 255, 255, 255, 255, 255, 99, 99, 99, 99, 59, 255, 255, 1};
char StrBuffer[12];
byte ROM_VAL[ROM_Size], pID, pPos, crtScr, LED_R, LED_G, LED_B, t_h, t_m, t_s, i;
float LightSensor;
boolean IsInScr, IsAlarm;
unsigned long tick;
int T;
long P;
/////////////////////////////////////////////////////////
//Description:Loads from PROGMEM a string
//Parameters: String array to load
//Returns: the string
/////////////////////////////////////////////////////////
char* GetPrgStr(byte Idx)
{
StrBuffer[0] = '\0';
strcpy_P(StrBuffer, (char*)pgm_read_word(&(Strings[Idx])));
return StrBuffer;
}
/////////////////////////////////////////////////////////
//Description: General function asociated with menu item. If an menu item has a sub menu this function will load the sub menu
//Parameters: CrtMenu - which menu to load
//Returns: None
/////////////////////////////////////////////////////////
void fMenu(byte MenuID)
{
switch(MenuID)
{
case 100:
SetCrtMenu(MainMenu, MainMenuSize, MenuID);
break;
case 110:
SetCrtMenu(TimeMenu, TimeMenuSize, MenuID);
break;
case 120:
SetCrtMenu(AlarmMenu, AlarmMenuSize, MenuID);
break;
case 130:
SetCrtMenu(ComfortMenu, ComfortMenuSize, MenuID);
break;
case 140:
SetCrtMenu(TimingMenu, TimingMenuSize, MenuID);
break;
case 150:
SetCrtMenu(ColorMenu, ColorMenuSize, MenuID);
break;
case 131:
SetCrtMenu(HLTMenu, HLTMenuSize, MenuID);
break;
case 132:
SetCrtMenu(HLRHMenu, HLRHMenuSize, MenuID);
break;
case 151:
SetCrtMenu(ColorHMenu, ColorXMenuSize, MenuID);
break;
case 152:
SetCrtMenu(ColorNMenu, ColorXMenuSize, MenuID);
break;
case 153:
SetCrtMenu(ColorCMenu, ColorXMenuSize, MenuID);
break;
case 160:
Save(pID);
break;
//case 170:
//Show screen
//break;
}
}
/////////////////////////////////////////////////////////
//Description: Saves the parameters values in to EEPROM for a given Menu
//Parameters: ii - crt menu
//Returns: None
/////////////////////////////////////////////////////////
void Save(byte ii)
{
byte s, e;
switch(ii)
{
case 110:
{
s = ROM_TH;
e = ROM_AH;
myClock.set_Year(ROM_VAL[ROM_TY]);
myClock.set_Month(ROM_VAL[ROM_MM]);
myClock.set_Date(ROM_VAL[ROM_TD]);
myClock.set_Day(ROM_VAL[ROM_WD]);
myClock.set_Hour(ROM_VAL[ROM_TH]);
myClock.set_Minutes(ROM_VAL[ROM_TM]);
myClock.set_Seconds(ROM_VAL[ROM_TS]);
}
break;
case 120:
s = ROM_AH; e = ROM_HR;
break;
case 131:
s = ROM_HT; e = ROM_HRR;
break;
case 132:
s = ROM_HRR; e = ROM_ST;
break;
case 140:
s = ROM_ST; e = ROM_Size;
break;
case 151:
s = ROM_HR; e = ROM_NR;
break;
case 152:
s = ROM_NR; e = ROM_CR;
break;
case 153:
s = ROM_CR; e = ROM_HT;
break;
}
for(byte idx = s; idx < e; idx++)
eeprom_write_byte((uint8_t*)idx, ROM_VAL[idx]); //Save all items from Menu
}
/////////////////////////////////////////////////////////
//Description: General function asociated with menu item. If an menu item has an value this function will change that value
//Parameters: Which - Parameter Value to change
//Returns: None
/////////////////////////////////////////////////////////
void fValue(byte Param)
{
boolean GetOut = false;
while(!GetOut)
{
byte OldParamVal = ROM_VAL[Param];
switch(GetKey())
{
case Key_R:
ROM_VAL[Param] = ROM_VAL[Param] + 20;
if(ROM_VAL[Param] > MAX_VAL[Param]) ROM_VAL[Param] -= MAX_VAL[Param];
delay(10);
break;
case Key_U:
ROM_VAL[Param]++;
if(ROM_VAL[Param] > MAX_VAL[Param]) ROM_VAL[Param] = 0;
delay(10);
break;
case Key_D:
ROM_VAL[Param]--;
if(ROM_VAL[Param] > MAX_VAL[Param]) ROM_VAL[Param] = MAX_VAL[Param];
delay(10);
break;
case Key_L:
ROM_VAL[Param] = (ROM_VAL[Param] < 20) ? MAX_VAL[Param] + ROM_VAL[Param] - 20 : ROM_VAL[Param] - 20;
delay(10);
break;
case Key_S:
GetOut = true;
break;
}
if(OldParamVal != ROM_VAL[Param])
{
switch(Param)
{
case ROM_SC:
lcd.contrast(ROM_VAL[ROM_SC]);
break;
case ROM_BL:
lcd.BkLight(ROM_VAL[ROM_BL]);
break;
case ROM_WD:
case ROM_A1:
case ROM_A2:
if(ROM_VAL[Param] == 0) ROM_VAL[Param] = 1;
break;
}
lcd.drawBG(3, 5 + CrtMenu.Pos * 14, 170, 0);
lcd.drawTextT(iX, 7 + CrtMenu.Pos * 14, GetPrgStr(CrtMenu.Item[CrtMenu.Pos].LabelIdx), hText);//Label
PutStringValue(Param);
lcd.drawTextT(144, 7 + CrtMenu.Pos * 14, StrBuffer, hText);//Value
}
}
tick = millis() + (ROM_VAL[ROM_ST] * 1000);
}
/////////////////////////////////////////////////////////
//Description: Sets the selected menu menu
//Parameters: MyItem[] - array containig the menu items; MySize - Selected menu size; ID - Selected menu identifier
//Returns: None
/////////////////////////////////////////////////////////
void SetCrtMenu(struct MenuItem MyItem[], byte MySize, byte ID)
{
CrtMenu.Item = MyItem;
CrtMenu.Size = MySize;
CrtMenu.Pos = 0;
CrtMenu.ID = ID;
DrawMenu();
}
/////////////////////////////////////////////////////////
//Description: Draws curent menu
//Parameters: None
//Returns: None
/////////////////////////////////////////////////////////
void DrawMenu()
{
if (CrtMenu.ID != pID)//Draw the whole menu
{
lcd.clear(bgColor);
pID = CrtMenu.ID;
pPos = 0;
for(byte idx = 0; idx < CrtMenu.Size; idx++)
{
if(idx == CrtMenu.Pos)// If i is the current position, then write the string on white on black bg
lcd.drawBG(3, 5 + idx * 14, 170, 0);
else// Else, write a normal string
lcd.drawBG(3, 5 + idx * 14, 170, 1);
lcd.drawTextT(iX, 7 + idx * 14, GetPrgStr(CrtMenu.Item[idx].LabelIdx), nText);//Label
PutStringValue(CrtMenu.Item[idx].fParam);
lcd.drawTextT(144, 7 + idx * 14, StrBuffer, nText);//Value
}
}
else //draw only the changed items if any
{
if(CrtMenu.Pos != pPos)
{
//Normal
lcd.drawBG(3, 5 + pPos * 14, 170, 1);
lcd.drawTextT(iX, 7 + pPos * 14, GetPrgStr(CrtMenu.Item[pPos].LabelIdx), nText);//Label
PutStringValue(CrtMenu.Item[pPos].fParam);
lcd.drawTextT(144, 7 + pPos * 14, StrBuffer, nText);//Value
//Highlight
lcd.drawBG(3, 5 + CrtMenu.Pos * 14, 170, 0);
lcd.drawTextT(iX, 7 + CrtMenu.Pos * 14, GetPrgStr(CrtMenu.Item[CrtMenu.Pos].LabelIdx), hText);//Label
PutStringValue(CrtMenu.Item[CrtMenu.Pos].fParam);
lcd.drawTextT(144, 7 + CrtMenu.Pos * 14, StrBuffer, hText);//Value
pPos = CrtMenu.Pos;
}
}
tick = millis() + (ROM_VAL[ROM_ST] * 1000);
}
//PB0 - DS1302//
//PB2 - S65_CS
//PB3 - S65_DAT
//PB4 - DS1302//
//PB5 - S65_CLK
//PC0 - Battery
//PC1 - Buttons
//PC2 - LDR//
//PC3 - S65_RST
//PC4 - SDA - BMP180//
//PC5 - SCL - BMP180//
//PD2 - WS2812//
//PD3 - DHT11//
//PD4 - S65_RS
//PD5 - S65_BK
//PD6 - Buzzer
void setup()
{
//Serial.begin(9600);
DDRC = B11111000;//Set analogue pins 0 to 2 as input
PORTC |= B00000111;// Turn on 20K pull-up on analogue 0, 1, 2
DDRD |= B0100000;//Set digital pin 6 as output
LED.setOutput(2);
//ResetEEPROM();//Reset EEPROM to default values
LoadEEPROM();//Load default values
myClock.writeProtect(false);//Start DS1302 clock
myClock.halt(false);
RH_Sensor.init(DHT11pin, theWrapper);//Init DHT11
PT.begin();//Init BMP180
//PT.getCalibration();
getSensors();//Request T,P and RH from BMP180 and DHT11
lcd.init();//Init LCD LS020
lcd.BkLight(ROM_VAL[ROM_BL]);//Set Back Light value for LS020
lcd.contrast(ROM_VAL[ROM_SC]);//Set contrast value for LS020
lcd.clear(bgColor);//Clear screen
for(i = 0; i < 10; i++)
{
LED.clear(1, 0, 0);
LED.sync();
LED.clear(0, 1, 0);
LED.sync();
LED.clear(0, 0, 1);
LED.sync();
LED.clear(0, 0, 0);
}
byte j = 0;
for(i = 0; i < 60; i++)
{
if(j == 3) j = 0;
switch (j)
{
case 0:
LED.set_crgb_at(i, 1, 0, 0); // Set value at LED found at index i - Red color
break;
case 1:
LED.set_crgb_at(i, 1, 1, 0); // Set value at LED found at index i - Red color
break;
case 2:
LED.set_crgb_at(i, 0, 0, 1); // Set value at LED found at index i - Red color
break;
}
LED.sync(); // Sends the value to the LED
delay(50); // Wait 100 ms
j++;
}
pID = 0;
pPos = 0;
crtScr = 0;
tick = millis() + (ROM_VAL[ROM_ST] * 1000);
SetCrtMenu(MainMenu, MainMenuSize,100);
}
void loop()
{
switch(GetKey())
{
case Key_U:
CrtMenu.Pos--;
if(CrtMenu.Pos == 255) CrtMenu.Pos = CrtMenu.Size - 1;
DrawMenu();
break;
case Key_D:
CrtMenu.Pos++;
if(CrtMenu.Pos > (CrtMenu.Size - 1)) CrtMenu.Pos = 0;
DrawMenu();
break;
//case Key_R:
//case Key_L:
case Key_S:
CrtMenu.Item[CrtMenu.Pos].fTarget(CrtMenu.Item[CrtMenu.Pos].fParam);
break;
}
if(millis() > tick)//long time since a button was pressed or time to change the screen
{
if(CrtMenu.ID == 170)
crtScr++;
else if(CrtMenu.ID == 100)
{
crtScr = 0;
CrtMenu.ID = 170;
}
if(crtScr > 1) crtScr = 0;
tick = millis() + (ROM_VAL[ROM_ST] * 1000);
IsInScr = true;
ShowScreen();
}
SetRingClock();
//Serial.println(analogRead(A2));
}
/////////////////////////////////////////////////////////
//Description: This wrapper is in charge of calling the DHT11 lib. Must be defined like this for the lib work
//Parameters: None
//Returns: None
/////////////////////////////////////////////////////////
void theWrapper()
{
RH_Sensor.callBack();
}
/////////////////////////////////////////////////////////
//Description: This function creates a beep
//Parameters: None
//Returns: None
/////////////////////////////////////////////////////////
void Sound()
{
for (i = 0; i < 128; i++)// 1 / 2048Hz = 488uS, or 244uS high and 244uS low to create 50% duty cycle
{
Buzzer_On;
delayMicroseconds(244);
Buzzer_Off;
delayMicroseconds(244);
}
}
////////////////////////////////////////////////////////
//Description: This function creates the buzzer sound for 1/2 second
//Parameters: None
//Returns: None
/////////////////////////////////////////////////////////
void PlaySound()
{
for (i = 0; i < 16; i++)
Sound();
}
/////////////////////////////////////////////////////////
//Description: This function is handling the alarm option
//Parameters: None
//Returns: None
/////////////////////////////////////////////////////////
void WakeUpAlarm()
{
if(IsAlarm && ROM_VAL[ROM_AM] == myClock.get_Minutes()) return;
while(analogRead(A1) > 870)
{
LED.clear(255, 0, 0);
LED.sync();
PlaySound();
LED.clear(0, 255, 0);
LED.sync();
PlaySound();
LED.clear(0, 0, 255);
LED.sync();
delay(10);
PlaySound();
}
LED.clear(0, 0, 0);
LED.sync();
IsAlarm = true;
SetRingClock();
}
/////////////////////////////////////////////////////////
//Description: Gets the temperature, pressure and RH from BMP180 and DH11
//Parameters: None
//Returns: None
/////////////////////////////////////////////////////////
void getSensors()
{
long UT, UP;
RH_Sensor.acquire();//Request DHT11 data - it takes about 22ms to get it
PT.startT();//Request from BMP180 to start measuring the raw temperature - requires 4.5ms
delay(5);
UT = PT.getUT();
PT.startP();//Request from BMP180 to start measuring the raw pressure it takes 25.5ms
delay(26);
UP = PT.getUP();
PT.getT(UT, T);
PT.getP(UP, P);
setLED();//Calculate and set the LED colors
//Serial.print("Humidity ");Serial.println(RH_Sensor.getHumidity());
//Serial.print("DewPoint ");Serial.println(RH_Sensor.getDewPointSlow());
// Serial.print("UT ");Serial.println(UT);
// Serial.print("T ");Serial.println(T);
// Serial.print("UP ");Serial.println(UP);
// Serial.print("P ");Serial.println(P);
}
/////////////////////////////////////////////////////////
//Description: Sets the LED color depending on temperature and the colors defined by user
//Parameters: None
//Returns: None
/////////////////////////////////////////////////////////
void setLED()
{
LightSensor = (analogRead(A2)/1020.0);
if(T < 20)
{
LED_R = (float)ROM_VAL[ROM_HR] * LightSensor;
LED_G = (float)ROM_VAL[ROM_HG] * LightSensor;
LED_B = (float)ROM_VAL[ROM_HB] * LightSensor;
}
else if ((T >= 18) && (T < 26))
{
LED_R = (float)ROM_VAL[ROM_NR] * LightSensor;
LED_G = (float)ROM_VAL[ROM_NG] * LightSensor;
LED_B = (float)ROM_VAL[ROM_NB] * LightSensor;
}
else
{
LED_R = (float)ROM_VAL[ROM_CR] * LightSensor;
LED_G = (float)ROM_VAL[ROM_CG] * LightSensor;
LED_B = (float)ROM_VAL[ROM_CB] * LightSensor;
}
if(!LED_R) LED_R = 1;
if(!LED_G) LED_G = 1;
if(!LED_B) LED_B = 1;
// Serial.print(LightSensor);Serial.print("-");
// Serial.print(LED_R);Serial.print("-");
// Serial.print(LED_G);Serial.print("-");
// Serial.println(LED_B);
}
/////////////////////////////////////////////////////////
//Description: Sets the LEDs on the ring according to time
//Parameters: None
//Returns: None
/////////////////////////////////////////////////////////
void SetRingClock()
{
byte ls = myClock.get_Seconds();
byte myDay = myClock.get_Day();
byte marker = LightSensor*10;
if(ls != t_s) // the second has changed
{
t_s = ls;
t_m = myClock.get_Minutes();
t_h = myClock.get_Hour();
LED.clear(0, 0, 0);//clear buffer
if((myDay >= ROM_VAL[ROM_A1]) && (myDay <= ROM_VAL[ROM_A2]) && (ROM_VAL[ROM_AH] == t_h) && (ROM_VAL[ROM_AM] == t_m)) WakeUpAlarm();
// Serial.print(ROM_VAL[ROM_AM]);Serial.print(":::");
// Serial.print(t_h);Serial.print(":"); Serial.println(t_m);
LED.set_crgb_at(0, marker, marker, marker);//Markers
LED.set_crgb_at(15, marker, marker, marker);
LED.set_crgb_at(30, marker, marker, marker);
LED.set_crgb_at(45, marker, marker, marker);
if(t_h > 12)
LED.set_crgb_at((t_h - 12) * 5, LED_R, 0, 0);//Hour LED
else
LED.set_crgb_at(t_h * 5, LED_R, 0, 0);//Hour LED
LED.set_crgb_at(t_m, 0, LED_G, 0);//Minute LED
LED.set_crgb_at(t_s, 0, 0, LED_B);//Second LED
LED.sync();//send updated data to ring
}
}
/////////////////////////////////////////////////////////
//Description: Displays the screens with data
//Parameters: None
//Returns: none
/////////////////////////////////////////////////////////
void ShowScreen()
{
lcd.clear(bgColor);//clear screen
SetRingClock();
byte ss = t_s;
if(!crtScr)
{
NumberToStr(t_h, 1);
lcd.drawTextT(30, 50, StrBuffer, sText);//Show Hours
lcd.drawTextT(46, 50, ":", hText);
NumberToStr(t_m, 1);
lcd.drawTextT(54, 50, StrBuffer, sText);//Show Minutes
lcd.drawTextT(70, 50, ":", hText);
NumberToStr(ss, 1);
lcd.drawText(78, 50, StrBuffer, sText, bgColor);//Show Seconds
lcd.drawTextT(30, 70, GetPrgStr(30 + myClock.get_Day()), sText);//Show Day Name
NumberToStr(myClock.get_Date(), 1);
lcd.drawTextT(62, 70, StrBuffer, sText);//Show Month Day
lcd.drawTextT(78, 70, ".", hText);
NumberToStr(myClock.get_Month(), 1);
lcd.drawTextT(86, 70, StrBuffer, sText);//Show Month
lcd.drawTextT(102, 70, ".", hText);
NumberToStr(myClock.get_Year(), 1);
lcd.drawTextT(110, 70, StrBuffer, sText);//Show Year
while(millis() < tick)
{
SetRingClock();
if(t_s != ss)
{
ss = t_s;
NumberToStr(ss, 1);
lcd.drawText(78, 50, StrBuffer, sText, bgColor);//Show Seconds
}
delay(250);// check 4 times per second
}
}
else//Temperature and pressure screen
{
getSensors();
lcd.drawTextT(30, 30, GetPrgStr(40), sText);//Show Temp
NumberToStr(T, 2);
lcd.drawTextT(70, 30, StrBuffer, hText);//Show Temp value
lcd.drawTextT(100, 30, GetPrgStr(41), sText);//Show UM
lcd.drawTextT(30, 50, GetPrgStr(42), sText);//Show Pressure
NumberToStr(P, 4);
//Serial.println(P);
lcd.drawTextT(70, 50, StrBuffer, hText);//Show Pressure value
lcd.drawTextT(118, 50, GetPrgStr(43), sText);//Show UM
lcd.drawTextT(30, 70, GetPrgStr(44), sText);//Show RH
NumberToStr(RH_Sensor.getHumidity(), 1);
lcd.drawTextT(70, 70, StrBuffer, hText);//Show RH value
lcd.drawTextT(92, 70, GetPrgStr(45), sText);//Show UM
lcd.drawTextT(30, 90, GetPrgStr(46), sText);//Show Dew Point
NumberToStr(RH_Sensor.getDewPointSlow(), 2);
lcd.drawTextT(70, 90, StrBuffer, hText);//Show Dew Point value
lcd.drawTextT(102, 90, GetPrgStr(47), sText);//Show UM
}
}
/////////////////////////////////////////////////////////
//Description: Returns the text value coresponding to ROM_VAL[Param].Value
//Parameters: Param - index on value
//Returns: string value
/////////////////////////////////////////////////////////
void PutStringValue(byte Param)
{
if(Param > 99)
{
StrBuffer[0] = '\0';
return;
}
if(Param == ROM_BL)
GetPrgStr((ROM_VAL[Param] + 38));
else if((Param == ROM_WD) || (Param == ROM_A1) || (Param == ROM_A2))
GetPrgStr((ROM_VAL[Param] + 30));
else
NumberToStr(ROM_VAL[Param], getLen(MAX_VAL[Param]));
}
/////////////////////////////////////////////////////////
//Description: Gets the length of a number
//Parameters: Value to measure
//Returns: Length
/////////////////////////////////////////////////////////
byte getLen(unsigned int Value)
{
if(Value < 10)
return 0;
else if(Value < 100)
return 1;
else if(Value < 1000)
return 2;
else if(Value < 10000)
return 3;
else
return 4;
}
/////////////////////////////////////////////////////////
//Description: Turns a number in to a string
//Parameters: Value to transform; Maximum value; If value is 123 and maxim is 9999 then Ret will be 0123
//Returns: None
/////////////////////////////////////////////////////////
void NumberToStr(long Value, byte Length)
{
StrBuffer[0] = '\0';
div_t x;//see http://www.nongnu.org/avr-libc/user-manual/group__avr__stdlib.html
for (int z = Length; z >= 0; z--)
{
x = div(Value, 10);
StrBuffer[z] = (char)(x.rem) + '0';
Value = x.quot;
//Divide by 10: (((uint32_t)A * (uint32_t)0xCCCD) >> 16) >> 3
//Value = ((((uint32_t)Value * (uint32_t)0xCCCD) >> 16) >> 3);
//if(Length == 4) Serial.println(x.rem);
}
StrBuffer[Length + 1] = '\0';
}
/////////////////////////////////////////////////////////
//Description: Keys monitor function
//Parameters: None
//Returns: None
/////////////////////////////////////////////////////////
byte GetKey()
{
unsigned int KeyVal = analogRead(A1);
//0Serial.println(KeyVal);
if(KeyVal > 866) return Key_0;
byte btn = Key_0;
delay(1);
if(KeyVal == analogRead(A1))
{
if (KeyVal <= 872 && KeyVal > 852)
btn = Key_M;
else if (KeyVal <= 713 && KeyVal > 693)
btn = Key_S;
else if (KeyVal <= 550 && KeyVal > 530)
btn = Key_U;
else if (KeyVal <= 385 && KeyVal > 365)
btn = Key_D;
else if (KeyVal <= 214 && KeyVal > 196)
btn = Key_L;
else if (KeyVal <= 26)
btn = Key_R;
}
if(btn)
{
while(analogRead(A1) <= 866)
Sound();//delayMicroseconds(100);
}
if(IsInScr)
{
IsInScr = false;
pID = 170;
SetCrtMenu(MainMenu, MainMenuSize,100);
}
return btn;
}
/////////////////////////////////////////////////////////
//Description:Loads from EEPROM settings values and store in to array
//Parameters: None
//Returns: None
/////////////////////////////////////////////////////////
void LoadEEPROM()
{
for(byte idx = 0; idx < ROM_Size; idx++)
ROM_VAL[idx] = eeprom_read_byte((uint8_t*)(idx));
}
/////////////////////////////////////////////////////////
//Description: Resets the values stored in EEPROM to the predefined ones
//Parameters: Profile to reset 0-2
//Returns: None
/////////////////////////////////////////////////////////
void ResetEEPROM()
{
eeprom_write_byte((uint8_t*)ROM_TH, 21); //Time Hour 0-23
eeprom_write_byte((uint8_t*)ROM_TM, 5); //Time Minute 0-59
eeprom_write_byte((uint8_t*)ROM_TS, 0); //Time Second 0-59
eeprom_write_byte((uint8_t*)ROM_TY, 15); //Time Year 0-99 2000-2099
eeprom_write_byte((uint8_t*)ROM_MM, 1); //Time Month 1-12
eeprom_write_byte((uint8_t*)ROM_TD, 8); //Time Day 1-31
eeprom_write_byte((uint8_t*)ROM_WD, 5); //Day of week 1-7
eeprom_write_byte((uint8_t*)ROM_AH, 21); //Alrm Hour 0-24
eeprom_write_byte((uint8_t*)ROM_AM, 06); //Alarm Minute 0-59
eeprom_write_byte((uint8_t*)ROM_A1, 1); //Alarm Start Day 0-6
eeprom_write_byte((uint8_t*)ROM_A2, 5); //Alarm End Day 0-6
eeprom_write_byte((uint8_t*)ROM_HR , 0); //Hot Color RED 0-255
eeprom_write_byte((uint8_t*)ROM_HG, 0); //Hot Color GREEN 0-255
eeprom_write_byte((uint8_t*)ROM_HB, 255); //Hot Color BLUE 0-255
eeprom_write_byte((uint8_t*)ROM_NR, 0); //Normal Color RED 0-255
eeprom_write_byte((uint8_t*)ROM_NG, 255); //Normal Color GREEN 0-255
eeprom_write_byte((uint8_t*)ROM_NB, 0); //Normal Color BLUE 0-255
eeprom_write_byte((uint8_t*)ROM_CR, 255); //Cold Color RED 0-255
eeprom_write_byte((uint8_t*)ROM_CG, 0); //Cold Color GREEN 0-255
eeprom_write_byte((uint8_t*)ROM_CB, 0); //Cold Color BLUE 0-255
eeprom_write_byte((uint8_t*)ROM_HT, 26); //Temperature Alarm High 0-99
eeprom_write_byte((uint8_t*)ROM_LT, 17); //Temperature Alarm Low 0-99
eeprom_write_byte((uint8_t*)ROM_HRR,80); //RH Alarm High 0-99
eeprom_write_byte((uint8_t*)ROM_LR, 40); //RH Alarm Low 0-99
eeprom_write_byte((uint8_t*)ROM_ST, 5); //Screen time 0-59
eeprom_write_byte((uint8_t*)ROM_SE, 128); //Light sensor threshold 0-255
eeprom_write_byte((uint8_t*)ROM_SC, 128); //Screen contrast 0-255
eeprom_write_byte((uint8_t*)ROM_BL, 1); //Screen BackLight 0 or 1
}
