Gроект для аквариума (акваконтроллер для led, temp, time, co2)

bwn
Offline
Зарегистрирован: 25.08.2014

dimon9597 пишет:

Привет формучане! Кто с может помочь с кнопками IR (чтобы работало вкл/выкл и с пульта и по таймерам).Заранее спасибо!

А разве у ТС как то иначе?

dimon9597
Offline
Зарегистрирован: 18.02.2016

Да скетч то такой же только у меня диммирования нет поэтому разобратся немогу (либо пульт работает,таймер нет или на оборот). Раз как то методом тыка получилась и с пульта вкл и выкл и по таймерам все нормально но: когда свет по таймеру "ВКЛЮЧЕН" с пульта выключаешь  он тухнет, а релюшка грется до ужаса и контролька на ней в пол накала светится 

"Меню" сделал работает замечательно уже неделю на банке стоит. СПАСИБО вам огромное!!! Только есть одно "но"; Почему то когда в каком либо таймере на"ВЫКЛЮЧЕНИЕ" ставиш 00:00 включается вообще все и не как не выключишь приходится перезапускать ардуинку. Так и должно быть?

 А на счет рассвет/закат так он мне и не нужен в принципи мне и живого хватает, да и финансы пока не позволяют как говорится: " собираю из того что есть"!

bwn
Offline
Зарегистрирован: 25.08.2014

Разбирайте функцию "Timer" из 282 поста, все что относится к диммерам (OUT4,5) надо переделать с analogWrite на digitalWrite, убрать все счетчики. Должно остаться ВКЛ-ВЫКЛ. Писалось давно, все уже не вспомнить, но у ТС вроде все тщательно прокомментировано. Если сразу сложно, то возьмите бумажку и разрисуйте, как вызываются подфункции из функции "Timer", что и как они изменяют. За автоматическую работу полностью отвечает она.

"Почему то когда в каком либо таймере на"ВЫКЛЮЧЕНИЕ" ставиш 00:00 включается вообще все и не как не выключишь приходится перезапускать ардуинку. Так и должно быть?" - Проверьте формулы расчета времени, возможно данная ситуация является запрещенной, а вы первый на эти грабли наступили.
 

 

dimon9597
Offline
Зарегистрирован: 18.02.2016

bwn спасибо вам огромное!

Хотел бы вас еще попросить что бы вы мне со скетчем на автокормушку помогли!

 

dimon9597
Offline
Зарегистрирован: 18.02.2016

А то у самого мозгов не хватит!:)

 

bwn
Offline
Зарегистрирован: 25.08.2014

dimon9597 пишет:

bwn спасибо вам огромное!

Хотел бы вас еще попросить что бы вы мне со скетчем на автокормушку помогли!

А чем он вас смущает? Как работать с часами, надеюсь поняли. Дальше определиться, как она управляется: открыть клапан (задвижку), кол-во оборотов или какой то период времени? Под это и разрабатывать алгоритм.

dimon9597
Offline
Зарегистрирован: 18.02.2016

Смущает он меня всем! Я далек от програмирования"только методом подставление в чужие коды могу".

Кормушка у меня барабанная принцип работы: Что бы включалась по таймеру работала на выставленой скорости и промежуток времени(в сек.) 

Меню вроде такое?


void setavtocorm(){
  byte pos=0;   
  setHorClockOn=EEPROM.read(winMe*4+1);
  setMinClockOn=EEPROM.read(winMe*4+2);
  setSpeedmotor=  EEPROM.read(winMe*4+3); 
  setdelay =  EEPROM.read(winMe*4+4);
      lcd.clear();                                     //Очищаем на всякий случай дисплейчик
    while(keyIr()!=1){                                 //Крутим цикл пока не будет Setup
    byte KEY=keyIr();                                  //Читаем состояние кнопок
    val=0;
     // delay(200);                                    //Если убрать, не работает подсветка уст.позиции
    
    
    lcd.setCursor(0, 0);
    lcd.print(winMe+1,DEC);                            //Печатаем номер программы таймера
    lcd.print("|");
    lcd.print(pos/3,DEC);                              //Печатаем позицию настройки параметра (замена blink)
    lcd.print("->");  
    
    lcd.setCursor(6,0);                                  //Выводим инфу о часах и минутах
    if (setHorClockOn<10) lcd.print("0");
    lcd.print(setHorClockOn,DEC);
    lcd.print(":");
    if (setMinClockOn<10) lcd.print("0"); 
    lcd.print(setMinClockOn,DEC);       
    lcd.print(" ");
    
    lcd.setCursor(5,1);
     if (setSpeedmotor<100) lcd.print("0"); 
    lcd.print(setSpeedmotor);  
    lcd.print(" ");     
    
    lcd.setCursor(13,1); 
     if (setdelay<10) lcd.print("0");
    lcd.print(setdelay);
    lcd.print(" ");
    
    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) 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) setSpeedmotor++;
    else if (pos==9 && KEY==4) setSpeedmotor--;    
    else if (pos==12 && KEY==3) setdelay++;
    else if (pos==12 && KEY==4) setdelay--; 
    
     if (setHorClockOn>23) setHorClockOn=0;                //Ограничиваем значения
    else if (setMinClockOn>59) setMinClockOn=0;
    
    else if (setSpeedmotor>253) setSpeedmotor=0;
    else if (setdelay>59) setdelay=0;
}                                                         //Конец цикла
      lcd.clear();                                        //Очищаем на всякий случай дисплейчик
   EEPROM.write(winMe*4+1, setHorClockOn);                 //Записываем НОВЫЕ значения
   EEPROM.write(winMe*4+1, setMinClockOn);
   EEPROM.write(winMe*4+2, setSpeedmotor); 
   EEPROM.write(winMe*4+3, setdelay);
   lcd.setCursor(4,0);
   lcd.print("== Saved ==");
   delay(zadTime[4]);
}

таймер на включение(Правельно или нет?)

void avtocorm()
{
int fullMinutes=hours*60+minutes;                                 //Переводим часы + минуты к полным минутам
  int fullMinutesOn=EEPROM.read(1)*60+EEPROM.read(2); 
  
if (fullMinutes>=fullMinutesOn) {isAcorm=1;}        //Проверяем интервал
   else {isAcorm=0;}                           //Если необходимо включить                                       
if(fullMinutes-fullMinutesOn>=0) {isAcorm=1;}
}

дальше вообще не чего в голову не лезет!:)

tarasui
Offline
Зарегистрирован: 29.01.2016

Здрасте а почему бы не контролировать уровень растворенного кислорода в акварюме. Без кислорода рыбы проживут 2 минуты, а без кормушки проживут недельну.

bwn
Offline
Зарегистрирован: 25.08.2014

tarasui пишет:

Здрасте а почему бы не контролировать уровень растворенного кислорода в акварюме. Без кислорода рыбы проживут 2 минуты, а без кормушки проживут недельну.

Вы это прикалываетесь или всерьез?

bwn
Offline
Зарегистрирован: 25.08.2014

dimon9597 пишет:

Смущает он меня всем! Я далек от програмирования"только методом подставление в чужие коды могу".

Кормушка у меня барабанная принцип работы: Что бы включалась по таймеру работала на выставленой скорости и промежуток времени(в сек.) 

Как понимать "на выставленой скорости"? Она чем то меняется или константа?
Если постоянная, то включили в заданное время, отсчитали требуемый интервал, выключили.

 

dimon9597
Offline
Зарегистрирован: 18.02.2016

Хотелось бы скорость вращения из меню выставлять!

bwn
Offline
Зарегистрирован: 25.08.2014

dimon9597 пишет:

Хотелось бы скорость вращения из меню выставлять!

Тогда, забросьте на время проект и разберитесь с этим и этим.
При помощи первого учимся регулировать скорость, второго - отмерять требуемые интервалы без делаев.

tarasui
Offline
Зарегистрирован: 29.01.2016

bwn пишет:

Вы это прикалываетесь или всерьез?

А что тут такого ?

любая УЗВ начинаеться с этого. Это влияет на рост рыбы, размножения, плотность посадки

bwn
Offline
Зарегистрирован: 25.08.2014

tarasui пишет:

bwn пишет:

Вы это прикалываетесь или всерьез?

А что тут такого ?

любая УЗВ начинаеться с этого. Это влияет на рост рыбы, размножения, плотность посадки

Мы здесь вроде не про рыбоводческие хозяйства. Нормальный аквариум должен существовать достаточно автономно, а не на аппарате сердце-легкие. ИМХО.

dimon9597
Offline
Зарегистрирован: 18.02.2016

Здраствуйте bwn прочитал то что вы мне дали! На пустой ардуинки попробывал и со скоростью и интервалами по эксперементировать! Получилось, со скоростью разобрался как сделать а вот с милсами так и не понял как их применить в скетче!кормушка крутится по интервалу только при перезагруски,а как дальше делать в голову даже не лезет!

bwn
Offline
Зарегистрирован: 25.08.2014

Включили, запомнили время, ушли в основной цикл, каждый проход возвращаемся и проверяем достижение интервала, достигли - выключили.
Посмотрите еще здесь. Там для Далласов температурных, но принцип тот же. 47 пост

P/S только вход в функцию надо делать не постоянный, а при наступлении времени кормления.

serega.gram
Offline
Зарегистрирован: 15.04.2015

Добрый день. Собрал себе контроллер по скетчу Thorn, всё хорошо только не пойму почему разделитель часов мигает не синхронно с секундами. То в месте то в разбежку мигают. И как подключить вольтметр что бы экран не пустовал по нолям. Зараннее спасибо.

bwn
Offline
Зарегистрирован: 25.08.2014

