Код: Выделить всё
/*Скетч с использованием UNIX-времени
По материалам www.aqa.ru и благодаря стараниям ZORS
Версия от 06 ноября 2014
Управление 4-мя реле (СО2, термореле воды и радиаторов ЛЭД, вкл/выкл драйверов ЛЭД)
ШИМ ЛЭД по 2-м каналам
Вывод на экран температуры, времени, даты, состояния включенных функций
Коррекция неточных RTC
Работа с 5-ю кнопками: вкл/выкл подсветки дисплея меню дисплея, время на 21:00,
управление СО2, светом.
*/
//Загрузка библиотек
#include <OneWire.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <RTClib.h>
//Установка экрана
LiquidCrystal_I2C lcd(0x27,16,2);
//Подключение выходов
const int RelCO2 = 4; //реле СО2 на выходе 4
const int RelLdd = 7;//выход 7 реле DC для драйверов LDD
const int Led1 = 5; //ШИМ утро-вечер выходе 5
const int Led2 = 6; //ШИМ день на выходе 6
const int TermRel1 = 8;//выход 8 для реле термодатчика воды
const int TermRel2 = 12; //выход 12 для реле радиаторов
//Установки параметров ШИМ
#define PWM_MIN 0 //минимальное значение ШИМ
#define PWM_MAX 255//максимальное значение ШИМ
#define PWM_LOW 180//сниженное значение ШИМ
//Значения минут и часов в секундах
#define mn 60UL
#define hr 3600UL
//Установки времени вкл\выкл ШИМ-сигнала на 5 и 6 выходах (время в секундах UNIX)
const long Led1On = 14*hr;//время включения теплых диодов на 5 выходе (начало восхода)
const long Led1Off = 20*hr;//выключение (начало заката)
const long Led1Dur = 60*mn;//длительность восхода-заката при помощи ШИМ
const long Led2On = 16*hr;//включение основных диодов на 6 выходе
const long Led2Off = 20*hr;//начало выключения основных диодов
const long Led2Dur = 15*mn;//длительность диммирования основных диодов
const long CO2On = Led2On-hr;//включение СО2
const long CO2Off = Led2Off;//выключение СО2
//Установка RTC и их коррекция
RTC_DS1307 RTC;
uint32_t TimeAdjustPeriod = 38*mn; //корректирровка времени на -1 сек за 38 мин
uint32_t TimeCorrection = 1;
unsigned long nextAdjustTime = 0;
//Установки для печати месяцев на экране
const char* months[] = {
"Jan", "Feb", "Mar",
"Apr", "May", "Jun",
"Jul","Aug", "Sep",
"Oct", "Nov", "Dec"};
//Установки для термодатчика
int TSensorPin1 = 10;
int TSensorPin2 = 9;
OneWire ds1(TSensorPin1);// создаем объект температурного датчика
OneWire ds2(TSensorPin2);
float t1 = 27.0;//установка температуры
float tGist1 = 0.5;//установка гистерезиса
//Установки для кнопки СО2 на выходе 2
const int ButtonCO2 = 2;
boolean flagCO2 = false;
int regimCO2 = 1;
//Установки для кнопок "Время 21:00", "Свет" и "Подсветка LCD на аналоговом входе А0
const int ButtonA0 = A0;
int analogA0 = 0;
boolean flagA0 = false;
int regimA0 = 1;
boolean flagA0LCD = false;
int regimA0LCD = 1;//Установки для кнопки "Меню экрана" на выходе 3
const int ButtonMenu = 3;
boolean flagMenu = false;
int regimMenu = 1;
//*********************************************************
void setup () {
Wire.begin();
RTC.begin();
//RTC.adjust(DateTime(__DATE__, __TIME__)); // строка только для первой компиляции!!!
DateTime myTime = RTC.now();
//RTC.adjust(DateTime(myTime.unixtime()+15)); //строка только для первой компиляции!!!
RTC.adjust(DateTime(myTime.unixtime()+3));//для второй компиляции, коррекция при перезагрузках Arduino на 3 сек.
//Первоначальные установки выходов
pinMode (RelCO2, OUTPUT);
pinMode (RelLdd, OUTPUT);
pinMode (TermRel1, OUTPUT);
pinMode (TermRel2, OUTPUT);
digitalWrite (RelCO2, LOW);
digitalWrite (RelLdd, LOW);
digitalWrite (TermRel1, LOW);
digitalWrite (TermRel2, LOW);
analogWrite(Led1, PWM_MIN);
analogWrite(Led2, PWM_MIN);
//Первоначальные надписи на дисплее
lcd.init();
lcd.backlight();
lcd.clear();
lcd.setCursor(5, 0);
lcd.print("iAQUA");//Слава мне, любимому
lcd.setCursor(3, 1);
lcd.print("v.6.11.14");
delay (3000);
lcd.clear();
lcd.noBacklight();
}
//***************************************************
void loop () {
//Работа часов с коррекцией
DateTime myTime = RTC.now();
uint32_t UTime = myTime.unixtime();
if (UTime > nextAdjustTime){
nextAdjustTime = UTime+TimeAdjustPeriod;
RTC.adjust(DateTime(UTime-TimeCorrection));
}
UTime %=86400;
analogA0=analogRead(A0);
if (analogA0>685 && analogA0<710)//коррекция времени нажатием кнопки (21:00)
{
DateTime myTime = RTC.now();
uint32_t UTime = myTime.unixtime();
UTime = 75600 + (UTime-UTime%86400);
RTC.adjust(DateTime(UTime));
}
if (analogA0>810 && analogA0<840 && !flagA0)//ручное и автоматическое управление светом
{
regimA0++;
flagA0 = true;
if (regimA0>3)
{
regimA0=1;
}
}
else if (analogA0<810 && flagA0)
{
flagA0=false;
}
if (regimA0==1)
{
if ((UTime>=(Led1On-1*mn)) && (UTime<(Led1Off+Led1Dur+1*mn)))//время вкл/выкл драйверов в авто-режиме
{
digitalWrite(RelLdd, HIGH);
long pwm;
if ((UTime<Led1On) || (UTime>=Led1Off + Led1Dur))
{
pwm=PWM_MIN;
}
else if((UTime>=Led1On) && (UTime<(Led1On + Led1Dur)))
{
pwm = ((UTime - Led1On)*(PWM_MAX-PWM_MIN)) / Led1Dur;
}
else if((UTime>=Led1Off) && (UTime<Led1Off + Led1Dur))
{
pwm=((Led1Off + Led1Dur - UTime)*(PWM_MAX-PWM_MIN))/Led1Dur;
}
else
{
pwm=PWM_MAX;
}
analogWrite(Led1, pwm);
if ((UTime<Led2On) || (UTime>=Led2Off + Led2Dur))
{
pwm=PWM_MIN;
}
else if((UTime>=Led2On) && (UTime<(Led2On + Led2Dur)))
{
pwm = ((UTime - Led2On)*(PWM_LOW-PWM_MIN)) / Led2Dur;
}
else if((UTime>=Led2Off) && (UTime<Led2Off + Led2Dur))
{
pwm=((Led2Off + Led2Dur - UTime)*(PWM_LOW-PWM_MIN))/Led2Dur;
}
else
{
pwm=PWM_LOW;
}
analogWrite(Led2, pwm);
}
else
{
digitalWrite(RelLdd, LOW);
}
}
if (regimA0 ==2)//выключение всех диодов в ручной режиме
{
digitalWrite(RelLdd, LOW);
}
if (regimA0 ==3)//включение теплых диодов в ручном режиме
{
digitalWrite(RelLdd, HIGH);
analogWrite(Led1, PWM_LOW);
analogWrite(Led2, PWM_MIN);
}
if (analogA0>580 && analogA0<610 && !flagA0LCD)//управление подсветкой экрана
{
regimA0LCD++;
flagA0LCD = true;
if (regimA0LCD > 2)
{
regimA0LCD = 1;
}
}
else if(analogA0 < 580 && flagA0LCD)
{
flagA0LCD = false;
}
if (regimA0LCD==1)
{
lcd.noBacklight();
}
if (regimA0LCD !=1)
{
lcd.backlight();
}
//Управление СО2
if (digitalRead(ButtonCO2)==HIGH && !flagCO2)
{
regimCO2++;
flagCO2=true;
if(regimCO2>3)
{
regimCO2=1;
}
}
else if (digitalRead(ButtonCO2)==LOW && flagCO2)
{
flagCO2=false;
}
if(regimCO2==1)
{
if (UTime>=CO2On && UTime<CO2Off)
{
digitalWrite (RelCO2, HIGH);
}
else
{
digitalWrite (RelCO2, LOW);
}
}
else if(regimCO2==2)
{
digitalWrite(RelCO2, HIGH);
}
else if(regimCO2==3)
{
digitalWrite(RelCO2, LOW);
}
//управление термореле воды в период 9:00-22:00
float temp1 = getTemp1();
//lcd.setCursor(9,1);
if((temp1 > (t1 + tGist1)) && (UTime >= 9*hr) && (UTime < 22*hr))
{
digitalWrite(TermRel1,HIGH);
}
else if ((temp1 < (t1 - tGist1)) || UTime <9*hr || UTime >= 22*hr)
{
digitalWrite(TermRel1,LOW);
}
float temp2 = getTemp2();//управление термореле радиаторов
if (UTime>=Led1On && UTime<(Led1Off+Led1Dur))
{
digitalWrite(TermRel2, HIGH);
}
else if (UTime<Led1On || UTime>=Led1Off)
{
digitalWrite(TermRel2, LOW);
}
//Управление кнопкой "Меню экрана"
if (digitalRead(ButtonMenu)==HIGH && !flagMenu)
{
lcd.clear();
flagMenu = true;
regimMenu ++;
if (regimMenu>3)
{
regimMenu=1;
}
}
else if (digitalRead(ButtonMenu)==LOW && flagMenu)
{
flagMenu=false;
}
if (regimMenu==1) //меню "1" вывод на экран времени и календаря
{
lcd.setCursor(4, 0);
if (myTime.hour() < 10) lcd.print ("0");
lcd.print(myTime.hour());
lcd.print(':');
if (myTime.minute() < 10) lcd.print ("0");
lcd.print(myTime.minute());
lcd.print(':');
if (myTime.second() < 10) lcd.print ("0");
lcd.print(myTime.second());
lcd.setCursor(0, 1);
if (myTime.day() < 10) lcd.print ("0");
lcd.print(myTime.day());
lcd.setCursor(3, 1);
lcd.print (months[myTime.month()-1]);
lcd.setCursor(7,1);
lcd.print(myTime.year());
lcd.setCursor(13,1);
int dow = (myTime.dayOfWeek());
switch (dow){
case 0:
lcd.print("Sun");
break;
case 1:
lcd.print("Mon");
break;
case 2:
lcd.print("Tue");
break;
case 3:
lcd.print("Wed");
break;
case 4:
lcd.print("Thu");
break;
case 5:
lcd.print("Fri");
break;
case 6:
lcd.print("Sat");
break;
}
}
else if (regimMenu==2)//меню "2" вывод на экран CO2, T, режима работы диодов
{
lcd.setCursor(0,0);
lcd.print("CO2");
lcd.setCursor(4,0);
if (digitalRead(RelCO2)==HIGH)
{
lcd.print("On ");
}
else
{
lcd.print("Off");
}
lcd.setCursor(8,0);
if (regimCO2 == 1)
{
lcd.print("Auto");
}
else if (regimCO2 !=1)
{
lcd.print("Hand");
}
lcd.setCursor(13,1);
if(UTime<Led1On || UTime >=(Led1Off+Led1Dur))
{
lcd.print("Ngt");
}
else if (UTime>=(Led1On) && UTime < Led2On)
{
lcd.print("Mrg");
}
else if(UTime >= Led2On && UTime < Led2Off)
{
lcd.print("Day");
}
else if (UTime >= Led2Off && UTime < (Led1Off+Led1Dur))
{
lcd.print("Evg");
}
lcd.setCursor(0,1);
if (digitalRead(RelLdd)==HIGH && regimA0 ==1)
{
lcd.print("LED On Auto");
}
else if (digitalRead(RelLdd) == LOW && regimA0 ==1)
{
lcd.print("LED Off Auto");
}
else if (digitalRead(RelLdd) == HIGH && regimA0 ==3)
{
lcd.print("LED On Hand");
}
else
{
lcd.print("LED Off Hand");
}
}
else if(regimMenu==3)// меню "3" вывод на экран температуры
{
lcd.setCursor(0,0);
lcd.print("Water t=");
lcd.print(temp1,1);
lcd.setCursor(13,0);
if (digitalRead(TermRel1)==HIGH)
{
lcd.print("*");
}
else
{
lcd.print(" ");
}
lcd.setCursor(0,1);
lcd.print("Air t=");
lcd.print(temp2,1);
lcd.setCursor(13,1);
}
}
//*****************************************************
//Функции чтения с датчиков температуры
float getTemp1(){
byte data[12];
byte addr[8];
if ( !ds1.search(addr)) {
//no more sensors on chain, reset search
ds1.reset_search();
return -1001;
}
if ( OneWire::crc8( addr, 7) != addr[7]) {
return -1002;
}
if ( addr[0] != 0x10 && addr[0] != 0x28) {
return -1003;
}
ds1.reset();
ds1.select(addr);
ds1.write(0x44,1);
byte present = ds1.reset();
ds1.select(addr);
ds1.write(0xBE);
for (int i = 0; i < 9; i++) {
data[i] = ds1.read();
}
ds1.reset_search();
byte MSB = data[1];
byte LSB = data[0];
float TRead = ((MSB<<8) | LSB);
float Temperature = TRead / 16;
return Temperature;
}
float getTemp2(){
byte data[12];
byte addr[8];
if ( !ds2.search(addr)) {
//no more sensors on chain, reset search
ds2.reset_search();
return -1001;
}
if ( OneWire::crc8( addr, 7) != addr[7]) {
return -1002;
}
if ( addr[0] != 0x10 && addr[0] != 0x28) {
return -1003;
}
ds2.reset();
ds2.select(addr);
ds2.write(0x44,1);
byte present = ds2.reset();
ds2.select(addr);
ds2.write(0xBE);
for (int i = 0; i < 9; i++) {
data[i] = ds2.read();
}
ds2.reset_search();
byte MSB = data[1];
byte LSB = data[0];
float TRead = ((MSB<<8) | LSB);
float Temperature = TRead / 16;
return Temperature;
}