RGB Clock + Micro Weather Station

RGB Clock + Micro Weather Station

Please read Liability Disclaimer and License Agreement CAREFULLY

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

 {youtube}https://www.youtube.com/watch?v=g5lGNkS5TE0{/youtube}

//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
}

Comments powered by CComment

Who’s online

We have 477 guests and no members online