Да скетч то такой же только у меня диммирования нет поэтому разобратся немогу (либо пульт работает,таймер нет или на оборот). Раз как то методом тыка получилась и с пульта вкл и выкл и по таймерам все нормально но: когда свет по таймеру "ВКЛЮЧЕН" с пульта выключаешь он тухнет, а релюшка грется до ужаса и контролька на ней в пол накала светится
"Меню" сделал работает замечательно уже неделю на банке стоит. СПАСИБО вам огромное!!! Только есть одно "но"; Почему то когда в каком либо таймере на"ВЫКЛЮЧЕНИЕ" ставиш 00:00 включается вообще все и не как не выключишь приходится перезапускать ардуинку. Так и должно быть?
А на счет рассвет/закат так он мне и не нужен в принципи мне и живого хватает, да и финансы пока не позволяют как говорится: " собираю из того что есть"!
Разбирайте функцию "Timer" из 282 поста, все что относится к диммерам (OUT4,5) надо переделать с analogWrite на digitalWrite, убрать все счетчики. Должно остаться ВКЛ-ВЫКЛ. Писалось давно, все уже не вспомнить, но у ТС вроде все тщательно прокомментировано. Если сразу сложно, то возьмите бумажку и разрисуйте, как вызываются подфункции из функции "Timer", что и как они изменяют. За автоматическую работу полностью отвечает она.
"Почему то когда в каком либо таймере на"ВЫКЛЮЧЕНИЕ" ставиш 00:00 включается вообще все и не как не выключишь приходится перезапускать ардуинку. Так и должно быть?" - Проверьте формулы расчета времени, возможно данная ситуация является запрещенной, а вы первый на эти грабли наступили.
Хотел бы вас еще попросить что бы вы мне со скетчем на автокормушку помогли!
А чем он вас смущает? Как работать с часами, надеюсь поняли. Дальше определиться, как она управляется: открыть клапан (задвижку), кол-во оборотов или какой то период времени? Под это и разрабатывать алгоритм.
Смущает он меня всем! Я далек от програмирования"только методом подставление в чужие коды могу".
Кормушка у меня барабанная принцип работы: Что бы включалась по таймеру работала на выставленой скорости и промежуток времени(в сек.)
Меню вроде такое?
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;}
}
Здрасте а почему бы не контролировать уровень растворенного кислорода в акварюме. Без кислорода рыбы проживут 2 минуты, а без кормушки проживут недельну.
Здрасте а почему бы не контролировать уровень растворенного кислорода в акварюме. Без кислорода рыбы проживут 2 минуты, а без кормушки проживут недельну.
Смущает он меня всем! Я далек от програмирования"только методом подставление в чужие коды могу".
Кормушка у меня барабанная принцип работы: Что бы включалась по таймеру работала на выставленой скорости и промежуток времени(в сек.)
Как понимать "на выставленой скорости"? Она чем то меняется или константа?
Если постоянная, то включили в заданное время, отсчитали требуемый интервал, выключили.
Тогда, забросьте на время проект и разберитесь с этим и этим.
При помощи первого учимся регулировать скорость, второго - отмерять требуемые интервалы без делаев.
Здраствуйте bwn прочитал то что вы мне дали! На пустой ардуинки попробывал и со скоростью и интервалами по эксперементировать! Получилось, со скоростью разобрался как сделать а вот с милсами так и не понял как их применить в скетче!кормушка крутится по интервалу только при перезагруски,а как дальше делать в голову даже не лезет!
Включили, запомнили время, ушли в основной цикл, каждый проход возвращаемся и проверяем достижение интервала, достигли - выключили.
Посмотрите еще здесь. Там для Далласов температурных, но принцип тот же. 47 пост
P/S только вход в функцию надо делать не постоянный, а при наступлении времени кормления.
Добрый день. Собрал себе контроллер по скетчу Thorn, всё хорошо только не пойму почему разделитель часов мигает не синхронно с секундами. То в месте то в разбежку мигают. И как подключить вольтметр что бы экран не пустовал по нолям. Зараннее спасибо.
Добрый день. Собрал себе контроллер по скетчу Thorn, всё хорошо только не пойму почему разделитель часов мигает не синхронно с секундами. То в месте то в разбежку мигают.
Там мигалка к часам не привязана, просто через миллис. Если только часы и минуты отображать, то это незаметно.
Вывод на экран в функции с 989 строки, частота опроса Далласов - строка 1087, сам массив с временем задержек в блоке инициализации. Поставите часто, экран может мерцать. Скетч из 282 поста.
Уже довольно давно сижу над кодом автора переделал под себя , освободил памяти убрал лишние . Хочу сказать огромное спасибо Thorn и bwn.
Ви написали хорошую програму которая при небольших зусилиях переделивается под свои нужди.
немного переделиваю внешний вид главного окна .
Делаю сейчас авто долив води в аквариум.
Пока в пути датчик ткмператури и барометр
Памяти использовано на даний момент 25204 байт так что есть куда писать)
serega.gram, для болие бистрого обновления температури нужно изменить значение в строчке if (millis()-prvMlsVo>zadTime[7]){ //Проверяем интервал для обновления
именно цифру 7 на меньше но зачем?
зачем вам обновлять температуру чаще чем раз в минуту?
вот код настройки таймеров, я в один таймер добавил кроме настройки времени включения выключения еще настройку максимального значения диммирования на этом таймере, это значение хранится в переменной 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]);
}
svidrak, эту часть кода ТС полностью писал сам, мне особо и вспомнить нечего. Если смотреть 282 пост, переменные экранов объявлены с 90 строки, под каждый экран зарезервировано четыре однобайтовых ячейки. Получается, либо увеличить каждый экран до 5 байт
winMe*5+1........winMe*5+5 и внимательно посмотреть логику чтения-записи, чтобы не нарушить или добавить по образу и подобию еще один из четырех переменных. Как то так.
UPD, боюсь, так безбольно не получится. Посмотрел еще раз, там есть экраны и с семью ячейками. Надо расписывать всю карту EEPROM, чтобы не наехать на другие ячейки. Проще наверно будет все меню с нуля переписать. Или ТС на связь выйдет, подскажет.
Да и максимальные значения диммирования уже в коде присутствуют, придется с ними как то разбираться.
bwn, да есть максимальное значение но оно для всех таймеров.
А я добавил именно настройку для 2 таймера, так как 'тот таймер в основном включается ночью а там нужно максимум 20-50 процентов 1 светильника.
Все работает в принципе только если перезагрузить ардуино то настройка диммирования слетает до первоначальной настройки в сетапе.
В принципе не страшно но хочется розобратся)
сначала дествительно добавил по образу подобному в коде но наехал на другие значения .
Как самый безбольный вариант, правда из меню не получится регулировать, прописать требуемое значение принудительно в EEPROM, условно в 50 ячейку, а потом использовать его. Иначе без рисования карты и переделки логики не обойтись.((((
Либо эту дополнительную переменную попробовать писать напрямую в заведомо свободную ячейку, там запись происходит в той же функции экрана. Попробуйте, ваш maxPWM = EEPROM.read(100);, покрутили и потом в конце EEPROM.write(100, maxPWM);, не изящно, но должно вроде взлететь.
Сам еще не прикрутил барометр тоже в пути 180 говорят что они замениемие и код подходит от 085 к 180.
Но нужно проверят .На крайняк заменить библиотеку и несколько строчек кода.
Пробежался по програме вроде нет калибровки по месности.
По местности их вроде калибруют под девайсы типа измерения высоты или что то подобное. Когда придет обратите внимание на обвязку. Модули на 085 были толерантнты к 5В питанию и сигналам, по 180 лучше уточнить.
Кто небудь имел дело с пультами RC6 ?
нашол класний пльт на роботе от ноутбука HP но кодировка у него RC6 и не могу розобратся если вписать коди етого пульта то на кнопки реагирует на одно нажатие 3 раза исполняет команду.
может кто что подскажет?
Кто небудь имел дело с пультами RC6 ?
нашол класний пльт на роботе от ноутбука HP но кодировка у него RC6 и не могу розобратся если вписать коди етого пульта то на кнопки реагирует на одно нажатие 3 раза исполняет команду.
может кто что подскажет?
Так посмотрите через сериал как команды проходят, может надо задержку между приемами поставить, типа как на обычную кнопку. Чисто предположения.
Да посмотрел приходит почему то код 3 раза скорей всего библиотека плохо код расшифровывает.
Пока проблему не смог найти скорей всего придется отказаться от пульта но жаль удобний.
Виставлял задержку не помагает
сделал сибе символьний вивод информации .
все прибори имеют свой значек и в зависимости от включен виключен меняються.
На удивление такой вивод занимает намного даже меньше места в ардуине.
и одна стролка свободная
а как провильно сделать програмно ето?
вот мой обработчик кнопок
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;
}
Что то вроде if (old_ret == ret && time < 1сек....){ Возврат }
Либо вход в обработчик не раньше, чем через секунду-две после приема значащей команды (на флаге и миллисе).
Пришла значащая команда, запомнили миллис, пока не прошел интервал в функцию опроса не входим, даже флаг не нужен.
Правда будет тормозить, когда надо нажав кнопку увеличивать-уменьшать что то.
Можно правило входа распространить только на те, которые одно нажатие требуют.
В целом, по своей задаче алгоритм обыгрывать.
Да желание есть завтра еще посмотрю в принципе в примере код декодируется нормально и один раз, а в программе автора почемуто 3 раза виставлял и делей итд не помогает.
нажиатие может один раз код прилететь, а может и три раза, если подержать прилетает один и тот самий код, а если нажимать два разних по очереди.
У меня еще проблема есть такая не могу понять программная она или железо.
Если включен полностью свет все 3 канала с разним интервалом иногда на секунду выключается реле компрессора включается но при этом выключаются 2 реле света
Да посмотрел приходит почему то код 3 раза скорей всего библиотека плохо код расшифровывает.
Пока проблему не смог найти скорей всего придется отказаться от пульта но жаль удобний.
Виставлял задержку не помагает
сделал сибе символьний вивод информации .
все прибори имеют свой значек и в зависимости от включен виключен меняються.
На удивление такой вивод занимает намного даже меньше места в ардуине.
и одна стролка свободная
Здравствуйте, От пультов Самсунг приходит только один код. От остальных сколько смотрел по 3. Есть решение у Дмитрия Осипова на ютубе. Удачи.
Здравствуйте Уважаемый! Можно Вас попросить просветить в одной позиции кода акваконтроллера? Суть дела такова, от програмирования я оооочень далек, но, собрал пару контроллеров из одного из форумов, методом тыка подогнал под то что мне нужно было, всё работает нареканий нет (к аквариумам можно подходить просто помедитировать, всё само работает). Решил переделать свет в аквариумах, переделал но попутно хотел задействовать с изначального кода функцию рассвет/закат и тута столкнулся с проблемкой. После загрузки кода в ардуину так сказать по умолчанию в настройках рассвет/закат стоит время длительности 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;
}
}
Витенька, понимаете, у вас в 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 ТС:
Все выведено в функции, отладка и изменение сводится к модификации и отладке одного небольшого кусочка без перелопачивания всей портянки.
Вывод: "Чем такого лечить, проще нового сделать". Раздербаньте свой код на самодостаточные кусочки и слепите его обратно из кусочков-функций, тогда будете сами понимать что и где происходит. А изучать и ловить переходы-изменения в Ваших 2000 строк мало у кого появится желание. ИМХО.
здраствуйте. как я и говорил, для правильного отображения давления датчиком bmp180 нужна калибровка по местности. то есть вручную прописываеться высота над уровнем моря, что я делаю в библиотеке bmp085 и у меня совпадает показание с прогнозом на мой город. НУ ТОЛЬКО Я НЕ ПОЙМУ КАК СОХРАНИТЬ ЭТУ ВЫСОТУ В ЭТОЙ БИБЛИОТЕКЕ BMP085 ДЛЯ ТОГО ЧТО БЫ МОЙ СКЕТЧ ПРИ ЗАЛИВКЕ ВЗЯЛ МОЮ ПОПИСАННУЮ ВЫСОТУ С ЭТОЙ ДОЛБАННОЙ БИБЛЕОТЕКИ
здраствуйте, подскажите пожалуйста в скетче Thorna прописано три термореле для охлаждения. а у меня такая проблема первое реле настраевается макс на 30 град, а из трех реле только одно вкл и выкл а остальные два включаются но не отключаются даже после достижения нужной охлаждённой температуры
Привет формучане! Кто с может помочь с кнопками IR (чтобы работало вкл/выкл и с пульта и по таймерам).Заранее спасибо!
А разве у ТС как то иначе?
Да скетч то такой же только у меня диммирования нет поэтому разобратся немогу (либо пульт работает,таймер нет или на оборот). Раз как то методом тыка получилась и с пульта вкл и выкл и по таймерам все нормально но: когда свет по таймеру "ВКЛЮЧЕН" с пульта выключаешь он тухнет, а релюшка грется до ужаса и контролька на ней в пол накала светится
"Меню" сделал работает замечательно уже неделю на банке стоит. СПАСИБО вам огромное!!! Только есть одно "но"; Почему то когда в каком либо таймере на"ВЫКЛЮЧЕНИЕ" ставиш 00:00 включается вообще все и не как не выключишь приходится перезапускать ардуинку. Так и должно быть?
А на счет рассвет/закат так он мне и не нужен в принципи мне и живого хватает, да и финансы пока не позволяют как говорится: " собираю из того что есть"!
Разбирайте функцию "Timer" из 282 поста, все что относится к диммерам (OUT4,5) надо переделать с analogWrite на digitalWrite, убрать все счетчики. Должно остаться ВКЛ-ВЫКЛ. Писалось давно, все уже не вспомнить, но у ТС вроде все тщательно прокомментировано. Если сразу сложно, то возьмите бумажку и разрисуйте, как вызываются подфункции из функции "Timer", что и как они изменяют. За автоматическую работу полностью отвечает она.
"Почему то когда в каком либо таймере на"ВЫКЛЮЧЕНИЕ" ставиш 00:00 включается вообще все и не как не выключишь приходится перезапускать ардуинку. Так и должно быть?" - Проверьте формулы расчета времени, возможно данная ситуация является запрещенной, а вы первый на эти грабли наступили.
bwn спасибо вам огромное!
Хотел бы вас еще попросить что бы вы мне со скетчем на автокормушку помогли!
А то у самого мозгов не хватит!:)
bwn спасибо вам огромное!
Хотел бы вас еще попросить что бы вы мне со скетчем на автокормушку помогли!
А чем он вас смущает? Как работать с часами, надеюсь поняли. Дальше определиться, как она управляется: открыть клапан (задвижку), кол-во оборотов или какой то период времени? Под это и разрабатывать алгоритм.
Смущает он меня всем! Я далек от програмирования"только методом подставление в чужие коды могу".
Кормушка у меня барабанная принцип работы: Что бы включалась по таймеру работала на выставленой скорости и промежуток времени(в сек.)
Меню вроде такое?
таймер на включение(Правельно или нет?)
дальше вообще не чего в голову не лезет!:)
Здрасте а почему бы не контролировать уровень растворенного кислорода в акварюме. Без кислорода рыбы проживут 2 минуты, а без кормушки проживут недельну.
Здрасте а почему бы не контролировать уровень растворенного кислорода в акварюме. Без кислорода рыбы проживут 2 минуты, а без кормушки проживут недельну.
Вы это прикалываетесь или всерьез?
Смущает он меня всем! Я далек от програмирования"только методом подставление в чужие коды могу".
Кормушка у меня барабанная принцип работы: Что бы включалась по таймеру работала на выставленой скорости и промежуток времени(в сек.)
Как понимать "на выставленой скорости"? Она чем то меняется или константа?
Если постоянная, то включили в заданное время, отсчитали требуемый интервал, выключили.
Хотелось бы скорость вращения из меню выставлять!
Хотелось бы скорость вращения из меню выставлять!
Тогда, забросьте на время проект и разберитесь с этим и этим.
При помощи первого учимся регулировать скорость, второго - отмерять требуемые интервалы без делаев.
Вы это прикалываетесь или всерьез?
А что тут такого ?
любая УЗВ начинаеться с этого. Это влияет на рост рыбы, размножения, плотность посадки
Вы это прикалываетесь или всерьез?
А что тут такого ?
любая УЗВ начинаеться с этого. Это влияет на рост рыбы, размножения, плотность посадки
Мы здесь вроде не про рыбоводческие хозяйства. Нормальный аквариум должен существовать достаточно автономно, а не на аппарате сердце-легкие. ИМХО.
Здраствуйте bwn прочитал то что вы мне дали! На пустой ардуинки попробывал и со скоростью и интервалами по эксперементировать! Получилось, со скоростью разобрался как сделать а вот с милсами так и не понял как их применить в скетче!кормушка крутится по интервалу только при перезагруски,а как дальше делать в голову даже не лезет!
Включили, запомнили время, ушли в основной цикл, каждый проход возвращаемся и проверяем достижение интервала, достигли - выключили.
Посмотрите еще здесь. Там для Далласов температурных, но принцип тот же. 47 пост
P/S только вход в функцию надо делать не постоянный, а при наступлении времени кормления.
Добрый день. Собрал себе контроллер по скетчу Thorn, всё хорошо только не пойму почему разделитель часов мигает не синхронно с секундами. То в месте то в разбежку мигают. И как подключить вольтметр что бы экран не пустовал по нолям. Зараннее спасибо.
Там мигалка к часам не привязана, просто через миллис. Если только часы и минуты отображать, то это незаметно.
Ещё вопрос. Идёт отчет секунд и секунды съедаются может быть так : 2 3 5 6 7 9 10 : может что то с модулем часов
Я уже код не помню, если отображение через миллис сделано, попробуйте переделать на вывод при изменении значения секунды и мигать вместе с ней.
Добрый вечер, скажите какую строчку нужно изменить для более быстрого обновления температуры на экране
Вывод на экран в функции с 989 строки, частота опроса Далласов - строка 1087, сам массив с временем задержек в блоке инициализации. Поставите часто, экран может мерцать. Скетч из 282 поста.
Уже довольно давно сижу над кодом автора переделал под себя , освободил памяти убрал лишние . Хочу сказать огромное спасибо Thorn и bwn.
Ви написали хорошую програму которая при небольших зусилиях переделивается под свои нужди.
немного переделиваю внешний вид главного окна .
Делаю сейчас авто долив води в аквариум.
Пока в пути датчик ткмператури и барометр
Памяти использовано на даний момент 25204 байт так что есть куда писать)
serega.gram, для болие бистрого обновления температури нужно изменить значение в строчке if (millis()-prvMlsVo>zadTime[7]){ //Проверяем интервал для обновления
именно цифру 7 на меньше но зачем?
зачем вам обновлять температуру чаще чем раз в минуту?
bwn, бил би признателен за подсказку .
вот код настройки таймеров, я в один таймер добавил кроме настройки времени включения выключения еще настройку максимального значения диммирования на этом таймере, это значение хранится в переменной maxPWM как мне правильно добавить код чтобы значение этой переменной записывало в еепром ?
Не до конца разобрался с этими строчками кода, а именно не понимаю как правильно указать адрес куда записать значение переменной .
Весь код настройки
svidrak, эту часть кода ТС полностью писал сам, мне особо и вспомнить нечего. Если смотреть 282 пост, переменные экранов объявлены с 90 строки, под каждый экран зарезервировано четыре однобайтовых ячейки. Получается, либо увеличить каждый экран до 5 байт
winMe*5+1........winMe*5+5 и внимательно посмотреть логику чтения-записи, чтобы не нарушить или добавить по образу и подобию еще один из четырех переменных. Как то так.
UPD, боюсь, так безбольно не получится. Посмотрел еще раз, там есть экраны и с семью ячейками. Надо расписывать всю карту EEPROM, чтобы не наехать на другие ячейки. Проще наверно будет все меню с нуля переписать. Или ТС на связь выйдет, подскажет.
Да и максимальные значения диммирования уже в коде присутствуют, придется с ними как то разбираться.
bwn, да есть максимальное значение но оно для всех таймеров.
А я добавил именно настройку для 2 таймера, так как 'тот таймер в основном включается ночью а там нужно максимум 20-50 процентов 1 светильника.
Все работает в принципе только если перезагрузить ардуино то настройка диммирования слетает до первоначальной настройки в сетапе.
В принципе не страшно но хочется розобратся)
сначала дествительно добавил по образу подобному в коде но наехал на другие значения .
Как самый безбольный вариант, правда из меню не получится регулировать, прописать требуемое значение принудительно в EEPROM, условно в 50 ячейку, а потом использовать его. Иначе без рисования карты и переделки логики не обойтись.((((
Либо эту дополнительную переменную попробовать писать напрямую в заведомо свободную ячейку, там запись происходит в той же функции экрана. Попробуйте, ваш maxPWM = EEPROM.read(100);, покрутили и потом в конце EEPROM.write(100, maxPWM);, не изящно, но должно вроде взлететь.
bwn, как я понимаю для рисования карти еепрома нужно подсчитать все значения куда записываются с програми?
В принципе вроде прокатило с вашим предложением работает но по хорошому все равно хочу разобраться с этой еепром.
Да, брать все используемые с EEPROM переменные и по листингу выписывать, что куда записывается по физическим адресам. Нудно и тошно.((((
Здраствуйте. Я ёще вопрос задам, если вместо BMP 085 поставлю 180 ни смертельно это. И как делалась калибровка датчика по местности. А то разное пишут
Сам еще не прикрутил барометр тоже в пути 180 говорят что они замениемие и код подходит от 085 к 180.
Но нужно проверят .На крайняк заменить библиотеку и несколько строчек кода.
Пробежался по програме вроде нет калибровки по месности.
По местности их вроде калибруют под девайсы типа измерения высоты или что то подобное. Когда придет обратите внимание на обвязку. Модули на 085 были толерантнты к 5В питанию и сигналам, по 180 лучше уточнить.
Кто небудь имел дело с пультами RC6 ?
нашол класний пльт на роботе от ноутбука HP но кодировка у него RC6 и не могу розобратся если вписать коди етого пульта то на кнопки реагирует на одно нажатие 3 раза исполняет команду.
может кто что подскажет?
Кто небудь имел дело с пультами RC6 ?
нашол класний пльт на роботе от ноутбука HP но кодировка у него RC6 и не могу розобратся если вписать коди етого пульта то на кнопки реагирует на одно нажатие 3 раза исполняет команду.
может кто что подскажет?
Так посмотрите через сериал как команды проходят, может надо задержку между приемами поставить, типа как на обычную кнопку. Чисто предположения.
Да посмотрел приходит почему то код 3 раза скорей всего библиотека плохо код расшифровывает.

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

Пока проблему не смог найти скорей всего придется отказаться от пульта но жаль удобний.
Виставлял задержку не помагает
сделал сибе символьний вивод информации .
все прибори имеют свой значек и в зависимости от включен виключен меняються.
На удивление такой вивод занимает намного даже меньше места в ардуине.
и одна стролка свободная
bwm
Здравствуйте Уважаемый! Можно Вас попросить просветить в одной позиции кода акваконтроллера? Суть дела такова, от програмирования я оооочень далек, но, собрал пару контроллеров из одного из форумов, методом тыка подогнал под то что мне нужно было, всё работает нареканий нет (к аквариумам можно подходить просто помедитировать, всё само работает). Решил переделать свет в аквариумах, переделал но попутно хотел задействовать с изначального кода функцию рассвет/закат и тута столкнулся с проблемкой. После загрузки кода в ардуину так сказать по умолчанию в настройках рассвет/закат стоит время длительности 127 минут на рассвет и так же на закат, как мне показалось многовато. При изменении времени длительности рассвета/заката в настройках (при уменьшении этого времени) старт рассвета смещается и начинается можно сказать уже со средней яркости засвечивания светодиодов. Снова методом тыка долез до одной из позиций в коде где стартовую яркость вроде бы победил, к закатам пока не дошел долго сидеть над ним нужно. Пожалуйста объясните назначение, функцию, или не знаю как ещё это обозвать строк из кода. После изменения в строке 473 B01111111 на B11111111 и уменьшении в настройках длительности времени рассвета старт начался более-менее с слабого засвечивания светодиодов, к закату еще не добрался. Ну и вот сама суть вопроса, как зависят эти строки на функцию рассвета/заката, количество цифр, какие именно цифры за что отвечают, вопрос идиотский но всё же если можно объясните для особо не догоняющего обычным народным матом эту позицию?
Витенька, понимаете, у вас в loop набилось все, что можно и нельзя. Соответственно проследить логику работы становится проблематичным. В коде данной темы, обработка сделана просто:
Начинаем с нуля и последовательно увеличиваем яркость с интервалом "pManDimmUp", который задан жестко и рассчитан как кол.сек.треб/255. Изменение происходит по достижении интервала. У вас оно похоже увеличивается один раз в минуту и плавность уже не достигнуть.
Также обратите внимание на loop ТС:
Все выведено в функции, отладка и изменение сводится к модификации и отладке одного небольшого кусочка без перелопачивания всей портянки.
Вывод: "Чем такого лечить, проще нового сделать". Раздербаньте свой код на самодостаточные кусочки и слепите его обратно из кусочков-функций, тогда будете сами понимать что и где происходит. А изучать и ловить переходы-изменения в Ваших 2000 строк мало у кого появится желание. ИМХО.
Ясно, что дело тёмное. Спасибо Большое!
здраствуйте. как я и говорил, для правильного отображения давления датчиком bmp180 нужна калибровка по местности. то есть вручную прописываеться высота над уровнем моря, что я делаю в библиотеке bmp085 и у меня совпадает показание с прогнозом на мой город. НУ ТОЛЬКО Я НЕ ПОЙМУ КАК СОХРАНИТЬ ЭТУ ВЫСОТУ В ЭТОЙ БИБЛИОТЕКЕ BMP085 ДЛЯ ТОГО ЧТО БЫ МОЙ СКЕТЧ ПРИ ЗАЛИВКЕ ВЗЯЛ МОЮ ПОПИСАННУЮ ВЫСОТУ С ЭТОЙ ДОЛБАННОЙ БИБЛЕОТЕКИ
здраствуйте, подскажите пожалуйста в скетче Thorna прописано три термореле для охлаждения. а у меня такая проблема первое реле настраевается макс на 30 град, а из трех реле только одно вкл и выкл а остальные два включаются но не отключаются даже после достижения нужной охлаждённой температуры