serega.gram пишет:
Добрый день. Собрал себе контроллер по скетчу Thorn, всё хорошо только не пойму почему разделитель часов мигает не синхронно с секундами. То в месте то в разбежку мигают.

Там мигалка к часам не привязана, просто через миллис. Если только часы и минуты отображать, то это незаметно.

serega.gram
Offline
Зарегистрирован: 15.04.2015

Ещё вопрос. Идёт отчет секунд и секунды съедаются может быть так : 2 3 5 6 7 9 10 : может что то с модулем часов

bwn
Offline
Зарегистрирован: 25.08.2014

Я уже код не помню, если отображение через миллис сделано, попробуйте переделать на вывод при изменении значения секунды и мигать вместе с ней.

serega.gram
Offline
Зарегистрирован: 15.04.2015

Добрый вечер, скажите какую строчку нужно изменить для более быстрого обновления температуры на экране

bwn
Offline
Зарегистрирован: 25.08.2014

Вывод на экран в функции с 989 строки, частота опроса Далласов - строка 1087, сам массив с временем задержек в блоке инициализации. Поставите часто, экран может мерцать. Скетч из 282 поста.

svidrak
Offline
Зарегистрирован: 20.01.2017

Уже довольно давно сижу над кодом автора переделал под себя , освободил памяти убрал лишние . Хочу сказать огромное спасибо Thorn и bwn. 
Ви написали хорошую програму которая при небольших зусилиях переделивается под свои нужди.
немного переделиваю внешний вид главного окна .
Делаю сейчас авто долив  води в аквариум.
Пока в пути датчик ткмператури и барометр 
Памяти использовано на даний момент 25204 байт так что есть куда писать)

serega.gram, для болие бистрого обновления температури нужно изменить значение в строчке    if (millis()-prvMlsVo>zadTime[7]){     //Проверяем интервал для обновления

именно цифру 7 на меньше но зачем?
зачем вам обновлять температуру чаще чем раз в минуту? 

svidrak
Offline
Зарегистрирован: 20.01.2017

bwn, бил би признателен за подсказку . 

вот код настройки таймеров, я в один таймер добавил кроме настройки времени включения выключения еще настройку максимального значения диммирования на этом таймере, это значение хранится в переменной maxPWM как мне правильно добавить код чтобы значение этой переменной записывало в еепром ? 

Не до конца разобрался с этими строчками кода,  а именно не понимаю как правильно указать адрес куда записать значение переменной .
 

EEPROM.write(winMe*4+1, setHorClockOn);                //Записываем НОВЫЕ значения
   EEPROM.write(winMe*4+2, setMinClockOn); 
   EEPROM.write(winMe*4+3, setHorClockOff);
   EEPROM.write(winMe*4+4, setMinClockOff);

Весь код настройки
 

//=========== Обработка Меню, параметры и настройка
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.cursor();                                    //Показываем курсор
//      lcd.blink();
//      delay(200);                                        //Если убрать, не работает подсветка уст.позиции
//      lcd.noBlink();                                     //Больше мигать не нужно
//      lcd.noCursor();                                    //Прячем курсор    
    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,2);
    if (winMe==1) 
      {
      if (maxPWM<10) lcd.print ("0");                       // Вивод максимального значения димирования в  2 таймере
      lcd.print(maxPWM);
      lcd.print(" Dimm");
      }
     
    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<14) 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--; 
    else if (pos==15 && KEY==3) maxPWM++;
    else if (pos==15 && KEY==4) maxPWM--; 

    
    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]);
}

 

bwn
Offline
Зарегистрирован: 25.08.2014

svidrak, эту часть кода ТС полностью писал сам, мне особо и вспомнить нечего. Если смотреть 282 пост, переменные экранов объявлены с 90 строки, под каждый экран зарезервировано четыре однобайтовых ячейки. Получается, либо увеличить каждый экран до 5 байт
winMe*5+1........winMe*5+5 и внимательно посмотреть логику чтения-записи, чтобы не нарушить или добавить по образу и подобию еще один из четырех переменных. Как то так.
 

UPD, боюсь, так безбольно не получится. Посмотрел еще раз, там есть экраны и с семью ячейками. Надо расписывать всю карту EEPROM, чтобы не наехать на другие ячейки. Проще наверно будет все меню с нуля переписать. Или ТС на связь выйдет, подскажет.
Да и максимальные значения диммирования уже в коде присутствуют, придется с ними как то разбираться.

svidrak
Offline
Зарегистрирован: 20.01.2017

bwn, да есть максимальное значение но оно для всех таймеров. 

А я добавил именно настройку для 2 таймера, так как 'тот таймер в основном включается ночью а там нужно максимум 20-50 процентов 1 светильника. 

Все работает в принципе только если перезагрузить ардуино то настройка диммирования  слетает до первоначальной настройки в сетапе.
В принципе не страшно но хочется розобратся)
сначала дествительно добавил по образу подобному в коде но наехал на другие значения .

bwn
Offline
Зарегистрирован: 25.08.2014

