Ну тогда наверно все таки делать блокировку клавиш. Это проще по исполнению, чем все экранами обвешивать. На остальное я так понял не влияет, только IR колбасит.
Вкорячил его назад, все как и было, нажато - возвращает, ненажато - тишина. :)
Теперь работа в таком виде с меню и параметрами.
Хочу сам попробовать победить и вот чтовыходит, меню:
void menu(){
tft.fillScreen(ST7735_BLUE); // Clear screen
tft.setTextSize(1);
tft.setTextColor(ST7735_WHITE, ST7735_BLUE);
char menuTxt[5][17] = {"set Timer 1 >>>>", "set Timer 2 >>>>","set Timer Lcd >>","set MoonLight >>","set Timer Co2 >>"}; //Массив с наименованиями для экрана
byte pos=0;
while(1) { //Бесконечный цикл
tft.setCursor(5,55);
tft.print(pos+1); //Печатаем номер.
tft.print(". ");
tft.print(menuTxt[pos]); //Печатаем название
if (val==KEY3 && pos>0) {pos--;} //Уменьшить увеличить + блокировка кнопки
if (val==KEY4 && pos<4) {pos++;}
winMe=pos; //Переменная номера таймера
/* Здесь переходим на подменю. Если останется как сейчас, то достаточно. Сейчас можно перейти на разные подменю.
if (KEY==5) setOnOff(); */
if (val==KEY5 && pos==0) setOnOff();
if (val==KEY5 && pos==1) setOnOff();
if (val==KEY5 && pos==2) setOnOff();
if (val==KEY5 && pos==3) setOnOff();
if (val==KEY5 && pos==4) setOnOff();
if (val==KEY1){ //Выход из меню с проверкой и установкой блокировки от возврата
tft.fillScreen(ST7735_BLACK); // Clear screen
break; }
}
}
(снова tft имхо тестово) .В таком виде по нажатию KEY1 я попадаю в меню и ТУТ-же из него вылетаю, мгновенно. Хочу спросить строка while(1) { //Бесконечный цикл это не нажатие-ли кнопки 1 из нашего старого кода работы с кнопками?
И фукнкция настройки параметров в меню:
void setOnOff(){
byte pos=0;
setHorClockOn= EEPROM.read(winMe*4+1); //Считываем записанные значения таймеров
setMinClockOn= EEPROM.read(winMe*4+2); //Адрес определяется как номер таймера*4 + четыре ячейки
setHorClockOff= EEPROM.read(winMe*4+3);
setMinClockOff= EEPROM.read(winMe*4+4);
// lcd.blink();
tft.fillScreen(ST7735_RED); //Clear screen
while(val!=KEY1) { //Крутим цикл пока не будет Setup
// delay(200); //Если убрать, не работает подсветка уст.позиции
tft.setCursor(45,40);
tft.setTextColor(ST7735_YELLOW,ST7735_RED);
tft.setTextSize(1);
Правильно-ли описал здесь работу while(val!=KEY1) { //Крутим цикл пока не будет Setup
Добрый день. По первому коду, вас выбрасывает 22 строка. Я когда писал пример, там была блокировка этой клавиши на какое-то время. Ее надо вводить при входе и также при возврате из подменю. В подменю возврат из while вроде правильный.
Только вторая строка первого кода должна быть в loop-е и setTimeOn (вроде правильно функцию назвал) и применятся в момент перехода в основной экран меню, иначе вы там и будете висеть, т.к. условия выхода никогда не достигнете.
О, первая прическа, попробуйте если все работает, будем дальше чесать. Я свои варианты по currentMillis пока закомментил в коде, смотрите сами, что использовать. Тайминги опросов датчиков пока не трогал.
#include <EEPROM.h>
#include <Wire.h> //Подключаем библиотеку для использования однопроводного интерфейса
#include <LiquidCrystal_I2C.h> //Подключаем библиотеку для использования I2C интерфейса
#include <OneWire.h> //Подключаем библиотеку для температурного датчика DS18B20
#include <BMP085.h> //Подключаем библиотеку для маленького барометра
#include <IRremote.h> //Подключаем библиотеку для IR сенсора
LiquidCrystal_I2C lcd(0x27,20,4); //Устанавливаем LCD-адрес 0x27 для отображения 20 символов и 4 линии
byte currentLight=0; //Переменная включения подсветки LCD
//=====BT*
char inByte; //Ввходящие данные BT (Bluetooth модуля)
//=====IR_Sensor*
#define recvPin 3 //Вход IR-приемника и кнопки пульта
uint32_t val;
IRrecv irrecv(recvPin);
decode_results results;
//=====IR_Dimmer*
byte angData1, angData2=0; //Переменная выходов диммирования (из двух половинок :))
byte maxDimm=255; //Переменная определяет МАКСИМАЛЬНОЕ значение диммирования
byte upR2=210; //Переменная включения 2 свето-релейного канала
byte upR3=240; //Переменная включения 3 свето-релейного канала
byte downR2=205; //Переменная выключения 2 свето-релейного канала
byte downR3=235; //Переменная выключения 3 свето-релейного канала
int pManDimmUp=800; //Период увеличения яркости
int pManDimmDown=500; //Период уменьшения яркости
byte flagDimm=0; //Флаг для обработки "НЕОБРАТИМОГО" выключения Power_Off
unsigned long tDimm=millis(); //Переменная задержки auto_dimmer
//=====Termo_Relay*
const int RelayChn1=4; //Используем цифровой ПОРТ 4 для ПЕРВОГО канала термо-реле (вода)
const int RelayChn2=A1; //Используем цифровой ПОРТ A1 для ВТОРОГО канала термо-реле (радиатор)
//=====Led_Relay*
#define OUT1 7 //Используем цифровой ПОРТ 7 для 1 свето-релейного канала Dimm
#define OUT2 8 //Используем цифровой ПОРТ 8 для 2 свето-релейного канала
#define OUT3 9 //Используем цифровой ПОРТ 9 для 3 свето-релейного канала
//=====Other_Relay*
#define OUT0 10 //Используем цифровой ПОРТ 10 для ATX (включение ATX (зелёный + черный))
//#define OUT6 31 //Используем цифровой ПОРТ 11 для CO2
//#define OUT7 32 //Используем цифровой ПОРТ 12 для другое
//=====Dimmer_Out*
#define OUT4 5 //Используем цифровой ПОРТ 5 для 1/2 SunSet канала (dimmer)
#define OUT5 6 //Используем цифровой ПОРТ 6 для 1/2 SunSet канала (dimmer)
//=====VoltMeter*
int voltInput=A7; //Используем аналоговый вход A7 для измерения напряжения
float vout=0.0;
float vin=0.0;
float R1=21700.0; //Resistance of R1 (22K) - see text!
float R2=12770.0; //Resistance of R2 (12K) - see text!
int valueVo=0;
//=====Pressure*
BMP085 dps=BMP085(); // Digital Pressure Sensor
long Pressure=0;
unsigned long timeDps=0;
//=====Termo_Sensor*
int tempPin=2; //Определяем порт шины OneWire (IC) для температурного датчика DS18B20
OneWire ds(tempPin); //Создаем объект для работы с термометром
byte flagDallas=0; //Флаг для обработки показаний с датчиков Dallas
byte data[12];
byte addr1[8] = {0x28, 0xC5, 0x3B, 0x5C, 0x06, 0x00, 0x00, 0x85}; //адрес датчика DS18B20_Вода в аквариуме
byte addr2[8] = {0x28, 0x86, 0x48, 0xEA, 0x05, 0x00, 0x00, 0xF6}; //адрес датчика DS18B20_Радиатор (2-ой канал, центр)
byte addr3[8] = {0x28, 0xF2, 0x29, 0xEB, 0x05, 0x00, 0x00, 0xE1}; //адрес датчика DS18B20_Блок реле
unsigned int raw; //Если экранированный кабель, можно подключать до 32 термо-датчиков DS18B20
//float temp1, temp2, temp3; //Температура аквариума \ радиаторов Led \ блока реле
float temp[3];
//float t1=25.0; //Переменная предела срабатывания реле RelayChn1
//float t2=47.0; //Переменная предела срабатывания реле RelayChn2
//float t3=55.0; //Переменная предела срабатывания реле RelayChn3
float t[]={25.0, 47.0, 55.0};
float tGistrsis=1.0; //Гистерезис температур (по 0,25 в каждую сторону)
//=====Rtc_Clock*
#define DS3231_I2C_ADDRESS 104
byte seconds, minutes, hours, day, date, month, year;
//=====Timer*
// long lghtIntv=60000; //Интервал для проверки вкл./выкл. освещения аквариума, 1 минута
byte lcdStat=0; //Флаг подсветки Lcd если включена, то в 1
//byte lghtStat1=0; //Флаг освещения, если включена, то в 1 в первом таймере
//byte lghtStat2=0; //Флаг освещения, если включена, то в 1 во втором таймере
byte lghtStat[2];
byte co2Stat=0; //Флаг Co2, если включена, то в 1
byte isLcdt=0; //Флаг для обработки необходимости включить подсветку Lcd
//byte isLght1=0; //Флаг для обработки необходимости включить реле освещения в первом таймере
//byte isLght2=0; //Флаг для обработки необходимости включить реле освещения во втором таймере
byte isLght[2];
byte isCo2t=0; //Флаг для обработки необходимости включить реле Co2
byte isNight=0; //Если включаем на ночь, т.е. начальное время больше конечного
//=====Menu*
byte setHorClockOn; //Часы включения
byte setMinClockOn; //Минуты включения
byte setHorClockOff; //Часы вЫключения
byte setMinClockOff; //Минуты вЫключения
//byte setTempt1; //Максимальная температура t1 (вода в аквариуме)
//byte setTempt2; //Максимальная температура t2 (радиатор Led)
//byte setTempt3; //Максимальная температура t3 (блок коммутации, реле)
byte setTempt[3];
byte winMe; //Номер экрана меню
//=====Delays*
//unsigned long tmIntv=1000; //Интервал для обновления времени на экране каждую секунду
//unsigned long razdIntv=2000; //Интервал для обновления ":" на экране каждые 2 секунды
unsigned long prvMlsTm=0; //Предыдущее показание миллисекунд для обновления показания часов
unsigned long prvMlsRazd=0; //Предыдущее показание миллисекунд для обновления ":"
//unsigned long prvMlsLght=0; //Предыдущее показание проверки временного интервала
unsigned long prvMlsVo=0; //Предыдущее показание обновления показания вольтметра
//unsigned long voIntv=5000; //Интервал для обновления напряжения
unsigned long prvMlsOut=0; //Предыдущее показание обновления показания OUT
//unsigned long outIntv=1000; //Интервал для обновления OUT
unsigned long prvMlsBar=0; //Предыдущее показание обновления показания барометра
//unsigned long barIntv=10000; //Интервал для обновления барометра
unsigned long prvMlsTemp=0; //Предыдущее показание обновления температур
//unsigned long tempIntv=5000; //Интервал для обновления температур
unsigned long prvMlsTimer=0; //Предыдущее показание обновления таймера
//unsigned long timerIntv=10000; //Интервал для обновления таймера
unsigned long tzad=millis(); //Переменная задержки (пока для ds18b20, ds.write) и непользую....
// Все ваши переменные, которые мог, перевел в массив zadTime[]. Которые использовались в коде заменил.
//Те которые для дальнейшего развития, только предусмотрел значения в массиве.
unsigned long zadM[4]; //Массив для задержек меню
const long zadTime[] = {100,750,1000,2000,3000,5000,10000,60000};
const char menuTxt[5][17] = {"set Timer 1 >>>>", "set Timer 2 >>>>","set Timer Lcd >>","set MoonLight >>","set Timer Co2 >>"}; //Массив с наименованиями для экрана
//=====Byte_Symbol*
byte equ[8] = //Символ "=" но КОРОТКИЙ :)
{
B00000,
B00000,
B01110,
B00000,
B01110,
B00000,
B00000,
};
//Здесь чуть поизвращался
void relayHigh()
{
digitalWrite(OUT0,HIGH); //Определяем инверсный выход в HIGH реле ATX
digitalWrite(OUT1,HIGH); //Определяем инверсный выход в HIGH реле 1 канала Led
digitalWrite(OUT2,HIGH); //Определяем инверсный выход в HIGH реле 2 канала Led
digitalWrite(OUT3,HIGH); //Определяем инверсный выход в HIGH реле 3 канала Led
}
void setup() {
Wire.begin();
// Serial.begin(9600);
irrecv.enableIRIn(); //Включаем IR-сенсор
dps.init(MODE_STANDARD, 25000, true); //250 meters, true = using meter units
pinMode(voltInput,INPUT); //Определяем вход вольтметра
// pinMode(RelayChn1,OUTPUT); //Определяем выход 1-термореле охлаждения воды аквариума
// pinMode(RelayChn2,OUTPUT); //Определяем выход 2-термореле охлаждения радиаторов Led
// digitalWrite(RelayChn1,HIGH); //Определяем инверсный выход в HIGH охлаждения воды аквариума
// digitalWrite(RelayChn2,HIGH); //Определяем инверсный выход в HIGH охлаждения радиаторов Led
pinMode(OUT0,OUTPUT); //Определяем инверсный выход реле ATX
pinMode(OUT1,OUTPUT); //Определяем инверсные выходы реле 1 канала Led
pinMode(OUT2,OUTPUT); //Определяем инверсные выходы реле 2 канала Led
pinMode(OUT3,OUTPUT); //Определяем инверсные выходы реле 3 канала Led
// pinMode(OUT6,OUTPUT);
// pinMode(OUT7,OUTPUT);
//digitalWrite(OUT0,HIGH); //Определяем инверсный выход в HIGH реле ATX
//digitalWrite(OUT1,HIGH); //Определяем инверсный выход в HIGH реле 1 канала Led
//digitalWrite(OUT2,HIGH); //Определяем инверсный выход в HIGH реле 2 канала Led
//digitalWrite(OUT3,HIGH); //Определяем инверсный выход в HIGH реле 3 канала Led
relayHigh();
// digitalWrite(OUT6,HIGH);
// digitalWrite(OUT7,HIGH);
analogWrite(OUT4,angData2); //Инициация выхода 1/2 диммера
analogWrite(OUT5,angData1); //Инициация выхода 1/2 диммера
lcd.init(); //Инициализируем дисплейчик
lcd.setBacklight(1);
lcd.clear(); //Очищаем на всякий случай дисплейчик
lcd.setCursor(2,0);
lcd.print("Aqua Controller"); //Выводим версию и прочее
lcd.setCursor(2,1);
lcd.print(" v1.1 ");
lcd.setCursor(1,3);
lcd.print("_0802_menu_NoEp_Dim_");
delay(zadTime[3]);
lcd.clear(); //Очистка дисплея и void (printTime, printDin, printStat)
}
//========== Обработка IR-сенсора, определение кнопок
byte keyIr(){
if (irrecv.decode(&results)) { //Если пришел пакет и этот пакет не FF сохраняем правильный пакет в переменную
// if (results.value!=0xFFFFFFFF) { //Если пришел FF, соответственно пропускаем.
val=results.value; //} //Сверяем значение из переменной val.. если пришла команда повтора (пакет с FF)
irrecv.resume(); } //В переменной останется прошлый, правильный, пакет и код выполнится повторно.
// Serial.println(val,HEX);
// Serial.println(" ");
if (val==0x41BEB04F) return 5; //right KEY5
if (val==0x41BE609F) return 4; //down KEY4
if (val==0x41BED02F) return 3; //up KEY3
if (val==0x41BE40BF) return 2; //left KEY2
if (val==0x41BEC03F) return 1; //setup KEY1
if (val==0x41BEA05F) return 10; //stop KEY10
if (val==0x41BE20DF) return 9; //slide KEY9
if (val==0x41BE10EF) return 8; //vol_up KEY8
if (val==0x41BE708F) return 7; //vol_down KEY9
if (val==0x41BEF00F) return 6; //exit POWER_KEY
else return 0;
}
//========== Обработка IR-кнопок
void keyI()
{
byte KEY=keyIr();
//========== Обработка Входа в Меню
if (KEY==1)
{ //***ВХОД В МЕНЮ и проверка блокировки от возврата. Принимаем код клавиши
val=0;
menu();
} //Если setup идем в меню
//========== Отключение LCD с кнопки
if (KEY==9)
{ val=0;
lcd.setBacklight(currentLight);
currentLight = !currentLight;
}
//========== Увеличение яркости (удержание кнопки)
if (KEY==5)
{ val=0;
//Данная конструкция неработоспособна. Контролирует только второй параметр.
//if (angData1, angData2<255) angData1++, angData2++; //Начало увеличения диммирования
if (angData1<255) angData1++, angData2=angData1;
analogWrite(OUT4, angData2);
analogWrite(OUT5, angData1);
//if (angData1, angData2>0) { //Включаем реле ATX и диммера на первом шаге (начало диммирования)
if (angData1>0)
{
digitalWrite(OUT0,LOW); //Включаем реле ATX
digitalWrite(OUT1,LOW);
}
}
//========== Уменьшение яркости (удержание кнопки)
if (KEY==2)
{ val=0;
//if (angData1, angData2!=0) angData1--, angData2--; //Начало снижения диммирования
if (angData1!=0) angData1--, angData2=angData1;
analogWrite(OUT4, angData2);
analogWrite(OUT5, angData1);
//if (angData1, angData2==0) { //Выключаем реле диммера (по окончании диммирования)
if (angData1==0)
{
relayHigh();
//digitalWrite(OUT1,HIGH);
//digitalWrite(OUT2,HIGH);
//digitalWrite(OUT3,HIGH);
//digitalWrite(OUT0,HIGH);
} //Выключаем реле ATX
}
//========== Обработка "одного" нажатия
if (KEY==8 & flagDimm==0)
{ //Если нажата кнопка УВЕЛИЧЕНИЯ диммирования
if (tDimm<millis())
{ //и не дана команда на полное выключение
pManDimmUp; dimmUp();
} //Интервал УВЕЛИЧЕНИЯ диммирования
}
if (KEY==7 & flagDimm==0)
{ //Здесь аналогично увеличению яркости
if (tDimm<millis())
{
pManDimmDown; dimmDown();
} //Интервал Снижения диммирования
}
if (KEY==6 & angData2!=0)
{ //Power_Off. Если диммер включен, устанавливаем флаг
flagDimm=1;
}
if (flagDimm==1)
{ //Если флаг установлен, продолжаем уменьшение яркости
if (angData2==0)
{ //Яркость на 0, флаг сбросили.
flagDimm=0;
relayHigh();
//digitalWrite(OUT1,HIGH);
//digitalWrite(OUT2,HIGH);
//digitalWrite(OUT3,HIGH);
//digitalWrite(OUT0,HIGH);
}
if (tDimm<millis())
{ //Последовательно уменьшаем яркость, кнопки заблокированы
pManDimmDown=300; dimmDown();
} //Интервал СНИЖЕНИЯ диммирования (по Power_Off)
val=0;
}
//========== Обработка ATX, НЕдиммируемых реле
// if (KEY == 6) digitalWrite(OUT0, !digitalRead(OUT0)); //Power_KEY, ON/OFF_KEY, включение ATX
// else if (KEY == 6) digitalWrite(OUT0, !digitalRead(OUT0));
if (KEY==3)
{
val=0; if (!digitalRead(OUT1)!=0 && angData2 >=1) digitalWrite(OUT2,!digitalRead(OUT2));
}
if (KEY==3)
{
val=0; if (!digitalRead(OUT1)!=0 && angData2!=0) digitalWrite(OUT2,digitalRead(OUT2));
}
if (KEY==4)
{
val=0; if (digitalRead(OUT1)==0 && angData2>=1) digitalWrite(OUT3,!digitalRead(OUT3));
}
if (KEY==4)
{
val=0; if (digitalRead(OUT1)==0 && angData2!=0) digitalWrite(OUT3,digitalRead(OUT3));
}
}
//========== Увеличение яркости (auto)
void dimmUp()
{
if (angData2<maxDimm)
{ //Ограничение верхнего значения диммирования, (0-255)
angData2++; //Начало подъёма диммирования
//angData1++;
angData1=angData2;
analogWrite(OUT4,angData2); //Пишем в порт
analogWrite(OUT5,angData1);
if (angData2>0)
{ //Включаем реле ATX и диммера на первом шаге (начало диммирования)
digitalWrite(OUT0,LOW);
digitalWrite(OUT1,LOW);
}
if (angData2==upR2)
{ //Включаем Второе реле при upR2
digitalWrite(OUT2,LOW);
}
if (angData2==upR3)
{ //Включаем Третье реле при upR3
digitalWrite(OUT3,LOW);
}
tDimm=millis()+pManDimmUp;
} //Устанавливаем время следующего шага
if (angData2==maxDimm) {val=0;}
}
//========== Уменьшение яркости (auto)
void dimmDown() {
if (angData2>0) {
angData2--; //Начало снижения диммирования
//angData1--;
angData1=angData2;
analogWrite(OUT4,angData2);
analogWrite(OUT5,angData1);
if (angData2==downR3){ //Выключаем Третье реле при downR3
digitalWrite(OUT3,HIGH); }
if (angData2==downR2){ //Выключаем Втором реле при downR2
digitalWrite(OUT2,HIGH); }
if (angData2 == 0){ //Выключаем реле диммера (по окончании диммирования)
relayHigh();
//digitalWrite(OUT0,HIGH);
//digitalWrite(OUT1,HIGH);
//digitalWrite(OUT2,HIGH);
//digitalWrite(OUT3,HIGH); }
tDimm=millis()+pManDimmDown; } //Устанавливаем время следующего шага
if (angData2==0){val=0;}
}
//=========== Обработка Меню, выбор экрана
void menu(){
lcd.clear(); //Очищаем на всякий случай дисплейчик
// Переместил в блок начальной инициализации, здесь это лишнее.
//char menuTxt[5][17] = {"set Timer 1 >>>>", "set Timer 2 >>>>","set Timer Lcd >>","set MoonLight >>","set Timer Co2 >>"}; //Массив с наименованиями для экрана
byte pos=0;
while(1) { //Бесконечный цикл
byte KEY=keyIr();
val=0;
lcd.setCursor(0,1);
lcd.print(pos+1); //Печатаем номер.
lcd.print(". ");
lcd.print(menuTxt[pos]); //Печатаем название
if (KEY==3 && pos>0) {pos--;} //Уменьшить увеличить + блокировка кнопки
if (KEY==4 && pos<4) {pos++;}
winMe=pos; //Переменная номера таймера
/*
Здесь переходим на подменю. Если останется как сейчас, то достаточно. Сейчас можно перейти на разные подменю.
if (KEY == 5) setOnOff();
*/
if (KEY == 5) setOnOff();
//Подменю вы неиспользуете, поэтому выбросил
//if (KEY==5 && pos==0) setOnOff();
//if (KEY==5 && pos==1) setOnOff();
//if (KEY==5 && pos==2) setOnOff();
//if (KEY==5 && pos==3) setOnOff();
//if (KEY==5 && pos==4) setOnOff();
if (KEY==1) { //Выход из меню с проверкой и установкой блокировки от возврата
lcd.clear(); //Очищаем на всякий случай дисплейчик
break; }
}
}
//=========== Обработка Меню, параметры и настройка
void setOnOff(){
byte pos=0;
setHorClockOn= EEPROM.read(winMe*4+1); //Считываем записанные значения таймеров
setMinClockOn= EEPROM.read(winMe*4+2); //Адрес определяется как номер таймера*4 + четыре ячейки
setHorClockOff= EEPROM.read(winMe*4+3);
setMinClockOff= EEPROM.read(winMe*4+4);
lcd.clear(); //Очищаем на всякий случай дисплейчик
lcd.blink();
while(keyIr()!=1) { //Крутим цикл пока не будет Setup
byte KEY=keyIr(); //Читаем состояние кнопок
val=0;
// delay(200); //Если убрать, не работает подсветка уст.позиции
lcd.setCursor(7,0);
lcd.print("-On- -Off-");
lcd.setCursor(0,3);
lcd.print("=== push to save ===");
lcd.setCursor(1, 1);
lcd.print(winMe+1,DEC); //Печатаем номер программы таймера
lcd.print("|");
lcd.print(pos/3,DEC); //Печатаем позицию настройки параметра (замена blink)
lcd.print("->");
lcd.setCursor(7,1); //Выводим инфу о часах и минутах
if (setHorClockOn<10) lcd.print("0");
lcd.print(setHorClockOn,DEC);
lcd.print(":");
if (setMinClockOn<10) lcd.print("0");
lcd.print(setMinClockOn,DEC);
lcd.print(" ");
if (setHorClockOff<10) lcd.print("0");
lcd.print(setHorClockOff,DEC);
lcd.print(":");
if (setMinClockOff<10) lcd.print("0");
lcd.print(setMinClockOff,DEC);
// Здесь подправил, вроде должно правильно мигать блинком
//lcd.setCursor(pos, 0); //Устанавливаем курсор согласно позиции
lcd.setCursor(pos, 1); //Это если время устанавливаемое в первой строке (строки считаем 0-1-2-3)
if (pos<3) pos=3;
if (KEY==5 && pos<11) pos += 3; //Крутим позицию право-лево
else if (KEY==2 && pos>3) pos -= 3;
else if (pos==3 && KEY==3) setHorClockOn++; //Крутим значения
else if (pos==3 && KEY==4) setHorClockOn--;
else if (pos==6 && KEY==3) setMinClockOn++;
else if (pos==6 && KEY==4) setMinClockOn--;
else if (pos==9 && KEY==3) setHorClockOff++;
else if (pos==9 && KEY==4) setHorClockOff--;
else if (pos==12 && KEY==3) setMinClockOff++;
else if (pos==12 && KEY==4) setMinClockOff--;
if (setHorClockOn>23) setHorClockOn=0; //Ограничиваем значения
else if (setMinClockOn>59) setMinClockOn=0;
else if (setHorClockOff>23) setHorClockOff=0;
else if (setMinClockOff>59) setMinClockOff=0;
} //Конец цикла
lcd.noBlink();
lcd.clear(); //Очищаем на всякий случай дисплейчик
EEPROM.write(winMe*4+1, setHorClockOn); //Записываем НОВЫЕ значения
EEPROM.write(winMe*4+2, setMinClockOn);
EEPROM.write(winMe*4+3, setHorClockOff);
EEPROM.write(winMe*4+4, setMinClockOff);
lcd.setCursor(4,2);
lcd.print("== Saved ==");
delay(zadTime[3]);
}
//========== Считывание напряжения
void voltM() {
valueVo=analogRead(voltInput); //Read the value at analog input
vout=(valueVo*5.0)/1024.0; //See text
vin=vout/(R2/(R1+R2));
if (vin<0.09) {
vin=0.0; } //Statement to quash undesired reading
}
//========== Считывание Давления
void bar() {
if (((millis()-timeDps)/1000.0)>=1.0) //Конструкция жуткая и жрущая море ресурсов при расчете вещественных чисел.
//if (timeDps<millis()) //Я бы закомментил ваши и попробовал так
{
dps.calcTrueTemperature();
timeDps=millis();
// timeDps=millis()+1000;
}
dps.getPressure(&Pressure);
}
//=========== Считывание температур
void dallas(){
ds.reset();
ds.write(0xCC); //Команда инициации
ds.write(0x44); //Start conversion, with parasite power on at the end
tzad=millis()+750; flagDallas=1; }
float DS18B20(byte *adres){ //flagDallas=0;
ds.reset();
ds.select(adres);
ds.write(0xBE); //Read Scratchpad
for (byte i=0; i<9; i++) data[i]=ds.read(); //We need 9 bytes
int raw=(data[1]<<8) | data[0]; // Переводим в температуру
float celsius=(float)raw/16.0;
return celsius;
}
//=========== Обработка Термо-Реле
void tempRelay(){
temp[0] = DS18B20(addr1);
temp[1] = DS18B20(addr2);
temp[2] = DS18B20(addr3);
if (temp[0]>t[0]-tGistrsis/2){
digitalWrite(RelayChn1,LOW); //Термо-реле 1-включается
// lcd.setCursor(8, 2);
// lcd.print("*");
}
else if (temp[0]<t[0]+tGistrsis/2){
digitalWrite(RelayChn1,HIGH); //Термо-реле 1-выключается
// lcd.setCursor(8, 2);
// lcd.print("-");
}
if (temp[1]>t[1]-tGistrsis/2){
digitalWrite(RelayChn2,LOW); //Термо-реле 2-включается
// lcd.setCursor(18, 2);
// lcd.print("*");
}
else if (temp[1]<t[1]+tGistrsis/2){
digitalWrite(RelayChn2,HIGH); //Термо-реле 2-выключается
// lcd.setCursor(18, 2);
// lcd.print("-");
}
}
//=========== Обработка RTC часов
void timeRtc(){
Wire.beginTransmission(DS3231_I2C_ADDRESS); //104 is DS3231 device address
Wire.write(0x00); //Start at register 0
Wire.endTransmission();
Wire.requestFrom(DS3231_I2C_ADDRESS, 7); //Request seven bytes
if(Wire.available()) {
seconds = Wire.read(); //Get second
minutes = Wire.read(); //Get minute
hours = Wire.read(); //Get hour
day = Wire.read();
date = Wire.read();
month = Wire.read(); //Get month
year = Wire.read();
seconds = (((seconds & B11110000)>>4)*10 + (seconds & B00001111)); //Convert BCD to decimal
minutes = (((minutes & B11110000)>>4)*10 + (minutes & B00001111));
hours = (((hours & B00110000)>>4)*10 + (hours & B00001111)); //Convert BCD to decimal (assume 24 hour mode)
day = (day & B00000111); // 1-7
date = (((date & B00110000)>>4)*10 + (date & B00001111)); //Convert BCD to decimal 1-31
month = (((month & B00010000)>>4)*10 + (month & B00001111)); //msb7 is century overflow
year = (((year & B11110000)>>4)*10 + (year & B00001111));
}
}
//=========== Обработка Таймеров
void timer(){
//========== Таймер №1
int fullMinutes=hours*60+minutes; //Переводим часы + минуты к полным минутам
int fullMinutesOn1=EEPROM.read(1)*60+EEPROM.read(2); //Переводим часы + минуты включения 1 реле к полным минутам
int fullMinutesOff1=EEPROM.read(3)*60+EEPROM.read(4); //Переводим часы + минуты выключения 1 реле к полным минутам
int fullMinutesOn2=EEPROM.read(5)*60+EEPROM.read(6); //Переводим часы + минуты включения 2 реле к полным минутам
int fullMinutesOff2=EEPROM.read(7)*60+EEPROM.read(8); //Переводим часы + минуты выключения 2 реле к полным минутам
int fullMinutesOnLcd=EEPROM.read(9)*60+EEPROM.read(10); //Переводим часы + минуты включения Lcd к полным минутам
int fullMinutesOffLcd=EEPROM.read(11)*60+EEPROM.read(12); //Переводим часы + минуты выключения Lcd к полным минутам
int fullMinutesOffOut3=EEPROM.read(13)*60+EEPROM.read(14); //Переводим часы + минуты включения OUT3 к полным минутам
int fullMinutesOffOut2=EEPROM.read(15)*60+EEPROM.read(16); //Переводим часы + минуты выключения OUT2 к полным минутам
if (fullMinutesOn1>fullMinutesOff1) {isNight=1;} //Если ночное время
if (isNight==0) { //Если день
if (fullMinutes>=fullMinutesOn1&&fullMinutes<fullMinutesOff1) {isLght[0]=1;} //Проверяем интервал
else {isLght[0]=0;} //Если необходимо включить свет
} else { //Если ночь
if(fullMinutes-fullMinutesOn1>=0) {isLght[0]=1;} //Если больше или равно верхнему значению, то необходимо включить свет
else { //Если необходимо включить свет
if(fullMinutes<fullMinutesOff1) {isLght[0]=1;} //Если меньше нижнего значения, то необходимо включить свет
else {isLght[0]=0;} //Если необходимо включить свет
}
}
if((isLght[0]==1)&&(lghtStat[0]==0)){ //Если свет еще не включен и выставлен флаг необходимости включить
if (tDimm < millis()) { //И не дана команда на полное выключение
pManDimmUp; dimmUp(); }
if (angData2==maxDimm) {lghtStat[0]=1;}
} else {
if(isLght[0]==0&&lghtStat[0]==1){
if (tDimm < millis()) {
pManDimmDown; dimmDown(); }
if (angData2==0){lghtStat[0]=0;}
}
}
//========== Таймер №2
if (fullMinutesOn2>fullMinutesOff2) {isNight=1;} //Если ночное время
if (isNight==0) { //Если день
if (fullMinutes>=fullMinutesOn2&&fullMinutes<fullMinutesOff2) {isLght[1]=1;} //Проверяем интервал
else {isLght[1]=0; } //Если необходимо включить свет
} else { //Если ночь
if(fullMinutes-fullMinutesOn2>=0) {isLght[1]=1;} //Если больше или равно верхнему значению, то необходимо включить свет
else { //Если необходимо включить свет
if(fullMinutes<fullMinutesOff2) {isLght[1]=1;} //Если меньше нижнего значения, то необходимо включить свет
else {isLght[1]=0; } //Если необходимо включить свет
}
}
if((isLght[1]==1)&&(lghtStat[1]==0)){ //Если свет еще не включен и выставлен флаг необходимости включить
if (tDimm < millis()) { //И не дана команда на полное выключение
pManDimmUp; dimmUp(); }
if (angData2==maxDimm) {lghtStat[1]=1;}
} else {
if(isLght[1]==0&&lghtStat[1]==1){
if (tDimm < millis()) {
pManDimmDown; dimmDown(); }
if (angData2==0){lghtStat[1]=0;}
}
}
//========== Таймер Lcd-подсветки
if (fullMinutesOnLcd>fullMinutesOffLcd) {isNight=1;} //Если ночное время
if (isNight==0) { //Если день
if (fullMinutes>=fullMinutesOnLcd&&fullMinutes<fullMinutesOffLcd) {isLcdt=1;} //Проверяем интервал
else {isLcdt=0;} //Если необходимо включить подсветку Lcd
} else { //Если ночь
if(fullMinutes-fullMinutesOnLcd>=0) {isLcdt=1;} //Если больше или равно верхнему значению, то необходимо включить подсветку Lcd
else { //Если необходимо включить подсветку Lcd
if(fullMinutes<fullMinutesOffLcd) {isLcdt=1;} //Если меньше нижнего значения, то необходимо включить подсветку Lcd
else {isLcdt=0;} //Если необходимо включить подсветку Lcd
}
}
if((isLcdt==1)&&(lcdStat==0)){ //Если подсветка Lcd еще не включена и выставлен флаг необходимости включить
lcd.backlight(); lcdStat=1;
} else {
if(isLcdt==0&&lcdStat==1){
lcd.noBacklight(); lcdStat=0;
}
}
//========== Таймер "Лунного света"
if (fullMinutes>=fullMinutesOffOut3) {
digitalWrite(OUT3,HIGH);}
if (fullMinutes>=fullMinutesOffOut2) {
digitalWrite(OUT2,HIGH);
}
//========== Таймер СО2
}
//=========== Обработка Bluetooth
//=========== Обработки печати и вывода на дисплейчик (часы)
void printTime() {
// Зачем создавать лишнюю переменную?
unsigned long currentMillis=millis();
//if (millis()- prvMlsTm>zadTime[2]) {
if(currentMillis-prvMlsTm>zadTime[2]) { //Проверяем интервал для обновления часов
prvMlsTm=currentMillis; //Вызываем ф-цию вывода времени на экран
//prvMlsTm=millis(); // В этом случае currentMillis становится ненужным.
lcd.setCursor(0,0);
if (hours<10) {lcd.print(0);lcd.print(hours);} else {lcd.print(hours);}
lcd.print(":");
if (minutes<10) {lcd.print(0);lcd.print(minutes);} else {lcd.print(minutes);}
lcd.print(":");
if (seconds<10) {lcd.print(0);lcd.print(seconds);} else {lcd.print(seconds);}
}
//Здесь аналогичный вопрос по целесообразности.
// if (millis()- prvMlsRazd > zadTime[3]) {
if(currentMillis - prvMlsRazd > zadTime[3]) { //Проверяем интервал для обновления ":"
//prvMlsRazd=millis();
prvMlsRazd=currentMillis;
lcd.setCursor(2,0);
lcd.print(" ");
lcd.setCursor(5,0);
lcd.print(" ");
lcd.setCursor(8,0);
lcd.print(" ");
}
}
//=========== Обработки печати и вывода на дисплейчик (напряжения, температуры, давление)
void printDin() {
unsigned long currentMillis=millis();
//if (millis()- prvMlsVo>zadTime[5]){
if(currentMillis-prvMlsVo>zadTime[5]){ //Проверяем интервал для обновления напряжения
//prvMlsVo=millis();
prvMlsVo=currentMillis;
lcd.setCursor(2,2); //Вывод значений температур на LCD
lcd.print((temp[0]),1);
lcd.setCursor(9,2);
lcd.print((temp[1]),1);
lcd.setCursor(16,2);
lcd.print((temp[2]),1);
lcd.setCursor(9,3);
lcd.print(vin);
lcd.setCursor(4,1);
lcd.print(Pressure/133.3,1); //Выводим на экранчик показания атм.давления в мм.
}
}
//=========== Обработки печати и вывода на дисплейчик СТАТИКИ
void printStat() {
unsigned long currentMillis=millis();
//if (millis()- prvMlsTimer>zadTime[6]){
if(currentMillis-prvMlsTimer>zadTime[6]){ //Проверяем интервал для обновления
//prvMlsTimer=millis();
prvMlsTimer=currentMillis;
lcd.setCursor(16,1);
lcd.print("pw\1");
lcd.setCursor(0,1);
lcd.print("bar\1");
lcd.setCursor(0,2);
lcd.print("a\1");
lcd.setCursor(7,2);
lcd.print("b\1");
lcd.setCursor(14,2);
lcd.print("c\1");
lcd.setCursor(0,3);
lcd.print("~");
lcd.setCursor(2,3);
lcd.print(":");
lcd.setCursor(4,3);
lcd.print(":");
lcd.setCursor(7,3);
lcd.print("v\1");
lcd.setCursor(15,3);
lcd.print("%\1");
lcd.setCursor(9,0);
if (date<10) {lcd.print(0);lcd.print(date);} else {lcd.print(date);}
lcd.print("/");
if (month==1){lcd.print ("Jan");}
if (month==2){lcd.print ("Feb");}
if (month==3){lcd.print ("Mar");}
if (month==4){lcd.print ("Apr");}
if (month==5){lcd.print ("May");}
if (month==6){lcd.print ("Jun");}
if (month==7){lcd.print ("Jul");}
if (month==8){lcd.print ("Aug");}
if (month==9){lcd.print ("Sep");}
if (month==10){lcd.print ("Oct");}
if (month==11){lcd.print ("Nov");}
if (month==12){lcd.print ("Dec");}
lcd.print("/");
lcd.print(year+zadTime[3]);
lcd.setCursor(12,1);
if (day==1){lcd.print ("Sun");}
if (day==2){lcd.print ("Mon");}
if (day==3){lcd.print ("Tue");}
if (day==4){lcd.print ("Wed");}
if (day==5){lcd.print ("Thu");}
if (day==6){lcd.print ("Fri");}
if (day==7){lcd.print ("Sat");}
lcd.setCursor(19,1); //Вывод состояния ATX (Power ON\OFF)
lcd.print(!digitalRead(OUT0));
lcd.setCursor(1,3); //Вывод состояния выходов реле освещения
lcd.print(!digitalRead(OUT1));
lcd.setCursor(3,3);
lcd.print(!digitalRead(OUT2));
lcd.setCursor(5,3);
lcd.print(!digitalRead(OUT3));
}
lcd.setCursor(17,3); //Вывод состояния аналогового выхода диммирования
lcd.print(angData2);
lcd.setCursor(18,3);
lcd.print(" ");
lcd.setCursor(17,3);
lcd.print(angData2);
}
void loop(){
timeRtc();
timer();
keyI();
dallas();
tempRelay();
voltM();
bar();
// bluetooth();
printTime();
printDin();
printStat();
}
Отличненько работает, вы объединили релюшки в одну функцию - здорово и строк сразу меньшеи массиввам иопределили температуры и задержки - это как пример будет для будующих переделок. Вход и выход из меню и функции параметров void setOnOff() теперь корректно и без задержек.
Единственноя вынес ЗА пределы работы функции кнопок keyI(); функцию //========== Обработка "одного" нажатия
если оставить как есть ТО любое условие прерывает её и диммирование ++ или -- прерывается и останавливается на последней комманде, если вынести её в отдельную к примеру в auto_key_dimmer() { и лупить в loop то после выполнения комманды (даже после выхода из меню) диммирование ++ или -- продолжится.
Вот, размер стал меньше пусть и нехначительно но меньше, главное строк меньше стало :) и сложнее сам код, чуть но сложнее а это главное в обучении, нестоять на месте
Так, сейчас логика работы не требует второй переменной angData2, будем ее убирать? Если захотите два независимых канала, функции управления придется переделывать серьезно. Которые сейчас, точно не подойдут.
Так, сейчас логика работы не требует второй переменной angData2, будем ее убирать? Если захотите два независимых канала, функции управления придется переделывать серьезно. Которые сейчас, точно не подойдут.
Это я понимал в самом начале, а для чего разделил? Да просто два канала по 5-ть драйверов и на них сигнал PWM с ардуинки, подумал, ВДРУГ незватит токовой нагрузки и подстраховался, так как подключение напрямую без транзистров и прочей лабуды (драйвер хорошо защищен и нетребует высоких токов) - сделать ДВА канала но СИММЕТРИЧНЫХ. На самом деле драйвера пищат хоть и несильно но пищат и просто оставлять их в "не краних" положениях ( между 0 и 255) ненужно - главное ПЛАВНО поднять освещение на angData2 канале (предварительно задав там 0 и включив реле на OUT1) - что сейчас шикарно делается.
вернул строки 338 и 364 без них при увеличении яркости (автодиммировании) по таймеру только ОДИН канал работал. При ручном - оба. Сначала невкурил даже что то неочень ряко + свист легкий на angData2=255 (а н легкий фон пропадает уже после 200) так что их нужно приравнивать с angData1 ранее.
Добавил есчо одно на мой взляд НЕЛИШНЮЮ настройку диммирования, 21 -25 строки (надо бы ещё и 26, 27 вкорячить) (пост #256)
Добавил в строку меню:
const char menuTxt[6][17] = {"set Timer 1 >>>>", "set Timer 2 >>>>","set Timer Lcd >>","set MoonLight >>","set Timer Co2 >>","set Dimmer >>>>"}; //Массив с наименованиями для экрана
Также новую функцию (пока коряво НО уже работает):
//=========== Обработка Меню, параметры диммирования
void setDimmer(){
byte pos=0;
maxDimm= EEPROM.read(winMe*5+1); //Считываем записанные значения таймеров
upR2= EEPROM.read(winMe*5+2); //Адрес определяется как номер таймера*5 + пять ячейки
downR2= EEPROM.read(winMe*5+3);
upR3= EEPROM.read(winMe*5+4);
downR3= EEPROM.read(winMe*5+5);
tft.fillScreen(ST7735_RED); //Clear screen
while(keyIr()!=1) { //Крутим цикл пока не будет Setup
byte KEY=keyIr(); //Читаем состояние кнопок
val=0;
tft.setTextSize(1);
tft.setCursor(5,90);
tft.setTextColor(ST7735_GREEN, ST7735_RED);
tft.print("=== set to save ===");
tft.setCursor(5, 55);
tft.print(winMe+1,DEC); //Печатаем номер программы таймера
tft.print("|");
tft.print(pos/3,DEC); //Печатаем позицию настройки параметра (замена blink)
tft.print(" ->");
tft.setCursor(45, 55); //Выводим инфу о часах и минутах
if (maxDimm < 10) tft.print("0");
tft.print(maxDimm,DEC);
tft.print(" dim");
tft.setCursor(5,75);
tft.setTextColor(ST7735_YELLOW,ST7735_RED);
tft.setTextSize(1);
if (upR2 < 10) tft.print("0");
tft.print(upR2,DEC);
tft.print(" | ");
if (downR2 < 10) tft.print("0");
tft.print(downR2,DEC);
tft.print(" || ");
if (upR3 < 10) tft.print("0");
tft.print(upR3,DEC);
tft.print(" | ");
if (downR3 < 10) tft.print("0");
tft.print(downR3,DEC);
tft.setCursor(pos, 0); //Устанавливаем курсор согласно позиции
if (pos<3) pos=3;
if (KEY==5 && pos<15) pos += 3; //Крутим позицию право-лево
else if (KEY==2 && pos>3) pos -= 3;
else if (pos==3 && KEY==3) maxDimm++; //Крутим значения
else if (pos==3 && KEY==4) maxDimm--;
else if (pos==6 && KEY==3) upR2++;
else if (pos==6 && KEY==4) upR2--;
else if (pos==9 && KEY==3) downR2++;
else if (pos==9 && KEY==4) downR2--;
else if (pos==12 && KEY==3) upR3++;
else if (pos==12 && KEY==4) upR3--;
else if (pos==15 && KEY==3) downR3++;
else if (pos==15 && KEY==4) downR3--;
} // конец цикла
// lcd.noBlink();
tft.fillScreen(ST7735_BLACK); // Clear screen
EEPROM.write(winMe*5+1, maxDimm); //Записываем НОВЫЕ значения
EEPROM.write(winMe*5+2, upR2);
EEPROM.write(winMe*5+3, downR2);
EEPROM.write(winMe*5+4, upR3);
EEPROM.write(winMe*5+5, downR3);
tft.setCursor(25,105);
tft.setTextColor(ST7735_WHITE,ST7735_BLACK);
tft.setTextSize(1);
tft.print("== Saved ==");
delay(zadTime[3]);
}
Ну и в саму функцию меню строчки заменил на:
tft.print(menuTxt[pos]); //Печатаем название
if (KEY==3 && pos>0) {pos--;} //Уменьшить увеличить + блокировка кнопки
if (KEY==4 && pos<5) {pos++;}
winMe=pos; //Переменная номера таймера
if (KEY==5 && pos==0) setOnOff();
if (KEY==5 && pos==1) setOnOff();
if (KEY==5 && pos==2) setOnOff();
if (KEY==5 && pos==3) setMoonLgh();
if (KEY==5 && pos==4) setOnOff();
if (KEY==5 && pos==5) setDimmer();
if (KEY==1) { //Выход из меню с проверкой и установкой блокировки от возврата
tft.fillScreen(ST7735_BLACK); // Clear screen
break; }
- это часть из кода. Коненчое в функции таймера заменил чтение присвоенных переменных (в объявлении переменных они у меня были заданы "=") на чтение из ЕПРОМ.
Это меню действительно "находка" и памяти увеличилсоь чуть более на 1кб всего :)
Нене, всё отличненько и входит и выходит. Нмогу понять почему у меня свободные ячеки ЕПРОМ правда образовались между 9 и 10 строкой последнего кода, тоетсь заканчиваются настройки pos==4 далее (5 пустых ячеек) и pos==5 с её пятью ячейками. Проверал, загружая стандартный скетч чтения:
/*
* EEPROM Read
*
* Reads the value of each byte of the EEPROM and prints it
* to the computer.
* This example code is in the public domain.
*/
#include <EEPROM.h>
// start reading from the first byte (address 0) of the EEPROM
int address = 0;
byte value;
void setup()
{
// initialize serial and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
}
void loop()
{
// read a byte from the current address of the EEPROM
value = EEPROM.read(address);
Serial.print(address);
Serial.print("\t");
Serial.print(value, DEC);
Serial.println();
// advance to the next address of the EEPROM
address = address + 1;
// there are only 512 bytes of EEPROM, from 0 to 511, so if we're
// on address 512, wrap around to address 0
if (address == 512)
address = 0;
delay(500);
}
А я не пересчитывал. Считаем: winMe принимает от 0 до 5 значит
winMe=0 поля 0*4+1 (1) до 0*4+4(4); =1 1*4+1(5) до 1*4+4(8); =2 (9) до (12); =3 (13) до (16); =4 (17) до (20)
а дальше вы изменили формулу winMe*5+1(5) и получили winMe=5 5*5+1(26) до 5*5+5(30). Вот они 5 недостающих. Здесь либо алгоритм адресации менять либо мирится.
Либо убрать один самый первый параметр maxDimm= EEPROM.read(winMe*5+1); из этой функции и перенести, но получится уже нетак красиво,Хотя у мнея же ещё НЕОБРАБОТАНЫ два настраиваемых: пост #256
026 int pManDimmUp=800; //Период увеличения яркости
027 int pManDimmDown=500; //Период уменьшения яркости
Вот попробую к ним, тогда останется один незадействован.
Так зачем, второй экран меню можете спокойно использовать для всего где нужны пять ячеек. Ну будет этот разрыв, какая беда? Периоды поделите на 10 и тоже можете в меню забить, только при использовании не забывать умножать обратно. В экранчике написать сек/100*255
Добавил вход в даллас из loop + отработка температурных реле по таймингу (они завязаны с далласом) и изменил, где вы реле через функцию releHigh() не сделали. Все angData1,2 заменил на одну переменную angData.
Больше ничего не трогал.
#include <EEPROM.h>
#include <Wire.h> //Подключаем библиотеку для использования однопроводного интерфейса
#include <LiquidCrystal_I2C.h> //Подключаем библиотеку для использования I2C интерфейса
#include <OneWire.h> //Подключаем библиотеку для температурного датчика DS18B20
#include <BMP085.h> //Подключаем библиотеку для маленького барометра
#include <IRremote.h> //Подключаем библиотеку для IR сенсора
LiquidCrystal_I2C lcd(0x27,20,4); //Устанавливаем LCD-адрес 0x27 для отображения 20 символов и 4 линии
byte currentLight=0; //Переменная включения подсветки LCD
//=====BT*
char inByte; //Ввходящие данные BT (Bluetooth модуля)
//=====IR_Sensor*
#define recvPin 3 //Вход IR-приемника и кнопки пульта
uint32_t val;
IRrecv irrecv(recvPin);
decode_results results;
//=====IR_Dimmer*
byte angData=0; //Переменная выходов диммирования (из двух половинок :))
byte maxDimm=255; //Переменная определяет МАКСИМАЛЬНОЕ значение диммирования
byte upR2=210; //Переменная включения 2 свето-релейного канала
byte upR3=240; //Переменная включения 3 свето-релейного канала
byte downR2=205; //Переменная выключения 2 свето-релейного канала
byte downR3=235; //Переменная выключения 3 свето-релейного канала
int pManDimmUp=500; //Период увеличения яркости
int pManDimmDown=400; //Период уменьшения яркости
byte flagDimm=0; //Флаг для обработки "НЕОБРАТИМОГО" выключения Power_Off
unsigned long tDimm=millis(); //Переменная задержки auto_dimmer
//=====Termo_Relay*
const int RelayChn1=4; //Используем цифровой ПОРТ 4 для ПЕРВОГО канала термо-реле (вода)
const int RelayChn2=A1; //Используем цифровой ПОРТ A1 для ВТОРОГО канала термо-реле (радиатор)
//=====Led_Relay*
#define OUT1 7 //Используем цифровой ПОРТ 7 для 1 свето-релейного канала Dimm
#define OUT2 8 //Используем цифровой ПОРТ 8 для 2 свето-релейного канала
#define OUT3 9 //Используем цифровой ПОРТ 9 для 3 свето-релейного канала
//=====Other_Relay*
#define OUT0 10 //Используем цифровой ПОРТ 10 для ATX (включение ATX (зелёный + черный))
//#define OUT6 11 //Используем цифровой ПОРТ 11 для CO2
//#define OUT7 12 //Используем цифровой ПОРТ 12 для другое
//=====Dimmer_Out*
#define OUT4 5 //Используем цифровой ПОРТ 5 для 1/2 SunSet канала (dimmer)
#define OUT5 6 //Используем цифровой ПОРТ 6 для 1/2 SunSet канала (dimmer)
//=====VoltMeter*
int voltInput=A7; //Используем аналоговый вход A7 для измерения напряжения
float vout=0.0;
float vin=0.0;
float R1=21700.0; //Resistance of R1 (22K) - see text!
float R2=12770.0; //Resistance of R2 (12K) - see text!
int valueVo=0;
//=====Pressure*
BMP085 dps=BMP085(); // Digital Pressure Sensor
long Pressure=0;
unsigned long timeDps=0;
//=====Termo_Sensor*
int tempPin=2; //Определяем порт шины OneWire (IC) для температурного датчика DS18B20
OneWire ds(tempPin); //Создаем объект для работы с термометром
byte flagDallas=0; //Флаг для обработки показаний с датчиков Dallas
byte data[12];
byte addr1[8] = {0x28, 0xC5, 0x3B, 0x5C, 0x06, 0x00, 0x00, 0x85}; //адрес датчика DS18B20_Вода в аквариуме
byte addr2[8] = {0x28, 0x86, 0x48, 0xEA, 0x05, 0x00, 0x00, 0xF6}; //адрес датчика DS18B20_Радиатор (2-ой канал, центр)
byte addr3[8] = {0x28, 0xF2, 0x29, 0xEB, 0x05, 0x00, 0x00, 0xE1}; //адрес датчика DS18B20_Блок реле
unsigned int raw; //Если экранированный кабель, можно подключать до 32 термо-датчиков DS18B20
float temp[3]; //Температура аквариума \ радиаторов Led \ блока реле
float t[]={25.0, 47.0, 55.0}; //Переменная предела срабатывания реле RelayChn1, RelayChn1, RelayChn1
float tGistrsis=1.0; //Гистерезис температур (по 0,5 в каждую сторону)
//=====Rtc_Clock*
#define DS3231_I2C_ADDRESS 104
byte seconds, minutes, hours, day, date, month, year;
//=====Timer*
// long lghtIntv=60000; //Интервал для проверки вкл./выкл. освещения аквариума, 1 минута
byte lcdStat=0; //Флаг подсветки Lcd если включена, то в 1
byte lghtStat[2]; //Флаг освещения, если включена, то в 1 в первом и втором таймере
byte co2Stat=0; //Флаг Co2, если включена, то в 1
byte isLcdt=0; //Флаг для обработки необходимости включить подсветку Lcd
byte isLght[2]; //Флаг для обработки необходимости включить реле освещения в первом и втором таймере
byte isCo2t=0; //Флаг для обработки необходимости включить реле Co2
byte isNight=0; //Если включаем на ночь, т.е. начальное время больше конечного
//=====Menu*
byte setHorClockOn; //Часы включения
byte setMinClockOn; //Минуты включения
byte setHorClockOff; //Часы вЫключения
byte setMinClockOff; //Минуты вЫключения
byte setTempt1; //Максимальная температура t1 (вода в аквариуме)
byte setTempt2; //Максимальная температура t2 (радиатор Led)
byte setTempt3; //Максимальная температура t3 (блок коммутации, реле)
byte winMe; //Номер экрана меню
//=====Delays*
//unsigned long tmIntv=1000; //Интервал для обновления времени на экране каждую секунду
//unsigned long razdIntv=2000; //Интервал для обновления ":" на экране каждые 2 секунды
unsigned long prvMlsTm=0; //Предыдущее показание миллисекунд для обновления показания часов
unsigned long prvMlsRazd=0; //Предыдущее показание миллисекунд для обновления ":"
//unsigned long prvMlsLght=0; //Предыдущее показание проверки временного интервала
unsigned long prvMlsVo=0; //Предыдущее показание обновления показания вольтметра
//unsigned long voIntv=5000; //Интервал для обновления напряжения
unsigned long prvMlsOut=0; //Предыдущее показание обновления показания OUT
//unsigned long outIntv=1000; //Интервал для обновления OUT
unsigned long prvMlsBar=0; //Предыдущее показание обновления показания барометра
//unsigned long barIntv=10000; //Интервал для обновления барометра
unsigned long prvMlsTemp=0; //Предыдущее показание обновления температур
//unsigned long tempIntv=5000; //Интервал для обновления температур
unsigned long prvMlsTimer=0; //Предыдущее показание обновления таймера
//unsigned long timerIntv=10000; //Интервал для обновления таймера
unsigned long tzad=millis(); //Переменная задержки (пока для ds18b20, ds.write) и непользую....
unsigned long zadM[4]; //Массив для задержек меню
const long zadTime[] = {100,750,1000,2000,3000,5000,10000,60000};
const char menuTxt[5][17] = {"set Timer 1 >>>>", "set Timer 2 >>>>","set Timer Lcd >>","set MoonLight >>","set Timer Co2 >>"}; //Массив с наименованиями для экрана
//=====Byte_Symbol*
byte equ[8] = //Символ "=" но КОРОТКИЙ :)
{
B00000,
B00000,
B01110,
B00000,
B01110,
B00000,
B00000,
};
void setup() {
Wire.begin();
// Serial.begin(9600);
irrecv.enableIRIn(); //Включаем IR-сенсор
// dps.init(MODE_STANDARD, 25000, true); //250 meters, true = using meter units
pinMode(voltInput,INPUT); //Определяем вход вольтметра
// pinMode(RelayChn1,OUTPUT); //Определяем выход 1-термореле охлаждения воды аквариума
// pinMode(RelayChn2,OUTPUT); //Определяем выход 2-термореле охлаждения радиаторов Led
// digitalWrite(RelayChn1,HIGH); //Определяем инверсный выход в HIGH охлаждения воды аквариума
// digitalWrite(RelayChn2,HIGH); //Определяем инверсный выход в HIGH охлаждения радиаторов Led
pinMode(OUT0,OUTPUT); //Определяем инверсный выход реле ATX
pinMode(OUT1,OUTPUT); //Определяем инверсные выходы реле 1 канала Led
pinMode(OUT2,OUTPUT); //Определяем инверсные выходы реле 2 канала Led
pinMode(OUT3,OUTPUT); //Определяем инверсные выходы реле 3 канала Led
// pinMode(OUT6,OUTPUT);
// pinMode(OUT7,OUTPUT);
relayHigh(); //Определяем инверсный выход в HIGH реле ATX, OUT1,2,3
// digitalWrite(OUT6,HIGH);
// digitalWrite(OUT7,HIGH);
analogWrite(OUT4,angData); //Инициация выхода 1/2 диммера
analogWrite(OUT5,angData); //Инициация выхода 1/2 диммера
lcd.init(); //Инициализируем дисплейчик
lcd.setBacklight(1);
lcd.clear(); //Очищаем на всякий случай дисплейчик
lcd.setCursor(2,0);
lcd.print("Aqua Controller"); //Выводим версию и прочее
lcd.setCursor(2,1);
lcd.print(" v1.1 ");
lcd.setCursor(0,3);
lcd.print("_0902_menu_NoEp_Dim_");
delay(2000);
lcd.clear(); //Очистка дисплея и void (printTime, printDin, printStat)
}
//========== Обработка IR-сенсора, определение кнопок
byte keyIr(){
if (irrecv.decode(&results)) { //Если пришел пакет и этот пакет не FF сохраняем правильный пакет в переменную
// if (results.value!=0xFFFFFFFF) { //Если пришел FF, соответственно пропускаем.
val=results.value; //} //Сверяем значение из переменной val.. если пришла команда повтора (пакет с FF)
irrecv.resume(); } //В переменной останется прошлый, правильный, пакет и код выполнится повторно.
// Serial.println(val,HEX);
// Serial.println(" ");
if (val==0x41BEC03F) return 1; //setup KEY1
if (val==0x41BE40BF) return 2; //left KEY2
if (val==0x41BED02F) return 3; //up KEY3
if (val==0x41BE609F) return 4; //down KEY4
if (val==0x41BEB04F) return 5; //right KEY5
if (val==0x41BEF00F) return 6; //exit POWER_KEY
if (val==0x41BE708F) return 7; //vol_down KEY9
if (val==0x41BE10EF) return 8; //vol_up KEY8
if (val==0x41BE20DF) return 9; //slide KEY9
if (val==0x41BEA05F) return 10; //stop KEY10
else return 0;
}
//========== Обработка IR-кнопок
void keyI(){
byte KEY=keyIr();
//========== Обработка Входа в Меню
if (KEY==1){ //***ВХОД В МЕНЮ и проверка блокировки от возврата. Принимаем код клавиши
val=0;
menu(); } //Если setup идем в меню
//========== Отключение LCD с кнопки
if (KEY==9){ val=0;
lcd.setBacklight(currentLight);
currentLight = !currentLight; }
//========== Увеличение яркости (удержание кнопки)
if (KEY==5){ val=0;
if (angData<255) angData++; //Начало увеличения диммирования
analogWrite(OUT4, angData);
analogWrite(OUT5, angData);
if (angData>0){ //Включаем реле ATX и диммера на первом шаге (начало диммирования)
digitalWrite(OUT0,LOW); //Включаем реле ATX
digitalWrite(OUT1,LOW); }
}
//========== Уменьшение яркости (удержание кнопки)
if (KEY==2){ val=0;
if (angData!=0) angData--; //Начало снижения диммирования
analogWrite(OUT4, angData);
analogWrite(OUT5, angData);
if (angData==0) { //Выключаем реле диммера (по окончании диммирования)
relayHigh();
//digitalWrite(OUT1,HIGH);
//digitalWrite(OUT2,HIGH);
//digitalWrite(OUT3,HIGH);
//digitalWrite(OUT0,HIGH); } //Выключаем реле ATX
}
}
//========== Обработка "одного" нажатия
if (KEY==8 & flagDimm==0){ //Если нажата кнопка УВЕЛИЧЕНИЯ диммирования
if (tDimm<millis()){ //и не дана команда на полное выключение
pManDimmUp; dimmUp(); } //Интервал УВЕЛИЧЕНИЯ диммирования
}
if (KEY==7 & flagDimm==0){ //Здесь аналогично увеличению яркости
if (tDimm<millis()) {
pManDimmDown; dimmDown(); } //Интервал Снижения диммирования
}
if (KEY==6 & angData!=0){ //Power_Off. Если диммер включен, устанавливаем флаг
flagDimm=1; }
if (flagDimm==1) { //Если флаг установлен, продолжаем уменьшение яркости
if (angData==0) { //Яркость на 0, флаг сбросили.
flagDimm=0;
relayHigh(); }
if (tDimm<millis()){ //Последовательно уменьшаем яркость, кнопки заблокированы
pManDimmDown=200; dimmDown(); } //Интервал СНИЖЕНИЯ диммирования (по Power_Off)
val=0;
}
//========== Обработка ATX, НЕдиммируемых реле
//if (KEY==6) {
// val=0; if (digitalWrite(OUT0, !digitalRead(OUT0))); //Power_KEY, ON/OFF_KEY, включение ATX
//if (KEY==6) {
// val=0; if (digitalWrite(OUT0, !digitalRead(OUT0)));
if (KEY==3) {
val=0; if (!digitalRead(OUT1)!=0 && angData >=1) digitalWrite(OUT2,!digitalRead(OUT2));}
if (KEY==3) {
val=0; if (!digitalRead(OUT1)!=0 && angData!=0) digitalWrite(OUT2,digitalRead(OUT2));}
if (KEY==4) {
val=0; if (digitalRead(OUT1)==0 && angData>=1) digitalWrite(OUT3,!digitalRead(OUT3));}
if (KEY==4) {
val=0; if (digitalRead(OUT1)==0 && angData!=0) digitalWrite(OUT3,digitalRead(OUT3));}
}
//========== Увеличение яркости (auto)
void dimmUp() {
if (angData<maxDimm){ //Ограничение верхнего значения диммирования, (0-255)
angData++; //Начало подъёма диммирования
analogWrite(OUT4,angData); //Пишем в порт
analogWrite(OUT5,angData);
if (angData>0){ //Включаем реле ATX и диммера на первом шаге (начало диммирования)
digitalWrite(OUT0,LOW);
digitalWrite(OUT1,LOW); }
if (angData==upR2) { //Включаем Второе реле при upR2
digitalWrite(OUT2,LOW); }
if (angData==upR3) { //Включаем Третье реле при upR3
digitalWrite(OUT3,LOW); }
tDimm=millis()+pManDimmUp; } //Устанавливаем время следующего шага
if (angData==maxDimm){val=0;}
}
//========== Уменьшение яркости (auto)
void dimmDown() {
if (angData>0) {
angData--; //Начало снижения диммирования
analogWrite(OUT4,angData);
analogWrite(OUT5,angData);
if (angData==downR3){ //Выключаем Третье реле при downR3
digitalWrite(OUT3,HIGH); }
if (angData==downR2){ //Выключаем Втором реле при downR2
digitalWrite(OUT2,HIGH); }
if (angData == 0){ //Выключаем реле диммера (по окончании диммирования)
relayHigh();
//digitalWrite(OUT0,HIGH);
//digitalWrite(OUT1,HIGH);
//digitalWrite(OUT2,HIGH);
//digitalWrite(OUT3,HIGH); }
}
tDimm=millis()+pManDimmDown; } //Устанавливаем время следующего шага
if (angData==0){val=0;}
}
//=========== Обработка Меню, выбор экрана
void menu(){
lcd.clear(); //Очищаем на всякий случай дисплейчик
byte pos=0;
while(1) { //Бесконечный цикл
byte KEY=keyIr();
val=0;
lcd.setCursor(0,1);
lcd.print(pos+1); //Печатаем номер.
lcd.print(". ");
lcd.print(menuTxt[pos]); //Печатаем название
if (KEY==3 && pos>0) {pos--;} //Уменьшить увеличить + блокировка кнопки
if (KEY==4 && pos<4) {pos++;}
winMe=pos; //Переменная номера таймера
// Здесь переходим на подменю. Если останется как сейчас, то достаточно. Сейчас можно перейти на разные подменю.
if (KEY==5) setOnOff();
//Подменю вы неиспользуете, поэтому выбросил
//if (KEY==5 && pos==0) setOnOff();
//if (KEY==5 && pos==1) setOnOff();
//if (KEY==5 && pos==2) setOnOff();
//if (KEY==5 && pos==3) setOnOff();
//if (KEY==5 && pos==4) setOnOff();
if (KEY==1) { //Выход из меню с проверкой и установкой блокировки от возврата
lcd.clear(); //Очищаем на всякий случай дисплейчик
break; }
}
}
//=========== Обработка Меню, параметры и настройка
void setOnOff(){
byte pos=0;
setHorClockOn= EEPROM.read(winMe*4+1); //Считываем записанные значения таймеров
setMinClockOn= EEPROM.read(winMe*4+2); //Адрес определяется как номер таймера*4 + четыре ячейки
setHorClockOff= EEPROM.read(winMe*4+3);
setMinClockOff= EEPROM.read(winMe*4+4);
lcd.clear(); //Очищаем на всякий случай дисплейчик
lcd.blink();
while(keyIr()!=1) { //Крутим цикл пока не будет Setup
byte KEY=keyIr(); //Читаем состояние кнопок
val=0;
delay(300); //Если убрать, не работает подсветка уст.позиции
lcd.setCursor(7,0);
lcd.print("-On- -Off-");
lcd.setCursor(0,3);
lcd.print("=== push to save ===");
lcd.setCursor(1, 1);
lcd.print(winMe+1,DEC); //Печатаем номер программы таймера
lcd.print("|");
lcd.print(pos/3,DEC); //Печатаем позицию настройки параметра (замена blink)
lcd.print("->");
lcd.setCursor(7,1); //Выводим инфу о часах и минутах
if (setHorClockOn<10) lcd.print("0");
lcd.print(setHorClockOn,DEC);
lcd.print(":");
if (setMinClockOn<10) lcd.print("0");
lcd.print(setMinClockOn,DEC);
lcd.print(" ");
if (setHorClockOff<10) lcd.print("0");
lcd.print(setHorClockOff,DEC);
lcd.print(":");
if (setMinClockOff<10) lcd.print("0");
lcd.print(setMinClockOff,DEC);
lcd.setCursor(pos,1); //Устанавливаем курсор согласно позиции
if (pos<3) pos=3;
if (KEY==5 && pos<11) pos += 3; //Крутим позицию право-лево
else if (KEY==2 && pos>3) pos -= 3;
else if (pos==3 && KEY==3) setHorClockOn++; //Крутим значения
else if (pos==3 && KEY==4) setHorClockOn--;
else if (pos==6 && KEY==3) setMinClockOn++;
else if (pos==6 && KEY==4) setMinClockOn--;
else if (pos==9 && KEY==3) setHorClockOff++;
else if (pos==9 && KEY==4) setHorClockOff--;
else if (pos==12 && KEY==3) setMinClockOff++;
else if (pos==12 && KEY==4) setMinClockOff--;
if (setHorClockOn>23) setHorClockOn=0; //Ограничиваем значения
else if (setMinClockOn>59) setMinClockOn=0;
else if (setHorClockOff>23) setHorClockOff=0;
else if (setMinClockOff>59) setMinClockOff=0;
} //Конец цикла
lcd.noBlink();
lcd.clear(); //Очищаем на всякий случай дисплейчик
EEPROM.write(winMe*4+1, setHorClockOn); //Записываем НОВЫЕ значения
EEPROM.write(winMe*4+2, setMinClockOn);
EEPROM.write(winMe*4+3, setHorClockOff);
EEPROM.write(winMe*4+4, setMinClockOff);
lcd.setCursor(4,2);
lcd.print("== Saved ==");
delay(zadTime[3]);
}
//========== Считывание напряжения
void voltM() {
valueVo=analogRead(voltInput); //Read the value at analog input
vout=(valueVo*5.0)/1024.0; //See text
vin=vout/(R2/(R1+R2));
if (vin<0.09) {
vin=0.0; } //Statement to quash undesired reading
}
//========== Считывание Давления
void bar() {
if (((millis()-timeDps)/1000.0)>=1.0) { //Конструкция жуткая и жрущая море ресурсов при расчете вещественных чисел.
//if (timeDps<millis()) //Я бы закомментил ваши и попробовал так
// dps.calcTrueTemperature();
timeDps=millis(); }
// timeDps=millis()+1000;
// dps.getPressure(&Pressure);
}
//=========== Считывание температур
void dallas(){
ds.reset();
ds.write(0xCC); //Команда инициации
ds.write(0x44); //Start conversion, with parasite power on at the end
tzad=millis()+750;
flagDallas=1;
}
float DS18B20(byte *adres){ //flagDallas=0;
ds.reset();
ds.select(adres);
ds.write(0xBE); //Read Scratchpad
for (byte i=0; i<9; i++) data[i]=ds.read(); //We need 9 bytes
int raw=(data[1]<<8) | data[0]; //Переводим в температуру
float celsius=(float)raw/16.0;
return celsius;
}
//=========== Обработка Термо-Реле
void tempRelay(){
if (tzad<millis()&&flagDallas==1){
temp[0] = DS18B20(addr1);
temp[1] = DS18B20(addr2);
temp[2] = DS18B20(addr3);
prvMlsTemp=millis();
flagDallas=0;
}
if (temp[0]>t[0]-tGistrsis/2){
digitalWrite(RelayChn1,LOW); //Термо-реле 1-включается
// lcd.setCursor(8, 2);
// lcd.print("*");
}
else if (temp[0]<t[0]+tGistrsis/2){
digitalWrite(RelayChn1,HIGH); //Термо-реле 1-выключается
// lcd.setCursor(8, 2);
// lcd.print("-");
}
if (temp[1]>t[1]-tGistrsis/2){
digitalWrite(RelayChn2,LOW); //Термо-реле 2-включается
// lcd.setCursor(18, 2);
// lcd.print("*");
}
else if (temp[1]<t[1]+tGistrsis/2){
digitalWrite(RelayChn2,HIGH); //Термо-реле 2-выключается
// lcd.setCursor(18, 2);
// lcd.print("-");
}
}
//=========== Обработка RTC часов
void timeRtc(){
Wire.beginTransmission(DS3231_I2C_ADDRESS); //104 is DS3231 device address
Wire.write(0x00); //Start at register 0
Wire.endTransmission();
Wire.requestFrom(DS3231_I2C_ADDRESS, 7); //Request seven bytes
if(Wire.available()) {
seconds = Wire.read(); //Get second
minutes = Wire.read(); //Get minute
hours = Wire.read(); //Get hour
day = Wire.read();
date = Wire.read();
month = Wire.read(); //Get month
year = Wire.read();
seconds = (((seconds & B11110000)>>4)*10 + (seconds & B00001111)); //Convert BCD to decimal
minutes = (((minutes & B11110000)>>4)*10 + (minutes & B00001111));
hours = (((hours & B00110000)>>4)*10 + (hours & B00001111)); //Convert BCD to decimal (assume 24 hour mode)
day = (day & B00000111); // 1-7
date = (((date & B00110000)>>4)*10 + (date & B00001111)); //Convert BCD to decimal 1-31
month = (((month & B00010000)>>4)*10 + (month & B00001111)); //msb7 is century overflow
year = (((year & B11110000)>>4)*10 + (year & B00001111));
}
}
//=========== Обработка Таймеров
void timer(){
//========== Таймер №1
int fulMin=hours*60+minutes; //Переводим часы + минуты к полным минутам
int fulMinOn1=EEPROM.read(1)*60+EEPROM.read(2); //Переводим часы + минуты включения 1 реле к полным минутам
int fulMinOff1=EEPROM.read(3)*60+EEPROM.read(4); //Переводим часы + минуты выключения 1 реле к полным минутам
int fulMinOn2=EEPROM.read(5)*60+EEPROM.read(6); //Переводим часы + минуты включения 2 реле к полным минутам
int fulMinOff2=EEPROM.read(7)*60+EEPROM.read(8); //Переводим часы + минуты выключения 2 реле к полным минутам
int fulMinOnLcd=EEPROM.read(9)*60+EEPROM.read(10); //Переводим часы + минуты включения Lcd к полным минутам
int fulMinOffLcd=EEPROM.read(11)*60+EEPROM.read(12); //Переводим часы + минуты выключения Lcd к полным минутам
int fulMinOffOut3=EEPROM.read(13)*60+EEPROM.read(14); //Переводим часы + минуты выключения OUT3 к полным минутам
int fulMinOffOut2=EEPROM.read(15)*60+EEPROM.read(16); //Переводим часы + минуты выключения OUT2 к полным минутам
if (fulMinOn1>fulMinOff1) {isNight=1;} //Если ночное время
if (isNight==0) { //Если день
if (fulMin>=fulMinOn1&&fulMin<fulMinOff1) {isLght[0]=1;} //Проверяем интервал
else {isLght[0]=0;} //Если необходимо включить свет
} else { //Если ночь
if(fulMin-fulMinOn1>=0) {isLght[0]=1;} //Если больше или равно верхнему значению, то необходимо включить свет
else { //Если необходимо включить свет
if(fulMin<fulMinOff1) {isLght[0]=1;} //Если меньше нижнего значения, то необходимо включить свет
else {isLght[0]=0;} //Если необходимо включить свет
}
}
if((isLght[0]==1)&&(lghtStat[0]==0)){ //Если свет еще не включен и выставлен флаг необходимости включить
if (tDimm < millis()) { //И не дана команда на полное выключение
pManDimmUp; dimmUp(); }
if (angData==maxDimm) {lghtStat[0]=1;}
} else {
if(isLght[0]==0&&lghtStat[0]==1){
if (tDimm < millis()) {
pManDimmDown; dimmDown(); }
if (angData==0){lghtStat[0]=0;}
}
}
//========== Таймер №2
if (fulMinOn2>fulMinOff2) {isNight=1;} //Если ночное время
if (isNight==0) { //Если день
if (fulMin>=fulMinOn2&&fulMin<fulMinOff2) {isLght[1]=1;} //Проверяем интервал
else {isLght[1]=0; } //Если необходимо включить свет
} else { //Если ночь
if(fulMin-fulMinOn2>=0) {isLght[1]=1;} //Если больше или равно верхнему значению, то необходимо включить свет
else { //Если необходимо включить свет
if(fulMin<fulMinOff2) {isLght[1]=1;} //Если меньше нижнего значения, то необходимо включить свет
else {isLght[1]=0; } //Если необходимо включить свет
}
}
if((isLght[1]==1)&&(lghtStat[1]==0)){ //Если свет еще не включен и выставлен флаг необходимости включить
if (tDimm < millis()) { //И не дана команда на полное выключение
pManDimmUp; dimmUp(); }
if (angData==maxDimm) {lghtStat[1]=1;}
} else {
if(isLght[1]==0&&lghtStat[1]==1){
if (tDimm < millis()) {
pManDimmDown; dimmDown(); }
if (angData==0){lghtStat[1]=0;}
}
}
//========== Таймер Lcd-подсветки
if (fulMinOnLcd>fulMinOffLcd) {isNight=1;} //Если ночное время
if (isNight==0) { //Если день
if (fulMin>=fulMinOnLcd&&fulMin<fulMinOffLcd) {isLcdt=1;} //Проверяем интервал
else {isLcdt=0;} //Если необходимо включить подсветку Lcd
} else { //Если ночь
if(fulMin-fulMinOnLcd>=0) {isLcdt=1;} //Если больше или равно верхнему значению, то необходимо включить подсветку Lcd
else { //Если необходимо включить подсветку Lcd
if(fulMin<fulMinOffLcd) {isLcdt=1;} //Если меньше нижнего значения, то необходимо включить подсветку Lcd
else {isLcdt=0;} //Если необходимо включить подсветку Lcd
}
}
if((isLcdt==1)&&(lcdStat==0)){ //Если подсветка Lcd еще не включена и выставлен флаг необходимости включить
lcd.backlight(); lcdStat=1;
} else {
if(isLcdt==0&&lcdStat==1){
lcd.noBacklight(); lcdStat=0;
}
}
//========== Таймер "Лунного света"
if (fulMin>=fulMinOffOut3) {
digitalWrite(OUT3,HIGH);}
if (fulMin>=fulMinOffOut2) {
digitalWrite(OUT2,HIGH);
}
//========== Таймер СО2
}
//=========== Обработка (групповая реле) в ВЫКЛ.
void relayHigh(){
digitalWrite(OUT0,HIGH); //Определяем инверсный выход в HIGH реле ATX
digitalWrite(OUT1,HIGH); //Определяем инверсный выход в HIGH реле 1 канала Led
digitalWrite(OUT2,HIGH); //Определяем инверсный выход в HIGH реле 2 канала Led
digitalWrite(OUT3,HIGH); //Определяем инверсный выход в HIGH реле 3 канала Led
}
//=========== Обработка Bluetooth
void bluetooth() {
}
//=========== Обработки печати и вывода на дисплейчик (часы)
void printTime() {
unsigned long currentMillis=millis();
if(currentMillis-prvMlsTm>zadTime[2]){ //Проверяем интервал для обновления часов
prvMlsTm=currentMillis; //Вызываем ф-цию вывода времени на экран
lcd.setCursor(0,0);
if (hours<10) {lcd.print(0);lcd.print(hours);} else {lcd.print(hours);}
lcd.print(":");
if (minutes<10) {lcd.print(0);lcd.print(minutes);} else {lcd.print(minutes);}
lcd.print(":");
if (seconds<10) {lcd.print(0);lcd.print(seconds);} else {lcd.print(seconds);}
}
if(currentMillis - prvMlsRazd > zadTime[3]){ //Проверяем интервал для обновления ":"
prvMlsRazd=currentMillis;
lcd.setCursor(2,0);
lcd.print(" ");
lcd.setCursor(5,0);
lcd.print(" ");
lcd.setCursor(8,0);
lcd.print(" ");
}
}
//=========== Обработки печати и вывода на дисплейчик (напряжения, температуры, давление)
void printDin() {
unsigned long currentMillis=millis();
if(currentMillis-prvMlsVo>zadTime[5]){ //Проверяем интервал для обновления напряжения
prvMlsVo=currentMillis;
lcd.setCursor(2,2); //Вывод значений температур на LCD
lcd.print((temp[0]),1);
lcd.setCursor(9,2);
lcd.print((temp[1]),1);
lcd.setCursor(16,2);
lcd.print((temp[2]),1);
lcd.setCursor(9,3);
lcd.print(vin);
lcd.setCursor(4,1);
lcd.print(Pressure/133.3,1); //Выводим на экранчик показания атм.давления в мм.рт.столба
}
}
//=========== Обработки печати и вывода на дисплейчик СТАТИКИ
void printStat() {
unsigned long currentMillis=millis();
if(currentMillis-prvMlsTimer>zadTime[6]){ //Проверяем интервал для обновления
prvMlsTimer=currentMillis;
lcd.setCursor(16,1);
lcd.print("pw\1");
lcd.setCursor(0,1);
lcd.print("bar\1");
lcd.setCursor(0,2);
lcd.print("a\1");
lcd.setCursor(7,2);
lcd.print("b\1");
lcd.setCursor(14,2);
lcd.print("c\1");
lcd.setCursor(0,3);
lcd.print("~");
lcd.setCursor(2,3);
lcd.print(":");
lcd.setCursor(4,3);
lcd.print(":");
lcd.setCursor(7,3);
lcd.print("v\1");
lcd.setCursor(15,3);
lcd.print("%\1");
lcd.setCursor(9,0);
if (date<10) {lcd.print(0);lcd.print(date);} else {lcd.print(date);}
lcd.print("/");
if (month==1){lcd.print ("Jan");}
if (month==2){lcd.print ("Feb");}
if (month==3){lcd.print ("Mar");}
if (month==4){lcd.print ("Apr");}
if (month==5){lcd.print ("May");}
if (month==6){lcd.print ("Jun");}
if (month==7){lcd.print ("Jul");}
if (month==8){lcd.print ("Aug");}
if (month==9){lcd.print ("Sep");}
if (month==10){lcd.print ("Oct");}
if (month==11){lcd.print ("Nov");}
if (month==12){lcd.print ("Dec");}
lcd.print("/");
lcd.print(year+2000);
lcd.setCursor(12,1);
if (day==1){lcd.print ("Sun");}
if (day==2){lcd.print ("Mon");}
if (day==3){lcd.print ("Tue");}
if (day==4){lcd.print ("Wed");}
if (day==5){lcd.print ("Thu");}
if (day==6){lcd.print ("Fri");}
if (day==7){lcd.print ("Sat");}
lcd.setCursor(19,1); //Вывод состояния ATX (Power ON\OFF)
lcd.print(!digitalRead(OUT0));
lcd.setCursor(1,3); //Вывод состояния выходов реле освещения
lcd.print(!digitalRead(OUT1));
lcd.setCursor(3,3);
lcd.print(!digitalRead(OUT2));
lcd.setCursor(5,3);
lcd.print(!digitalRead(OUT3));
}
//ПОка для быстрого мониторинга прорисовка диммирования "постоянная"
lcd.setCursor(17,3); //Вывод состояния аналогового выхода диммирования
lcd.print(angData);
lcd.setCursor(18,3);
lcd.print(" ");
lcd.setCursor(17,3);
lcd.print(angData);
}
void loop(){
timeRtc();
timer();
keyI();
if (millis()-prvMlsTemp>zadTime[6]&&flagDallas!=1){
dallas();}
tempRelay();
voltM();
bar();
// bluetooth();
printTime();
printDin();
printStat();
}
Шикарненько, ну вот недумал никогда что можно как высделали в строках 155 и 156 - потому и делал из двух частей на два "пина" :(
ПО термореле, теперечи начал понимать, что вы мне в самом начале толковали про флаги замер\флаг - сравнили с заданным\флаг- ну и вывод на на дисплейчик (строки 421 и 443, и условие в 703 - всё верно? :) )
С каждым разом все меньше размер и строк, ваша коррекция (без моих доп. окошек меню и неубранных currentMillis :) всего 22,5кб - эдак и до AtMegи рукой подать, шутка конечное. Счас главное стабильность и скорость выросла. Я ваши правкив свой кусок с менюшками и на ночь.... теститься.
Шикарненько, ну вот недумал никогда что можно как высделали в строках 155 и 156 - потому и делал из двух частей на два "пина" :(
ПО термореле, теперечи начал понимать, что вы мне в самом начале толковали про флаги замер\флаг - сравнили с заданным\флаг- ну и вывод на на дисплейчик (строки 421 и 443, и условие в 703 - всё верно? :) )
С каждым разом все меньше размер и строк, ваша коррекция (без моих доп. окошек меню и неубранных currentMillis :) всего 22,5кб - эдак и до AtMegи рукой подать, шутка конечное. Счас главное стабильность и скорость выросла. Я ваши правкив свой кусок с менюшками и на ночь.... теститься.
Так я вам сразу говорил, что если всякими tft не баловатся, наны за глаза хватит.
Ну что... все работает стабильно и шустро. ПО меню его счас облизываю. Утомляет "невозможность" менять позиции winMe (окон меню) в "цикличной последовательности". Ваш код и строки 314 -315 описал так:
tft.print(menuTxt[pos]); //Печатаем название
if (KEY==3 && pos>0) {pos--;} //Уменьшить/увеличить позицию окна меню
else if (pos==0 && KEY==3) {pos=5;} //Уменьшить/увеличить (циклично)
if (KEY==4 && pos<5) {pos++;}
else if (pos==5 && KEY==4) {pos=0;}
стало нааамного веселее, зная что окошек меню может теперь быть и не 6 а много больше :) (ну и на будущее вдруг понадобится).
Попытался с часами тоже сделать (ну чтобы не начинать с 0 до 23 часов в одну строноу а потмо вдругую) решил также "зациклить" получилось но как т осмешновато. минуты дошли до 59 пытаемся перейти в 00 и тутже меняются и часы (вроде и удобно но ненужно) а назад вообще в мгновение возврат с 0 в 255 !!! и в 0, в 59 никак. Вот какой у меня рисунок кода:
if (setHorClockOn>23) setHorClockOn=0; //Ограничиваем значения
if (setHorClockOn==0 && KEY==4) {setHorClockOn--;}
else if (setHorClockOn==23 && KEY==3) {setHorClockOn++;}
if (setMinClockOn>59) setMinClockOn=0;
if (setMinClockOn==0 && KEY==4) {setMinClockOn--;}
else if (setMinClockOn==59 && KEY==3) {setHorClockOn++;}
if (setHorClockOff>23) setHorClockOff=0;
if (setHorClockOff==0 && KEY==4) {setHorClockOff--;}
else if (setHorClockOff==23 && KEY==3) {setHorClockOff++;}
if (setMinClockOff>59) setMinClockOff=0;
if (setMinClockOff==0 && KEY==4) {setMinClockOff--;}
else if (setMinClockOff==59 && KEY==3) {setHorClockOff++;}
это строки 380 -383 из поста #270
мне кажется будет прощще и короче на switch \ case (может на данном примере покажите как) при возможности.
if (pos<3) pos=3;
if (KEY==5 && pos<11) pos += 3; //Крутим позицию право-лево
if (KEY==2 && pos>3) pos -= 3;
else if (pos==3 && KEY==3) setHorClockOn++; //Крутим значения
else if (pos==3 && KEY==4) setHorClockOn--;
else if (pos==6 && KEY==3) setMinClockOn++;
else if (pos==6 && KEY==4) setMinClockOn--;
else if (pos==9 && KEY==3) setHorClockOff++;
else if (pos==9 && KEY==4) setHorClockOff--;
else if (pos==12 && KEY==3) setMinClockOff++;
else if (pos==12 && KEY==4) setMinClockOff--;
if (setHorClockOn>23) setHorClockOn=0; //Ограничиваем значения
else if (setHorClockOn<0) setHorClockOn=23
else if (setMinClockOn>59) setMinClockOn=0;
else if (setMinClockOn<0) setMinClockOn=59;
else if (setHorClockOff>23) setHorClockOff=0;
else if (setHorClockOff<0) setHorClockOff=23;
else if (setMinClockOff>59) setMinClockOff=0;
else if (setMinClockOff<0) setMinClockOff=59;
Работает толко "++" с 23 на 0 далее 1 2 3 . А вот в "--" неа. тоетсь 2 1 0 и всё, нули. Счас поколдую над вашим, может надо чередовать if else для промежуточныйх значнеи >23 и <0
У меня кончается "свободное место". Немного переделал подменю, теперь их уже семь (пара таймеров на свет, один на со2, один на досветку "луна" типа, диммирование и установка часов), чуток поправил переменные. В итоге размер уже 29,4кб - на свооде почти ничего. А впереди есчо должна была быть блютусина или wi-fi, неговорю уже про влажность и уровень воды в банке - хотел добавить :)
Что делать relg оптимизироват md первую голову. Библиотек то и нету почти (за исключением IR и барометра - остальные стандартно и без них нельзя. Вотон скетчик - всё работает и стабильно, всё настраивается. Кстати заметил что всё чт ов епром запихивается после сохранения в подменю вступает в силу после RESSET на ардуинке. Код:
#include <EEPROM.h>
#include <Wire.h> //Подключаем библиотеку для использования однопроводного интерфейса
#include <LiquidCrystal_I2C.h> //Подключаем библиотеку для использования I2C интерфейса
#include <OneWire.h> //Подключаем библиотеку для температурного датчика DS18B20
#include <BMP085.h> //Подключаем библиотеку для маленького барометра
#include <IRremote.h> //Подключаем библиотеку для IR сенсора
LiquidCrystal_I2C lcd(0x27,20,4); //Устанавливаем LCD-адрес 0x27 для отображения 20 символов и 4 линии
byte currentLight=0; //Переменная включения подсветки LCD
//=====BT*
char inByte; //Ввходящие данные BT (Bluetooth модуля)
//=====IR_Sensor*
#define recvPin 3 //Вход IR-приемника и кнопки пульта
uint32_t val;
IRrecv irrecv(recvPin);
decode_results results;
//=====IR_Dimmer*
byte angData=0; //Переменная выходов диммирования (из двух половинок :))
byte flagDimm=0; //Флаг для обработки "НЕОБРАТИМОГО" выключения Power_Off
unsigned long tDimm=millis(); //Переменная задержки auto_dimmer
//=====Termo_Relay*
const int RelayChn1=4; //Используем цифровой ПОРТ 4 для ПЕРВОГО канала термо-реле (вода)
const int RelayChn2=A1; //Используем цифровой ПОРТ A1 для ВТОРОГО канала термо-реле (радиатор)
//=====Led_Relay*
#define OUT1 7 //Используем цифровой ПОРТ 7 для 1 свето-релейного канала Dimm
#define OUT2 8 //Используем цифровой ПОРТ 8 для 2 свето-релейного канала
#define OUT3 9 //Используем цифровой ПОРТ 9 для 3 свето-релейного канала
//=====Other_Relay*
#define OUT0 10 //Используем цифровой ПОРТ 10 для ATX (включение ATX (зелёный + черный))
//#define OUT6 11 //Используем цифровой ПОРТ 11 для CO2
//#define OUT7 12 //Используем цифровой ПОРТ 12 для другое
//=====Dimmer_Out*
#define OUT4 5 //Используем цифровой ПОРТ 5 для 1/2 SunSet канала (dimmer)
#define OUT5 6 //Используем цифровой ПОРТ 6 для 1/2 SunSet канала (dimmer)
//=====Blink led*
#define bLink 13 //Индикатор и аварийный сброс
//=====VoltMeter*
int voltInput=A7; //Используем аналоговый вход A7 для измерения напряжения
float vout=0.0;
float vin=0.0;
float R1=21700.0; //Resistance of R1 (22K) - see text!
float R2=12770.0; //Resistance of R2 (12K) - see text!
int valueVo=0;
//=====Pressure*
BMP085 dps=BMP085(); // Digital Pressure Sensor
long Pressure=0;
unsigned long timeDps=0;
//=====Termo_Sensor*
int tempPin=2; //Определяем порт шины OneWire (IC) для температурного датчика DS18B20
OneWire ds(tempPin); //Создаем объект для работы с термометром
byte flagDallas=0; //Флаг для обработки показаний с датчиков Dallas
byte data[12];
byte addr1[8]={0x28,0xC5,0x3B,0x5C,0x06,0x00,0x00,0x85}; //адрес датчика DS18B20_Вода в аквариуме
byte addr2[8]={0x28,0x86,0x48,0xEA,0x05,0x00,0x00,0xF6}; //адрес датчика DS18B20_Радиатор (2-ой канал, центр)
byte addr3[8]={0x28,0xF2,0x29,0xEB,0x05,0x00,0x00,0xE1}; //адрес датчика DS18B20_Блок реле
unsigned int raw; //Если экранированный кабель, можно подключать до 32 термо-датчиков DS18B20
float temp[3]; //Температура аквариума \ радиаторов Led \ блока реле
float t[]={25.0, 47.0, 55.0}; //Переменная предела срабатывания реле RelayChn1, RelayChn1, RelayChn1
float tGistrsis=1.0; //Гистерезис температур (по 0,5 в каждую сторону)
//=====Rtc_Clock*
#define DS3231_I2C_ADDRESS 104
byte seconds, minutes, hours, day, date, month, year;
byte decToBcd (byte val){return((val/10*16)+(val%10));}
//=====Timer*
// long lghtIntv=60000; //Интервал для проверки вкл./выкл. освещения аквариума, 1 минута
byte lcdStat=0; //Флаг подсветки Lcd если включена, то в 1
byte lghtStat[2]; //Флаг освещения, если включена, то в 1 в первом и втором таймере
byte co2Stat=0; //Флаг Co2, если включена, то в 1
byte isLcdt=0; //Флаг для обработки необходимости включить подсветку Lcd
byte isLght[2]; //Флаг для обработки необходимости включить реле освещения в первом и втором таймере
byte isCo2t=0; //Флаг для обработки необходимости включить реле Co2
byte isNight=0; //Если включаем на ночь, т.е. начальное время больше конечного
//=====Menu*
byte winMe; //Номер экрана меню
byte setHorClockOn; //Часы включения Таймера
byte setMinClockOn; //Минуты включения Таймера
byte setHorClockOff; //Часы вЫключения Таймера
byte setMinClockOff; //Минуты вЫключения Таймера
byte setHorClockOffR3; //Часы вЫключения OUT3, (R3)
byte setMinClockOffR3; //Минуты вЫключения OUT3, (R3)
byte setHorClockOffR2; //Часы вЫключения OUT2, (R2)
byte setMinClockOffR2; //Минуты вЫключения OUT2, (R2)
byte setTempt1; //Максимальная температура t1 (вода в аквариуме)
byte setTempt2; //Максимальная температура t2 (радиатор Led)
byte setTempt3; //Максимальная температура t3 (блок коммутации, реле)
byte maxDimm; //Переменная определяет МАКСИМАЛЬНОЕ значение диммирования
byte upR2; //Переменная включения OUT2
byte downR2; //Переменная вЫключения OUT2
byte upR3; //Переменная включения OUT3
byte downR3; //Переменная вЫключения OUT3
byte pManDimmUp; //Период увеличения яркости
byte pManDimmDown; //Период уменьшения яркости
//=====Delays*
//unsigned long tmIntv=1000; //Интервал для обновления времени на экране каждую секунду
unsigned long prvMlsTm=0; //Предыдущее показание миллисекунд для обновления показания часов
unsigned long prvMlsRazd=0; //Предыдущее показание миллисекунд для обновления ":"
unsigned long prvMlsVo=0; //Предыдущее показание обновления показания вольтметра
unsigned long prvMlsOut=0; //Предыдущее показание обновления показания OUT
unsigned long prvMlsBar=0; //Предыдущее показание обновления показания барометра
unsigned long prvMlsTemp=0; //Предыдущее показание обновления температур
unsigned long prvMlsTimer=0; //Предыдущее показание обновления таймера
unsigned long prvMlsbLink=0; //Предыдущее показание миллисекунд для обновления "blink led"
unsigned long tzad=millis(); //Переменная задержки (пока для ds18b20, ds.write) и непользую....
unsigned long zadM[4]; //Массив для задержек меню
const long zadTime[]={100,500,750,1000,2000,3000,5000,10000,60000};
const char menuTxt[7][17]={"set Timer 1 >>>>","set Timer 2 >>>>","set Timer Lcd >>","set MoonLight >>","set Timer Co2 >>","set Dimmer >>>>>","set Clock >>>>>>"}; //Массив с наименованиями для экрана
//=====Byte_Symbol*
byte equ[8]={B00000,B00000,B01110,B00000,B01110,B00000,B00000}; //Символ "=" но КОРОТКИЙ :)
void setup() {
Wire.begin();
// Serial.begin(9600);
irrecv.enableIRIn(); //Включаем IR-сенсор
dps.init(MODE_STANDARD, 25000, true); //250 meters, true = using meter units
pinMode(voltInput,INPUT); //Определяем вход вольтметра
// pinMode(RelayChn1,OUTPUT); //Определяем выход 1-термореле охлаждения воды аквариума
// pinMode(RelayChn2,OUTPUT); //Определяем выход 2-термореле охлаждения радиаторов Led
// digitalWrite(RelayChn1,HIGH); //Определяем инверсный выход в HIGH охлаждения воды аквариума
// digitalWrite(RelayChn2,HIGH); //Определяем инверсный выход в HIGH охлаждения радиаторов Led
pinMode(OUT0,OUTPUT); //Определяем инверсный выход реле ATX
pinMode(OUT1,OUTPUT); //Определяем инверсные выходы реле 1 канала Led
pinMode(OUT2,OUTPUT); //Определяем инверсные выходы реле 2 канала Led
pinMode(OUT3,OUTPUT); //Определяем инверсные выходы реле 3 канала Led
pinMode(bLink,OUTPUT); //Определяем аварийный "blink led"
// pinMode(OUT6,OUTPUT);
// pinMode(OUT7,OUTPUT);
// digitalWrite(OUT0,HIGH); //Определяем инверсный выход в HIGH реле ATX
// digitalWrite(OUT1,HIGH); //Определяем инверсный выход в HIGH реле 1 канала Led
// digitalWrite(OUT2,HIGH); //Определяем инверсный выход в HIGH реле 2 канала Led
// digitalWrite(OUT3,HIGH); //Определяем инверсный выход в HIGH реле 3 канала Led
relayHigh(); //Определяем инверсный выход в HIGH реле ATX, OUT1,2,3
digitalWrite(bLink,HIGH); //Определяем аварийный "blink led" в HIGH
// digitalWrite(OUT6,HIGH);
// digitalWrite(OUT7,HIGH);
analogWrite(OUT4,angData); //Инициация выхода 1/2 диммера
analogWrite(OUT5,angData); //Инициация выхода 1/2 диммера
lcd.init(); //Инициализируем дисплейчик
lcd.setBacklight(1);
lcd.createChar(1,equ); //Создаем символ под номером 1
lcd.clear(); //Очищаем на всякий случай дисплейчик
lcd.setCursor(2,0);
lcd.print("Aqua Controller"); //Выводим версию и прочее
lcd.setCursor(2,1);
lcd.print(" v3.1 ");
lcd.setCursor(0,3);
lcd.print("_1702_menu_setRtc_");
delay(2000);
lcd.clear(); //Очистка дисплея и void (printTime, printDin, printStat)
}
//========== Обработка IR-сенсора, определение кнопок
byte keyIr(){
if (irrecv.decode(&results)){ //Если пришел пакет и этот пакет не FF сохраняем правильный пакет в переменную
// if (results.value!=0xFFFFFFFF){ //Если пришел FF, соответственно пропускаем.
val=results.value; //} //Сверяем значение из переменной val.. если пришла команда повтора (пакет с FF)
irrecv.resume();} //В переменной останется прошлый, правильный, пакет и код выполнится повторно.
// Serial.println(val,HEX);
// Serial.println(" ");
if (val==0x41BEC03F) return 1; //setup KEY1
if (val==0x41BE40BF) return 2; //left KEY2
if (val==0x41BED02F) return 3; //up KEY3
if (val==0x41BE609F) return 4; //down KEY4
if (val==0x41BEB04F) return 5; //right KEY5
if (val==0x41BEF00F) return 6; //exit POWER_KEY
if (val==0x41BE708F) return 7; //vol_down KEY9
if (val==0x41BE10EF) return 8; //vol_up KEY8
if (val==0x41BE20DF) return 9; //slide KEY9
if (val==0x41BEA05F) return 10; //stop KEY10
else return 0;
}
//========== Обработка IR-кнопок
void keyI(){
byte KEY=keyIr();
//========== Обработка Входа в Меню
if (KEY==1){ //ВХОД В МЕНЮ и проверка блокировки от возврата. Принимаем код клавиши
val=0;
menu();} //Если setup идем в меню
//========== Отключение LCD с кнопки
if (KEY==9){ val=0;
lcd.setBacklight(currentLight);
currentLight=!currentLight;}
//========== Увеличение яркости (удержание кнопки)
if (KEY==5){ val=0;
if (angData<255) angData; //Начало увеличения диммирования
analogWrite(OUT4,angData);
analogWrite(OUT5,angData);
if (angData>0){ //Включаем реле ATX и диммера на первом шаге (начало диммирования)
digitalWrite(OUT0,LOW); //Включаем реле ATX
digitalWrite(OUT1,LOW);}
}
//========== Уменьшение яркости (удержание кнопки)
if (KEY==2){ val=0;
if (angData!=0) angData--; //Начало снижения диммирования
analogWrite(OUT4, angData);
analogWrite(OUT5, angData);
if (angData==0){ //Выключаем реле диммера (по окончании диммирования)
// digitalWrite(OUT1,HIGH);
// digitalWrite(OUT2,HIGH);
// digitalWrite(OUT3,HIGH);
// digitalWrite(OUT0,HIGH);
relayHigh();} //Выключаем реле ATX
}
//========== Обработка "одного" нажатия
if (KEY==8 & flagDimm==0){ //Если нажата кнопка УВЕЛИЧЕНИЯ диммирования
if (tDimm<millis()){ //и не дана команда на полное выключение
(EEPROM.read(26)*50); dimmUp();} //Интервал УВЕЛИЧЕНИЯ диммирования
}
if (KEY==7 & flagDimm==0){ //Здесь аналогично увеличению яркости
if (tDimm<millis()){
(EEPROM.read(27)*50); dimmDown();} //Интервал Снижения диммирования
}
if (KEY==6 & angData!=0){ //Power_Off. Если диммер включен, устанавливаем флаг
flagDimm=1; }
if (flagDimm==1){ //Если флаг установлен, продолжаем уменьшение яркости
if (angData==0){ //Яркость на 0, флаг сбросили.
flagDimm=0;
// digitalWrite(OUT1,HIGH);
// digitalWrite(OUT2,HIGH);
// digitalWrite(OUT3,HIGH);
// digitalWrite(OUT0,HIGH);
relayHigh();}
if (tDimm<millis()){ //Последовательно уменьшаем яркость, кнопки заблокированы
(EEPROM.read(27)*50)/2; dimmDown();} //Интервал СНИЖЕНИЯ диммирования (по Power_Off)
val=0;
}
//========== Обработка ATX, НЕдиммируемых реле
//if (KEY==6){
// val=0; if (digitalWrite(OUT0, !digitalRead(OUT0))); //Power_KEY, ON/OFF_KEY, включение ATX
//if (KEY==6){
// val=0; if (digitalWrite(OUT0, !digitalRead(OUT0)));
if (KEY==3){
val=0; if (!digitalRead(OUT1)!=0 && angData>=1) digitalWrite(OUT2,!digitalRead(OUT2));}
if (KEY==3){
val=0; if (!digitalRead(OUT1)!=0 && angData!=0) digitalWrite(OUT2,digitalRead(OUT2));}
if (KEY==4){
val=0; if (digitalRead(OUT1)==0 && angData>=1) digitalWrite(OUT3,!digitalRead(OUT3));}
if (KEY==4){
val=0; if (digitalRead(OUT1)==0 && angData!=0) digitalWrite(OUT3,digitalRead(OUT3));}
}
//========== Увеличение яркости (auto)
void dimmUp(){
if (angData<EEPROM.read(21)){ //Ограничение верхнего значения диммирования, (0-255)
angData++; //Начало подъёма диммирования
analogWrite(OUT4,angData); //Пишем в порт
analogWrite(OUT5,angData);
if (angData>0){ //Включаем реле ATX и диммера на первом шаге (начало диммирования)
digitalWrite(OUT0,LOW);
digitalWrite(OUT1,LOW);}
if (angData==EEPROM.read(22)){ //Включаем Второе реле при upR2
digitalWrite(OUT2,LOW);}
if (angData==EEPROM.read(24)){ //Включаем Третье реле при upR3
digitalWrite(OUT3,LOW);}
tDimm=millis()+(EEPROM.read(26)*50);} //Устанавливаем время следующего шага
if (angData==EEPROM.read(21)){val=0;}
}
//========== Уменьшение яркости (auto)
void dimmDown(){
if (angData>0){
angData--; //Начало снижения диммирования
analogWrite(OUT4,angData);
analogWrite(OUT5,angData);
if (angData==EEPROM.read(25)){ //Выключаем Третье реле при downR3
digitalWrite(OUT3,HIGH);}
if (angData==EEPROM.read(23)){ //Выключаем Втором реле при downR2
digitalWrite(OUT2,HIGH);}
if (angData==0){ //Выключаем реле диммера (по окончании диммирования)
// digitalWrite(OUT0,HIGH);
// digitalWrite(OUT1,HIGH);
// digitalWrite(OUT2,HIGH);
// digitalWrite(OUT3,HIGH);
relayHigh();}
tDimm=millis()+(EEPROM.read(27)*50);} //Устанавливаем время следующего шага
if (angData==0){val=0;}
}
//=========== Обработка Меню, выбор экрана
void menu(){
lcd.clear(); //Очищаем на всякий случай дисплейчик
byte pos=0;
while(1){ bLinkLed(); //Бесконечный цикл
byte KEY=keyIr();
val=0;
lcd.setCursor(0,1);
lcd.print(pos+1); //Печатаем номер.
lcd.print(". ");
lcd.print(menuTxt[pos]); //Печатаем название
if (KEY==3 && pos>0) {pos--;} //Уменьшить/увеличить позицию окна меню
else if (pos==0 && KEY==3) {pos=6;} //Уменьшить/увеличить (циклично)
if (KEY==4 && pos<6) {pos++;}
else if (pos==6 && KEY==4) {pos=0;}
winMe=pos; //Переменная номера окна подменю
if (KEY==5 && pos==0) setOnOff(); //"set Timer 1 >>>>" 0
if (KEY==5 && pos==1) setOnOff(); //"set Timer 2 >>>>" 1
if (KEY==5 && pos==2) setOnOff(); //"set Timer Lcd >>" 2
if (KEY==5 && pos==3) setMoonLgh(); //"set MoonLight >>" 3
if (KEY==5 && pos==4) setOnOff(); //"set Timer Co2 >>" 4
if (KEY==5 && pos==5) setDimmer(); //"set Dimmer >>>>>" 5
if (KEY==5 && pos==6) setClock(); //"set Clock >>>>>>" 6
if (KEY==1){ //Выход из меню с проверкой и установкой блокировки от возврата
lcd.clear(); //Очищаем на всякий случай дисплейчик
break;}
}
}
//=========== Обработка Меню, параметры и настройка
void setOnOff(){
byte pos=0;
setHorClockOn= EEPROM.read(winMe*4+1); //Считываем записанные значения таймеров
setMinClockOn= EEPROM.read(winMe*4+2); //Адрес определяется как номер таймера*4 + четыре ячейки
setHorClockOff= EEPROM.read(winMe*4+3);
setMinClockOff= EEPROM.read(winMe*4+4);
lcd.clear(); //Очищаем на всякий случай дисплейчик
// lcd.blink();
while(keyIr()!=1){ //Крутим цикл пока не будет Setup
byte KEY=keyIr(); //Читаем состояние кнопок
val=0;
// delay(200); //Если убрать, не работает подсветка уст.позиции
lcd.setCursor(7,0);
lcd.print("-On- -Off-");
lcd.setCursor(0,3);
lcd.print("=== push to save ===");
lcd.setCursor(1,1);
lcd.print(winMe+1,DEC); //Печатаем номер программы таймера
lcd.print("|");
lcd.print(pos/3,DEC); //Печатаем позицию настройки параметра (замена blink)
lcd.print("->");
lcd.setCursor(7,1); //Выводим инфу о часах и минутах
if (setHorClockOn<10) lcd.print("0");
lcd.print(setHorClockOn,DEC);
lcd.print(":");
if (setMinClockOn<10) lcd.print("0");
lcd.print(setMinClockOn,DEC);
lcd.print(" ");
if (setHorClockOff<10) lcd.print("0");
lcd.print(setHorClockOff,DEC);
lcd.print(":");
if (setMinClockOff<10) lcd.print("0");
lcd.print(setMinClockOff,DEC);
lcd.setCursor(pos,1); //Устанавливаем курсор согласно позиции
if (pos<3) pos=3;
if (KEY==5 && pos<11) pos += 3; //Крутим позицию право-лево
else if (KEY==2 && pos>3) pos -= 3;
else if (pos==3 && KEY==3) setHorClockOn++; //Крутим значения
else if (pos==3 && KEY==4) setHorClockOn--;
else if (pos==6 && KEY==3) setMinClockOn++;
else if (pos==6 && KEY==4) setMinClockOn--;
else if (pos==9 && KEY==3) setHorClockOff++;
else if (pos==9 && KEY==4) setHorClockOff--;
else if (pos==12 && KEY==3) setMinClockOff++;
else if (pos==12 && KEY==4) setMinClockOff--;
if (setHorClockOn>23) setHorClockOn=0; //Ограничиваем значения
else if (setMinClockOn>59) setMinClockOn=0;
else if (setHorClockOff>23) setHorClockOff=0;
else if (setMinClockOff>59) setMinClockOff=0;
} //Конец цикла
// lcd.noBlink();
lcd.clear(); //Очищаем на всякий случай дисплейчик
EEPROM.write(winMe*4+1, setHorClockOn); //Записываем НОВЫЕ значения
EEPROM.write(winMe*4+2, setMinClockOn);
EEPROM.write(winMe*4+3, setHorClockOff);
EEPROM.write(winMe*4+4, setMinClockOff);
lcd.setCursor(4,2);
lcd.print("== Saved ==");
delay(zadTime[4]);
}
//=========== Обработка Меню, Лунный свет
void setMoonLgh(){
byte pos=0;
setHorClockOffR3= EEPROM.read(winMe*4+1); //Считываем записанные значения таймеров
setMinClockOffR3= EEPROM.read(winMe*4+2); //Адрес определяется как номер таймера*4 + четыре ячейки
setHorClockOffR2= EEPROM.read(winMe*4+3);
setMinClockOffR2= EEPROM.read(winMe*4+4);
lcd.clear(); //Очищаем на всякий случай дисплейчик
// lcd.blink();
while(keyIr()!=1){ //Крутим цикл пока не будет Setup
byte KEY=keyIr(); //Читаем состояние кнопок
val=0;
// delay(200); //Если убрать, не работает подсветка уст.позиции
lcd.setCursor(7,0);
lcd.print("-R3- -R2-");
lcd.setCursor(0,3);
lcd.print("=== push to save ===");
lcd.setCursor(1, 1);
lcd.print(winMe+1,DEC); //Печатаем номер программы таймера
lcd.print("|");
lcd.print(pos/3,DEC); //Печатаем позицию настройки параметра (замена blink)
lcd.print("->");
lcd.setCursor(7,1); //Выводим инфу о часах и минутах
if (setHorClockOffR3<10) lcd.print("0");
lcd.print(setHorClockOffR3,DEC);
lcd.print(":");
if (setMinClockOffR3<10) lcd.print("0");
lcd.print(setMinClockOffR3,DEC);
lcd.print(" ");
if (setHorClockOffR2<10) lcd.print("0");
lcd.print(setHorClockOffR2,DEC);
lcd.print(":");
if (setMinClockOffR2<10) lcd.print("0");
lcd.print(setMinClockOffR2,DEC);
lcd.setCursor(pos,1); //Устанавливаем курсор согласно позиции
if (pos<3) pos=3;
if (KEY==5 && pos<11) pos += 3; //Крутим позицию право-лево
else if (KEY==2 && pos>3) pos -= 3;
else if (pos==3 && KEY==3) setHorClockOffR3++; //Крутим значения
else if (pos==3 && KEY==4) setHorClockOffR3--;
else if (pos==6 && KEY==3) setMinClockOffR3++;
else if (pos==6 && KEY==4) setMinClockOffR3--;
else if (pos==9 && KEY==3) setHorClockOffR2++;
else if (pos==9 && KEY==4) setHorClockOffR2--;
else if (pos==12 && KEY==3) setMinClockOffR2++;
else if (pos==12 && KEY==4) setMinClockOffR2--;
if (setHorClockOffR3>23) setHorClockOffR3=0; //Ограничиваем значения
if (setHorClockOffR2>23) setHorClockOffR2=0; //Ограничиваем значения
else if (setMinClockOffR3>59) setMinClockOffR3=0;
else if (setMinClockOffR2>59) setMinClockOffR2=0;
} //Конец цикла
// lcd.noBlink();
lcd.clear(); //Очищаем на всякий случай дисплейчик
EEPROM.write(winMe*4+1, setHorClockOffR3); //Записываем НОВЫЕ значения
EEPROM.write(winMe*4+2, setMinClockOffR3);
EEPROM.write(winMe*4+3, setHorClockOffR2);
EEPROM.write(winMe*4+4, setMinClockOffR2);
lcd.setCursor(4,2);
lcd.print("== Saved ==");
delay(zadTime[4]);
}
//=========== Обработка Меню, параметры диммирования (максимальное значение и пределы OUT2,3)
void setDimmer(){
byte pos=0;
maxDimm= EEPROM.read(winMe*4+1); //Считываем записанные значения диммирования
upR2= EEPROM.read(winMe*4+2); //Адрес определяется как номер диммера*4 + семь ячеек
downR2= EEPROM.read(winMe*4+3);
upR3= EEPROM.read(winMe*4+4);
downR3= EEPROM.read(winMe*4+5);
pManDimmUp= EEPROM.read(winMe*4+6);
pManDimmDown= EEPROM.read(winMe*4+7);
lcd.clear(); //Очищаем на всякий случай дисплейчик
// lcd.blink();
while(keyIr()!=1){ //Крутим цикл пока не будет Setup
byte KEY=keyIr(); //Читаем состояние кнопок
val=0;
// delay(200); //Если убрать, не работает подсветка уст.позиции
lcd.setCursor(0,3);
lcd.print("=== push to save ===");
lcd.setCursor(0, 0);
lcd.print(winMe+1,DEC); //Печатаем номер программы таймера
lcd.print("|");
lcd.print(pos/3,DEC); //Печатаем позицию настройки параметра (замена blink)
lcd.print("->");
lcd.setCursor(7,0); //Выводим инфу о часах и минутах
if (maxDimm<10) lcd.print("0");
lcd.print(maxDimm);
lcd.print(" dimm");
lcd.setCursor(0,1);
if (upR2<10) lcd.print("0");
lcd.print(upR2);
lcd.print("/");
if (downR2<10) lcd.print("0");
lcd.print(downR2);
lcd.print(" | ");
if (upR3<10) lcd.print("0");
lcd.print(upR3);
lcd.print("/");
if (downR3<10) lcd.print("0");
lcd.print(downR3);
lcd.setCursor(0,2); //Выводим инфу о часах и минутах
if (pManDimmUp<10) lcd.print("0");
lcd.print(pManDimmUp,DEC);
lcd.print(" *50ms");
lcd.print(" | ");
if (pManDimmDown<10) lcd.print("0");
lcd.print(pManDimmDown,DEC);
lcd.print(" *50ms");
lcd.setCursor(pos,0); //Устанавливаем курсор согласно позиции
if (pos<3) pos=3;
if (KEY==5 && pos<21) pos += 3; //Крутим позицию право-лево
else if (KEY==2 && pos>3) pos -= 3;
else if (pos==3 && KEY==3) maxDimm++; //Крутим значения
else if (pos==3 && KEY==4) maxDimm--;
else if (pos==6 && KEY==3) upR2++;
else if (pos==6 && KEY==4) upR2--;
else if (pos==9 && KEY==3) downR2++;
else if (pos==9 && KEY==4) downR2--;
else if (pos==12 && KEY==3) upR3++;
else if (pos==12 && KEY==4) upR3--;
else if (pos==15 && KEY==3) downR3++;
else if (pos==15 && KEY==4) downR3--;
else if (pos==18 && KEY==3) pManDimmUp++;
else if (pos==18 && KEY==4) pManDimmUp--;
else if (pos==21 && KEY==3) pManDimmDown++;
else if (pos==21 && KEY==4) pManDimmDown--;
if (pManDimmUp==0 && KEY==4) pManDimmUp=30; //Реверсивное изменение значений
if (pManDimmUp>30) pManDimmUp=0; //Ограничиваем значения
if (pManDimmDown==0 && KEY==4) pManDimmDown=30;
if (pManDimmDown>30) pManDimmDown=0;
} //Конец цикла
// lcd.noBlink();
lcd.clear(); //Очищаем на всякий случай дисплейчик
EEPROM.write(winMe*4+1, maxDimm); //Записываем НОВЫЕ значения
EEPROM.write(winMe*4+2, upR2);
EEPROM.write(winMe*4+3, downR2);
EEPROM.write(winMe*4+4, upR3);
EEPROM.write(winMe*4+5, downR3);
EEPROM.write(winMe*4+6, pManDimmUp);
EEPROM.write(winMe*4+7, pManDimmDown);
lcd.setCursor(4,2);
lcd.print("== Saved ==");
delay(zadTime[4]);
}
//=========== Обработка Меню, параметры установки времени и прочее
void setClock(){ // установка часов
byte pos=0;
lcd.clear(); //Очищаем на всякий случай дисплейчик
// lcd.blink();
while(keyIr()!=1){ //Крутим цикл пока не будет Setup
byte KEY=keyIr(); //Читаем состояние кнопок
val=0;
// delay(200); //Если убрать, не работает подсветка уст.позиции
lcd.setCursor(0,3);
lcd.print("=== push to save ===");
lcd.setCursor(0, 0);
lcd.print(winMe+1,DEC); //Печатаем номер программы таймера
lcd.print("|");
lcd.print(pos/3,DEC); //Печатаем позицию настройки параметра (замена blink)
lcd.print("->");
lcd.setCursor(7,0);
if (hours<10) lcd.print("0");
lcd.print(hours);
lcd.print(":");
if (minutes<10) lcd.print("0");
lcd.print(minutes);
lcd.print(":");
if (seconds<10) lcd.print("0");
lcd.print(seconds);
lcd.setCursor(0,1);
if (day<10) lcd.print("0");
lcd.print(day);
lcd.print(" | ");
if (date<10) lcd.print("0");
lcd.print(date);
lcd.print("/");
if (month<10) lcd.print("0");
lcd.print(month);
lcd.print("/");
if (year<10) lcd.print("0");
lcd.print(year);
lcd.setCursor(pos,0);
if (pos<3) pos=3; //Устанавливаем курсор согласно позиции
if (KEY==5 && pos<21) pos += 3; //Крутим позицию право-лево
else if (KEY==2 && pos>3) pos -= 3;
else if (pos==3 && KEY==3) hours++; //Крутим значения
else if (pos==3 && KEY==4) hours--;
else if (pos==6 && KEY==3) minutes++;
else if (pos==6 && KEY==4) minutes--;
else if (pos==9 && KEY==3) seconds++;
else if (pos==9 && KEY==4) seconds--;
else if (pos==12 && KEY==3) day++;
else if (pos==12 && KEY==4) day--;
else if (pos==15 && KEY==3) date++;
else if (pos==15 && KEY==4) date--;
else if (pos==18 && KEY==3) month++;
else if (pos==18 && KEY==4) month--;
else if (pos==21 && KEY==3) year++;
else if (pos==21 && KEY==4) year--;
if (hours>23) hours=0;
else if (minutes>59) minutes=0;
else if (seconds>59) seconds=0;
else if (day>7) day=1;
else if (date>31) date=1;
else if (month>12) month=1;
else if (year>99) year=0;
}
// lcd.noBlink();
lcd.clear(); //Очищаем на всякий случай дисплейчик
setRtc(seconds, minutes, hours, day, date, month, year);
lcd.setCursor(4,2);
lcd.print("== Saved ==");
delay(zadTime[4]);
}
//========== Считывание напряжения
void voltM(){
valueVo=analogRead(voltInput); //Read the value at analog input
vout=(valueVo*5.0)/1024.0; //See text
vin=vout/(R2/(R1+R2));
if (vin<0.09){
vin=0.0;} //Statement to quash undesired reading
}
//========== Считывание Давления
void bar(){
if (timeDps<millis()){ //Конструкция жуткая и жрущая море ресурсов при расчете вещественных чисел.
dps.calcTrueTemperature();
timeDps=millis()+1000;}
dps.getPressure(&Pressure);
}
//=========== Считывание температур
void dallas(){
ds.reset();
ds.write(0xCC); //Команда инициации
ds.write(0x44); //Start conversion, with parasite power on at the end
tzad=millis()+750; flagDallas=1;}
float DS18B20(byte *adres){
ds.reset();
ds.select(adres);
ds.write(0xBE); //Read Scratchpad
for (byte i=0; i<9; i++) data[i]=ds.read(); //We need 9 bytes
int raw=(data[1]<<8) | data[0]; //Переводим в температуру
float celsius=(float)raw/16.0; //Для ds18b20 делим на "16", для ds18s20 на "2"
return celsius;
}
//=========== Обработка Термо-Реле
void tempRelay(){
if (tzad<millis()&&flagDallas==1){
temp[0]=DS18B20(addr1);
temp[1]=DS18B20(addr2);
temp[2]=DS18B20(addr3);
prvMlsTemp=millis();
flagDallas=0;}
if (temp[0]>t[0]-tGistrsis/2){
digitalWrite(RelayChn1,LOW); //Термо-реле 1-включается
// lcd.setCursor(8, 2);
// lcd.print("*");
}
else if (temp[0]<t[0]+tGistrsis/2){
digitalWrite(RelayChn1,HIGH); //Термо-реле 1-выключается
// lcd.setCursor(8, 2);
// lcd.print("-");
}
if (temp[1]>t[1]-tGistrsis/2){
digitalWrite(RelayChn2,LOW); //Термо-реле 2-включается
// lcd.setCursor(18, 2);
// lcd.print("*");
}
else if (temp[1]<t[1]+tGistrsis/2){
digitalWrite(RelayChn2,HIGH); //Термо-реле 2-выключается
// lcd.setCursor(18, 2);
// lcd.print("-");
}
}
//=========== Обработка установки RTC часов
void setRtc(byte seconds, byte minutes, byte hours, byte day, byte date, byte month, byte year){
Wire.beginTransmission(DS3231_I2C_ADDRESS); //104 is DS3231 device address
Wire.write(0x00); //Start at register 0
Wire.write(decToBcd(seconds));
Wire.write(decToBcd(minutes));
Wire.write(decToBcd(hours));
Wire.write(decToBcd(day));
Wire.write(decToBcd(date));
Wire.write(decToBcd(month));
Wire.write(decToBcd(year));
Wire.endTransmission();
}
//=========== Обработка RTC часов
void timeRtc(){
Wire.beginTransmission(DS3231_I2C_ADDRESS); //104 is DS3231 device address
Wire.write(0x00); //Start at register 0
Wire.endTransmission();
Wire.requestFrom(DS3231_I2C_ADDRESS, 7); //Request seven bytes
if(Wire.available()) {
seconds = Wire.read(); //Get second
minutes = Wire.read(); //Get minute
hours = Wire.read(); //Get hour
day = Wire.read();
date = Wire.read();
month = Wire.read(); //Get month
year = Wire.read();
seconds = (((seconds & B11110000)>>4)*10 + (seconds & B00001111)); //Convert BCD to decimal
minutes = (((minutes & B11110000)>>4)*10 + (minutes & B00001111));
hours = (((hours & B00110000)>>4)*10 + (hours & B00001111)); //Convert BCD to decimal (assume 24 hour mode)
day = (day & B00000111); // 1-7
date = (((date & B00110000)>>4)*10 + (date & B00001111)); //Convert BCD to decimal 1-31
month = (((month & B00010000)>>4)*10 + (month & B00001111)); //msb7 is century overflow
year = (((year & B11110000)>>4)*10 + (year & B00001111));
}
}
//=========== Обработка Таймеров
void timer(){
//========== Таймер №1
int fulMin=hours*60+minutes; //Переводим часы + минуты к полным минутам
int fulMinOn1= EEPROM.read(1)*60+EEPROM.read(2); //Переводим часы + минуты включения 1 реле к полным минутам
int fulMinOff1= EEPROM.read(3)*60+EEPROM.read(4); //Переводим часы + минуты выключения 1 реле к полным минутам
int fulMinOn2= EEPROM.read(5)*60+EEPROM.read(6); //Переводим часы + минуты включения 2 реле к полным минутам
int fulMinOff2= EEPROM.read(7)*60+EEPROM.read(8); //Переводим часы + минуты выключения 2 реле к полным минутам
int fulMinOnLcd= EEPROM.read(9)*60+EEPROM.read(10); //Переводим часы + минуты включения Lcd к полным минутам
int fulMinOffLcd= EEPROM.read(11)*60+EEPROM.read(12); //Переводим часы + минуты выключения Lcd к полным минутам
int fulMinOffOut3= EEPROM.read(13)*60+EEPROM.read(14); //Переводим часы + минуты выключения OUT3 к полным минутам
int fulMinOffOut2= EEPROM.read(15)*60+EEPROM.read(16); //Переводим часы + минуты выключения OUT2 к полным минутам
if (fulMinOn1>fulMinOff1) {isNight=1;} //Если ночное время
if (isNight==0){ //Если день
if (fulMin>=fulMinOn1&&fulMin<fulMinOff1) {isLght[0]=1;} //Проверяем интервал
else {isLght[0]=0;} //Если необходимо включить свет
} else { //Если ночь
if(fulMin-fulMinOn1>=0) {isLght[0]=1;} //Если больше или равно верхнему значению, то необходимо включить свет
else { //Если необходимо включить свет
if(fulMin<fulMinOff1) {isLght[0]=1;} //Если меньше нижнего значения, то необходимо включить свет
else {isLght[0]=0;} //Если необходимо включить свет
}
}
if((isLght[0]==1)&&(lghtStat[0]==0)){ //Если свет еще не включен и выставлен флаг необходимости включить
if (tDimm < millis()){ //И не дана команда на полное выключение
(EEPROM.read(26)*50); dimmUp();}
if (angData==EEPROM.read(21)) {lghtStat[0]=1;}
} else {
if(isLght[0]==0&&lghtStat[0]==1){
if (tDimm < millis()){
(EEPROM.read(27)*50); dimmDown();}
if (angData==0){lghtStat[0]=0;}
}
}
//========== Таймер №2
if (fulMinOn2>fulMinOff2) {isNight=1;} //Если ночное время
if (isNight==0){ //Если день
if (fulMin>=fulMinOn2&&fulMin<fulMinOff2) {isLght[1]=1;} //Проверяем интервал
else {isLght[1]=0;} //Если необходимо включить свет
} else { //Если ночь
if(fulMin-fulMinOn2>=0) {isLght[1]=1;} //Если больше или равно верхнему значению, то необходимо включить свет
else { //Если необходимо включить свет
if(fulMin<fulMinOff2) {isLght[1]=1;} //Если меньше нижнего значения, то необходимо включить свет
else {isLght[1]=0; } //Если необходимо включить свет
}
}
if((isLght[1]==1)&&(lghtStat[1]==0)){ //Если свет еще не включен и выставлен флаг необходимости включить
if (tDimm < millis()){ //И не дана команда на полное выключение
(EEPROM.read(26)*50); dimmUp();}
if (angData==EEPROM.read(21)) {lghtStat[1]=1;}
} else {
if(isLght[1]==0&&lghtStat[1]==1){
if (tDimm < millis()){
(EEPROM.read(27)*50); dimmDown();}
if (angData==0){lghtStat[1]=0;}
}
}
//========== Таймер Lcd-подсветки
if (fulMinOnLcd>fulMinOffLcd) {isNight=1;} //Если ночное время
if (isNight==0){ //Если день
if (fulMin>=fulMinOnLcd&&fulMin<fulMinOffLcd) {isLcdt=1;} //Проверяем интервал
else {isLcdt=0;} //Если необходимо включить подсветку Lcd
} else { //Если ночь
if(fulMin-fulMinOnLcd>=0) {isLcdt=1;} //Если больше или равно верхнему значению, то необходимо включить подсветку Lcd
else { //Если необходимо включить подсветку Lcd
if(fulMin<fulMinOffLcd) {isLcdt=1;} //Если меньше нижнего значения, то необходимо включить подсветку Lcd
else {isLcdt=0;} //Если необходимо включить подсветку Lcd
}
}
if((isLcdt==1)&&(lcdStat==0)){ //Если подсветка Lcd еще не включена и выставлен флаг необходимости включить
lcd.backlight(); lcdStat=1;
} else {
if(isLcdt==0&&lcdStat==1){
lcd.noBacklight(); lcdStat=0;
}
}
//========== Таймер "Лунного света"
if (fulMin>=fulMinOffOut3) {
digitalWrite(OUT3,HIGH);}
if (fulMin>=fulMinOffOut2) {
digitalWrite(OUT2,HIGH);
}
//========== Таймер СО2
}
/*
//=========== Обработка Bluetooth
void bluetooth() {
if (Serial.available()>0){
}
*/
//=========== Обработка Аврийного индикатора
void bLinkLed(){
if (prvMlsbLink+zadTime[1]<millis()){ //Проверка условия
prvMlsbLink=millis(); //Установка задержки
digitalWrite(bLink,!digitalRead(bLink));} //Инверсия значения
}
//=========== Обработка отключения ВСЕХ OUT (реле)
void relayHigh(){
digitalWrite(OUT0,HIGH); //Определяем инверсный выход в HIGH реле ATX
digitalWrite(OUT1,HIGH); //Определяем инверсный выход в HIGH реле 1 канала Led
digitalWrite(OUT2,HIGH); //Определяем инверсный выход в HIGH реле 2 канала Led
digitalWrite(OUT3,HIGH); //Определяем инверсный выход в HIGH реле 3 канала Led
}
//=========== Обработки печати и вывода на дисплейчик (часы)
void printTime(){
if (millis()-prvMlsTm>zadTime[3]){ //Проверяем интервал для обновления часов
prvMlsTm=millis(); //Вызываем ф-цию вывода времени на экран
lcd.setCursor(0,0);
if (hours<10) {lcd.print(0);lcd.print(hours);} else {lcd.print(hours);}
lcd.print(":");
if (minutes<10) {lcd.print(0);lcd.print(minutes);} else {lcd.print(minutes);}
lcd.print(":");
if (seconds<10) {lcd.print(0);lcd.print(seconds);} else {lcd.print(seconds);}
}
if (millis()-prvMlsRazd>zadTime[4]){ //Проверяем интервал для обновления ":"
prvMlsRazd=millis();
lcd.setCursor(2,0);
lcd.print(" ");
lcd.setCursor(5,0);
lcd.print(" ");
lcd.setCursor(8,0);
lcd.print(" ");
}
}
//=========== Обработки печати и вывода на дисплейчик (напряжения, температуры, давление)
void printDin(){
if (millis()-prvMlsVo>zadTime[7]){ //Проверяем интервал для обновления
prvMlsVo=millis();
lcd.setCursor(2,2); //Вывод значений температур на LCD
lcd.print((temp[0]),1);
lcd.setCursor(9,2);
lcd.print((temp[1]),1);
lcd.setCursor(16,2);
lcd.print((temp[2]),1);
lcd.setCursor(9,3);
lcd.print(vin);
lcd.setCursor(4,1);
lcd.print(Pressure/133.3,1); //Выводим на экранчик показания атм.давления в мм.рт.столба
}
}
//=========== Обработки печати и вывода на дисплейчик СТАТИКИ
void printStat(){
if (millis()-prvMlsTimer>zadTime[8]){ //Проверяем интервал для обновления
prvMlsTimer=millis();
lcd.setCursor(16,1);
lcd.print("pw\1");
lcd.setCursor(0,1);
lcd.print("bar\1");
lcd.setCursor(0,2);
lcd.print("a\1");
lcd.setCursor(7,2);
lcd.print("b\1");
lcd.setCursor(14,2);
lcd.print("c\1");
lcd.setCursor(0,3);
lcd.print("~");
lcd.setCursor(2,3);
lcd.print(":");
lcd.setCursor(4,3);
lcd.print(":");
lcd.setCursor(7,3);
lcd.print("v\1");
lcd.setCursor(15,3);
lcd.print("%\1");
lcd.setCursor(9,0);
if (date<10) {lcd.print(0);lcd.print(date);} else {lcd.print(date);}
lcd.print("/");
if (month==1){lcd.print ("Jan");}
if (month==2){lcd.print ("Feb");}
if (month==3){lcd.print ("Mar");}
if (month==4){lcd.print ("Apr");}
if (month==5){lcd.print ("May");}
if (month==6){lcd.print ("Jun");}
if (month==7){lcd.print ("Jul");}
if (month==8){lcd.print ("Aug");}
if (month==9){lcd.print ("Sep");}
if (month==10){lcd.print ("Oct");}
if (month==11){lcd.print ("Nov");}
if (month==12){lcd.print ("Dec");}
lcd.print("/");
lcd.print(year+2000);
lcd.setCursor(12,1);
if (day==1){lcd.print ("Sun");}
if (day==2){lcd.print ("Mon");}
if (day==3){lcd.print ("Tue");}
if (day==4){lcd.print ("Wed");}
if (day==5){lcd.print ("Thu");}
if (day==6){lcd.print ("Fri");}
if (day==7){lcd.print ("Sat");}
lcd.setCursor(19,1); //Вывод состояния ATX (Power ON\OFF)
lcd.print(!digitalRead(OUT0));
lcd.setCursor(1,3); //Вывод состояния выходов реле освещения
lcd.print(!digitalRead(OUT1));
lcd.setCursor(3,3);
lcd.print(!digitalRead(OUT2));
lcd.setCursor(5,3);
lcd.print(!digitalRead(OUT3));
}
if (millis()-prvMlsOut>zadTime[0]){ //Проверяем интервал для обновления
prvMlsOut=millis();
lcd.setCursor(17,3); //Вывод состояния аналогового выхода диммирования
lcd.print(angData);
lcd.setCursor(18,3);
lcd.print(" ");
lcd.setCursor(17,3);
lcd.print(angData);
}
}
void loop(){
timeRtc();
timer();
keyI();
if (millis()-prvMlsTemp>zadTime[6]&&flagDallas!=1){dallas();}
tempRelay();
voltM();
bar();
// bluetooth();
printTime();
printDin();
printStat();
}
Блютусина или вафля планировались для передачи параметров на смарт или на страничку. Без них можно но уж очень хочется. Вот почему в ардуинках нет 64кб к примеру а или 128 или 32 (за минусом загрузчиков и пр).
Как нету, Мега 256, там аж 256К. По большому счету, глобально убавить не выйдет, либо от чего то отказыватся, либо голый C+ учить((((, но ассемблер круче))))
350Сегодня приехал наконец ДХТ-11 , разобрал и впаял между первой и второй ногами (+ и data) резистрор в 10кОм, третий вывод неиспользовался и на четвертый GND. Добавил библиотеку, и воткнул в код. Размер увеличился всего на 350кБ а это значит что зря очковал и место ещё вполне....
выглядит так функция влажности к моему акваконтроллеру:
#include <DHT.h> //Подключаем библиотеку для датчика влажности и температуры
//=====Humidity*
#define dhtPin 10 //What pin we're connected to
#define dhtType DHT11 //DHT 11
DHT dht(dhtPin, dhtType);
float hmdt,tmpr; //Температуру можно выкинуть и невключать в гл.переменную тем более такую как float :))
void setup() {
dht.begin(); }
//========== Считывание Влажности
void humiDity(){
hmdt=dht.readHumidity(); //Reading temperature or humidity takes about 250 milliseconds!
// tmpr=dht.readTemperature(); //Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
}
void printDin(){
if (millis()-prvMlsVo>zadTime[7]){ //Проверяем интервал для обновления напряжения
prvMlsVo=millis();
tft.setTextSize(1);
tft.setTextColor(ST7735_YELLOW, ST7735_BLACK);
tft.setCursor(98,50);
tft.print(hmdt);
}
void loop(){
humiDity();
}
Само собой кусочек пока из тестовой МЕГИ, в Nano и Lcd перенесу как потестю как следует. Вот и мне кажется брешет падлюка, показывет 21-23% ну этоже нивкакие ворота. Это почти пустыня.. Может резистро ненужен "подтягивающий". Вобщем или это шляпи и нужно что рекомендовали выше постами или пусть будет :)
Думаю можно выложить готовый вариант скетча, уже успешно отработанный и работающий более месяца при частых отключениях электричества и высоких токах нагрузки (до 23А).
Сам скетч, урезал максимально и то нехватило метса для авариынйх индикаторво и отключений, невлезла функция определения "уровня воды", работа с Wi-Fi. Пока довольствуюсь блютусинкой.
Итак скетчик для lcd:
#include <EEPROM.h>
#include <Wire.h> //Подключаем библиотеку для использования однопроводного интерфейса
#include <LiquidCrystal_I2C.h> //Подключаем библиотеку для использования I2C интерфейса
#include <OneWire.h> //Подключаем библиотеку для температурного датчика DS18B20
#include <BMP085.h> //Подключаем библиотеку для маленького барометра
#include <DHT.h> //Подключаем библиотеку для маленького барометра (темп., абс.высота и атм.давление)
#include <IRremote.h> //Подключаем библиотеку для IR сенсора
LiquidCrystal_I2C lcd(0x27,20,4); //Устанавливаем LCD-адрес 0x27 для отображения 20 символов и 4 линии
byte currentLight=0; //Переменная включения подсветки LCD
//=====IR_Sensor*
#define recvPin 3 //Вход IR-приемника и кнопки пульта
uint32_t val;
IRrecv irrecv(recvPin);
decode_results results;
//=====IR_Dimmer*
byte angData=0; //Переменная выходов диммирования (из двух половинок :))
byte flagDimm=0; //Флаг для обработки "НЕОБРАТИМОГО" выключения Power_Off
unsigned long tDimm=millis(); //Переменная задержки auto_dimmer
//=====Termo_Relay*
#define tOUT1 4 //Используем цифровой ПОРТ 4 для ПЕРВОГО канала термо-реле (вода)
#define tOUT2 A1 //Используем цифровой ПОРТ A1 для ВТОРОГО канала термо-реле (радиатор)
#define tOUT3 A3 //Используем цифровой ПОРТ A3 для ТРЕТЬЕГО канала термо-реле (блок реле)
//=====Led_Relay*
#define OUT1 7 //Используем цифровой ПОРТ 7 для 1 свето-релейного канала Dimm
#define OUT2 8 //Используем цифровой ПОРТ 8 для 2 свето-релейного канала
#define OUT3 9 //Используем цифровой ПОРТ 9 для 3 свето-релейного канала
//=====Other_Relay*
#define OUT0 10 //Используем цифровой ПОРТ 10 для ATX (включение ATX (зелёный + черный))
#define OUT6 11 //Используем цифровой ПОРТ 11 для CO2
//#define OUT7 12 //Используем цифровой ПОРТ 12 для другое
//=====Dimmer_Out*
#define OUT4 5 //Используем цифровой ПОРТ 5 для 1/2 SunSet канала (dimmer)
#define OUT5 6 //Используем цифровой ПОРТ 6 для 1/2 SunSet канала (dimmer)
//=====Blink led*
//#define bLink 13 //Индикатор и аварийный сброс
//=====VoltMeter*
int voltInput=A7; //Используем аналоговый вход A7 для измерения напряжения
float vout=0.0;
float vin=0.0;
float R1=21700.0; //Resistance of R1 (22K) - see text!
float R2=10370.0; //Resistance of R2 (12K) - see text!
int valueVo=0;
//=====Pressure*
BMP085 dps=BMP085(); //Digital Pressure Sensor
long Pressure=0;
unsigned long timeDps=0;
//=====Humidity*
#define dhtPin A2 //Используем цифровой ПОРТ 14 для входа датчика влажности DHT11
#define dhtType DHT11 //Определяем порт шины DHT11
DHT dht(dhtPin, dhtType);
float hmdt;
//=====Termo_Sensor*
int tempPin=2; //Определяем порт шины OneWire (IC) для температурного датчика DS18B20
OneWire ds(tempPin); //Создаем объект для работы с термометром
byte flagDallas=0; //Флаг для обработки показаний с датчиков Dallas
byte data[12];
byte addr1[8]={0x28,0xC5,0x3B,0x5C,0x06,0x00,0x00,0x85}; //адрес датчика DS18B20_Вода в аквариуме
byte addr2[8]={0x28,0x86,0x48,0xEA,0x05,0x00,0x00,0xF6}; //адрес датчика DS18B20_Радиатор (2-ой канал, центр)
byte addr3[8]={0x28,0xF2,0x29,0xEB,0x05,0x00,0x00,0xE1}; //адрес датчика DS18B20_Блок реле
unsigned int raw; //Если экранированный кабель, можно подключать до 32 термо-датчиков DS18B20
float temp[3]; //Температура аквариума / радиаторов Led / блока реле
//=====Rtc_Clock*
#define DS3231_I2C_ADDRESS 104
byte seconds, minutes, hours, day, date, month, year;
byte decToBcd (byte val){return((val/10*16)+(val%10));}
//=====Timer*
// long lghtIntv=60000; //Интервал для проверки вкл./выкл. освещения аквариума, 1 минута
byte lcdStat=0; //Флаг подсветки Lcd если включена, то в 1
byte lghtStat[2]; //Флаг освещения, если включена, то в 1 в первом и втором таймере
byte co2Stat=0; //Флаг Co2, если включена, то в 1
byte isLcdt=0; //Флаг для обработки необходимости включить подсветку Lcd
byte isLght[2]; //Флаг для обработки необходимости включить реле освещения в первом и втором таймере
byte isCo2t=0; //Флаг для обработки необходимости включить реле Co2
byte isNight=0; //Если включаем на ночь, т.е. начальное время больше конечного
//=====Menu*
byte winMe; //Номер экрана меню
byte setHorClockOn; //Часы включения Таймера
byte setMinClockOn; //Минуты включения Таймера
byte setHorClockOff; //Часы вЫключения Таймера
byte setMinClockOff; //Минуты вЫключения Таймера
byte setHorClockOffR3; //Часы вЫключения OUT3, (R3)
byte setMinClockOffR3; //Минуты вЫключения OUT3, (R3)
byte setHorClockOffR2; //Часы вЫключения OUT2, (R2)
byte setMinClockOffR2; //Минуты вЫключения OUT2, (R2)
byte setTemptGist; //Гистерезис температур (по 1/2 в каждую сторону)
byte setTemptAqu; //Максимальная температура t1 (вода в аквариуме)
byte setTemptLed; //Максимальная температура t2 (радиатор Led)
byte setTemptRel; //Максимальная температура t3 (блок коммутации, реле)
byte maxDimm; //Переменная определяет МАКСИМАЛЬНОЕ значение диммирования
byte upR2; //Переменная включения OUT2
byte downR2; //Переменная вЫключения OUT2
byte upR3; //Переменная включения OUT3
byte downR3; //Переменная вЫключения OUT3
byte pManDimmUp; //Период увеличения яркости
byte pManDimmDown; //Период уменьшения яркости
//=====Delays*
unsigned long prvMlsTm=0; //Предыдущее показание миллисекунд для обновления показания часов
unsigned long prvMlsRazd=0; //Предыдущее показание миллисекунд для обновления ":"
unsigned long prvMlsVo=0; //Предыдущее показание обновления показания вольтметра
unsigned long prvMlsOut=0; //Предыдущее показание обновления показания OUT
//unsigned long prvMlsBar=0; //Предыдущее показание обновления показания барометра
unsigned long prvMlsTemp=0; //Предыдущее показание обновления температур
unsigned long prvMlsTimer=0; //Предыдущее показание обновления таймера
unsigned long prvMlsbLink=0; //Предыдущее показание миллисекунд для обновления "blink led"
unsigned long tzad=millis(); //Переменная задержки (пока для ds18b20, ds.write)
//unsigned long zadM[4]; //Массив для задержек меню
const long zadTime[]={100,500,750,1000,2000,3000,5000,10000,60000};
const char menuTxt[8][17]={"set Timer 1 >>>>","set Timer 2 >>>>","set Timer Lcd >>",
"set MoonLight >>","set Timer Co2 >>","set Termorele >>",
"set Dimmer >>>>>","set Clock >>>>>>"}; //Массив с наименованиями для экрана
//=====Byte_Symbol*
byte equ[8]={B00000,B00000,B01110,B00000,B01110,B00000,B00000}; //Символ "=" но КОРОТКИЙ :)
void setup() {
Wire.begin();
Serial.begin(9600);
irrecv.enableIRIn(); //Включаем IR-сенсор
dps.init(MODE_STANDARD, 25000, true); //250 meters, true = using meter units
pinMode(voltInput,INPUT); //Определяем вход вольтметра
pinMode(tOUT1,OUTPUT); //Определяем выход 1-термореле охлаждения воды аквариума
pinMode(tOUT2,OUTPUT); //Определяем выход 2-термореле охлаждения радиаторов Led
pinMode(tOUT3,OUTPUT); //Определяем выход 2-термореле охлаждения блока реле
digitalWrite(tOUT1,HIGH); //Определяем инверсный выход в HIGH охлаждения воды аквариума
digitalWrite(tOUT2,HIGH); //Определяем инверсный выход в HIGH охлаждения радиаторов Led
digitalWrite(tOUT3,HIGH); //Определяем инверсный выход в HIGH охлаждения блока реле
pinMode(OUT0,OUTPUT); //Определяем инверсный выход реле ATX
pinMode(OUT1,OUTPUT); //Определяем инверсные выходы реле 1 канала Led
pinMode(OUT2,OUTPUT); //Определяем инверсные выходы реле 2 канала Led
pinMode(OUT3,OUTPUT); //Определяем инверсные выходы реле 3 канала Led
pinMode(OUT6,OUTPUT); //Определяем инверсные выходы реле подачи СО2
// pinMode(bLink,OUTPUT); //Определяем аварийный "blink led"
// pinMode(OUT7,OUTPUT);
digitalWrite(OUT0,HIGH); //Определяем инверсный выход в HIGH реле ATX
digitalWrite(OUT1,HIGH); //Определяем инверсный выход в HIGH реле 1 канала Led
digitalWrite(OUT2,HIGH); //Определяем инверсный выход в HIGH реле 2 канала Led
digitalWrite(OUT3,HIGH); //Определяем инверсный выход в HIGH реле 3 канала Led
digitalWrite(OUT6,HIGH); //Определяем инверсный выход в HIGH реле СО2
// digitalWrite(bLink,HIGH); //Определяем аварийный "blink led" в HIGH
// digitalWrite(OUT7,HIGH);
analogWrite(OUT4,angData); //Инициация выхода 1/2 диммера
analogWrite(OUT5,angData); //Инициация выхода 1/2 диммера
lcd.init(); //Инициализируем дисплейчик
lcd.setBacklight(1);
lcd.createChar(1,equ); //Создаем символ под номером 1
lcd.clear(); //Очищаем на всякий случай дисплейчик
lcd.setCursor(2,0);
lcd.print("Aqua Controller"); //Выводим версию и прочее
lcd.setCursor(2,1);
lcd.print(" v4.2 ");
lcd.setCursor(0,3);
lcd.print("_0703_menu_app_");
delay(2000);
lcd.clear(); //Очистка дисплея и void (printTime, printDin, printStat)
}
//========== Обработка IR-сенсора, определение кнопок
byte keyIr(){
if (irrecv.decode(&results)){ //Если пришел пакет и этот пакет не FF сохраняем правильный пакет в переменную
// if (results.value!=0xFFFFFFFF){ //Если пришел FF, соответственно пропускаем.
val=results.value; //} //Сверяем значение из переменной val.. если пришла команда повтора (пакет с FF)
irrecv.resume();} //В переменной останется прошлый, правильный, пакет и код выполнится повторно.
// Serial.println(val,HEX); //Далее, очистить входящий буфер
// Serial.println(" ");
if (val==0x41BEC03F) return 1; //setup KEY1
if (val==0x41BE40BF) return 2; //left KEY2
if (val==0x41BED02F) return 3; //up KEY3
if (val==0x41BE609F) return 4; //down KEY4
if (val==0x41BEB04F) return 5; //right KEY5
if (val==0x41BEF00F) return 6; //exit POWER_KEY
if (val==0x41BE708F) return 7; //vol_down KEY9
if (val==0x41BE10EF) return 8; //vol_up KEY8
if (val==0x41BE20DF) return 9; //slide KEY9
if (val==0x41BEA05F) return 10; //stop KEY10
else return 0; //ежели ничего ненажмато
}
//========== Обработка IR-кнопок
void keyI(){
byte KEY=keyIr();
//========== Обработка Входа в Меню
if (KEY==1){ //ВХОД В МЕНЮ и проверка блокировки от возврата. Принимаем код клавиши
val=0;
menu();} //Если setup идем в меню
//========== Отключение LCD с кнопки
if (KEY==9){ val=0;
lcd.setBacklight(currentLight);
currentLight=!currentLight;}
//========== Увеличение яркости (удержание кнопки) 188кБ
if (KEY==5){ val=0;
if (angData<255) angData++;
analogWrite(OUT4,angData);
analogWrite(OUT5,angData);
if (angData>0){
digitalWrite(OUT0,LOW); //Включаем реле ATX
digitalWrite(OUT1,LOW); }
}
//========== Уменьшение яркости (удержание кнопки)
if (KEY==2){ val=0;
if (angData!=0) angData--;
analogWrite(OUT4,angData);
analogWrite(OUT5,angData);
if (angData==0) { //Выключаем реле диммера (по окончании диммирования)
digitalWrite(OUT1,HIGH);
digitalWrite(OUT2,HIGH);
digitalWrite(OUT3,HIGH);
digitalWrite(OUT0,HIGH);} //Выключаем реле ATX
}
//========== Обработка "одного" нажатия
if (KEY==8 & flagDimm==0){ //Если нажата кнопка УВЕЛИЧЕНИЯ диммирования
if (tDimm<millis()){ //и не дана команда на полное выключение
(EEPROM.read(30)*50); dimmUp();} //Интервал УВЕЛИЧЕНИЯ диммирования
}
if (KEY==7 & flagDimm==0){ //Здесь аналогично увеличению яркости
if (tDimm<millis()){
(EEPROM.read(31)*50); dimmDown();} //Интервал Снижения диммирования
}
if (KEY==6 & angData!=0){ //Power_Off. Если диммер включен, устанавливаем флаг
flagDimm=1; }
if (flagDimm==1){ //Если флаг установлен, продолжаем уменьшение яркости
if (angData==0){ //Яркость на 0, флаг сбросили.
flagDimm=0;
digitalWrite(OUT1,HIGH);
digitalWrite(OUT2,HIGH);
digitalWrite(OUT3,HIGH);
digitalWrite(OUT0,HIGH);}
if (tDimm<millis()){ //Последовательно уменьшаем яркость, кнопки заблокированы
(EEPROM.read(31)*50)/2; dimmDown();} //Интервал СНИЖЕНИЯ диммирования (по Power_Off)
val=0;
}
//========== Обработка ATX, НЕдиммируемых реле
if (KEY==3){
val=0; if (!digitalRead(OUT1)!=0 && angData>=1) digitalWrite(OUT2,!digitalRead(OUT2));}
if (KEY==3){
val=0; if (!digitalRead(OUT1)!=0 && angData!=0) digitalWrite(OUT2,digitalRead(OUT2));}
if (KEY==4){
val=0; if (digitalRead(OUT1)==0 && angData>=1) digitalWrite(OUT3,!digitalRead(OUT3));}
if (KEY==4){
val=0; if (digitalRead(OUT1)==0 && angData!=0) digitalWrite(OUT3,digitalRead(OUT3));}
}
//========== Увеличение яркости (auto)
void dimmUp(){
if (angData<EEPROM.read(25)){ //Ограничение верхнего значения диммирования, (0-255)
angData++; //Начало подъёма диммирования
analogWrite(OUT4,angData); //Пишем в порты
analogWrite(OUT5,angData);
if (angData>0){ //Включаем реле ATX и диммера на первом шаге (начало диммирования)
digitalWrite(OUT0,LOW);
digitalWrite(OUT1,LOW);}
if (angData==EEPROM.read(26)){ //Включаем Второе реле при upR2
digitalWrite(OUT2,LOW);}
if (angData==EEPROM.read(28)){ //Включаем Третье реле при upR3
digitalWrite(OUT3,LOW);}
tDimm=millis()+(EEPROM.read(30)*50);} //Устанавливаем время следующего шага
if (angData==EEPROM.read(25)){val=0;}
}
//========== Уменьшение яркости (auto)
void dimmDown(){
if (angData>0){
angData--; //Начало снижения диммирования
analogWrite(OUT4,angData);
analogWrite(OUT5,angData);
if (angData==EEPROM.read(29)){ //Выключаем Третье реле при downR3
digitalWrite(OUT3,HIGH);}
if (angData==EEPROM.read(27)){ //Выключаем Втором реле при downR2
digitalWrite(OUT2,HIGH);}
if (angData==0){ //Выключаем реле диммера (по окончании диммирования)
digitalWrite(OUT0,HIGH);
digitalWrite(OUT1,HIGH);
digitalWrite(OUT2,HIGH);
digitalWrite(OUT3,HIGH);}
tDimm=millis()+(EEPROM.read(31)*50);} //Устанавливаем время следующего шага
if (angData==0){val=0;}
}
//=========== Обработка Меню, выбор экрана
void menu(){
lcd.clear(); //Очищаем на всякий случай дисплейчик
byte pos=0;
while(1){ //bLinkLed(); //Бесконечный цикл
byte KEY=keyIr();
val=0;
lcd.setCursor(0,1);
lcd.print(pos+1); //Печатаем номер
lcd.print(". ");
lcd.print(menuTxt[pos]); //Печатаем название
if (KEY==3 && pos>0) {pos--;} //Уменьшить/увеличить позицию окна меню
else if (pos==0 && KEY==3) {pos=7;} //Уменьшить/увеличить (циклично)
if (KEY==4 && pos<7) {pos++;}
else if (pos==7 && KEY==4) {pos=0;}
winMe=pos; //Переменная номера окна подменю
if (KEY==5 && pos==0) setOnOff(); //"set Timer 1 >>>>" 0
if (KEY==5 && pos==1) setOnOff(); //"set Timer 2 >>>>" 1
if (KEY==5 && pos==2) setOnOff(); //"set Timer Lcd >>" 2
if (KEY==5 && pos==3) setMoonLgh(); //"set MoonLight >>" 3
if (KEY==5 && pos==4) setOnOff(); //"set Timer Co2 >>" 4
if (KEY==5 && pos==5) setTermorele(); //"set Termorele >>" 5
if (KEY==5 && pos==6) setDimmer(); //"set Dimmer >>>>>" 6
if (KEY==5 && pos==7) setClock(); //"set Clock >>>>>>" 7
if (KEY==1){ //Выход из меню с проверкой и установкой блокировки от возврата
lcd.clear(); //Очищаем на всякий случай дисплейчик
break;}
}
}
//=========== Обработка Меню, параметры и настройка
void setOnOff(){
byte pos=0;
setHorClockOn= EEPROM.read(winMe*4+1); //Считываем записанные значения таймеров
setMinClockOn= EEPROM.read(winMe*4+2); //Адрес определяется как номер таймера*4 + четыре ячейки
setHorClockOff= EEPROM.read(winMe*4+3);
setMinClockOff= EEPROM.read(winMe*4+4);
lcd.clear(); //Очищаем на всякий случай дисплейчик
// lcd.blink();
while(keyIr()!=1){ //Крутим цикл пока не будет Setup
byte KEY=keyIr(); //Читаем состояние кнопок
val=0;
// delay(200); //Если убрать, не работает подсветка уст.позиции
lcd.setCursor(7,0);
lcd.print("-On- -Off-");
lcd.setCursor(0,3);
lcd.print("=== push to save ===");
lcd.setCursor(1,1);
lcd.print(winMe+1,DEC); //Печатаем номер программы таймера
lcd.print("|");
lcd.print(pos/3,DEC); //Печатаем позицию настройки параметра (замена blink)
lcd.print("->");
lcd.setCursor(7,1); //Выводим инфу о часах и минутах
if (setHorClockOn<10) lcd.print("0");
lcd.print(setHorClockOn,DEC);
lcd.print(":");
if (setMinClockOn<10) lcd.print("0");
lcd.print(setMinClockOn,DEC);
lcd.print(" ");
if (setHorClockOff<10) lcd.print("0");
lcd.print(setHorClockOff,DEC);
lcd.print(":");
if (setMinClockOff<10) lcd.print("0");
lcd.print(setMinClockOff,DEC);
if (KEY==2 && pos==3){ //Выход из подменю без сохранения
lcd.clear(); //Очищаем на всякий случай дисплейчик
return; winMe=pos;}
lcd.setCursor(pos,1); //Устанавливаем курсор согласно позиции
if (pos<3) pos=3;
if (KEY==5 && pos<11) pos += 3; //Крутим позицию право-лево
else if (KEY==2 && pos>3) pos -= 3;
else if (pos==3 && KEY==3) setHorClockOn++; //Крутим значения
else if (pos==3 && KEY==4) setHorClockOn--;
else if (pos==6 && KEY==3) setMinClockOn++;
else if (pos==6 && KEY==4) setMinClockOn--;
else if (pos==9 && KEY==3) setHorClockOff++;
else if (pos==9 && KEY==4) setHorClockOff--;
else if (pos==12 && KEY==3) setMinClockOff++;
else if (pos==12 && KEY==4) setMinClockOff--;
if (setHorClockOn>23) setHorClockOn=0; //Ограничиваем значения
else if (setMinClockOn>59) setMinClockOn=0;
else if (setHorClockOff>23) setHorClockOff=0;
else if (setMinClockOff>59) setMinClockOff=0;
} //Конец цикла
// lcd.noBlink();
lcd.clear(); //Очищаем на всякий случай дисплейчик
EEPROM.write(winMe*4+1, setHorClockOn); //Записываем НОВЫЕ значения
EEPROM.write(winMe*4+2, setMinClockOn);
EEPROM.write(winMe*4+3, setHorClockOff);
EEPROM.write(winMe*4+4, setMinClockOff);
lcd.setCursor(4,2);
lcd.print("== Saved ==");
delay(zadTime[4]);
}
//=========== Обработка Меню, Лунный свет
void setMoonLgh(){
byte pos=0;
setHorClockOffR3= EEPROM.read(winMe*4+1); //Считываем записанные значения таймеров
setMinClockOffR3= EEPROM.read(winMe*4+2); //Адрес определяется как номер таймера*4 + четыре ячейки
setHorClockOffR2= EEPROM.read(winMe*4+3);
setMinClockOffR2= EEPROM.read(winMe*4+4);
lcd.clear(); //Очищаем на всякий случай дисплейчик
// lcd.blink();
while(keyIr()!=1){ //Крутим цикл пока не будет Setup
byte KEY=keyIr(); //Читаем состояние кнопок
val=0;
// delay(200); //Если убрать, не работает подсветка уст.позиции
lcd.setCursor(7,0);
lcd.print("-R3- -R2-");
lcd.setCursor(0,3);
lcd.print("=== push to save ===");
lcd.setCursor(1, 1);
lcd.print(winMe+1,DEC); //Печатаем номер программы таймера
lcd.print("|");
lcd.print(pos/3,DEC); //Печатаем позицию настройки параметра (замена blink)
lcd.print("->");
lcd.setCursor(7,1); //Выводим инфу о часах и минутах
if (setHorClockOffR3<10) lcd.print("0");
lcd.print(setHorClockOffR3,DEC);
lcd.print(":");
if (setMinClockOffR3<10) lcd.print("0");
lcd.print(setMinClockOffR3,DEC);
lcd.print(" ");
if (setHorClockOffR2<10) lcd.print("0");
lcd.print(setHorClockOffR2,DEC);
lcd.print(":");
if (setMinClockOffR2<10) lcd.print("0");
lcd.print(setMinClockOffR2,DEC);
if (KEY==2 && pos==3){ //Выход из подменю без сохранения
lcd.clear(); //Очищаем на всякий случай дисплейчик
return;}
lcd.setCursor(pos,1); //Устанавливаем курсор согласно позиции
if (pos<3) pos=3;
if (KEY==5 && pos<11) pos += 3; //Крутим позицию право-лево
else if (KEY==2 && pos>3) pos -= 3;
else if (pos==3 && KEY==3) setHorClockOffR3++; //Крутим значения
else if (pos==3 && KEY==4) setHorClockOffR3--;
else if (pos==6 && KEY==3) setMinClockOffR3++;
else if (pos==6 && KEY==4) setMinClockOffR3--;
else if (pos==9 && KEY==3) setHorClockOffR2++;
else if (pos==9 && KEY==4) setHorClockOffR2--;
else if (pos==12 && KEY==3) setMinClockOffR2++;
else if (pos==12 && KEY==4) setMinClockOffR2--;
if (setHorClockOffR3>23) setHorClockOffR3=0; //Ограничиваем значения
if (setHorClockOffR2>23) setHorClockOffR2=0; //Ограничиваем значения
else if (setMinClockOffR3>59) setMinClockOffR3=0;
else if (setMinClockOffR2>59) setMinClockOffR2=0;
} //Конец цикла
// lcd.noBlink();
lcd.clear(); //Очищаем на всякий случай дисплейчик
EEPROM.write(winMe*4+1, setHorClockOffR3); //Записываем НОВЫЕ значения
EEPROM.write(winMe*4+2, setMinClockOffR3);
EEPROM.write(winMe*4+3, setHorClockOffR2);
EEPROM.write(winMe*4+4, setMinClockOffR2);
lcd.setCursor(4,2);
lcd.print("== Saved ==");
delay(zadTime[4]);
}
//=========== Обработка Меню, параметры Термореле
void setTermorele(){
byte pos=0;
setTemptGist= EEPROM.read(winMe*4+1); //Считываем записанные значения таймеров
setTemptAqu= EEPROM.read(winMe*4+2); //Адрес определяется как номер таймера*4 + четыре ячейки
setTemptLed= EEPROM.read(winMe*4+3);
setTemptRel= EEPROM.read(winMe*4+4);
lcd.clear(); //Очищаем на всякий случай дисплейчик
// lcd.blink();
while(keyIr()!=1){ //Крутим цикл пока не будет Setup
byte KEY=keyIr(); //Читаем состояние кнопок
val=0;
// delay(200); //Если убрать, не работает подсветка уст.позиции
lcd.setCursor(0,3);
lcd.print("=== push to save ===");
lcd.setCursor(0, 0);
lcd.print(winMe+1,DEC); //Печатаем номер программы таймера
lcd.print("|");
lcd.print(pos/3,DEC); //Печатаем позицию настройки параметра (замена blink)
lcd.print("->");
lcd.setCursor(7,0); //Выводим инфу о часах и минутах
if (setTemptGist<10) lcd.print("0");
lcd.print(setTemptGist);
lcd.print(" C^");
lcd.setCursor(0,1);
if (setTemptAqu<10) lcd.print("0");
lcd.print(setTemptAqu);
lcd.print(" | ");
if (setTemptLed<10) lcd.print("0");
lcd.print(setTemptLed);
lcd.print(" | ");
if (setTemptRel<10) lcd.print("0");
lcd.print(setTemptRel);
if (KEY==2 && pos==3){ //Выход из подменю без сохранения
lcd.clear(); //Очищаем на всякий случай дисплейчик
return;}
lcd.setCursor(pos,0); //Устанавливаем курсор согласно позиции
if (pos<3) pos=3;
if (KEY==5 && pos<12) pos += 3; //Крутим позицию право-лево
else if (KEY==2 && pos>3) pos -= 3;
else if (pos==3 && KEY==3) setTemptGist++;
else if (pos==3 && KEY==4) setTemptGist--;
else if (pos==6 && KEY==3) setTemptAqu++; //Крутим значения
else if (pos==6 && KEY==4) setTemptAqu--;
else if (pos==9 && KEY==3) setTemptLed++;
else if (pos==9 && KEY==4) setTemptLed--;
else if (pos==12 && KEY==3) setTemptRel++;
else if (pos==12 && KEY==4) setTemptRel--;
if (setTemptGist>5) setTemptGist=1; //Ограничиваем значения
else if (setTemptAqu>30) setTemptAqu=20;
else if (setTemptLed>65) setTemptLed=35;
else if (setTemptRel>70) setTemptRel=40;
} //Конец цикла
// lcd.noBlink();
lcd.clear(); //Очищаем на всякий случай дисплейчик
EEPROM.write(winMe*4+1, setTemptGist); //Записываем НОВЫЕ значения
EEPROM.write(winMe*4+2, setTemptAqu);
EEPROM.write(winMe*4+3, setTemptLed);
EEPROM.write(winMe*4+4, setTemptRel);
lcd.setCursor(4,2);
lcd.print("== Saved ==");
delay(zadTime[4]);
}
//=========== Обработка Меню, параметры диммирования (максимальное значение и пределы OUT2,3)
void setDimmer(){
byte pos=0;
maxDimm= EEPROM.read(winMe*4+1); //Считываем записанные значения диммирования
upR2= EEPROM.read(winMe*4+2); //Адрес определяется как номер диммера*4 + семь ячеек
downR2= EEPROM.read(winMe*4+3);
upR3= EEPROM.read(winMe*4+4);
downR3= EEPROM.read(winMe*4+5);
pManDimmUp= EEPROM.read(winMe*4+6);
pManDimmDown= EEPROM.read(winMe*4+7);
lcd.clear(); //Очищаем на всякий случай дисплейчик
// lcd.blink();
while(keyIr()!=1){ //Крутим цикл пока не будет Setup
byte KEY=keyIr(); //Читаем состояние кнопок
val=0;
// delay(200); //Если убрать, не работает подсветка уст.позиции
lcd.setCursor(0,3);
lcd.print("=== push to save ===");
lcd.setCursor(0, 0);
lcd.print(winMe+1,DEC); //Печатаем номер программы таймера
lcd.print("|");
lcd.print(pos/3,DEC); //Печатаем позицию настройки параметра (замена blink)
lcd.print("->");
lcd.setCursor(7,0); //Выводим инфу о часах и минутах
if (maxDimm<10) lcd.print("0");
lcd.print(maxDimm);
lcd.print(" dimm");
lcd.setCursor(0,1);
if (upR2<10) lcd.print("0");
lcd.print(upR2);
lcd.print("/");
if (downR2<10) lcd.print("0");
lcd.print(downR2);
lcd.print(" | ");
if (upR3<10) lcd.print("0");
lcd.print(upR3);
lcd.print("/");
if (downR3<10) lcd.print("0");
lcd.print(downR3);
lcd.setCursor(0,2); //Выводим инфу о часах и минутах
if (pManDimmUp<10) lcd.print("0");
lcd.print(pManDimmUp,DEC);
lcd.print(" *50ms");
lcd.print(" | ");
if (pManDimmDown<10) lcd.print("0");
lcd.print(pManDimmDown,DEC);
lcd.print(" *50ms");
if (KEY==2 && pos==3){ //Выход из подменю без сохранения
lcd.clear(); //Очищаем на всякий случай дисплейчик
return;}
lcd.setCursor(pos,0); //Устанавливаем курсор согласно позиции
if (pos<3) pos=3;
if (KEY==5 && pos<21) pos += 3; //Крутим позицию право-лево
else if (KEY==2 && pos>3) pos -= 3;
else if (pos==3 && KEY==3) maxDimm++; //Крутим значения
else if (pos==3 && KEY==4) maxDimm--;
else if (pos==6 && KEY==3) upR2++;
else if (pos==6 && KEY==4) upR2--;
else if (pos==9 && KEY==3) downR2++;
else if (pos==9 && KEY==4) downR2--;
else if (pos==12 && KEY==3) upR3++;
else if (pos==12 && KEY==4) upR3--;
else if (pos==15 && KEY==3) downR3++;
else if (pos==15 && KEY==4) downR3--;
else if (pos==18 && KEY==3) pManDimmUp++;
else if (pos==18 && KEY==4) pManDimmUp--;
else if (pos==21 && KEY==3) pManDimmDown++;
else if (pos==21 && KEY==4) pManDimmDown--;
if (pManDimmUp==0 && KEY==4) pManDimmUp=30; //Реверсивное изменение значений
if (pManDimmUp>30) pManDimmUp=0; //Ограничиваем значения
if (pManDimmDown==0 && KEY==4) pManDimmDown=30;
if (pManDimmDown>30) pManDimmDown=0;
} //Конец цикла
// lcd.noBlink();
lcd.clear(); //Очищаем на всякий случай дисплейчик
EEPROM.write(winMe*4+1, maxDimm); //Записываем НОВЫЕ значения
EEPROM.write(winMe*4+2, upR2);
EEPROM.write(winMe*4+3, downR2);
EEPROM.write(winMe*4+4, upR3);
EEPROM.write(winMe*4+5, downR3);
EEPROM.write(winMe*4+6, pManDimmUp);
EEPROM.write(winMe*4+7, pManDimmDown);
lcd.setCursor(4,2);
lcd.print("== Saved ==");
delay(zadTime[4]);
}
//=========== Обработка Меню, параметры установки времени
void setClock(){ // установка часов
byte pos=0;
lcd.clear(); //Очищаем на всякий случай дисплейчик
// lcd.blink();
while(keyIr()!=1){ //Крутим цикл пока не будет Setup
byte KEY=keyIr(); //Читаем состояние кнопок
val=0;
// delay(200); //Если убрать, не работает подсветка уст.позиции
lcd.setCursor(0,3);
// lcd.print("=== push to save ===");
lcd.print("<< -Exit | Ok -Save");
lcd.setCursor(0, 0);
lcd.print(winMe+1,DEC); //Печатаем номер программы таймера
lcd.print("|");
lcd.print(pos/3,DEC); //Печатаем позицию настройки параметра (замена blink)
lcd.print("->");
lcd.setCursor(7,0);
if (hours<10) lcd.print("0");
lcd.print(hours);
lcd.print(":");
if (minutes<10) lcd.print("0");
lcd.print(minutes);
lcd.print(":");
if (seconds<10) lcd.print("0");
lcd.print(seconds);
lcd.setCursor(7,1);
if (day<10) lcd.print("0");
lcd.print(day);
lcd.print(" | ");
if (date<10) lcd.print("0");
lcd.print(date);
lcd.print("/");
if (month<10) lcd.print("0");
lcd.print(month);
lcd.print("/");
if (year<10) lcd.print("0");
lcd.print(year);
if (KEY==2 && pos==3){ //Выход из подменю без сохранения
lcd.clear(); //Очищаем на всякий случай дисплейчик
return;}
lcd.setCursor(pos,0);
if (pos<3) pos=3; //Устанавливаем курсор согласно позиции
if (KEY==5 && pos<21) pos += 3; //Крутим позицию право-лево
else if (KEY==2 && pos>3) pos -= 3;
else if (pos==3 && KEY==3) hours++; //Крутим значения
else if (pos==3 && KEY==4) hours--;
else if (pos==6 && KEY==3) minutes++;
else if (pos==6 && KEY==4) minutes--;
else if (pos==9 && KEY==3) seconds++;
else if (pos==9 && KEY==4) seconds--;
else if (pos==12 && KEY==3) day++;
else if (pos==12 && KEY==4) day--;
else if (pos==15 && KEY==3) date++;
else if (pos==15 && KEY==4) date--;
else if (pos==18 && KEY==3) month++;
else if (pos==18 && KEY==4) month--;
else if (pos==21 && KEY==3) year++;
else if (pos==21 && KEY==4) year--;
if (hours>23) hours=0;
else if (minutes>59) minutes=0;
else if (seconds>59) seconds=0;
else if (day>7) day=1;
else if (date>31) date=1;
else if (month>12) month=1;
else if (year>99) year=0;
}
// lcd.noBlink();
lcd.clear(); //Очищаем на всякий случай дисплейчик
setRtc(seconds, minutes, hours, day, date, month, year);
lcd.setCursor(4,2);
lcd.print("== Saved ==");
delay(zadTime[4]);
}
//========== Считывание напряжения
void voltM(){
valueVo=analogRead(voltInput); //Read the value at analog input
vout=(valueVo*5.0)/1024.0; //See text
vin=vout/(R2/(R1+R2));
if (vin<0.09) {vin=0.0;} //Statement to quash undesired reading
}
//========== Считывание Давления
void bar(){
if (timeDps<millis()){ //Конструкция жуткая и жрущая море ресурсов при расчете вещественных чисел.
timeDps=millis()+1000;}
dps.getPressure(&Pressure);
}
//========== Считывание Влажности
void humiDity(){
hmdt=(dht.readHumidity()+9); //Reading temperature or humidity takes about 250 milliseconds!
}
//=========== Считывание температур
void dallas(){
ds.reset();
ds.write(0xCC); //Команда инициации
ds.write(0x44); //Start conversion, with parasite power on at the end
tzad=millis()+750; flagDallas=1;}
float DS18B20(byte *adres){
ds.reset();
ds.select(adres);
ds.write(0xBE); //Read Scratchpad
for (byte i=0; i<9; i++) data[i]=ds.read(); //We need 9 bytes
int raw=(data[1]<<8) | data[0]; //Переводим в температуру
float celsius=(float)raw/16.0; //Для ds18b20 делим на "16", для ds18s20 на "2"
return celsius;
}
//=========== Обработка Термо-Реле
void tempRele(){
if (tzad<millis()&&flagDallas==1){
temp[0]=DS18B20(addr1);
temp[1]=DS18B20(addr2);
temp[2]=DS18B20(addr3);
prvMlsTemp=millis();
flagDallas=0;}
if (temp[0]>EEPROM.read(22)-(EEPROM.read(21)/2)){
digitalWrite(tOUT1,LOW); //Термо-реле 1-включается
// lcd.setCursor(8, 2);
// lcd.print("*");
}
else if (temp[0]<EEPROM.read(22)+(EEPROM.read(21)/2)){
digitalWrite(tOUT1,HIGH); //Термо-реле 1-выключается
// lcd.setCursor(8, 2);
// lcd.print("-");
}
if (temp[1]>EEPROM.read(23)-(EEPROM.read(21)/2)){
digitalWrite(tOUT2,LOW); //Термо-реле 2-включается
// lcd.setCursor(18, 2);
// lcd.print("*");
}
else if (temp[1]>EEPROM.read(23)-(EEPROM.read(21)/2)){
digitalWrite(tOUT2,HIGH); //Термо-реле 2-выключается
// lcd.setCursor(18, 2);
// lcd.print("-");
}
if (temp[2]>EEPROM.read(24)-(EEPROM.read(21)/2)){
digitalWrite(tOUT3,LOW); //Термо-реле 3-включается
// lcd.setCursor(18, 2);
// lcd.print("*");
}
else if (temp[2]<EEPROM.read(24)+(EEPROM.read(21)/2)){
digitalWrite(tOUT3,HIGH); //Термо-реле 3-выключается
// lcd.setCursor(18, 2);
// lcd.print("-");
}
}
//=========== Обработка установки RTC часов
void setRtc(byte seconds, byte minutes, byte hours, byte day, byte date, byte month, byte year){
Wire.beginTransmission(DS3231_I2C_ADDRESS); //104 is DS3231 device address
Wire.write(0x00); //Start at register 0
Wire.write(decToBcd(seconds));
Wire.write(decToBcd(minutes));
Wire.write(decToBcd(hours));
Wire.write(decToBcd(day));
Wire.write(decToBcd(date));
Wire.write(decToBcd(month));
Wire.write(decToBcd(year));
Wire.endTransmission();
}
//=========== Обработка RTC часов
void timeRtc(){
Wire.beginTransmission(DS3231_I2C_ADDRESS); //104 is DS3231 device address
Wire.write(0x00); //Start at register 0
Wire.endTransmission();
Wire.requestFrom(DS3231_I2C_ADDRESS, 7); //Request seven bytes
if(Wire.available()){
seconds = Wire.read(); //Get second
minutes = Wire.read(); //Get minute
hours = Wire.read(); //Get hour
day = Wire.read();
date = Wire.read();
month = Wire.read(); //Get month
year = Wire.read();
seconds = (((seconds & B11110000)>>4)*10 + (seconds & B00001111)); //Convert BCD to decimal
minutes = (((minutes & B11110000)>>4)*10 + (minutes & B00001111));
hours = (((hours & B00110000)>>4)*10 + (hours & B00001111)); //Convert BCD to decimal (assume 24 hour mode)
day = (day & B00000111); // 1-7
date = (((date & B00110000)>>4)*10 + (date & B00001111)); //Convert BCD to decimal 1-31
month = (((month & B00010000)>>4)*10 + (month & B00001111)); //msb7 is century overflow
year = (((year & B11110000)>>4)*10 + (year & B00001111));
}
}
//=========== Обработка Таймеров
void timer(){
int fulMin=hours*60+minutes; //Переводим часы + минуты к полным минутам
int fulMinOn1= EEPROM.read(1)*60+EEPROM.read(2); //Переводим часы + минуты включения 1 реле к полным минутам
int fulMinOff1= EEPROM.read(3)*60+EEPROM.read(4); //Переводим часы + минуты выключения 1 реле к полным минутам
int fulMinOn2= EEPROM.read(5)*60+EEPROM.read(6); //Переводим часы + минуты включения 2 реле к полным минутам
int fulMinOff2= EEPROM.read(7)*60+EEPROM.read(8); //Переводим часы + минуты выключения 2 реле к полным минутам
int fulMinOnLcd= EEPROM.read(9)*60+EEPROM.read(10); //Переводим часы + минуты включения Lcd к полным минутам
int fulMinOffLcd= EEPROM.read(11)*60+EEPROM.read(12); //Переводим часы + минуты выключения Lcd к полным минутам
int fulMinOffOut3= EEPROM.read(13)*60+EEPROM.read(14); //Переводим часы + минуты выключения OUT3 к полным минутам
int fulMinOffOut2= EEPROM.read(15)*60+EEPROM.read(16); //Переводим часы + минуты выключения OUT2 к полным минутам
int fulMinOnCo2= EEPROM.read(17)*60+EEPROM.read(18); //Переводим часы + минуты включения Co2 к полным минутам
int fulMinOffCo2= EEPROM.read(19)*60+EEPROM.read(20); //Переводим часы + минуты выключения Co2 к полным минутам
//========== Таймер №1
if (fulMinOn1>fulMinOff1) {isNight=1;} //Если ночное время
if (isNight==0){ //Если день
if (fulMin>=fulMinOn1&&fulMin<fulMinOff1) {isLght[0]=1;} //Проверяем интервал
else {isLght[0]=0;} //Если необходимо включить свет
} else { //Если ночь
if(fulMin-fulMinOn1>=0) {isLght[0]=1;} //Если больше или равно верхнему значению, то необходимо включить свет
else { //Если необходимо включить свет
if(fulMin<fulMinOff1) {isLght[0]=1;} //Если меньше нижнего значения, то необходимо включить свет
else {isLght[0]=0;} //Если необходимо включить свет
}
}
if((isLght[0]==1)&&(lghtStat[0]==0)){ //Если свет еще не включен и выставлен флаг необходимости включить
if (tDimm < millis()){ //И не дана команда на полное выключение
(EEPROM.read(30)*50); dimmUp();}
if (angData==EEPROM.read(25)) {lghtStat[0]=1;}
} else {
if(isLght[0]==0&&lghtStat[0]==1){
if (tDimm < millis()){
(EEPROM.read(31)*50); dimmDown();}
if (angData==0){lghtStat[0]=0;}
}
}
//========== Таймер №2
if (fulMinOn2>fulMinOff2) {isNight=1;} //Если ночное время
if (isNight==0){ //Если день
if (fulMin>=fulMinOn2&&fulMin<fulMinOff2) {isLght[1]=1;} //Проверяем интервал
else {isLght[1]=0;} //Если необходимо включить свет
} else { //Если ночь
if(fulMin-fulMinOn2>=0) {isLght[1]=1;} //Если больше или равно верхнему значению, то необходимо включить свет
else { //Если необходимо включить свет
if(fulMin<fulMinOff2) {isLght[1]=1;} //Если меньше нижнего значения, то необходимо включить свет
else {isLght[1]=0; } //Если необходимо включить свет
}
}
if((isLght[1]==1)&&(lghtStat[1]==0)){ //Если свет еще не включен и выставлен флаг необходимости включить
if (tDimm < millis()){ //И не дана команда на полное выключение
(EEPROM.read(30)*50); dimmUp();}
if (angData==EEPROM.read(25)) {lghtStat[1]=1;}
} else {
if(isLght[1]==0&&lghtStat[1]==1){
if (tDimm < millis()){
(EEPROM.read(31)*50); dimmDown();}
if (angData==0){lghtStat[1]=0;}
}
}
//========== Таймер Lcd-подсветки
if (fulMinOnLcd>fulMinOffLcd) {isNight=1;} //Если ночное время
if (isNight==0){ //Если день
if (fulMin>=fulMinOnLcd&&fulMin<fulMinOffLcd) {isLcdt=1;} //Проверяем интервал
else {isLcdt=0;} //Если необходимо включить подсветку Lcd
} else { //Если ночь
if(fulMin-fulMinOnLcd>=0) {isLcdt=1;} //Если больше или равно верхнему значению, то необходимо включить подсветку Lcd
else { //Если необходимо включить подсветку Lcd
if(fulMin<fulMinOffLcd) {isLcdt=1;} //Если меньше нижнего значения, то необходимо включить подсветку Lcd
else {isLcdt=0;} //Если необходимо включить подсветку Lcd
}
}
if((isLcdt==1)&&(lcdStat==0)){ //Если подсветка Lcd еще не включена и выставлен флаг необходимости включить
lcd.backlight(); lcdStat=1;
} else {
if(isLcdt==0&&lcdStat==1){
lcd.noBacklight(); lcdStat=0;
}
}
//========== Таймер СО2
if (fulMinOnCo2>fulMinOffCo2) {isNight=1;} //Если ночное время
if (isNight==0){ //Если день
if (fulMin>=fulMinOnCo2&&fulMin<fulMinOffCo2) {isCo2t=1;} //Проверяем интервал
else {isCo2t=0;} //Если необходимо включить Co2
} else { //Если ночь
if(fulMin-fulMinOnCo2>=0) {isCo2t=1;} //Если больше или равно верхнему значению, то необходимо включить Co2
else { //Если необходимо включить Co2
if(fulMin<fulMinOffCo2) {isCo2t=1;} //Если меньше нижнего значения, то необходимо включить Co2
else {isCo2t=0;} //Если необходимо включить Co2
}
}
if((isCo2t==1)&&(co2Stat==0)){ //Если Co2 еще не включен и выставлен флаг необходимости включить
digitalWrite(OUT6,LOW); co2Stat=1;
} else {
if(isCo2t==0&&co2Stat==1){
digitalWrite(OUT6,HIGH); co2Stat=0;
}
}
//========== Таймер "Лунного света"
if (fulMin>=fulMinOffOut3){
digitalWrite(OUT3,HIGH);}
if (fulMin>=fulMinOffOut2){
digitalWrite(OUT2,HIGH);
}
}
//=========== Обработка Bluetooth
void blueTooth(){
if (Serial.available()){
byte i=Serial.read()-48; //byte меньше int на 118 байт
if (i==2) {if (!digitalRead(OUT1)!=0 && angData>=1) digitalWrite(OUT2, !digitalRead(OUT2));}
if (i==2) {if (!digitalRead(OUT1)!=0 && angData!=0) digitalWrite(OUT2, digitalRead(OUT2));}
if (i==3) {if (digitalRead(OUT1)==0 && angData>=1) digitalWrite(OUT3, !digitalRead(OUT3));}
if (i==3) {if (digitalRead(OUT1)==0 && angData!=0) digitalWrite(OUT3, digitalRead(OUT3));}
// if (i==3)digitalWrite(OUT6,!digitalRead(OUT6));
if (i==4) Serial.print(temp[0]);
if (i==5) Serial.print(temp[1]);
if (i==6) Serial.print(temp[2]);
if (i==7) Serial.print(hmdt);
if (i==8) Serial.print(Pressure/133.3,1);
if (i==9) Serial.print(vin);
if (i==0){
if (tDimm < millis()){
(EEPROM.read(31)*50); dimmDown(); Serial.print(angData);}
}
if (i==1){
if (tDimm<millis()){
(EEPROM.read(30)*50); dimmUp(); Serial.print(angData);}
}
}
}
/*
//=========== Обработка Аврийного индикатора
void bLinkLed(){
if (prvMlsbLink+zadTime[1]<millis()){ //Проверка условия
prvMlsbLink=millis(); //Установка задержки
digitalWrite(bLink,!digitalRead(bLink));} //Инверсия значения
}
*/
//=========== Обработки печати и вывода на дисплейчик (часы)
void printTime(){
if (millis()-prvMlsTm>zadTime[3]){ //Проверяем интервал для обновления часов
prvMlsTm=millis(); //Вызываем ф-цию вывода времени на экран
lcd.setCursor(0,0);
if (hours<10) {lcd.print(0);lcd.print(hours);} else {lcd.print(hours);}
lcd.print(":");
if (minutes<10) {lcd.print(0);lcd.print(minutes);} else {lcd.print(minutes);}
lcd.print(":");
if (seconds<10) {lcd.print(0);lcd.print(seconds);} else {lcd.print(seconds);}
}
if (millis()-prvMlsRazd>zadTime[4]){ //Проверяем интервал для обновления ":"
prvMlsRazd=millis();
lcd.setCursor(2,0);
lcd.print(" ");
lcd.setCursor(5,0);
lcd.print(" ");
lcd.setCursor(8,0);
lcd.print(" ");
}
}
//=========== Обработки печати и вывода на дисплейчик (напряжения, температуры, давление)
void printDin(){
if (millis()-prvMlsVo>zadTime[7]){ //Проверяем интервал для обновления
prvMlsVo=millis();
lcd.setCursor(2,2); //Вывод значений температур на Lcd
lcd.print((temp[0]),1);
lcd.setCursor(9,2);
lcd.print((temp[1]),1);
lcd.setCursor(16,2);
lcd.print((temp[2]),1);
lcd.setCursor(9,3);
lcd.print(vin); //Выводим на экранчик значения напряжения
lcd.setCursor(2,1);
lcd.print(Pressure/133.3,1); //Выводим на экранчик показания атм.давления в мм.рт.столба
lcd.setCursor(8,1);
lcd.print(hmdt,0); //Выводим на экранчик показания влажности в %
}
}
//=========== Обработки печати и вывода на дисплейчик СТАТИКИ
void printStat(){
if (millis()-prvMlsTimer>zadTime[8]){ //Проверяем интервал для обновления
prvMlsTimer=millis();
lcd.setCursor(16,1);
lcd.print("pw\1");
lcd.setCursor(12,1);
lcd.print("~\1");
lcd.setCursor(0,1);
lcd.print("p\1");
lcd.setCursor(10,1);
lcd.print("%");
lcd.setCursor(0,2);
lcd.print("a\1");
lcd.setCursor(7,2);
lcd.print("b\1");
lcd.setCursor(14,2);
lcd.print("c\1");
lcd.setCursor(0,3);
lcd.print("~");
lcd.setCursor(2,3);
lcd.print(":");
lcd.setCursor(4,3);
lcd.print(":");
lcd.setCursor(7,3);
lcd.print("v\1");
lcd.setCursor(15,3);
lcd.print("%\1");
lcd.setCursor(9,0);
if (date<10) {lcd.print(0);lcd.print(date);} else {lcd.print(date);}
lcd.print("/");
if (month==1){lcd.print ("Jan");}
if (month==2){lcd.print ("Feb");}
if (month==3){lcd.print ("Mar");}
if (month==4){lcd.print ("Apr");}
if (month==5){lcd.print ("May");}
if (month==6){lcd.print ("Jun");}
if (month==7){lcd.print ("Jul");}
if (month==8){lcd.print ("Aug");}
if (month==9){lcd.print ("Sep");}
if (month==10){lcd.print ("Oct");}
if (month==11){lcd.print ("Nov");}
if (month==12){lcd.print ("Dec");}
lcd.print("/");
lcd.print(year+2000);
lcd.setCursor(14,1);
lcd.print(!digitalRead(OUT6)); //Вывод состояния Co2 (Реле Со2)
/*
if (day==1){lcd.print ("Sun");}
if (day==2){lcd.print ("Mon");}
if (day==3){lcd.print ("Tue");}
if (day==4){lcd.print ("Wed");}
if (day==5){lcd.print ("Thu");}
if (day==6){lcd.print ("Fri");}
if (day==7){lcd.print ("Sat");}
*/
lcd.setCursor(19,1); //Вывод состояния ATX (Power ON\OFF)
lcd.print(!digitalRead(OUT0));
lcd.setCursor(1,3); //Вывод состояния выходов реле освещения
lcd.print(!digitalRead(OUT1));
lcd.setCursor(3,3);
lcd.print(!digitalRead(OUT2));
lcd.setCursor(5,3);
lcd.print(!digitalRead(OUT3));
}
if (millis()-prvMlsOut>zadTime[0]){ //Проверяем интервал для обновления
prvMlsOut=millis();
lcd.setCursor(17,3); //Вывод состояния аналогового выхода диммирования
lcd.print(angData);
lcd.setCursor(18,3);
lcd.print(" ");
lcd.setCursor(17,3);
lcd.print(angData);
}
} //05.03.15 Размер 30 614. Размер был 30,614кБ из 30,720кБ Nano
void loop(){
timeRtc();
timer();
keyI();
if (millis()-prvMlsTemp>zadTime[6]&&flagDallas!=1){dallas();}
tempRele();
voltM();
bar();
humiDity();
blueTooth();
printTime();
printDin();
printStat();
}
В нем немного "кояво" работает "парсер" работы ползунка Андроид-приложения - для диммирования, нужно что то искать иное, нежели вставлять Serial.setTimeout(4); при работе с Serial.parseInt(); последний работает НЕКорреткно без Timeout().
В остально ВСЁ просто и шикарно, Огромное спасибо Уважаемому bwn за терпение с которым он меня технически и научил многим пользоваться.
Видео из трёх частей о самом контроллере, его возможностях и самом трудном и интересном в нём - это МЕНЮ :)
В целом вроде неплохо получилось, не зря мучались)))). Вы это лучше новой темой выложите с фотками, видео и конечным кодом, боюсь 7 страниц мало кто осилит, для желающих можно ссылку дать на эту тему.
По уменьшению размера, первое что просится, все текстовые сообщения длиной больше 3 знаков и повторяющиеся более 2 раз перенести в 129 строку (байт 200 выиграете). Еще почитайте "optiboot" для ардуино, сам не пробовал, но вроде как 1,5К можно убавить (тема была совсем на днях).
Да, проверил свой AM2301(DHT21), оказалось врет на 14%. Способ простой - баночка типа майонезной, на дно обычную соль, смачиваем водой с пипетки (должна быть влажная, не мокрая), засовываем датчик, закрываем плотнее и смотрим. Должно быть 75-76%.
Да, проверил свой AM2301(DHT21), оказалось врет на 14%. Способ простой - баночка типа майонезной, на дно обычную соль, смачиваем водой с пипетки (должна быть влажная, не мокрая), засовываем датчик, закрываем плотнее и смотрим. Должно быть 75-76%.
Ок, про оптимизацию почитаю обязательно. Ведь я вообще хотел ДВА постоянно меняющихся экранчика с инфой чтобы удобнее воспринимать не только мне, а в итоге бился за каждый десяток байт.
А вот про DHT-11 их я брал парочку и оба врут в итоге, сравнивал с несколькми тоже китайскими часиками в которых есть измерение влажнсоти и с метеостанцией Oregon, в итоге решил просто добавить "врущее" значение чтобы получить нужное (строка 0722 timeDps=millis()+1000;}) около 10-11% вранья в одном и 9% в другом, тестовом что на меге :)
Новую ветку сделаю и туда фоточки сборки контроллера его возможности и схему подключения (боюсь будет чт ото в фотошопе из фото модулей и их соединения:) )
ну у меня экран 1602 с клавай который занимает почти все пины, а у автора 2004. опять же надо будет меню переделывать под мой экран,да? . две релюшки которые шим, а на фото там целый бло реле. пульта нет
ну у меня экран 1602 с клавай который занимает почти все пины, а у автора 2004. опять же надо будет меню переделывать под мой экран,да? . две релюшки которые шим, а на фото там целый бло реле. пульта нет
Экран здесь будет самое нудное. ТС больше всего времени потратил на меню. Самый безбольный для вас путь взять типа этого и не делать работу второй раз (хотя все равно под себя править придется). Реле автору были нужны по жизненной необходимости (большая мощность на освещение), если ваши транзюки потянут (здесь не помогу, пробуйте сами), то можно те же самые сигналы подавать на них напрямую.
Для нагревателей и помп (не знаю, что у вас будет от 220в) нужны либо реле, либо симмисторные ключи (решать вам).
Пульт - три варианта: 1. Найти дома дохлый девайс, у которого было IR управление и выдрать оттуда (я так и сделал когда понадобился). 2. Купить (недорогие они). 3. Можно все переписать под кнопки (в начальных версиях так и было), но здесь придется менять логику управления, на пульте кнопок много, а вам лепить пианино ни к чему.
Все красоты типа давления, влажности, напряжения ТС лепил для личного удовольствия. Можно этим воспользоватся, а можно и выкинуть.
Доброго дня. Коненчое непротив, правда как вам уже говорил ув. Вадим (bwn) - эта ветка холливар ещё тот, а все потому что практически с "- 0". Но счас очень доволен, собрал после на мелкой ардуинк, моторшилде , блютусинке и аппинвенторе своему сыну ДУ мелкий танк, в пыжика своего в больших планах подключится к CAN-шине и замутить свой БК (306-ой он и в нем почти ничего нет:(. Однако по поводу акваконтроллера.
Я так понял менять яркость вы планируете силовыми транзисторами в мое м случае это было диммирование самим драйвером. Но суть то неменяется всеравно задается таймер и время приращения\уменьшения.
Реле я использовал именно для снижения энергопотребления и полного отключения простаиваемой автоматики. Но к сожалению заявленные токи до 10А они врядли безболезненно "вытянут". В моих цепях каждое коммутирует не более 7-8А и при этом нагрев свыше 50 град и в итоге крышку на корпус контроллера уже нельзя было использовать, пришлось реле оставлять открытому воздуху. Ну это так мелочи
Пульт ДУ ровно как и блютусину пользую редко, да они есть да с ними удобно и по меню и так повключать но самая главное что работает вся эта приблуда ардуиновская сама уже месяца три вообще без моего сиьного вмешательства, перенсит легко и перепаы напряжения и отключения ( тут должное надо отдать хорошей стабилизации и запасу мощности БП всей цепи).
Термоконтроль так и непригодился, Ледики негреют радиаторы более 48град при естественном охлаждении, вода ненагревается выше 24 град (при пользовании Т5 и Т8 вода неопускалась ниже 27 град :).
Показания вольтметра оказались и вовсе бесполезны. Ну чео их контролировать (что 5В что 12В) - там и 1% нет оклонений - уберу и тем самым место в коде увеличу.
Самый нужные оказались - это температуры, атм. давление и влажность как нестранно.
Со2 подается по времени - нет нужды замерять показания да и дорого.
ПО меню - самая моя любимая фишка, самое главное что ты независиш ни т вэб-морды, ни от загрузки настроек с ПК, выбрал нужное, сохранил вышел (правда вначале немог вкурить, почему изменения применённые неработают. казывается нужно РЕБУТАТЬ ардуинку).
После я заказывал самые простые энкодер и кнопу типа джлйстик PS. Последняя заменяет сразу 5 кнопок !!!! попробуйте её и места съэкономите и удобно. Энкодер продукт узкоспезиализированный, для нашего контроллера неочень.
Сожалею что немогу выложить схему электрическую принципиальную - всё только в фотошопе есть, смешно смотреть.
ПО меню - самая моя любимая фишка, самое главное что ты независиш ни т вэб-морды, ни от загрузки настроек с ПК, выбрал нужное, сохранил вышел (правда вначале немог вкурить, почему изменения применённые неработают. казывается нужно РЕБУТАТЬ ардуинку).
А чего молчите, это не правильно. Код сейчас смотреть нет желания, но 99%, что причина в переменных, которые считываются один раз при запуске. Лекарство - либо вместо переменной для сравнения применять значение EEPROM напрямую, либо сделать функцию обновления после внесения изменений и при запуске.
а не подскажете, я хочу переподключить экран через I2C освободить выходы. но у меня экран уже спаян с клавиатурой не придёться ли мне его отпаивать. или всё в кучи может работать через этот интерфейс и экран и кнопки. просто я его уже заказал.
а не подскажете, я хочу переподключить экран через I2C освободить выходы. но у меня экран уже спаян с клавиатурой не придёться ли мне его отпаивать. или всё в кучи может работать через этот интерфейс и экран и кнопки. просто я его уже заказал.
Мое личное мнение, что проще отпаять (аккуратно выкусить и впаять новую гребенку) экран от этого шилда и поставить на переходник I2C. Подпаятся можно и к шилду, но придется прозванивать выходы и разводить на переходник. Кнопки в этом случае останутся на аналоговом входе.
Но без пайки и проводов в любом случае не обойтись.
Всем приятного времени суток. Прошу помощи! Решил сделать авто управление аквариумом, автокормушка свет (закат, рассвет), включение фильтра ну и со временем еще чего нибудь прилеплю. Написал код для света по таймеру. Первая проблемма появилась когда включалось питание, то диоды загарались и когда проходило тестирование ардуины гасли и на чинали работать по заданному режиму. это дело исправл поставив реле на питание диодов с задержкой на время запуска ардуины. Вопрос, может можно как то обойтись без реле, а удалить проблемму программно? И вторая проблемма когда заканчивается рассвет то свет должен гореть энное время заданное таймером, а потом переходить в режим заката, но этого не происходит, свет либо гаснет полностью после рассвета или тут же переходит в закат. Код прилогаю ниже может кто поможет? Зарание большое спасибо.
//обзываем выводы соответственно цвету
int REDpin = 9;
int BLUEpin = 10;
int WHITEpin = 11;
int RELAYpin = 2;
void setup()
{
//включение реле
pinMode(RELAYpin, OUTPUT);
digitalWrite(RELAYpin, LOW);
delay(2000); //пауза
digitalWrite(RELAYpin, HIGH);}
void loop(){
for(int value = 0 ; value <= 255; value +=1)
{
//яркость света увеличивается
analogWrite(REDpin, 255-value);
analogWrite(BLUEpin, 255-value);
analogWrite(WHITEpin, 255-value);
delay(60); //пауза
}
for(int value = 255 ; value == 255; value ==1)
{
//свет горит
analogWrite(REDpin, 255);
analogWrite(BLUEpin, 255);
analogWrite(WHITEpin, 255);
delay(50000); //пауза
}
for(int value = 0 ; value <= 255; value +=1)
{
//яркость света уменьшается
analogWrite(REDpin, value);
analogWrite(BLUEpin, value);
analogWrite(WHITEpin, value);
delay(60); //пауза
}
for(int value = 0 ; value <= 255; value +=1)
{
//свет не горит
analogWrite(REDpin, 255);
analogWrite(BLUEpin, 255);
analogWrite(WHITEpin, 255);
delay(70); //пауза
}
}
Vallu, попробуйте поставить в setup: analogWrite(REDpin, 255); и аналогично для других.
зачем вам 13 строка?
строки с 27 по 34 делают что то непонятное, а скорее всего ничего не делают.
И ликвидируйте все delay() по максимуму. Сейчас это незаметно, потом может стать проблемой. При корректной работе строк с 27 по 34 вы завесите дуину на 3 часа((((.
//обзываем выводы
int REDpin = 9;
int BLUEpin = 10;
int WHITEpin = 11;
int RELAYpin = 2;
int val = 255;
void setup()
{
//включение реле
pinMode(RELAYpin, OUTPUT);
digitalWrite(RELAYpin, LOW);
delay(2000); //пауза
digitalWrite(RELAYpin, HIGH);}
void loop(){
for(int value = 0 ; value <= 255; value +=1)
{
//яркость света увеличивается
analogWrite(REDpin, 255-value);
analogWrite(BLUEpin, 255-value);
analogWrite(WHITEpin, 255-value);
delay(60); //пауза
}
for(int value = 0 ; value <= 255; value +=1)
{
//свет горит
analogWrite(REDpin, 0);
analogWrite(BLUEpin, 0);
analogWrite(WHITEpin, 0);
delay(60); //пауза
}
for(int value = 0 ; value <= 255; value +=1)
{
//яркость света уменьшается
analogWrite(REDpin, value);
analogWrite(BLUEpin, value);
analogWrite(WHITEpin, value);
delay(60); //пауза
}
for(int value = 0 ; value <= 255; value +=1)
{
//свет не горит
analogWrite(REDpin, 255);
analogWrite(BLUEpin, 255);
analogWrite(WHITEpin, 255);
delay(60); //пауза
}
}
строка 13 нужна для задержки реле на 2 сек что бы ардуино вошла в рабочее состояние, иначе диоды закараются и тутже тухнут. 27-34 нужны чтобы свет горел определенное время.
да забыл описать саму схему. Имеем ардуино пока УНО, драйвера света, диодные ленты, БП на 12 и 5 В. пок пробовал запитать один диод от ардуины все работало прекрасно без реле, но как подключил драйвера появилась вспышеа в начале работы.
Ну тогда наверно все таки делать блокировку клавиш. Это проще по исполнению, чем все экранами обвешивать. На остальное я так понял не влияет, только IR колбасит.
Доброго утречка!
Взял свой стаарый код, где обработка кнопок была по:
Вкорячил его назад, все как и было, нажато - возвращает, ненажато - тишина. :)
Теперь работа в таком виде с меню и параметрами.
Хочу сам попробовать победить и вот чтовыходит, меню:
(снова tft имхо тестово) .В таком виде по нажатию KEY1 я попадаю в меню и ТУТ-же из него вылетаю, мгновенно. Хочу спросить строка while(1) { //Бесконечный цикл это не нажатие-ли кнопки 1 из нашего старого кода работы с кнопками?
И фукнкция настройки параметров в меню:
Правильно-ли описал здесь работу while(val!=KEY1) { //Крутим цикл пока не будет Setup
Добрый день. По первому коду, вас выбрасывает 22 строка. Я когда писал пример, там была блокировка этой клавиши на какое-то время. Ее надо вводить при входе и также при возврате из подменю. В подменю возврат из while вроде правильный.
Ок, поменял 22 строку на:
где:
объявлены в переменных.
В меню попал и там пока повис (снова кнопки надо правильно прописывать :) ) Ну это уже лучьше...
Так что есть:
в 7 строке? Кнопка KEY1 может её иначе описать?
Только вторая строка первого кода должна быть в loop-е и setTimeOn (вроде правильно функцию назвал) и применятся в момент перехода в основной экран меню, иначе вы там и будете висеть, т.к. условия выхода никогда не достигнете.
О, первая прическа, попробуйте если все работает, будем дальше чесать. Я свои варианты по currentMillis пока закомментил в коде, смотрите сами, что использовать. Тайминги опросов датчиков пока не трогал.
Отличненько работает, вы объединили релюшки в одну функцию - здорово и строк сразу меньшеи массиввам иопределили температуры и задержки - это как пример будет для будующих переделок. Вход и выход из меню и функции параметров void setOnOff() теперь корректно и без задержек.
Единственноя вынес ЗА пределы работы функции кнопок keyI(); функцию //========== Обработка "одного" нажатия
если оставить как есть ТО любое условие прерывает её и диммирование ++ или -- прерывается и останавливается на последней комманде, если вынести её в отдельную к примеру в auto_key_dimmer() { и лупить в loop то после выполнения комманды (даже после выхода из меню) диммирование ++ или -- продолжится.
Вот, размер стал меньше пусть и нехначительно но меньше, главное строк меньше стало :) и сложнее сам код, чуть но сложнее а это главное в обучении, нестоять на месте
Сбрасывайте рабочий вариант скетча, буду дальше чесать. Кнопки не трогаю, у вас в динамике их проще проверить. Теперь задержки на опрос датчиков.
Сбросьте мне на почту вашу библу BMP085, у меня что то на нее фыркает.
Так, сейчас логика работы не требует второй переменной angData2, будем ее убирать? Если захотите два независимых канала, функции управления придется переделывать серьезно. Которые сейчас, точно не подойдут.
Так, сейчас логика работы не требует второй переменной angData2, будем ее убирать? Если захотите два независимых канала, функции управления придется переделывать серьезно. Которые сейчас, точно не подойдут.
Это я понимал в самом начале, а для чего разделил? Да просто два канала по 5-ть драйверов и на них сигнал PWM с ардуинки, подумал, ВДРУГ незватит токовой нагрузки и подстраховался, так как подключение напрямую без транзистров и прочей лабуды (драйвер хорошо защищен и нетребует высоких токов) - сделать ДВА канала но СИММЕТРИЧНЫХ. На самом деле драйвера пищат хоть и несильно но пищат и просто оставлять их в "не краних" положениях ( между 0 и 255) ненужно - главное ПЛАВНО поднять освещение на angData2 канале (предварительно задав там 0 и включив реле на OUT1) - что сейчас шикарно делается.
Про 258 пост не забыли?
http://arduino.ru/forum/proekty/groekt-dlya-akvariuma-akvakontroller-dly...
Про 258 пост не забыли?
http://arduino.ru/forum/proekty/groekt-dlya-akvariuma-akvakontroller-dlya-led-temp-time-co2?page=5#comment-99521
Упс, вот и неувидел её....сорри счас всё упакую.
Вот, вчера после работы залил дома скетчик вми проработанный. Сразу скажу - никаких граблей пока на IR-нет. Дополнительно я пищевой фольгой и на "минус" монтажную схемку с распайкой всех выводов отгородил, надо было сразу. Всеже драйвера фонят и фонят некисло. По скетчу... пост: http://arduino.ru/forum/proekty/groekt-dlya-akvariuma-akvakontroller-dlya-led-temp-time-co2?page=5#comment-99500
вернул строки 338 и 364 без них при увеличении яркости (автодиммировании) по таймеру только ОДИН канал работал. При ручном - оба. Сначала невкурил даже что то неочень ряко + свист легкий на angData2=255 (а н легкий фон пропадает уже после 200) так что их нужно приравнивать с angData1 ранее.
Библиотеки свои ВСЕ выслал.
Скетч который сейчас рабочий, тоже сбросьте, а то накодим в разных вариантах))). Потом три года не разберешся.
angData я вообще одну оставлю.
Добавил есчо одно на мой взляд НЕЛИШНЮЮ настройку диммирования, 21 -25 строки (надо бы ещё и 26, 27 вкорячить) (пост #256)
Добавил в строку меню:
Также новую функцию (пока коряво НО уже работает):
Ну и в саму функцию меню строчки заменил на:
- это часть из кода. Коненчое в функции таймера заменил чтение присвоенных переменных (в объявлении переменных они у меня были заданы "=") на чтение из ЕПРОМ.
Это меню действительно "находка" и памяти увеличилсоь чуть более на 1кб всего :)
Последний код, 8 строка будет работать некорректно. второе условие наверно pos<=4 (знаки сравнения, не уверен правильно ли поставил, может =<)
А у вас при выходе из первого экрана меню в loop, обратно не шмыгает в меню?
Нене, всё отличненько и входит и выходит. Нмогу понять почему у меня свободные ячеки ЕПРОМ правда образовались между 9 и 10 строкой последнего кода, тоетсь заканчиваются настройки pos==4 далее (5 пустых ячеек) и pos==5 с её пятью ячейками. Проверал, загружая стандартный скетч чтения:
А я не пересчитывал. Считаем: winMe принимает от 0 до 5 значит
winMe=0 поля 0*4+1 (1) до 0*4+4(4); =1 1*4+1(5) до 1*4+4(8); =2 (9) до (12); =3 (13) до (16); =4 (17) до (20)
а дальше вы изменили формулу winMe*5+1(5) и получили winMe=5 5*5+1(26) до 5*5+5(30). Вот они 5 недостающих. Здесь либо алгоритм адресации менять либо мирится.
Либо убрать один самый первый параметр maxDimm= EEPROM.read(winMe*5+1); из этой функции и перенести, но получится уже нетак красиво,Хотя у мнея же ещё НЕОБРАБОТАНЫ два настраиваемых: пост #256
026 int pManDimmUp=800; //Период увеличения яркости
027 int pManDimmDown=500; //Период уменьшения яркости
Вот попробую к ним, тогда останется один незадействован.
Так зачем, второй экран меню можете спокойно использовать для всего где нужны пять ячеек. Ну будет этот разрыв, какая беда? Периоды поделите на 10 и тоже можете в меню забить, только при использовании не забывать умножать обратно. В экранчике написать сек/100*255
Добавил вход в даллас из loop + отработка температурных реле по таймингу (они завязаны с далласом) и изменил, где вы реле через функцию releHigh() не сделали. Все angData1,2 заменил на одну переменную angData.
Больше ничего не трогал.
Шикарненько, ну вот недумал никогда что можно как высделали в строках 155 и 156 - потому и делал из двух частей на два "пина" :(
ПО термореле, теперечи начал понимать, что вы мне в самом начале толковали про флаги замер\флаг - сравнили с заданным\флаг- ну и вывод на на дисплейчик (строки 421 и 443, и условие в 703 - всё верно? :) )
С каждым разом все меньше размер и строк, ваша коррекция (без моих доп. окошек меню и неубранных currentMillis :) всего 22,5кб - эдак и до AtMegи рукой подать, шутка конечное. Счас главное стабильность и скорость выросла. Я ваши правкив свой кусок с менюшками и на ночь.... теститься.
Шикарненько, ну вот недумал никогда что можно как высделали в строках 155 и 156 - потому и делал из двух частей на два "пина" :(
ПО термореле, теперечи начал понимать, что вы мне в самом начале толковали про флаги замер\флаг - сравнили с заданным\флаг- ну и вывод на на дисплейчик (строки 421 и 443, и условие в 703 - всё верно? :) )
С каждым разом все меньше размер и строк, ваша коррекция (без моих доп. окошек меню и неубранных currentMillis :) всего 22,5кб - эдак и до AtMegи рукой подать, шутка конечное. Счас главное стабильность и скорость выросла. Я ваши правкив свой кусок с менюшками и на ночь.... теститься.
Так я вам сразу говорил, что если всякими tft не баловатся, наны за глаза хватит.
Доброго l@yz! :)
Ну что... все работает стабильно и шустро. ПО меню его счас облизываю. Утомляет "невозможность" менять позиции winMe (окон меню) в "цикличной последовательности". Ваш код и строки 314 -315 описал так:
стало нааамного веселее, зная что окошек меню может теперь быть и не 6 а много больше :) (ну и на будущее вдруг понадобится).
Попытался с часами тоже сделать (ну чтобы не начинать с 0 до 23 часов в одну строноу а потмо вдругую) решил также "зациклить" получилось но как т осмешновато. минуты дошли до 59 пытаемся перейти в 00 и тутже меняются и часы (вроде и удобно но ненужно) а назад вообще в мгновение возврат с 0 в 255 !!! и в 0, в 59 никак. Вот какой у меня рисунок кода:
это строки 380 -383 из поста #270
мне кажется будет прощще и короче на switch \ case (может на данном примере покажите как) при возможности.
А второй код если так?
Работает толко "++" с 23 на 0 далее 1 2 3 . А вот в "--" неа. тоетсь 2 1 0 и всё, нули. Счас поколдую над вашим, может надо чередовать if else для промежуточныйх значнеи >23 и <0
Я если честно, вообще здесь else не очень понимаю, но не экспериментировал.
Здравствуйте. БЛИН блин ....блин.
У меня кончается "свободное место". Немного переделал подменю, теперь их уже семь (пара таймеров на свет, один на со2, один на досветку "луна" типа, диммирование и установка часов), чуток поправил переменные. В итоге размер уже 29,4кб - на свооде почти ничего. А впереди есчо должна была быть блютусина или wi-fi, неговорю уже про влажность и уровень воды в банке - хотел добавить :)
Что делать relg оптимизироват md первую голову. Библиотек то и нету почти (за исключением IR и барометра - остальные стандартно и без них нельзя. Вотон скетчик - всё работает и стабильно, всё настраивается. Кстати заметил что всё чт ов епром запихивается после сохранения в подменю вступает в силу после RESSET на ардуинке. Код:
Блютусина или вафля планировались для передачи параметров на смарт или на страничку. Без них можно но уж очень хочется. Вот почему в ардуинках нет 64кб к примеру а или 128 или 32 (за минусом загрузчиков и пр).
Как нету, Мега 256, там аж 256К. По большому счету, глобально убавить не выйдет, либо от чего то отказыватся, либо голый C+ учить((((, но ассемблер круче))))
350Сегодня приехал наконец ДХТ-11 , разобрал и впаял между первой и второй ногами (+ и data) резистрор в 10кОм, третий вывод неиспользовался и на четвертый GND. Добавил библиотеку, и воткнул в код. Размер увеличился всего на 350кБ а это значит что зря очковал и место ещё вполне....
выглядит так функция влажности к моему акваконтроллеру:
Само собой кусочек пока из тестовой МЕГИ, в Nano и Lcd перенесу как потестю как следует. Вот и мне кажется брешет падлюка, показывет 21-23% ну этоже нивкакие ворота. Это почти пустыня.. Может резистро ненужен "подтягивающий". Вобщем или это шляпи и нужно что рекомендовали выше постами или пусть будет :)
11 он от рождения бяка, а 23% зимой с отоплением эт реально. Нужно с чем то сравнивать.
Вчера выткал DHT22, влажность ~23% ну и температура 28, при открытии окна падает температура до 26 влажность до 20%
Думаю можно выложить готовый вариант скетча, уже успешно отработанный и работающий более месяца при частых отключениях электричества и высоких токах нагрузки (до 23А).
Сам скетч, урезал максимально и то нехватило метса для авариынйх индикаторво и отключений, невлезла функция определения "уровня воды", работа с Wi-Fi. Пока довольствуюсь блютусинкой.
Итак скетчик для lcd:
В нем немного "кояво" работает "парсер" работы ползунка Андроид-приложения - для диммирования, нужно что то искать иное, нежели вставлять Serial.setTimeout(4); при работе с Serial.parseInt(); последний работает НЕКорреткно без Timeout().
В остально ВСЁ просто и шикарно, Огромное спасибо Уважаемому bwn за терпение с которым он меня технически и научил многим пользоваться.
Видео из трёх частей о самом контроллере, его возможностях и самом трудном и интересном в нём - это МЕНЮ :)
http://www.youtube.com/watch?v=8zrWyRNFKww
и
http://www.youtube.com/watch?v=PVPW8kwCJHM
и
http://www.youtube.com/watch?v=E0oZzMSKLUQ
В целом вроде неплохо получилось, не зря мучались)))). Вы это лучше новой темой выложите с фотками, видео и конечным кодом, боюсь 7 страниц мало кто осилит, для желающих можно ссылку дать на эту тему.
По уменьшению размера, первое что просится, все текстовые сообщения длиной больше 3 знаков и повторяющиеся более 2 раз перенести в 129 строку (байт 200 выиграете). Еще почитайте "optiboot" для ардуино, сам не пробовал, но вроде как 1,5К можно убавить (тема была совсем на днях).
Да, проверил свой AM2301(DHT21), оказалось врет на 14%. Способ простой - баночка типа майонезной, на дно обычную соль, смачиваем водой с пипетки (должна быть влажная, не мокрая), засовываем датчик, закрываем плотнее и смотрим. Должно быть 75-76%.
Да, проверил свой AM2301(DHT21), оказалось врет на 14%. Способ простой - баночка типа майонезной, на дно обычную соль, смачиваем водой с пипетки (должна быть влажная, не мокрая), засовываем датчик, закрываем плотнее и смотрим. Должно быть 75-76%.
Ок, про оптимизацию почитаю обязательно. Ведь я вообще хотел ДВА постоянно меняющихся экранчика с инфой чтобы удобнее воспринимать не только мне, а в итоге бился за каждый десяток байт.
А вот про DHT-11 их я брал парочку и оба врут в итоге, сравнивал с несколькми тоже китайскими часиками в которых есть измерение влажнсоти и с метеостанцией Oregon, в итоге решил просто добавить "врущее" значение чтобы получить нужное (строка 0722 timeDps=millis()+1000;}) около 10-11% вранья в одном и 9% в другом, тестовом что на меге :)
Новую ветку сделаю и туда фоточки сборки контроллера его возможности и схему подключения (боюсь будет чт ото в фотошопе из фото модулей и их соединения:) )
обалденный проект. если бы я раньше его нашёл, я бы заказал бы другие комплектующие. а блютуз там для чего
обалденный проект. если бы я раньше его нашёл, я бы заказал бы другие комплектующие. а блютуз там для чего
Блютуз для Андроида. А чем ваши комплектующие так сильно отличаются от здешних? Я же вам в самом начале на него ссылку давал.
ну у меня экран 1602 с клавай который занимает почти все пины, а у автора 2004. опять же надо будет меню переделывать под мой экран,да? . две релюшки которые шим, а на фото там целый бло реле. пульта нет
ну у меня экран 1602 с клавай который занимает почти все пины, а у автора 2004. опять же надо будет меню переделывать под мой экран,да? . две релюшки которые шим, а на фото там целый бло реле. пульта нет
Экран здесь будет самое нудное. ТС больше всего времени потратил на меню. Самый безбольный для вас путь взять типа этого и не делать работу второй раз (хотя все равно под себя править придется). Реле автору были нужны по жизненной необходимости (большая мощность на освещение), если ваши транзюки потянут (здесь не помогу, пробуйте сами), то можно те же самые сигналы подавать на них напрямую.
Для нагревателей и помп (не знаю, что у вас будет от 220в) нужны либо реле, либо симмисторные ключи (решать вам).
Пульт - три варианта: 1. Найти дома дохлый девайс, у которого было IR управление и выдрать оттуда (я так и сделал когда понадобился). 2. Купить (недорогие они). 3. Можно все переписать под кнопки (в начальных версиях так и было), но здесь придется менять логику управления, на пульте кнопок много, а вам лепить пианино ни к чему.
Все красоты типа давления, влажности, напряжения ТС лепил для личного удовольствия. Можно этим воспользоватся, а можно и выкинуть.
Thorn, если читаешь, надеюсь не обижаешься, что в твою ветку перебрались?
Доброго дня. Коненчое непротив, правда как вам уже говорил ув. Вадим (bwn) - эта ветка холливар ещё тот, а все потому что практически с "- 0". Но счас очень доволен, собрал после на мелкой ардуинк, моторшилде , блютусинке и аппинвенторе своему сыну ДУ мелкий танк, в пыжика своего в больших планах подключится к CAN-шине и замутить свой БК (306-ой он и в нем почти ничего нет:(. Однако по поводу акваконтроллера.
Я так понял менять яркость вы планируете силовыми транзисторами в мое м случае это было диммирование самим драйвером. Но суть то неменяется всеравно задается таймер и время приращения\уменьшения.
Реле я использовал именно для снижения энергопотребления и полного отключения простаиваемой автоматики. Но к сожалению заявленные токи до 10А они врядли безболезненно "вытянут". В моих цепях каждое коммутирует не более 7-8А и при этом нагрев свыше 50 град и в итоге крышку на корпус контроллера уже нельзя было использовать, пришлось реле оставлять открытому воздуху. Ну это так мелочи
Пульт ДУ ровно как и блютусину пользую редко, да они есть да с ними удобно и по меню и так повключать но самая главное что работает вся эта приблуда ардуиновская сама уже месяца три вообще без моего сиьного вмешательства, перенсит легко и перепаы напряжения и отключения ( тут должное надо отдать хорошей стабилизации и запасу мощности БП всей цепи).
Термоконтроль так и непригодился, Ледики негреют радиаторы более 48град при естественном охлаждении, вода ненагревается выше 24 град (при пользовании Т5 и Т8 вода неопускалась ниже 27 град :).
Показания вольтметра оказались и вовсе бесполезны. Ну чео их контролировать (что 5В что 12В) - там и 1% нет оклонений - уберу и тем самым место в коде увеличу.
Самый нужные оказались - это температуры, атм. давление и влажность как нестранно.
Со2 подается по времени - нет нужды замерять показания да и дорого.
ПО меню - самая моя любимая фишка, самое главное что ты независиш ни т вэб-морды, ни от загрузки настроек с ПК, выбрал нужное, сохранил вышел (правда вначале немог вкурить, почему изменения применённые неработают. казывается нужно РЕБУТАТЬ ардуинку).
После я заказывал самые простые энкодер и кнопу типа джлйстик PS. Последняя заменяет сразу 5 кнопок !!!! попробуйте её и места съэкономите и удобно. Энкодер продукт узкоспезиализированный, для нашего контроллера неочень.
Сожалею что немогу выложить схему электрическую принципиальную - всё только в фотошопе есть, смешно смотреть.
ПО меню - самая моя любимая фишка, самое главное что ты независиш ни т вэб-морды, ни от загрузки настроек с ПК, выбрал нужное, сохранил вышел (правда вначале немог вкурить, почему изменения применённые неработают. казывается нужно РЕБУТАТЬ ардуинку).
А чего молчите, это не правильно. Код сейчас смотреть нет желания, но 99%, что причина в переменных, которые считываются один раз при запуске. Лекарство - либо вместо переменной для сравнения применять значение EEPROM напрямую, либо сделать функцию обновления после внесения изменений и при запуске.
а не подскажете, я хочу переподключить экран через I2C освободить выходы. но у меня экран уже спаян с клавиатурой не придёться ли мне его отпаивать. или всё в кучи может работать через этот интерфейс и экран и кнопки. просто я его уже заказал.
а не подскажете, я хочу переподключить экран через I2C освободить выходы. но у меня экран уже спаян с клавиатурой не придёться ли мне его отпаивать. или всё в кучи может работать через этот интерфейс и экран и кнопки. просто я его уже заказал.
Мое личное мнение, что проще отпаять (аккуратно выкусить и впаять новую гребенку) экран от этого шилда и поставить на переходник I2C. Подпаятся можно и к шилду, но придется прозванивать выходы и разводить на переходник. Кнопки в этом случае останутся на аналоговом входе.
Но без пайки и проводов в любом случае не обойтись.
Всем приятного времени суток. Прошу помощи! Решил сделать авто управление аквариумом, автокормушка свет (закат, рассвет), включение фильтра ну и со временем еще чего нибудь прилеплю. Написал код для света по таймеру. Первая проблемма появилась когда включалось питание, то диоды загарались и когда проходило тестирование ардуины гасли и на чинали работать по заданному режиму. это дело исправл поставив реле на питание диодов с задержкой на время запуска ардуины. Вопрос, может можно как то обойтись без реле, а удалить проблемму программно? И вторая проблемма когда заканчивается рассвет то свет должен гореть энное время заданное таймером, а потом переходить в режим заката, но этого не происходит, свет либо гаснет полностью после рассвета или тут же переходит в закат. Код прилогаю ниже может кто поможет? Зарание большое спасибо.
Vallu, попробуйте поставить в setup: analogWrite(REDpin, 255); и аналогично для других.
зачем вам 13 строка?
строки с 27 по 34 делают что то непонятное, а скорее всего ничего не делают.
И ликвидируйте все delay() по максимуму. Сейчас это незаметно, потом может стать проблемой. При корректной работе строк с 27 по 34 вы завесите дуину на 3 часа((((.
Со второй проблемой разобрался
строка 13 нужна для задержки реле на 2 сек что бы ардуино вошла в рабочее состояние, иначе диоды закараются и тутже тухнут. 27-34 нужны чтобы свет горел определенное время.
Она входит в рабочее состояние до setup. Попробуйте инициацию как я написал. И как у вас светики подключены?
да забыл описать саму схему. Имеем ардуино пока УНО, драйвера света, диодные ленты, БП на 12 и 5 В. пок пробовал запитать один диод от ардуины все работало прекрасно без реле, но как подключил драйвера появилась вспышеа в начале работы.
По вашему последнему коду, если вы вместо стр.27-34 напишете просто delay(15300); результат будет тот же. Цикл там не нужен.
Понял, спасибо сейчас попробую. но главный вопрос по реле.