Как самый безбольный вариант, правда из меню не получится регулировать, прописать требуемое значение принудительно в EEPROM, условно в 50 ячейку, а потом использовать его. Иначе без рисования карты и переделки логики не обойтись.((((
Либо эту дополнительную переменную попробовать писать напрямую в заведомо свободную ячейку, там запись происходит в той же функции экрана. Попробуйте, ваш maxPWM = EEPROM.read(100);, покрутили и потом в конце EEPROM.write(100, maxPWM);, не изящно, но должно вроде взлететь.

svidrak
Offline
Зарегистрирован: 20.01.2017

bwn, как я понимаю для рисования карти еепрома нужно подсчитать все значения куда записываются с програми? 

В принципе вроде прокатило с вашим предложением работает но по хорошому все равно хочу разобраться с этой еепром. 

bwn
Offline
Зарегистрирован: 25.08.2014

Да, брать все используемые с EEPROM переменные и по листингу выписывать, что куда записывается по физическим адресам. Нудно и тошно.((((

serega.gram
Offline
Зарегистрирован: 15.04.2015

Здраствуйте. Я ёще вопрос задам, если вместо BMP 085 поставлю 180 ни смертельно это. И как делалась калибровка датчика по местности. А то разное пишут

svidrak
Offline
Зарегистрирован: 20.01.2017

Сам еще не  прикрутил барометр тоже в пути 180 говорят что они замениемие и код подходит от 085 к 180.
Но нужно проверят .На крайняк заменить библиотеку и несколько строчек кода.
Пробежался по програме вроде нет калибровки по месности.

bwn
Offline
Зарегистрирован: 25.08.2014

По местности их вроде калибруют под девайсы типа  измерения высоты или что то подобное. Когда придет обратите внимание на обвязку. Модули на 085 были толерантнты к 5В питанию и сигналам, по 180 лучше уточнить.

svidrak
Offline
Зарегистрирован: 20.01.2017

Кто небудь имел дело с пультами RC6 ?
нашол класний пльт на роботе от ноутбука HP но кодировка у него RC6 и не могу розобратся если вписать коди етого пульта то на кнопки реагирует на одно нажатие 3 раза исполняет команду.
может кто что подскажет?

bwn
Offline
Зарегистрирован: 25.08.2014

svidrak пишет:

Кто небудь имел дело с пультами RC6 ?
нашол класний пльт на роботе от ноутбука HP но кодировка у него RC6 и не могу розобратся если вписать коди етого пульта то на кнопки реагирует на одно нажатие 3 раза исполняет команду.
может кто что подскажет?

Так посмотрите через сериал как команды проходят, может надо задержку между приемами поставить, типа как на обычную кнопку. Чисто предположения.

svidrak
Offline
Зарегистрирован: 20.01.2017

Да посмотрел приходит почему то код 3 раза скорей всего библиотека плохо код расшифровывает. 

Пока проблему не смог найти скорей всего придется отказаться от пульта но жаль удобний.
Виставлял задержку не помагает 

сделал сибе символьний вивод информации .
все прибори имеют свой значек и в зависимости от включен виключен меняються.
На удивление такой вивод занимает намного даже меньше места в ардуине.
и одна стролка свободная

 
 
bwn
Offline
Зарегистрирован: 25.08.2014

А почему  проверку не сделать - повторный код считать правильным только через секунду-две?

svidrak
Offline
Зарегистрирован: 20.01.2017

а как провильно сделать програмно ето?
вот мой обработчик кнопок

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(" ");
  byte ret;
   switch (val) {
   case 0x80110422: {ret=1; break;};     //setup      KEY1
   case 0x80118420: {ret=2; break;};     //left       KEY2
   case 0x8011041E: {ret=3; break;};     //up         KEY3
   case 0x8011841F: {ret=4; break;};     //down       KEY4
   case 0x80110421: {ret=5; break;};     //right      KEY5
   case 0x8011840C: {ret=6; break;};     //exit       POWER_KEY
   case 0x80110412: {ret=7; break;};     //vol_down   KEY9
   case 0x80118413: {ret=8; break;};     //vol_up     KEY8
   case 0xFF30CF: {ret=9; break;};     //slide      KEY9
   case 0xFFB04F: {ret=10; break;};    //stop       KEY10
   case 0xFF18E7: {ret=11; break;};    /// течение  KEY11
   
default: ret=0;                           //ежели ничего не нажато
}
return ret;

}

 

bwn
Offline
Зарегистрирован: 25.08.2014

Что то вроде if (old_ret == ret && time < 1сек....){ Возврат }
Либо вход в обработчик не раньше, чем через секунду-две после приема значащей команды (на флаге и миллисе).
Пришла значащая команда, запомнили миллис, пока не прошел интервал в функцию опроса не входим, даже флаг не нужен.
Правда будет тормозить, когда надо нажав кнопку увеличивать-уменьшать что то.
Можно правило входа распространить только на те, которые  одно нажатие требуют.
В целом, по своей задаче алгоритм обыгрывать.

svidrak
Offline
Зарегистрирован: 20.01.2017

Да с етим пультом гемор.
он еще и отсправляет  на 1 нажатие один код на второе второй код одна кнопка 2 кода 

bwn
Offline
Зарегистрирован: 25.08.2014

Если нет сильного желания победить, наверно проще выкинуть.

svidrak
Offline
Зарегистрирован: 20.01.2017

Да желание есть завтра еще посмотрю в принципе в примере код декодируется нормально и один раз, а в программе автора почемуто 3 раза виставлял и делей итд не помогает. 

нажиатие может один раз код прилететь, а может и три раза, если подержать прилетает один и тот самий код, а если нажимать два разних по очереди.

svidrak
Offline
Зарегистрирован: 20.01.2017

У меня еще проблема есть такая не могу понять программная она или железо. 

Если включен полностью свет все 3 канала с разним интервалом иногда на секунду выключается реле компрессора включается но при этом выключаются 2 реле света

bwn
Offline
Зарегистрирован: 25.08.2014

Это скорее по питанию смотрите, где то похоже помеха пролазит.

Vallu
Vallu аватар
Offline
Зарегистрирован: 17.10.2014

Здравствуйте, От пультов самсунг приходит только один код. От остальных сколько смотрел по 3. Есть решение у Дмитрия Осипова на ютубе. Удачи.

Vallu
Vallu аватар
Offline
Зарегистрирован: 17.10.2014

svidrak пишет:

Да посмотрел приходит почему то код 3 раза скорей всего библиотека плохо код расшифровывает. 

Пока проблему не смог найти скорей всего придется отказаться от пульта но жаль удобний.
Виставлял задержку не помагает 

сделал сибе символьний вивод информации .
все прибори имеют свой значек и в зависимости от включен виключен меняються.
На удивление такой вивод занимает намного даже меньше места в ардуине.
и одна стролка свободная

 
Здравствуйте, От пультов Самсунг приходит только один код. От остальных сколько смотрел по 3. Есть решение у Дмитрия Осипова на ютубе. Удачи.

Витенька
Offline
Зарегистрирован: 03.04.2016

bwm

Здравствуйте Уважаемый! Можно Вас попросить просветить в одной позиции кода акваконтроллера? Суть дела такова, от програмирования я оооочень далек, но, собрал пару контроллеров из одного из форумов, методом тыка подогнал под то что мне нужно было, всё работает нареканий нет (к аквариумам можно подходить просто помедитировать, всё само работает). Решил переделать свет в аквариумах, переделал но попутно хотел задействовать с изначального кода функцию рассвет/закат и тута столкнулся с проблемкой. После загрузки кода в ардуину так сказать по умолчанию в настройках рассвет/закат стоит время длительности 127 минут на рассвет и так же на закат, как мне показалось многовато. При изменении времени длительности рассвета/заката в настройках (при уменьшении этого времени) старт рассвета смещается и начинается можно сказать уже со средней яркости засвечивания светодиодов. Снова методом тыка долез до одной из позиций в коде где стартовую яркость вроде бы победил, к закатам пока не дошел долго сидеть над ним нужно. Пожалуйста объясните назначение, функцию, или не знаю как ещё это обозвать строк из кода. После изменения в строке 473  B01111111 на B11111111 и уменьшении в настройках длительности времени рассвета старт начался более-менее с слабого засвечивания светодиодов, к закату еще не добрался. Ну и вот сама суть вопроса, как зависят эти строки на функцию рассвета/заката, количество цифр, какие именно цифры за что отвечают, вопрос идиотский но всё же если можно объясните для особо не догоняющего обычным народным матом эту позицию?

// Обращение к ним идет по номерам от 14 (для аналогового входа 0) до 19 (для аналогового входа 5).
#define EXT_FILTER_PIN 12
#define EXT_AIR_PIN 1  
#define EXT_HEATER_PIN 13  
#define EXT_COOLING_PIN 10  
#define EXT_LIGHT_1_PIN 15
#define EXT_LIGHT_2_PIN 16
#define EXT_CO2_PIN 0  

#define EXT_POWER_ON_PIN 20
#define EXT_LIGHT_LED_PIN 11

#define EXT_UDO_MICRO_PIN 17
#define EXT_UDO_MACRO_PIN 18
#define EXT_UDO_Fe_PIN 19

#define Key_PIN 7

#define DispLight_min 235 //минимальная подсветка в режиме часов
#define CorrTime 0      // коррекция хода системных часов [Сек] выполняется каждый час  
//const int CorrTime = -1;      // коррекция хода системных часов [Сек]  
// It is assumed that the LCD module is connected to
// the following pins using a levelshifter to get the
// correct voltage to the module.
//      SCK  - Pin 8
//      MOSI - Pin 9
//      DC   - Pin 10
//      RST  - Pin 11
//      CS   - Pin 12
//
#include <LCD5110_Graph.h>

#define LED_LIGHT_PIN 9  
LCD5110 myGLCD(8,7,6,4,5); 
extern uint8_t SmallFont[];
extern uint8_t BigNumbers[];
//extern unsigned char TinyFont[];
byte ledContrast;
byte ledLight;

//подключаем заголовочный файл библиотеки EEPROM
#include <EEPROM.h>

#include <OneWire.h> 
OneWire  temp(14);  // on pin 10 (a 4.7K resistor is necessary) 
float cur_temp = -999;
byte temp_type_s;
byte temp_data[12];
byte temp_addr[8];
byte temp_cicle = 0;
// I assume you know how to connect the DS1307.
// DS1307:  SDA pin   -> Arduino Digital 4
//          SCL pin   -> Arduino Digital 5

#include <DS1307.h>

// Init the DS1307
DS1307 rtc(3, 2); 
// Init a Time-data structure
Time  time; 
unsigned long currentTime;
unsigned long loopTime;


byte key = 0;
byte prev_key = 0;
byte idle_key = 0;
//const int max_idle_key = 100; //цыклов не активности перед скринсейвером
#define max_idle_key  100 //цыклов не активности перед скринсейвером

int cur_menu = 0;
int cur_item = 0;
boolean cur_item_edit = false;
byte aquaT;                   // Требуемая температура воды
boolean CoolingEnabled;             // Разрешено ли охлаждение куллером
boolean light1 = false;
boolean light2 = false;
boolean air = false;
boolean CO2 = false;
byte kormMin = 0;             // Остаток времени для кормления мин

byte minCool = 0;  // минимальные обороты кулера для вентиляции крышки и охлаждения ламп
byte maxCool = 0;  // максимальные обороты для охлаждения воды

void setup()
{
  pinMode(EXT_HEATER_PIN, OUTPUT);      // устанавливает режим работы - выход
  digitalWrite(EXT_HEATER_PIN, LOW);   // выключает
  pinMode(EXT_COOLING_PIN, OUTPUT);      // устанавливает режим работы - выход
  digitalWrite(EXT_COOLING_PIN, LOW);   // выключает
  pinMode(EXT_LIGHT_1_PIN, OUTPUT);      // устанавливает режим работы - выход
  digitalWrite(EXT_LIGHT_1_PIN, HIGH);   // выключает
  light1 = true;
  pinMode(EXT_LIGHT_2_PIN, OUTPUT);      // устанавливает режим работы - выход
  digitalWrite(EXT_LIGHT_2_PIN, LOW);   // выключает
  light2 = false;
  pinMode(EXT_FILTER_PIN, OUTPUT);      // устанавливает режим работы - выход
  digitalWrite(EXT_FILTER_PIN, HIGH);   // выключает
  pinMode(EXT_CO2_PIN, OUTPUT);      // устанавливает режим работы - выход
  digitalWrite(EXT_CO2_PIN, LOW);   // выключает
  CO2 = false;
  pinMode(EXT_AIR_PIN, OUTPUT);      // устанавливает режим работы - выход
  digitalWrite(EXT_AIR_PIN, HIGH);   // выключает
  air = true;
  CoolingEnabled = false;             // Разрешено ли охлаждение куллером


  pinMode(EXT_POWER_ON_PIN, OUTPUT);      // устанавливает режим работы - выход
  digitalWrite(EXT_POWER_ON_PIN, LOW);   // выключает
  pinMode(EXT_LIGHT_LED_PIN, OUTPUT);      // устанавливает режим работы - выход
  digitalWrite(EXT_LIGHT_LED_PIN, LOW);   // выключает
  pinMode(EXT_UDO_MICRO_PIN, OUTPUT);      // устанавливает режим работы - выход
  digitalWrite(EXT_UDO_MICRO_PIN, LOW);   // выключает
  pinMode(EXT_UDO_MACRO_PIN, OUTPUT);      // устанавливает режим работы - выход
  digitalWrite(EXT_UDO_MACRO_PIN, LOW);   // выключает
  pinMode(EXT_UDO_Fe_PIN, OUTPUT);      // устанавливает режим работы - выход
  digitalWrite(EXT_UDO_Fe_PIN, LOW);   // выключает

  //включит pullup резистор для входа:
//  pinMode(Key_PIN, INPUT);

// Init EEPROM
//  for(int e = 0; e < 2047; e++) EEPROM.write(e,0);
//  EEPROM.write(0,61);   // ledContrast  !!!!!!! Очень акуратно иначе белый либо черный экран
//  EEPROM.write(1,200);  // ledLight 
//  EEPROM.write(2,24);   // Требуемая температура воды
//  EEPROM.write(3,1);    // Разрешено ли охлаждение куллером
  
  ledContrast = EEPROM.read(0);
  // первичная установка контраста - иначе при первом запуске нихрена невидно
  if ((ledContrast==0)||(ledContrast==255)){
    ledContrast = 65;
  }

  ledLight = EEPROM.read(1);
  myGLCD.InitLCD(ledContrast);
  pinMode(LED_LIGHT_PIN, OUTPUT);      // устанавливает режим работы - выход
  analogWrite(LED_LIGHT_PIN,ledLight);
  aquaT = EEPROM.read(2);                   // Требуемая температура воды

  minCool = EEPROM.read(3);  // минимальные обороты кулера для вентиляции крышки и охлаждения ламп
  maxCool = EEPROM.read(4);  // максимальные обороты для охлаждения воды

  // Set the clock to run-mode
  rtc.halt(false); 
//  rtc.setDOW(SUNDAY);        // Set Day-of-Week to SUNDAY
//  rtc.setTime(12, 0, 0);     // Set the time to 12:00:00 (24hr format)
//  rtc.setDate(3, 10, 2010);   // Set the date to October 3th, 2010 
  
  myGLCD.setFont(SmallFont);
  myGLCD.clrScr();
  myGLCD.update();

/*
  myGLCD.setFont(SmallFont);
  myGLCD.clrScr();
  myGLCD.print("AQUA kontrolx", CENTER, 3);
  myGLCD.print("MIHS", CENTER, 20);
  myGLCD.drawRect(28, 18, 56, 28);
  for (int i=0; i<6; i++)
  {
    myGLCD.drawLine(57, 18+(i*2), 83-(i*3), 18+(i*2));
    myGLCD.drawLine((i*3), 28-(i*2), 28, 28-(i*2));
  }
//  myGLCD.setFont(TinyFont);
  myGLCD.print(" - 2016 - ", CENTER, 36);
//  myGLCD.print("AlexVOK@gmail.com", CENTER, 42);
  myGLCD.update();
  delay(1000);
*/
//-------------------------------------------------------------------------------
  byte b = 0;
  while ( (!temp.search(temp_addr))&&(b < 10)) {
    //Serial.println("Нет больше адресов.");
    temp.reset_search();
    delay(250);
    b++;
  }
//  if (OneWire::crc8(temp_addr, 7) != temp_addr[7]) {
//      Serial.println("CRC не является действительным!");
//  }

// Первый байт ROM указывает, какой чип
  switch (temp_addr[0]) {
    case 0x10:
//      Serial.println("  Chip = DS18S20"); 
      temp_type_s = 1;
      break;
    case 0x28:
//      Serial.println("  Chip = DS18B20");
      temp_type_s = 0;
      break;
    case 0x22:
//      Serial.println("  Chip = DS1822");
      temp_type_s = 0;
      break;
//    default:
//      Serial.println("Устройство не распознано");
  }

  currentTime = millis();
  loopTime = currentTime;   
}

//-----------------------------------------------------------------------------------
float getTemp(){
//  temp.reset();
//  temp.select(temp_addr);
//  temp.write(0x44, 1);        // start conversion, with parasite power on at the end
  
//  delay(1000);     // maybe 750ms is enough, maybe not
  // we might do a ds.depower() here, but the reset will take care of it.
  
  temp.reset();
  temp.select(temp_addr);    
  temp.write(0xBE);         // Read Scratchpad

  for (byte i = 0; i < 9; i++) {           // we need 9 bytes
    temp_data[i] = temp.read();
  }
//  Serial.print(OneWire::crc8(data, 8), HEX);

  // Convert the data to actual temperature
  // because the result is a 16 bit signed integer, it should
  // be stored to an "int16_t" type, which is always 16 bits
  // even when compiled on a 32 bit processor.
  int16_t raw = (temp_data[1] << 8) | temp_data[0];
  
  if (temp_type_s) {
    raw = raw << 3; // 9 bit resolution default
    if (temp_data[7] == 0x10) {
      // "count remain" gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - temp_data[6];
    }
  } else {
    byte cfg = (temp_data[4] & 0x60);
    // at lower res, the low bits are undefined, so let's zero them
    if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
    //// default is 12 bit resolution, 750 ms conversion time
  }
  return ((float)raw / 16.0);
}

//-----------------------------------------------------------------------------------
// Нажатые кнопки
//int button;
const byte BUTTON_NONE   = 0;
const byte BUTTON_UP     = 1;
const byte BUTTON_DOWN   = 2;
const byte BUTTON_OK     = 3;
const byte BUTTON_CANCEL = 4;

int getPressedButton()
{
 byte KeyNum=0;
 int KeyValue1=0;
 int KeyValue2=0;
 
//Читаем в цикле аналоговый вход, для подавления дребезга и нестабильности читаем по два раза подряд, пока значения не будут равны.
//Если значения равны 1023 – значит не была нажата ни  одна клавиша.
do {
 // считываем значения с аналогового входа(A0)  
 KeyValue1=analogRead(Key_PIN);
 delay(10);
 KeyValue2=analogRead(Key_PIN);
 delay(5);
 } while (KeyValue1!=KeyValue2);
 
//Интерпретируем полученное значение и определяем код нажатой клавиши
 if (KeyValue2 > 900) 
  {KeyNum = BUTTON_NONE;}
 else if (KeyValue2 > 450) 
       {KeyNum = BUTTON_CANCEL;}
      else if (KeyValue2 > 250) 
            {KeyNum = BUTTON_UP;}
           else if (KeyValue2 > 100) 
                 {KeyNum = BUTTON_DOWN;}
                else {KeyNum = BUTTON_OK;}
//Возвращаем код нажатой клавиши
return KeyNum;
}

//-----------------------------------------------------------------------------------
void naviKey(byte maxItems){
  if(key == BUTTON_UP){
    cur_item--;
    if(cur_item < 1)
      cur_item = maxItems;
  }
  if(key == BUTTON_DOWN){
    cur_item++;
    if(cur_item > maxItems)
      cur_item = 1;
  }
}
//-----------------------------------------------------------------------------------
void drawMenu(String mName, String item1, String item2, String item3, String item4){
  myGLCD.setFont(SmallFont);
  myGLCD.clrScr();
  
  myGLCD.print(mName,1,0);
  myGLCD.print(rtc.getTimeStr(FORMAT_SHORT),RIGHT,0);
  myGLCD.drawLine(0,8,83,8);
  myGLCD.drawLine(0,9,83,9);

  if(cur_item == 1){
    myGLCD.print(item1,3,12);
    myGLCD.drawRoundRect(0,11,83,20);
  }else  
    myGLCD.print(item1,0,12);
      
  if(cur_item == 2){
    myGLCD.print(item2,3,21);
    myGLCD.drawRoundRect(0,20,83,29);
  }else  
    myGLCD.print(item2,0,21);

  if(cur_item == 3){
    myGLCD.print(item3,3,30);
    myGLCD.drawRoundRect(0,29,83,38);
  }else  
    myGLCD.print(item3,0,30);

  if(cur_item == 4){
    myGLCD.print(item4,3,39);
    myGLCD.drawRoundRect(0,38,83,47);
  }else  
    myGLCD.print(item4,0,39);

  myGLCD.update();
}

byte menu_hh;
byte menu_mi;
byte menu_dd;
byte menu_mm;
int menu_yyyy;
byte menu_dow;
byte menu_off;
byte menu_item_count;
int alertAdr;
byte curLoad;

byte prMin = 0;
//-----------------------------------------------------------------------------------
void drawIntMenu(String mName, int minVal, int maxVal, int Val){
  myGLCD.setFont(SmallFont);
  myGLCD.clrScr();
  
  myGLCD.print(mName,1,0);
//  myGLCD.print(rtc.getTimeStr(FORMAT_SHORT),RIGHT,0);
  myGLCD.drawLine(0,8,83,8);
  myGLCD.drawLine(0,9,83,9);

  myGLCD.setFont(BigNumbers);
  myGLCD.printNumI(Val,CENTER,11);

  myGLCD.drawRoundRect(0,38,83,47);
  
  int k = 80*(Val-minVal)/(maxVal - minVal);
  for(int i = 2; i < k+2; i++)
    myGLCD.drawLine(i,40,i,46);
  myGLCD.update();
}

boolean  new_hour = true;
byte secc = 0;
byte LED_sunrise = 0;
byte LED_cur_pos = 0;
byte udo_tim = 0;
byte bt;
//*****************************************************************************************
//*****************************************************************************************
void loop() {
currentTime = millis();
key = getPressedButton();
if((currentTime >= (loopTime + 250))||(key != prev_key)){ // проверяем каждые 5мс (20 Гц)

  if((prev_key != key)&&(key != 0)){
    idle_key = 0;
  }else{ 
    idle_key++;
  }
  prev_key = key;


  if (key == 0) // Измереяем температуру только в состоянии простоя
  {
    if(temp_cicle == 0){
      temp.reset();
      temp.select(temp_addr);
      temp.write(0x44, 1);        // start conversion, with parasite power on at the end
    }
    if(temp_cicle == 4){
      cur_temp = getTemp();
      // Управление нагревом и охлаждением ----------------------------------------------
      if(cur_temp < (float)aquaT){
        digitalWrite(EXT_HEATER_PIN, HIGH);   // включает нагреватель
      }else  
        digitalWrite(EXT_HEATER_PIN, LOW);   // выключает  нагреватель
        
      if (CoolingEnabled) {
        if(cur_temp > ((float)aquaT+0.1)){               // Разрешено ли охлаждение куллером
          int coll_cur = minCool+(((float)(maxCool - minCool))/100)*(((float)(cur_temp-aquaT))/0.5)*100;
          if (coll_cur > maxCool) { coll_cur = maxCool;}
          analogWrite(EXT_COOLING_PIN, coll_cur);   // включает куллер
        }else{  
          analogWrite(EXT_COOLING_PIN, minCool);   // включаем режим проветривания
        }
      }else{
        if (air||light1){
//        if (air||light1||light2){
          analogWrite(EXT_COOLING_PIN, minCool);   // включаем режим проветривания
        }else{  
          digitalWrite(EXT_COOLING_PIN, LOW);   // выключает  куллер
        }
      } 
    }
    if(temp_cicle > 51){
      temp_cicle = 0;
    }else{
      temp_cicle++;
    }
  }

// --------------------------------------------------------------------------------


  if(secc > 4){
    secc = 0;
  }else{
    secc++;
  }

  
  // Get data from the DS1307
  time = rtc.getTime();   
  // коррекция хода системных часов [Сек]  
  if (time.min == 0){
    new_hour = true;
  }
  if ((time.min == 30)&&(new_hour)){
    int corr_sec = time.sec + CorrTime;    // коррекция хода системных часов [Сек]  
    byte corr_min = time.min;
    if (corr_sec < 0){
      corr_sec = corr_sec + 60;
      corr_min--;
    }
    if (corr_sec > 59){
      corr_sec = corr_sec - 60;
      corr_min++;
    }
    
    rtc.setTime(time.hour, corr_min, corr_sec);     // Set the time to 12:00:00 (24hr format)
    new_hour = false;
  }
  //-----
  // Новая минута ----------------------------------------------
   if(prMin != time.min){
    prMin = time.min;

  // Время для кормления мин
    if(kormMin > 0){
      digitalWrite(EXT_FILTER_PIN, LOW);   // выключает Фильтр
      kormMin--;
    }else{
      digitalWrite(EXT_FILTER_PIN, HIGH);   // включает Фильтр
    }  
    // Восход / Закат
    if (LED_sunrise > 0){
      byte led_val = (LED_sunrise&B01111111);
      byte led_tmp = 0;
      boolean is_sunrise = LED_sunrise&B10000000;
      if (LED_cur_pos >= led_val){
        led_tmp = 255;
        LED_sunrise = 0;
      }else{  
        led_tmp = LED_cur_pos*255/led_val;
      } 
      if(!is_sunrise){  // Закат
        led_tmp = 255 - led_tmp;
      }
      // Управляем блоком питания
      if (led_tmp == 0){
        digitalWrite(EXT_POWER_ON_PIN, LOW);
      }else{         
        digitalWrite(EXT_POWER_ON_PIN, HIGH);
      }  

      analogWrite(EXT_LIGHT_LED_PIN, led_tmp);   // LED
      LED_cur_pos++;
    } 
    
//-------ALARM------------------------------------------------------------------------- 
   for(int a = 100; a < 1001; a = a + 4){
     byte b1 = EEPROM.read(a);
//     if(((boolean)(b1&B10000000))&((boolean)(_BV(time.dow-1)&b1))){  // активная запись и день недели
     if(b1&B10000000){
      if((1<<(time.dow-1))&b1){  // активная запись и день недели
       byte b2 = EEPROM.read(a+1);
       if(time.hour == (byte)(b2&B00011111)){        // сравниваем часы
         byte b3 = EEPROM.read(a+2);
         if(time.min == (byte)(b3&B00111111)){        // сравниваем минути
           byte b4 = EEPROM.read(a+3);
           switch((byte)((b2>>5)&B00000111)){         // определяем нагрузку
             case 0:
               // Разрешено ли охлаждение куллером
               if (b4&B00000001){
                 CoolingEnabled = true;
                 analogWrite(EXT_COOLING_PIN, minCool);   // включаем режим проветривания
               }else{
                 CoolingEnabled = false;
                 digitalWrite(EXT_COOLING_PIN, LOW);
               }  
             break;
             case 1:  // Light1
               if (b4&B00000001){
                 digitalWrite(EXT_LIGHT_1_PIN, HIGH);
                 light1 = true;
               }else{
                 digitalWrite(EXT_LIGHT_1_PIN, LOW);
                 light1 = false;
               }  
             break;   
             case 2:  // Light2
               if (b4&B00000001){
                 digitalWrite(EXT_LIGHT_2_PIN, HIGH);
                 light2 = true;
               }else{
                 digitalWrite(EXT_LIGHT_2_PIN, LOW);
                 light2 = false;
               }  
             break;
             case 3:  // Air
               if (b4&B00000001){
                 digitalWrite(EXT_AIR_PIN, HIGH);
                 air = true;
               }else{
                 digitalWrite(EXT_AIR_PIN, LOW);
                 air = false;
               }  
             break;
             case 4:  // CO2
               if (b4&B00000001){
                 digitalWrite(EXT_CO2_PIN, HIGH);
                 CO2 = true;
               }else{
                 digitalWrite(EXT_CO2_PIN, LOW);
                 CO2 = false;
               }  
             break;
             case 5:  //LED
               // 8 бит 1 восход 0 закат остальные кол мин
               LED_sunrise = b4;
               LED_cur_pos = 0;
             break;
             case 6:  // UDO
               udo_tim = (byte)(b4&B00111111);
               digitalWrite(EXT_POWER_ON_PIN, HIGH);
               delay(100);  //Время на выход в режим БП
               switch((byte)((b4>>6)&B00000011)){
                 case 0:
                   digitalWrite(EXT_UDO_MICRO_PIN, HIGH);
                   delay(udo_tim*4.2);
                   digitalWrite(EXT_UDO_MICRO_PIN, LOW);
                 break;
                 case 1:
                   digitalWrite(EXT_UDO_MACRO_PIN, HIGH);
                   delay(udo_tim*4.2);
                   digitalWrite(EXT_UDO_MACRO_PIN, LOW);
                 break;
                 case 2:
                   digitalWrite(EXT_UDO_Fe_PIN, HIGH);
                   delay(udo_tim*4.2);
                   digitalWrite(EXT_UDO_Fe_PIN, LOW);
                 break;
                 case 3:

                 break;
               }
               digitalWrite(EXT_POWER_ON_PIN, LOW);
             break;
             case 7:
           
             break;
           } 
         }
       }
     }
    } 
   }
  }  
//------------------------------------------------------------------------------------ 
  if((idle_key > max_idle_key)&&(cur_menu != 0)){
    cur_menu = 0;
    cur_item = 0;
    cur_item_edit = false;
  }  
    
  switch(cur_menu){
    case 0: // Time
    {
      analogWrite(LED_LIGHT_PIN,DispLight_min);
      myGLCD.setFont(BigNumbers);
      myGLCD.clrScr();
      myGLCD.printNumI(time.hour,7,2,2,'0');
      myGLCD.drawCircle(42,9,3);
      myGLCD.drawCircle(42,19,3);
      if(secc < 2){
        myGLCD.drawCircle(42,9,2);
        myGLCD.drawCircle(42,19,2);
        myGLCD.drawRect(41,8,43,10);
        myGLCD.drawRect(41,18,43,20);
        myGLCD.setPixel(42,9);
        myGLCD.setPixel(42,19);
      }
      myGLCD.printNumI(time.min,49,2,2,'0');
      
      myGLCD.setFont(SmallFont);
      if(cur_temp < 1){
        myGLCD.print(" net dat`ika",3,38);
      }else{
        myGLCD.print("T:",3,38);
        myGLCD.printNumF(cur_temp,2,15,38);
      }
      myGLCD.update();
      if(key > 0)
        cur_menu = 1;      
        cur_item = 0;
        cur_item_edit = false;
        // Включаем подсветку LED
//        analogWrite(LED_LIGHT_PIN,ledLight);
      break;
    }
    case 1: // men/ -----------------------------------------------------------------
    {
    analogWrite(LED_LIGHT_PIN,ledLight);
    String ll;
      if(light1||light2){
        ll = "wkl";
      }else
        ll ="otkl";

      String aa;
      if(air){
        aa = "wkl";
      }else
        aa ="otkl";

      if(cur_item_edit&&(cur_item == 1))
        ll = "["+ll+"]";

      if(cur_item_edit&&(cur_item == 2))
        aa = "["+aa+"]";
        
      String lk = "";
      if(kormMin > 0){
        lk = " ("+(String)kormMin+")";
      }  
      drawMenu("men/","swet      "+ll,"wozduh    "+aa,"Kormlenie"+lk,"nastrojki");
      naviKey(4);
      switch(key){
        case BUTTON_OK:
          switch(cur_item){
            case 1:
              light1 = !light1;
              light2 = light1;
              if(light1){
                digitalWrite(EXT_LIGHT_1_PIN, HIGH);  // включает LED
              }else
                digitalWrite(EXT_LIGHT_1_PIN, LOW);   // выключает LED
              if(light2){
                digitalWrite(EXT_LIGHT_2_PIN, HIGH); // включает lightTUBE
              }else
                digitalWrite(EXT_LIGHT_2_PIN, LOW);  // выключает lightTUBE
            break;
            case 2:
              air = !air;
              if(air){
                digitalWrite(EXT_AIR_PIN, HIGH);  // включает
              }else
                digitalWrite(EXT_AIR_PIN, LOW);   // выключает
            break;
            case 3:
              kormMin = 20;
              digitalWrite(EXT_FILTER_PIN, LOW);   // выключает Фильтр
            break;
            case 4:
              cur_menu = 13;      
              cur_item = 0;
            break;
          }
        break;
        case BUTTON_CANCEL:
          cur_item_edit = false;
          cur_menu = 0;
          cur_item = 0;
        break;
      }
      break;
    }
    case 13: // nastrojki -----------------------------------------------------------------
    {
      drawMenu("nastrojki", "sistema","Termostat","zada`a","udo");
      naviKey(4);
      switch(key){
        case BUTTON_OK:
          switch(cur_item){
            case 1:
              cur_menu = 131;      
              cur_item = 0;
            break;
            case 2:
              cur_menu = 132;      
              cur_item = 0;
            break;
            case 3:
              cur_menu = 130;      
              cur_item = 1;
            break;
            case 4:
              cur_menu = 134;      
              cur_item = 0;
            break;
          }
        break;
        case BUTTON_CANCEL:
          cur_menu = 1;
          cur_item = 3;
        break;
      }
      break;
    }
    case 134: // udo -----------------------------------------------------------------
    { String uu; 
      if (CO2){
        uu = "wkl";
      }else{
        uu = "Otkl";
      }  
      drawMenu("udo", "CO2", "udo","CO2 "+uu,"");
      naviKey(3);
      switch(key){
        case BUTTON_OK:
          switch(cur_item){
            case 1:
              cur_menu = 133;      
              cur_item = 1;
              menu_off = 1;
              menu_item_count = 25;
              curLoad = 4;
            break;
            case 2:
              cur_menu = 133;      
              cur_item = 1;
              menu_off = 1;
              menu_item_count = 25;
              curLoad = 6;
            break;
            case 3:
              CO2 = !CO2;
              if (CO2){
                digitalWrite(EXT_CO2_PIN, HIGH);
              }else{
                digitalWrite(EXT_CO2_PIN, LOW);
              }  
            break;
            case 4:
//              cur_menu = 130;      
//              cur_item = 1;
            break;
          }
        break;
        case BUTTON_CANCEL:
          cur_menu = 13;
          cur_item = 4;
        break;
      }
      break;
    }
    case 130: // zada`a -----------------------------------------------------------------
    {
      drawMenu("zada`a","swet 1","swet 2","swet LED ","wozduh");
      naviKey(4);
      switch(key){
        case BUTTON_OK:
          switch(cur_item){
            case 1:
              cur_menu = 133;      
              cur_item = 1;
              menu_off = 1;
              menu_item_count = 25;
              curLoad = 1;
            break;
            case 2:
              cur_menu = 133;      
              cur_item = 1;
              menu_off = 1;
              menu_item_count = 25;
              curLoad = 2;
            break;
            case 3:
              cur_menu = 133;      
              cur_item = 1;
              menu_off = 1;
              menu_item_count = 25;
              curLoad = 5;
            break;
            case 4:
              cur_menu = 133;      
              cur_item = 1;
              menu_off = 1;
              menu_item_count = 25;
              curLoad = 3;
            break;
        }
        break;
        case BUTTON_CANCEL:
          cur_menu = 13;
          cur_item = 3;
        break;
      }
      break;
    }
    case 133: // zada`a Menu List -----------------------------------------------------------------
    {
      myGLCD.setFont(SmallFont);
      myGLCD.clrScr();
      int offf;
      switch(curLoad){
        case 0:
          myGLCD.print("nastroika",1,0);
          offf = 400;
        break;
        case 1:
          myGLCD.print("swet 1",1,0);
          offf = 100;
        break;
        case 2:
          myGLCD.print("swet 2",1,0);
          offf = 200;
        break;
        case 3:
          myGLCD.print("wozduh",1,0);
          offf = 300;
        break;
        case 4:
          myGLCD.print("CO2",1,0);
          offf = 500;
        break;
        case 5:
          myGLCD.print("LED",1,0);
          offf = 600;
        break;
        case 6:
          myGLCD.print("udo",1,0);
          offf = 700;
        break;
      }

      myGLCD.print(rtc.getTimeStr(FORMAT_SHORT),RIGHT,0);
      myGLCD.drawLine(0,8,83,8);
      myGLCD.drawLine(0,9,83,9);
      
      String tt;
      byte vy;
      for(byte j = menu_off; j <= min(menu_off+3,menu_item_count); j++){
        vy = 3+9*(j-menu_off+1);
        
        alertAdr = offf+(j-1)*4;
        bt = EEPROM.read(alertAdr+1)&B00011111;
        tt = (String)(j) + " ";
        if(bt < 10){
          tt = tt + "0";
        }
        tt = tt + (String)bt + ":";
        
        bt = EEPROM.read(alertAdr+2)&B00111111;
        if(bt < 10){
          tt = tt + "0";
        }
        tt = tt + (String)bt + " ";

      byte bt = EEPROM.read(alertAdr+3);
      switch(curLoad){
        case 5: // "TimerLED"
          if (bt&B10000000){
            tt = tt + "wkl";
          }else{
            tt = tt + "otkl";
          }  
        break;
        case 6:  //  "TimerUDO"
          switch((byte)((bt>>6)&B00000011)){
            case 0: // Micro
              tt = tt + "Micro";
            break;
            case 1: // Macro
              tt = tt + "Macro";
            break;
            case 2: // Fe+
              tt = tt + "Fe+";
            break;
            case 3: // Ka
              tt = tt + "Ka";
            break;
          }
        break;
        default:  
          if(bt > 0){
            tt = tt + "wkl";
          }else{
            tt = tt + "Otkl";
          }  
        break;
      }

//        tt = "Time "+(String)(j);
//        if(EEPROM.read(offf+(j-1)*4)&B10000000){
//          tt = tt+" Active";
//        }        
        if(cur_item == j){
          myGLCD.print(tt,3,vy);
          myGLCD.drawRoundRect(0,vy-1,83,vy+8);
        }else  
          myGLCD.print(tt,0,vy);

        // перечеркиваем не активные таймера
        if(!(EEPROM.read(offf+(j-1)*4)&B10000000)){
          myGLCD.drawLine(0,vy+5,83,vy+5);
        }        
          
      }

      switch(key){
        case BUTTON_UP:
          if(cur_item == 1){ 
            cur_item = menu_item_count;
            menu_off = menu_item_count - 3;
          }else{  
            cur_item--;
            if(cur_item < menu_off){
             menu_off = cur_item;
            }
          }  
        break;
        case BUTTON_DOWN:
          if(cur_item == menu_item_count){ 
            cur_item = 1;
            menu_off = 1;
          }else{  
            cur_item++;
            if(cur_item > menu_off+3){
             menu_off = cur_item-3;
            }
          }  
        break;
        case BUTTON_OK:
          alertAdr = offf+(cur_item-1)*4;
          cur_menu = 1330;
          cur_item = 1;
          cur_item_edit = false;
        break;
        case BUTTON_CANCEL:
          switch(curLoad){
           case 0:
             //"CoolTime"
             cur_menu = 132;
             cur_item = 2;
           break;
           case 1:
             //"Light1",
             cur_menu = 130;
             cur_item = 1;
           break;
           case 2:
             //"Light2"
             cur_menu = 130;
             cur_item = 2;
           break;
           case 3:
             //"Air"
             cur_menu = 130;
             cur_item = 4;
           break;
           case 4:
             //"CO2"
             cur_menu = 134;
             cur_item = 1;
           break;
           case 5:
             //"LED"
             cur_menu = 130;
             cur_item = 3;
           break;
           case 6:
             //"UDO"
             cur_menu = 134;
             cur_item = 2;
           break;
        }

          cur_item_edit = false;
        break;
      }
      myGLCD.update();
      break;
    }
    case 1330: // zada`a Menu -----------------------------------------------------------------
    {
      myGLCD.setFont(SmallFont);
      myGLCD.clrScr();
      
      switch(curLoad){
        case 0:
          myGLCD.print("nastroika",1,0);
        break;
        case 1:
          myGLCD.print("swet1",1,0);
        break;
        case 2:
          myGLCD.print("swet2",1,0);
        break;
        case 3:
          myGLCD.print("wozduh",1,0);
        break;
        case 4:
          myGLCD.print("CO2",1,0);
        break;
        case 5:
          myGLCD.print("LED",1,0);
        break;
        case 6:
          myGLCD.print("udo",1,0);
        break;
      }

      myGLCD.print(rtc.getTimeStr(FORMAT_SHORT),RIGHT,0);
      myGLCD.drawLine(0,8,83,8);
      myGLCD.drawLine(0,9,83,9);
      byte b1 = EEPROM.read(alertAdr);
      bt = b1;
      myGLCD.print("pnwtsr`tptsbws",0,11);
      for(int j = 1; j < 8; j++){
//        if((cur_item == j)&cur_item_edit){
        if(cur_item == j){
          myGLCD.drawRect(j*12-10,20,j*12-2,28);
        }  
        myGLCD.drawCircle(j*12-6,24,3);
        if(bt&B00000001){
          myGLCD.drawCircle(j*12-6,24,2);
          myGLCD.drawCircle(j*12-6,24,1);
        }
        bt = bt >> 1;
      }
      String stat = "";
      if(cur_item == 8){
        stat = stat + "[";
      }
      if(EEPROM.read(alertAdr)&B10000000){
        stat = stat + "aktiw";
      }else
        stat = stat + "ne aktiw";
      if(cur_item == 8){
        stat = stat + "]";
      }

      stat = stat + ".";
      if(cur_item == 9){
        stat = stat + "[";
      }
      byte tmpb = EEPROM.read(alertAdr+3);
      switch(curLoad){
        case 5: // "TimerLED"
          if (tmpb&B10000000){
            stat = stat + "wkl";
          }else{
            stat = stat + "Otkl";
          }  
          stat = stat + " " + (tmpb&B01111111)+"min";
        break;
        case 6:  //  "TimerUDO"
          switch((byte)((tmpb>>6)&B00000011)){
            case 0: // Micro
              stat = stat + "Micro";
            break;
            case 1: // Macro
              stat = stat + "Macro";
            break;
            case 2: // Fe+
              stat = stat + "Fe+";
            break;
            case 3: // Ka
              stat = stat + "Ka";
            break;
          }
          stat = stat + (tmpb&B00111111)+"mil";
        break;
        default:  
          if(tmpb > 0){
            stat = stat + "wkl";
          }else{
            stat = stat + "Otkl";
          }  
        break;
      }

      if(cur_item == 9){
        stat = stat + "]";
      }
      myGLCD.print(stat,0,29);
      
      stat = "wremq: ";
      if(cur_item == 10){
        stat = stat + "[";
      }
      bt = EEPROM.read(alertAdr+1)&B00011111;
      if(bt < 10){
        stat = stat + "0";
      }
      stat = stat + (String)bt;
      if(cur_item == 10){
        stat = stat + "]";
      }

      stat = stat + ":";

      if(cur_item == 11){
        stat = stat + "[";
      }
      bt = EEPROM.read(alertAdr+2)&B00111111;
      if(bt < 10){
        stat = stat + "0";
      }
      stat = stat + (String)bt;
      if(cur_item == 11){
        stat = stat + "]";
      }
      myGLCD.print(stat,0,39);

      switch(key){
        case BUTTON_UP:
          if(cur_item_edit){
            if((cur_item == 9)&&(curLoad > 4)){
              bt = EEPROM.read(alertAdr+3);
              //if(bt == 255){
              //  bt = 0;
              //}else
                bt++;
              EEPROM.write(alertAdr+3,bt);
            }
            if(cur_item == 10){
              bt = (EEPROM.read(alertAdr+1)&B00011111);
              if(bt == 23){
                bt = 0;
              }else
                bt++;
              EEPROM.write(alertAdr+1,bt^(curLoad<<5));
            }
            if(cur_item == 11){
              bt = EEPROM.read(alertAdr+2)&B00111111;
              if(bt == 59){
                bt = 0;
              }else
                bt++;
              EEPROM.write(alertAdr+2,bt);
            }
          }else
            if(cur_item == 1){ 
              cur_item = 11;
            }else  
              cur_item--;
        break;
        case BUTTON_DOWN:
          if(cur_item_edit){
            if((cur_item == 9)&&(curLoad > 4)){
              bt = EEPROM.read(alertAdr+3);
              //if(bt == 0){
              //  bt = 255;
              //}else
                bt--;
              EEPROM.write(alertAdr+3,bt);
            }
            if(cur_item == 10){
              bt = EEPROM.read(alertAdr+1)&B00011111;
              if(bt == 0){
                bt = 23;
              }else
                bt--;
              EEPROM.write(alertAdr+1,bt^(curLoad<<5));
            }
            if(cur_item == 11){
              bt = EEPROM.read(alertAdr+2)&B00111111;
              if(bt == 0){
                bt = 59;
              }else
                bt--;
              EEPROM.write(alertAdr+2,bt);
            }
          }else
            if(cur_item == 11){ 
              cur_item = 1;
            }else  
              cur_item++;
        break;
        case BUTTON_OK:
          EEPROM.write(alertAdr+1,((EEPROM.read(alertAdr+1)&B00011111)^(curLoad<<5))); // сохраняем номер нагрузки 
          switch(cur_item){
            case 8:
              EEPROM.write(alertAdr,(EEPROM.read(alertAdr)^B10000000));
            break;
            case 9:
              if(curLoad < 5){
                //EEPROM.write(alertAdr+3,(EEPROM.read(alertAdr+3)^B00000001));
                EEPROM.write(alertAdr+3,((EEPROM.read(alertAdr+3)&B00000001)^B00000001));
              }else{
                cur_item_edit = !cur_item_edit;
              }  
            break;
            case 10:
              cur_item_edit = !cur_item_edit;
            break;
            case 11:
              cur_item_edit = !cur_item_edit;
            break;
            default:
              EEPROM.write(alertAdr,(EEPROM.read(alertAdr)^(1<<(cur_item-1))));
            break;
          }
        break;
         case BUTTON_CANCEL:
          switch(curLoad){
           case 0:
             //CoolTime
             cur_menu = 132;
             cur_item = 2;
           break;
           case 1:
             //"Light1",
             cur_menu = 130;
             cur_item = 1;
           break;
           case 2:
             //"Light2"
             cur_menu = 130;
             cur_item = 2;
           break;
           case 3:
             //"Air"
             cur_menu = 130;
             cur_item = 4;
           break;
           case 4:
             //"CO2"
             cur_menu = 134;
             cur_item = 1;
           break;
           case 5:
             //"LED"
             cur_menu = 130;
             cur_item = 3;
           break;
           case 6:
             //"UDO"
             cur_menu = 134;
             cur_item = 2;
           break;
         }
          cur_item_edit = false;
        break;
      }
      myGLCD.update();
      break;
    }
    case 132: // Termostat -----------------------------------------------------------------
    {
      drawMenu("Termostat", "temp.woda["+(String)aquaT+"]","went.wremq","min.skor","maks.skor");
      naviKey(4);
      switch(key){
        case BUTTON_OK:
          switch(cur_item){
            case 1:
              cur_menu = 1321;      
              cur_item = 0;
            break;
            case 2:  //CoolTime
              cur_menu = 133;      
              cur_item = 1;
              menu_off = 1;
              menu_item_count = 8;
              curLoad = 0;
            break;
            case 3:  //minCool // минимальные обороты кулера для вентиляции крышки и охлаждения ламп
              cur_menu = 1323;      
            break;
            case 4:  //maxCool // максимальные обороты для охлаждения воды
              cur_menu = 1324;      
            break;
          }
        break;
        case BUTTON_CANCEL:
          cur_menu = 13;
          cur_item = 2;
          cur_item_edit = false;
        break;
      }
      break;
    }
    case 1321: // Aqua Temperature -----------------------------------------------------------------
    {
      drawIntMenu("maks.temp.woda",18,35,aquaT);
      switch(key){
        case BUTTON_UP:
          aquaT++;
          aquaT = min(aquaT, 35);
        break;
        case BUTTON_DOWN:
          aquaT--;
          aquaT = max(aquaT, 18);
        break;
        case BUTTON_OK:
          EEPROM.write(2,aquaT);                   // Требуемая температура воды
          cur_menu = 132;
          cur_item = 1;
        break;
        case BUTTON_CANCEL:
          aquaT = EEPROM.read(2);                   // Требуемая температура воды
          cur_menu = 132;
          cur_item = 1;
        break;
      }
      break;
    }
    case 1323: // min.skor // минимальные обороты кулера для вентиляции крышки и охлаждения ламп ------------------------------------------
    {
      drawIntMenu("min.skor",0,maxCool,minCool);
      switch(key){
        case BUTTON_UP:
          minCool++;
          minCool = min(minCool, maxCool);
          analogWrite(EXT_COOLING_PIN, minCool);
        break;
        case BUTTON_DOWN:
          minCool--;
          minCool = max(minCool, 0);
          analogWrite(EXT_COOLING_PIN, minCool);
        break;
        case BUTTON_OK:
          EEPROM.write(3,minCool);                   // минимальные обороты кулера для вентиляции крышки и охлаждения ламп
          cur_menu = 132;
          cur_item = 3;
        break;
        case BUTTON_CANCEL:
          minCool = EEPROM.read(3);                   // минимальные обороты кулера для вентиляции крышки и охлаждения ламп
          cur_menu = 132;
          cur_item = 3;
        break;
      }
      break;
    }
    case 1324: // maks.skor // максимальные обороты для охлаждения воды ------------------------------------------
    {
      drawIntMenu("maks.skor",0,255,maxCool);
      switch(key){
        case BUTTON_UP:
          maxCool++;
          maxCool = min(maxCool, 255);
          analogWrite(EXT_COOLING_PIN, maxCool);
        break;
        case BUTTON_DOWN:
          maxCool--;
          maxCool = max(maxCool, minCool);
          analogWrite(EXT_COOLING_PIN, maxCool);
        break;
        case BUTTON_OK:
          EEPROM.write(4,maxCool);                   // максимальные обороты для охлаждения воды
          cur_menu = 132;
          cur_item = 4;
        break;
        case BUTTON_CANCEL:
          maxCool = EEPROM.read(4);                   // максимальные обороты для охлаждения воды
          cur_menu = 132;
          cur_item = 4;
        break;
      }
      break;
    }
    case 131: // nastroika sistema -----------------------------------------------------------------
    {
      drawMenu("sistema", "wremq","data","disp kontrast","displ qrkostx");
      naviKey(4);
      switch(key){
        case BUTTON_OK:
          switch(cur_item){
            case 1:
              cur_menu = 1311;      
              cur_item = 0;
              menu_hh = time.hour;
              menu_mi = time.min;
            break;
            case 2:
              cur_menu = 1312;      
              cur_item = 0;
              menu_dd = time.date;
              menu_mm = time.mon;
              menu_yyyy = time.year;
              menu_dow = time.dow;
            break;
            case 3:
              cur_menu = 1313;      
              cur_item = 0;
            break;
            case 4:
              cur_menu = 1314;      
              cur_item = 0;
            break;
          }
        break;
        case BUTTON_CANCEL:
          cur_menu = 0;
          cur_item = 0;
        break;
      }
      break;
    }
    case 1311: // Time -----------------------------------------------------------------
    {
      myGLCD.setFont(SmallFont);
      myGLCD.clrScr();
  
      myGLCD.print("wremq",1,0);
      myGLCD.print(rtc.getTimeStr(FORMAT_SHORT),RIGHT,0);
      myGLCD.drawLine(0,8,83,8);
      myGLCD.drawLine(0,9,83,9);
      if((cur_item == 1)&&cur_item_edit) 
        myGLCD.invertText(true);
      myGLCD.printNumI(menu_hh,26,20,2,'0');
      myGLCD.invertText(false);
      myGLCD.print(":",39,20);
      if((cur_item == 2)&&cur_item_edit) 
        myGLCD.invertText(true);
      myGLCD.printNumI(menu_mi,46,20,2,'0');
      myGLCD.invertText(false);

      if(cur_item == 1)
        myGLCD.drawRoundRect(25,18,39,28);
      if(cur_item == 2)
        myGLCD.drawRoundRect(45,18,59,28);

      switch(key){
        case BUTTON_UP:
          if(!cur_item_edit){ 
            cur_item--;
            if(cur_item < 1)
              cur_item = 2;
          }else{
            if(cur_item == 1){
              menu_hh++;
              if(menu_hh == 24)
                menu_hh = 0;
            }
            if(cur_item == 2){
              menu_mi++;
              if(menu_mi == 60)
                menu_mi = 0;
            }
          }
        break;
        case BUTTON_DOWN:
          if(!cur_item_edit){ 
            cur_item++;
            if(cur_item > 2)
              cur_item = 1;
          }else{
            if(cur_item == 1){
              if(menu_hh == 0)
                menu_hh = 23;
              else  
                menu_hh--;
            }
            if(cur_item == 2){
              if(menu_mi == 0)
                menu_mi = 59;
              else
                menu_mi--;
            }
          }
        break;
        case BUTTON_OK:
          if(cur_item_edit){ 
            switch(cur_item){
              case 1:
                rtc.setTime(menu_hh, time.min, 0);     // Set the time to 12:00:00 (24hr format)
              break;
              case 2:
                rtc.setTime(time.hour, menu_mi, 0);     // Set the time to 12:00:00 (24hr format)
              break;
            }
            cur_item_edit = false;
          }else 
            cur_item_edit = true;
        break;
        case BUTTON_CANCEL:
          cur_item_edit = false;
          cur_menu = 131;      
          cur_item = 1;
        break;
      }
      myGLCD.update();
      break;
    }
    case 1312: // data -----------------------------------------------------------------
    {
      myGLCD.setFont(SmallFont);
      myGLCD.clrScr();
  
      myGLCD.print("data",1,0);
      myGLCD.print(rtc.getTimeStr(FORMAT_SHORT),RIGHT,0);
      myGLCD.drawLine(0,8,83,8);
      myGLCD.drawLine(0,9,83,9);

      if((cur_item == 1)&&cur_item_edit) 
        myGLCD.invertText(true);
      myGLCD.printNumI(menu_dd,12,20,2,'0');
      myGLCD.invertText(false);

      myGLCD.print(".",24,20);

      if((cur_item == 2)&&cur_item_edit) 
        myGLCD.invertText(true);
      myGLCD.printNumI(menu_mm,30,20,2,'0');
      myGLCD.invertText(false);

      myGLCD.print(".",42,20);

      if((cur_item == 3)&&cur_item_edit) 
        myGLCD.invertText(true);
      myGLCD.printNumI(menu_yyyy,48,20,4,'0');
      myGLCD.invertText(false);

      myGLCD.print("denx nedeli",0,32);
      if((cur_item == 4)&&cur_item_edit) 
        myGLCD.invertText(true);
      myGLCD.printNumI(menu_dow,68,32);
      myGLCD.invertText(false);

      switch(cur_item){
        case 1:
          myGLCD.drawRoundRect(11,18,25,28);
        break;  
        case 2:
          myGLCD.drawRoundRect(29,18,44,28);
        break;  
        case 3:
          myGLCD.drawRoundRect(47,18,73,28);
        break;  
        case 4:
          myGLCD.drawRoundRect(67,30,75,40);
        break;  
      }  

      switch(key){
        case BUTTON_UP:
          if(!cur_item_edit){ 
            cur_item--;
            if(cur_item < 1)
              cur_item = 4;
          }else{
            if(cur_item == 1){
              menu_dd++;
              if(menu_dd > 31)
                menu_dd = 1;
            }
            if(cur_item == 2){
              menu_mm++;
              if(menu_mm > 12)
                menu_mm = 1;
            }
            if(cur_item == 3){
              menu_yyyy++;
            }
            if(cur_item == 4){
              menu_dow++;
              if(menu_dow > 7)
                menu_dow = 1;
            }
          }
        break;
        case BUTTON_DOWN:
          if(!cur_item_edit){ 
            cur_item++;
            if(cur_item > 4)
              cur_item = 1;
          }else{
            if(cur_item == 1){
                menu_dd--;
              if(menu_dd < 1)
                menu_dd = 31;
            }
            if(cur_item == 2){
                menu_mm--;
              if(menu_mm < 1)
                menu_mm = 12;
            }
            if(cur_item == 3){
                menu_yyyy--;
                menu_yyyy = max(menu_yyyy,2013);
            }
            if(cur_item == 4){
                menu_dow--;
              if(menu_dow < 1)
                menu_dow = 7;
            }
          }
        break;
        case BUTTON_OK:
          if(cur_item_edit){ 
            switch(cur_item){
              case 1:
                rtc.setDate(menu_dd, time.mon, time.year);   // Set the date
              break;
              case 2:
                rtc.setDate(time.date, menu_mm, time.year);   // Set the date
              break;
              case 3:
                rtc.setDate(time.date, time.mon, menu_yyyy);   // Set the date
              break;
              case 4:
                 rtc.setDOW(menu_dow);     // Set Day-of-Week 
              break;
            }
            cur_item_edit = false;
          }else 
            cur_item_edit = true;
        break;
        case BUTTON_CANCEL:
          cur_item_edit = false;
          cur_menu = 131;      
          cur_item = 2;
        break;
      }
      myGLCD.update();
      break;
    }
    case 1313: // swet kontrast -----------------------------------------------------------------
    {
      drawIntMenu("displ kontrast",45,80,ledContrast);
      switch(key){
        case BUTTON_UP:
          ledContrast++;
          ledContrast = min(ledContrast, 80);
        break;
        case BUTTON_DOWN:
          ledContrast--;
          ledContrast = max(ledContrast, 45);
        break;
        case BUTTON_OK:
          EEPROM.write(0,ledContrast);
          cur_menu = 131;
          cur_item = 3;
        break;
        case BUTTON_CANCEL:
          ledContrast = EEPROM.read(0);
          cur_menu = 131;
          cur_item = 3;
        break;
      }
      myGLCD.setContrast(ledContrast);  
      break;
    }
    case 1314: // swet qrkostx  -----------------------------------------------------------------
    {
      drawIntMenu("displ qrkostx",0,255,ledLight);
      switch(key){
        case BUTTON_UP:
          ledLight++;
          ledLight = min(ledLight, 255);
        break;
        case BUTTON_DOWN:
          ledLight--;
          ledLight = max(ledLight, 0);
        break;
        case BUTTON_OK:
          EEPROM.write(1,ledLight);
          cur_menu = 131;
          cur_item = 4;
        break;
        case BUTTON_CANCEL:
          ledLight = EEPROM.read(1);
          cur_menu = 131;
          cur_item = 4;
        break;
      }
      analogWrite(LED_LIGHT_PIN,ledLight);
      break;
    }

    default:
      cur_menu = 0;
      cur_item = 0;
  }
 
loopTime = currentTime;   
}  
}

 

bwn
Offline
Зарегистрирован: 25.08.2014

Витенька, понимаете, у вас в loop набилось все, что можно и нельзя. Соответственно проследить логику работы становится проблематичным. В коде данной темы, обработка сделана просто:
 

//========== Увеличение яркости (auto)
void dimmUp() {
      if (angData2<maxDimm){                //Ограничение верхнего значения диммирования, (0-255)
    angData2++;                             //Начало подъёма диммирования
    angData1++;
    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;}
}

Начинаем с нуля и последовательно увеличиваем яркость с интервалом "pManDimmUp", который задан жестко и рассчитан как кол.сек.треб/255. Изменение происходит по достижении интервала. У вас оно похоже увеличивается один раз в минуту и плавность уже не достигнуть.
Также обратите внимание на loop ТС:
 

void loop(){
    timeRtc();
    timer();
    keyI();
    dallas();
    tempRelay();
    voltM();
    bar();
//    bluetooth();
    printTime();
    printDin();
    printStat();
}

Все выведено в функции, отладка и изменение сводится к модификации и отладке одного небольшого кусочка без перелопачивания всей портянки.
Вывод: "Чем такого лечить, проще нового сделать". Раздербаньте свой код на самодостаточные кусочки и слепите его обратно из кусочков-функций, тогда будете сами понимать что и где происходит. А изучать и ловить переходы-изменения в Ваших 2000 строк мало у кого появится желание. ИМХО.

Витенька
Offline
Зарегистрирован: 03.04.2016

Ясно, что дело тёмное. Спасибо Большое!

serega.gram
Offline
Зарегистрирован: 15.04.2015

здраствуйте. как я и говорил, для правильного отображения давления датчиком bmp180 нужна калибровка по местности. то есть вручную прописываеться высота над уровнем моря, что я делаю в библиотеке bmp085 и у меня совпадает показание с прогнозом на мой город. НУ ТОЛЬКО Я НЕ ПОЙМУ КАК СОХРАНИТЬ ЭТУ ВЫСОТУ В ЭТОЙ БИБЛИОТЕКЕ BMP085 ДЛЯ ТОГО ЧТО БЫ МОЙ СКЕТЧ ПРИ ЗАЛИВКЕ ВЗЯЛ МОЮ ПОПИСАННУЮ ВЫСОТУ С ЭТОЙ ДОЛБАННОЙ БИБЛЕОТЕКИ

serega.gram
Offline
Зарегистрирован: 15.04.2015

здраствуйте, подскажите пожалуйста в скетче Thorna прописано три термореле для охлаждения. а у меня такая проблема первое реле настраевается макс на 30 град, а из трех реле только одно вкл и выкл а остальные два включаются но не отключаются даже после достижения нужной охлаждённой температуры