В loop у меня это было, чтобы понять где нахожусь. Как там будет это не принципиально за исключением куска входа в меню. А он получается отрабатывает корректно или что то изменяли?
Да и непосредственно вход в функции key() промониторить. Попадаем ли мы туда?
В loop у меня это было, чтобы понять где нахожусь. Как там будет это не принципиально за исключением куска входа в меню. А он получается отрабатывает корректно или что то изменяли?
Да и непосредственно вход в функции key() промониторить. Попадаем ли мы туда?
В loop я добавил лиш работу с кнопками IR и если не окмментить очистку то надпись cikl перерисовывается циклически. Вот такой у меня loop
void loop() {
// tft.fillScreen(ST7735_BLACK); // Clear screen
if (irrecv.decode(&results)){
// lcd.clear();
//____________________________________________________________
//***ВХОД В МЕНЮ и проверка блокировки от возврата.
byte KEY=key(); //Принимаем код клавиши
if (KEY==1 && temp[0]<millis())
{
temp[0]=millis()+5000;
menu();
} //Если setup идем в меню
irrecv.resume(); }
//____________________________________________________________
tft.setCursor(10,100);
tft.print("cikl");
}
bwn пишет:
Тогда добавьте после 132 строки переменную KEY на экран, посмотреть какие значения она принимает. У меня на обычных кнопках все срабатывало нормально.
Сделал, всё отлично обрабатывает, вход в меню и возврат нажатой кнопки 1 select. Тоесть все корректно, далее 5 сек и снова возварт в cikl
И еще, что делает вот этот кусочек у вас в коде? Если его закоментить мы будем значения с IR получать?
if(irrecv.decode(&results)){
Ежели это убрать то мои IR нажатия вообще остаются незамеченными. Это я так понял стандартный код для работы с IR:
/*
* IRremote: IRrecvDemo - demonstrates receiving IR codes with IRrecv
* An IR detector/demodulator must be connected to the input RECV_PIN.
* Version 0.1 July, 2009
* Copyright 2009 Ken Shirriff
* http://arcfn.com
*/
#include <IRremote.h>
int RECV_PIN = 11;
IRrecv irrecv(RECV_PIN);
decode_results results;
void setup()
{
Serial.begin(9600);
irrecv.enableIRIn(); // Start the receiver
}
void loop() {
if (irrecv.decode(&results)) {
Serial.println(results.value, HEX);
irrecv.resume(); // Receive the next value
}
}
От, тогда получается, что этот кусок надо добавить в функцию key().
Мы уходя в меню перестаем взаимодействовать с loop, на все время работы с меню. Соответственно и не получаем никаких данных с IR (у вас опрос в loop). Надо его продублировать в функции.
"Сделал, всё отлично обрабатывает, вход в меню и возврат нажатой кнопки 1 select. Тоесть все корректно, далее 5 сек и снова возварт в cikl" - а вот это неправильно. Возврат должен был быть только при повторном нажатии select через две секунды. Получается, что у вас остается запомненным предыдущее состояние KEY и оно возвращает в loop. (кстати на 5 секунд зря меняли, это задержка, чтобы сразу не вернутся - вход и выход из первого меню по одной и той же клавише, автовозврата я сюда не писал, усложнить никогда не поздно.)
P/S примерно понял, почему происходит возврат - мы прекратили опрос и results.value == 0x41BEC03F остался в том же состоянии.
От, тогда получается, что этот кусок надо добавить в функцию key().
Мы уходя в меню перестаем взаимодействовать с loop, на все время работы с меню. Соответственно и не получаем никаких данных с IR (у вас опрос в loop). Надо его продублировать в функции.
Хехе всё пучком, наконецто вошли в menu?z же вот одним местом чуял что неспроста в старом коде где всё висело - ничего невисело ПРОСТО там необрабатывались кнопки IR - я то лол совсем забыл что когда мы в menu то loop НЕРАБОТАЕт и цикла по нему НЕТ.ВОт сюда продублировал:
while(1) //Бесконечный цикл
{
KEY=0;
if (irrecv.decode(&results)){
...
...
break;}
irrecv.resume(); }
}
}
Рано обрадовался :( - висит у меня счас первый таймер вида:
1 10:00 11:00
set to save
(значения видимо из моих СТАРЫХ проб записи в ЕПРОМ)
... и всё, видимо надо ещё кудато добавлять обработку кнопок . И вот ещё что, вы писали... "P/S примерно понял, почему происходит возврат - мы прекратили опрос и results.value == 0x41BEC03F остался в том же состоянии." ежели выводить в serial.print кнопки ТО именно 1-ка и возвращалась (setup) после того как я НTвошёл в menu, меня выкидывало в cikle а 1-ка - продолжала возвращаться!!! Так что всё верное вы догадались.
Вот меня смущает что немогу в tft обрабатывать blink курсором - я так понял после входа в меню сначала курсор становится на часы и начинает мигать?
Да, сперва мигает разряд единиц часов, потом минут и т.д. Как у вас в библиотеке и есть ли он там, тут уже не помогу. А без него не понять что устанавливаем.
На сегодня меня выгоняют из компьютера с ардуинкой :( . Доброй ночи.
Я всё-же вставил обработку IR аналогично с функции key в функцию void setOnOff() - ну чтоб наверняка. Вобщем тепреь заработали кнопки однако любое нажатие вызывает saved и всё, снова зависон - видимо кнопки IR работают иначе физических.
Завтра на работе буду отлаживать - главное знать где и мы с вами знаем :)
А я все таки настоятельно рекомендую делать это в key(), в том числе и из loop убрать. Когда что то происходит в одной функции, отладка намного проще становится, вы получили на выходе функции стабильный результат и больше к ней не возвращаетесь. А так вам приходится лазать по всему коду и ловить мелких блох.
Еще вопрос, что делает вот эта строка irrecv.resume();? Я так подозреваю, что дает разрешение на следующее считывание. Если так, то делает это с очисткой results.value или без?
Приветы. Сегодня на работе заметил... при входе в setup я кнопками (up - down) могу выбирать номер расписания от 1 до 5, однако они прорисовываются в одной строке поверх и собственно сами понимаете - нечитабельно, счас покурю где мне надо очищать дисплей перед выбором следующего расписания.
Далее я вхожу в расписание и всё, тут уже ничего непроисходит и кнопки необрабатываются. Работу с IR убрал пока отовсюду кроме loop и KEY.
Следуя вашему совету я счас уберу из loop? однако боюсь тогда несмогу войти в setup (кнопки то обрабатыватсья до него небудут).
Ну вот как я и думал из loop IR убирать НЕЛЬЗЯ, можно к примеру если работа с IR есть в функции которая запускается из loop, у меня так в моем акваконтроллере если вы помните в loop()
Когда я нахожусь в (setup) оно же char menuTxt[5][14] = {"set menu1 >>", "set menu2 >>","set menu3 >>","set menu4 >>","set menu5 >>"};
то Serial.println(key(),DEC); delay(500); - невозвращает мне НИЧЕГО хотя я спокойно выбираю set menu1 >> стрелками (up - down) как уже писал выше - чудес небывает я так понял снова пресловутый loop не лупицца и надо serial.Print дописат mb в KEY
Убрать отовсюду я имел в виду - перенести в key() и обращатся только к нему по мере надобности. Сейчас у вас уже пять мест где происходит это обращение (loop, dimmer и три меню), дальше будет больше. irrecv.resume(); думаю должно стоять перед каждым return в функции key(). Функцию key() переписать, чтобы она возвращала как KEY№ , так и от 0 до 5. Тогда вы сможете к ней обращатся из любого места, а брать нужное вам значение.
Экран на LCD у меня сам затирался, очистку не делал, лекарство - напечатать сперва пустую строку (можете ее даже в массив внести для тренировки.)
Ага интеренсная картинка вырисовывается. Вот с такой функцией menu() и кнопок KEY:
void menu(){
//Массив с наименованиями для экрана
char menuTxt[5][14] = {"set menu1 >>", "set menu2 >>","set menu3 >>","set menu4 >>","set menu5 >>"};
byte pos = 0;
byte KEY;
while(1) {//Бесконечный цикл
if (irrecv.decode(&results)){
Serial.println(key(),DEC); delay(500);
KEY=0;
if (temp[1]<millis()) KEY = key(); //Если прошел интервал, читаем код
tft.setCursor(5,55);
tft.print(pos+1); //Печатаем номер.
tft.print(".");
tft.print(menuTxt[pos]); //Печатаем название
// Уменьшить увеличить + блокировка кнопки
if (KEY == 3 && pos > 0) {pos--; temp[1]=millis()+300;}
if (KEY == 4 && pos < 4) {pos++; temp[1]=millis()+300;}
win=pos; //Переменная номера таймера
// Здесь переходим на подменю. Если останется как сейчас, то достаточно
// if (KEY == 5) setOnOff();
// Сейчас можно перейти на разные подменю.
if (KEY == 5 && pos == 0) setOnOff();
if (KEY == 5 && pos == 1) setOnOff();
if (KEY == 5 && pos == 2) setOnOff();
if (KEY == 5 && pos == 3) setOnOff();
if (KEY == 5 && pos == 4) setOnOff();
//Выход из меню с проверкой и установкой блокировки от возврата
if (KEY ==1 && temp[0]<millis())
{
temp[0]=millis()+2000;
// lcd.clear();
tft.fillScreen(ST7735_BLACK); // Clear screen
break;}
irrecv.resume(); }
}
}
//_________________________________________________________________
я получаю нажатые кнопки ДО собственно моента входа в set menu1 >> и тп. Ка ктолько вошёл всё снова кнопки IR необрабатываются. И кстаи снова навернео какието задержки потмоу как невсегда СРАЗУ я могу пробежаться по char menuTxt[5][14] = {"set menu1 >>", "set menu2 >>","set menu3 >>","set menu4 >>","set menu5 >>"};
чаще serial.Print мне вывел нажатую кнопку а собственно строка несменилась, Ну а далее если и сменилась то прорисовав поверх старой название
Убрать отовсюду я имел в виду - перенести в key() и обращатся только к нему по мере надобности. Сейчас у вас уже пять мест где происходит это обращение (loop, dimmer и три меню), дальше будет больше. irrecv.resume(); думаю должно стоять перед каждым return в функции key(). Функцию key() переписать, чтобы она возвращала как KEY№ , так и от 0 до 5. Тогда вы сможете к ней обращатся из любого места, а брать нужное вам значение.
Экран на LCD у меня сам затирался, очистку не делал, лекарство - напечатать сперва пустую строку (можете ее даже в массив внести для тренировки.)
Про то думал, но у меня на самом деле IR кнопки обрабатываются ТОЛЬКО один раз имеено в функции работы с диммированием (удержанием кнопки и отключение релюшек). Там пока тьфу три раза всё работает как часики. А тут да - меню штука своебразная. Счас подправлю согласн овашим рекомендациям irrect.resume
Если по вашему коду, он и не должен работать. Если лепить таким образом, то 37 строка должна быть после 10. Иначе вы производите инициацию после того, как уже ушли из меню.
void loop() {
Serial.println(key(),DEC); delay(100);
if (irrecv.decode(&results)){
...
}
и в menu(), код выше
А в меню, добавлять в 10 строку после KEY=key() и мониторить KEY. delay() не нужен. Когда вы вызываете конструкцией (key(),DEC) вы обращаетесь к функции и печатаете ее результат, а нас интересует переменная.
Если по вашему коду, он и не должен работать. Если лепить таким образом, то 37 строка должна быть после 10. Иначе вы производите инициацию после того, как уже ушли из меню.
Здесь немного вас обманул, работать будет, но возможно некорректная обработка при переходе на следующее меню.
не ничево неполучается, двигаю irrecv.resume(); } - меняется но не в лучьшую сторону, добавил перед return но уже в виде irrecv.resume();
Всё потмоу что для мнея сложно понимание массива и его переменных
byte pos = 0;
byte KEY;
if (temp[1]<millis()) KEY = key();
if (KEY == 3 && pos > 0) {pos--; temp[1]=millis()+300;}
вот этого всего :(((
Так массив это та же переменная - уберите из него квадратные скобки и получите temp0, temp1 и т.д. все остальные действия как с обычными переменными. В данном коде - задержка 0,3сек иначе у вас цифры будут лететь со скоростью цикла.
Правда "раком" стопроцентов, именно как вы НЕСОВЕТОВАЛИ. Всётаки дело в "непотребном" коде при работе с кнопками. Значит вот как у меня и всё работает и нажимается, весь код:
#include <EEPROM.h>
#include <Wire.h>
#include <IRremote.h> //Подключаем библиотеку для IR сенсора
//#include <LiquidCrystal.h>
#define DS1307_I2C_ADDRESS 0x68
//LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
//=====Tft*
#include <Adafruit_GFX.h> // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library
#include <SPI.h>
#define sclk 52
#define mosi 51
#define cs 4
#define dc 2
#define rst 3 // you can also connect this to the Arduino reset
Adafruit_ST7735 tft = Adafruit_ST7735(cs, dc, mosi, sclk, rst);
//=====IR*
#define RECV_PIN 11 //IR-приемник
uint32_t val;
IRrecv irrecv(RECV_PIN);
decode_results results;
//_____________________________________________________________
// Переменные для меню
byte setMinClockOn;
byte setHorClockOn;
byte setMinClockOff;
byte setHorClockOff;
byte win; //Номер экрана меню
unsigned long temp[2]; //Массив для задержек меню
//_____________________________________________________________
void setup() {
// lcd.begin(16, 2);
// lcd.clear();
Wire.begin();
Serial.begin(9600);
irrecv.enableIRIn();
tft.initR(INITR_BLACKTAB);
tft.fillScreen(ST7735_BLACK); // Clear screen
}
//______________________________________________________________
// Здесь вставите свою функцию, которая возвращает от 0 до 5
byte key(){
if (results.value == 0x41BEB04F) return 5;
if (results.value == 0x41BE609F) return 4;
if (results.value == 0x41BED02F) return 3;
if (results.value == 0x41BE40BF) return 2;
if (results.value == 0x41BEC03F) return 1;
else return 0;
}
/*
byte key()
{
int val = analogRead(0);
if (val < 50) return 5;
else if (val < 150) return 3;
else if (val < 350) return 4;
else if (val < 500) return 2;
else if (val < 800) return 1;
else return 0;
}
*/
//_____________________________________________________________
void setOnOff(){
byte pos = 0;
//Считываем записанные значения таймеров.
//Адрес определяется как номер таймера*4+четыре ячейки.
setMinClockOn = EEPROM.read(win*4+0); //
setHorClockOn = EEPROM.read(win*4+1);
setMinClockOff = EEPROM.read(win*4+2);
setHorClockOff = EEPROM.read(win*4+3);
// lcd.clear();
// lcd.blink();
tft.fillScreen(ST7735_BLACK); // Clear screen
while(key() != 1) {//Крутим цикл пока не будет Setup
if (irrecv.decode(&results)){
byte KEY = key(); // читаем состояние кнопок
Serial.println(key(),DEC); delay(500);
delay(200); //Если убрать, не работает подсветка уст.позиции
// lcd.setCursor(1, 1);
tft.setCursor(5,75);
tft.setTextColor(ST7735_WHITE,ST7735_BLACK);
tft.setTextSize(1);
tft.print("set to save");
tft.setCursor(5, 55);
tft.print(win+1,DEC); //Печатаем номер прогр.таймера.
tft.setCursor(35, 55); // выводим инфу
if (setHorClockOn < 10) tft.print("0");
tft.print(setHorClockOn,DEC);
tft.print(":");
if (setMinClockOn < 10) tft.print("0");
tft.print(setMinClockOn,DEC);
tft.print(" ");
if (setHorClockOff < 10) tft.print("0");
tft.print(setHorClockOff,DEC);
tft.print(":");
if (setMinClockOff < 10) tft.print("0");
tft.print(setMinClockOff,DEC);
tft.setCursor(pos, 0); // устанавливаем курсор согласно позиции
if (KEY == 5 && pos < 11) pos += 3; // крутим позицию право-лево
else if (KEY == 2 && pos > 3) pos -= 3;
else if (pos == 3 && KEY == 3) setHorClockOn++; // крутим значения
else if (pos == 3 && KEY == 4) setHorClockOn--;
else if (pos == 6 && KEY == 3) setMinClockOn++;
else if (pos == 6 && KEY == 4) setMinClockOn--;
else if (pos == 9 && KEY == 3) setHorClockOff++;
else if (pos == 9 && KEY == 4) setHorClockOff--;
else if (pos == 12 && KEY == 3) setMinClockOff++;
else if (pos == 12 && KEY == 4) setMinClockOff--;
if (setHorClockOn > 23) setHorClockOn = 0; //Ограничиваем значения
else if (setMinClockOn > 59) setMinClockOn = 0;
else if (setHorClockOff > 23) setHorClockOff = 0;
else if (setMinClockOff > 59) setMinClockOff = 0;
irrecv.resume(); }
}// конец цикла
// lcd.noBlink();
// lcd.clear();
tft.fillScreen(ST7735_BLACK); // Clear screen
EEPROM.write(win*4+0, setMinClockOn); //Записываем значения
EEPROM.write(win*4+1, setHorClockOn);
EEPROM.write(win*4+2, setMinClockOff);
EEPROM.write(win*4+3, setHorClockOff);
tft.print(" Saved");
delay(1500);
}
//_________________________________________________________________
void menu(){
//Массив с наименованиями для экрана
char menuTxt[5][14] = {"set menu1 >>", "set menu2 >>","set menu3 >>","set menu4 >>","set menu5 >>"};
byte pos = 0;
byte KEY;
while(1) {//Бесконечный цикл
if (irrecv.decode(&results)){
KEY=0;
if (temp[1]<millis()) KEY = key(); //Если прошел интервал, читаем код
// irrecv.resume();
Serial.println(key(),DEC); delay(500);
tft.setCursor(5,55);
tft.print(pos+1); //Печатаем номер.
tft.print(".");
tft.print(menuTxt[pos]); //Печатаем название
// Уменьшить увеличить + блокировка кнопки
if (KEY == 3 && pos > 0) {pos--; temp[1]=millis()+300;}
if (KEY == 4 && pos < 4) {pos++; temp[1]=millis()+300;}
win=pos; //Переменная номера таймера
// Здесь переходим на подменю. Если останется как сейчас, то достаточно
// if (KEY == 5) setOnOff();
// Сейчас можно перейти на разные подменю.
if (KEY == 5 && pos == 0) setOnOff();
if (KEY == 5 && pos == 1) setOnOff();
if (KEY == 5 && pos == 2) setOnOff();
if (KEY == 5 && pos == 3) setOnOff();
if (KEY == 5 && pos == 4) setOnOff();
//Выход из меню с проверкой и установкой блокировки от возврата
if (KEY ==1 && temp[0]<millis())
{
temp[0]=millis()+2000;
// lcd.clear();
tft.fillScreen(ST7735_BLACK); // Clear screen
break;}
irrecv.resume(); }
}
}
//_________________________________________________________________
void loop() {
if (irrecv.decode(&results)){
Serial.println(key(),DEC); delay(500);
// tft.fillScreen(ST7735_BLACK); // Clear screen
// lcd.clear();
//____________________________________________________________
//***ВХОД В МЕНЮ и проверка блокировки от возврата.
byte KEY=key(); //Принимаем код клавиши
if (KEY==1 && temp[0]<millis())
{
temp[0]=millis()+2000;
menu();
} //Если setup идем в меню
irrecv.resume(); }
//____________________________________________________________
tft.setCursor(10,100);
tft.print("cikl");
}
а именно как только вставил в void setOnOff() работу с IR, немного подвигал irrecv.resume(); } и всё завелось. То что невидно настраиваемого параметра в меню (нет блинка) небеда для отладки сойдёт, а вот то что НЕВСЕГДА каждое нажатие обрабатывает строку char menuTxt[5][14] = {"set menu1 >>", "set menu2 >>","set menu3 >>","set menu4 >>","set menu5 >>"}; - весьма напрягает.
Ну и немного замыленно (с запозданием после нажатия) обрабатываются
else if (pos == 3 && KEY == 3) setHorClockOn++; // крутим значения
else if (pos == 3 && KEY == 4) setHorClockOn--;
Как я понял нужно ВОВСЕ теперь отказатья от множествафункций, запускающих работу с IR - верно? Чтоб невозник коллапс :)
Вам задержку 90 и 155 строки дают, возможно пропускает значение во время delay().
В key() я имел в виду как то так:
//Первый вариант.
byte key(){
if (irrecv.decode(&results))
if (results.value == 0x41BEB04F) irrecv.resume(); return 5;
if (results.value == 0x41BE609F) irrecv.resume(); return 4;
if (results.value == 0x41BED02F) irrecv.resume(); return 3;
if (results.value == 0x41BE40BF) irrecv.resume(); return 2;
if (results.value == 0x41BEC03F) irrecv.resume(); return 1;
else irrecv.resume(); return 0;
}
//_____________________________________________________________
//Второй выриаант
byte key(){
if (irrecv.decode(&results))
{irrecv.resume();}
Serial.println(results.value,HEX);
if (results.value == 0x41BEB04F) return 5;
if (results.value == 0x41BE609F) return 4;
if (results.value == 0x41BED02F) return 3;
if (results.value == 0x41BE40BF) return 2;
if (results.value == 0x41BEC03F) return 1;
else return 0;
}
Но здесь меня смущает синтаксис, после decode до resume получается должно быть обернуто в фигурные скобки. Во втором варианте включил промониторить, обнуляется results.value или нет. Надо как то таким способом находить решение.
ПО первому варианту пробовал - неработает. ПО второму начинаются проблеммы с обновлениями экранов, НО это так навскидку. Счас заместто теста "cikl" вывел часики и кусок отображаемого кода с температурой.
Замечено что после установки времени к примеру и так как я сейчас невижу обновления экранчика блинком то нужно нажиать любую клавишу пульта чтобы обновить показания, иначе нажатие кнопки setup одновременно обновляет и записывает показания, которые на 1 ед. больше :)
Блин и размер - огромный матье го етить выходит. У меня всего на НАНО осталось 5-6кб (неоптимизированных) коненчое, но имеется ввиду то то сейчас работает, ка кбы непришлось отказываться от чего то в виде лишнего таймера или термо-реле :(
ПО первому варианту пробовал - неработает. ПО второму начинаются проблеммы с обновлениями экранов, НО это так навскидку. Счас заместто теста "cikl" вывел часики и кусок отображаемого кода с температурой.
Замечено что после установки времени к примеру и так как я сейчас невижу обновления экранчика блинком то нужно нажиать любую клавишу пульта чтобы обновить показания, иначе нажатие кнопки setup одновременно обновляет и записывает показания, которые на 1 ед. больше :)
Блин и размер - огромный матье го етить выходит. У меня всего на НАНО осталось 5-6кб (неоптимизированных) коненчое, но имеется ввиду то то сейчас работает, ка кбы непришлось отказываться от чего то в виде лишнего таймера или термо-реле :(
Счас поколдую ваш вариант KEY 2(вариант)
Я думаю это ваш дисплей кушает с душой. Да и потом повторяющиеся куски можно будет в функции завернуть. Кстати скиньте, что сейчас получилось, когда обновления экрана нет.
Чёрт побери - да вы гений. Убрал отовсюду работу с кнопками. Кнопки поменял на ваш вариант 2 (первый я делал - безрезультатно то синтаксис то неработают). Вынес в отдельную функцию ваш старый loop(), стало так ну неззаю мне чт ото работать с каждой по отдеьности приятнее чтоли:
void keyM(){
// if (irrecv.decode(&results)){
// timer();
// Serial.println(key(),DEC); delay(500);
// tft.fillScreen(ST7735_BLACK); // Clear screen
// lcd.clear();
//***ВХОД В МЕНЮ и проверка блокировки от возврата.
byte KEY=key(); //Принимаем код клавиши
if (KEY==1 && temp[0]<millis())
{
temp[0]=millis()+2000;
menu();
} //Если setup идем в меню
// irrecv.resume(); }
// tft.setCursor(10,100);
// tft.print("cikl");
}
Остались небольшие грабельки, после сохранения настроек на дисплейчик выводится вся инфа которая периодическ и прорисовывается. Если убрать коммент с очистки экрана в keyM9 то само собой экран начинает переисовыватсья после запуска скетча. И если войти в setup и потом нажать ОДЯИН раз up\down то меню САМО листается от 1 до 5 смотря куда жмакнуть :(
А вот так выглядит сейчас мой цикл():
void loop() {
eEPROMread();
timeRtc();
keyM();
}
где Епромчтение -это от старого, нынедействующего таймера и сам таймер. Счас покажу чего вышло когда есть часики и таймер :)
ПО дисплейчикам, разница в скетчах около 7 кб. НАНО имеет всего 30кб - счас у меня свободно как раз 6-7,
По уму, перед выходом из меню , самое правильное давать команду lcd.clear. Эта информация уже не нужна. А следующий блок уже должен выводить свою информацию.
Вот, тут косок с часиками простыми на ds1307, таймер и нагрузка в виде леидков. Весь код:
#include <EEPROM.h>
#include <Wire.h> //Подключаем библиотеку для использования однопроводного интерфейса
#include <OneWire.h> //Подключаем библиотеку для температурного датчика DS18B20
#include <IRremote.h> //Подключаем библиотеку для IR сенсора
//=====Tft*
#include <Adafruit_GFX.h> // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library
#include <SPI.h>
#define sclk 52
#define mosi 51
#define cs 4
#define dc 2
#define rst 3 // you can also connect this to the Arduino reset
Adafruit_ST7735 tft = Adafruit_ST7735(cs, dc, mosi, sclk, rst);
//=====Переменные для меню
byte setMinClockOn;
byte setHorClockOn;
byte setMinClockOff;
byte setHorClockOff;
byte win; //Номер экрана меню
unsigned long temp[2]; //Массив для задержек меню
#define RECV_PIN 11 //Вход IR-приемника и кнопки пульта
uint32_t val;
IRrecv irrecv(RECV_PIN);
decode_results results;
#define KEY10 0x41BE30CF //кнопка Setup пвход в меню настроек параметров
#define KEY2 0x41BEC03F //кнопка enter принятие установок и запись их
#define KEY1 0x41BED02F //кнопка Up меню
#define KEY3 0x41BE609F //кнопка Down возврата
#define KEY6 0x41BE40BF //уменьшение значения Left
#define KEY7 0x41BEB04F //увеличение значения Right
/*
byte key(){
if (results.value == 0x41BEB04F) return 5;
if (results.value == 0x41BE609F) return 4;
if (results.value == 0x41BED02F) return 3;
if (results.value == 0x41BE40BF) return 2;
if (results.value == 0x41BEC03F) return 1;
else return 0; }
*/
byte ledPin1 =7; //Светодиод
byte ledPin2 =9; //Светодиод
//=====Rtc_Clock*
#define DS1307_I2C_ADDRESS 0x68
byte seconds, minutes, hours, day, date, month, year;
long tmIntv = 1000; //Интервал для обновления времени на экране каждую секунду
//long razdIntv = 500; //Интервал для обновления ":" на экране каждые 2 секунды
long prvMlsTm = 0; //Предыдущее показание миллисекунд для обновления показания часов
//long prvMlsRazd = 0; //Предыдущее показание миллисекунд для обновления ":"
//long prvMlsLght = 0; //Предыдущее показание проверки временного интервала
//=====Timer*
// long lghtIntv = 60000; //Интервал для проверки включения/выключения освещения аквариума, 1 минута
byte lcdStat = 0; //Флаг подсветки Lcd если включена, то в 1
byte lghtStat1 = 0; //Флаг освещения, Реле Dimm, если включена, то в 1 в первом таймере
byte lghtStat2 = 0; //Флаг освещения, Реле Dimm, если включена, то в 1 во втором таймере
byte co2Stat = 0; //Флаг Co2, Реле, если включена, то в 1
byte isLcdt = 0; //Флаг для обработки необходимости включить подсветку Lcd
byte isLght1 = 0; //Флаг для обработки необходимости включить реле освещения на 1 канале в первом таймере
byte isLght2 = 0; //Флаг для обработки необходимости включить реле освещения на 1 канале во втором таймере
byte isCo2t = 0; //Флаг для обработки необходимости включить реле Co2
byte isNight = 0; //Если включаем на ночь, т.е. начальное время больше конечного
//=====Eeprom*
int hrOn_r1e; //переменные для хранения данных о вкл. выкл. реле1 после считывания с EEPROM
int mnOn_r1e;
int hrOff_r1e;
int mnOff_r1e;
int hrOn_r2e; //переменные для хранения данных о вкл. выкл. реле2 после считывания с EEPROM
int mnOn_r2e;
int hrOff_r2e;
int mnOff_r2e;
int hrOn_r3e; //переменные для хранения данных о вкл. выкл. реле3 CO2 после считывания с EEPROM
int mnOn_r3e;
int hrOff_r3e;
int mnOff_r3e;
int hrOn_lcde; //переменные для хранения данных о вкл. выкл. Lcd после считывания с EEPROM
int mnOn_lcde;
int hrOff_lcde;
int mnOff_lcde;
//***********************************************************************************************************
void setup() {
Wire.begin();
Serial.begin(9600);
irrecv.enableIRIn(); //Включаем IR-сенсор
tft.initR(INITR_BLACKTAB);
tft.fillScreen(ST7735_BLACK); // Clear screen
pinMode(ledPin1, OUTPUT);
pinMode(ledPin2, OUTPUT);
digitalWrite(ledPin1, HIGH);
digitalWrite(ledPin2, HIGH);
}
//====================================================
//=========== Обработка RTC часов
//====================================================
void timeRtc(){
Wire.beginTransmission(DS1307_I2C_ADDRESS); //104 is DS3231 device address
Wire.write(0x00); //Start at register 0
Wire.endTransmission();
Wire.requestFrom(DS1307_I2C_ADDRESS, 7); //Request seven bytes
if(Wire.available()) {
seconds = Wire.read(); //Get second
minutes = Wire.read(); //Get minute
hours = Wire.read(); //Get hour
day = Wire.read();
date = Wire.read();
month = Wire.read(); //Get month
year = Wire.read();
seconds = (((seconds & B11110000)>>4)*10 + (seconds & B00001111)); //Convert BCD to decimal
minutes = (((minutes & B11110000)>>4)*10 + (minutes & B00001111));
hours = (((hours & B00110000)>>4)*10 + (hours & B00001111)); //Convert BCD to decimal (assume 24 hour mode)
day = (day & B00000111); // 1-7
date = (((date & B00110000)>>4)*10 + (date & B00001111)); //Convert BCD to decimal 1-31
month = (((month & B00010000)>>4)*10 + (month & B00001111)); //msb7 is century overflow
year = (((year & B11110000)>>4)*10 + (year & B00001111));
}
tft.setCursor(15,5);
tft.setTextColor(ST7735_WHITE,ST7735_BLACK);
tft.setTextSize(2);
if (hours<10) {tft.print(0);tft.print(hours);} else {tft.print(hours);}
tft.print(":");
if (minutes<10) {tft.print(0);tft.print(minutes);} else {tft.print(minutes);}
tft.print(":");
if (seconds<10) {tft.print(0);tft.print(seconds);} else {tft.print(seconds);}
tft.setCursor(15,25);
tft.setTextColor(ST7735_GREEN,ST7735_BLACK);
tft.setTextSize(1);
if (date<10) {tft.print(0);tft.print(date);} else {tft.print(date);}
tft.print("/");
if (month==1){tft.print ("Jan");}
if (month==2){tft.print ("Feb");}
if (month==3){tft.print ("Mar");}
if (month==4){tft.print ("Apr");}
if (month==5){tft.print ("May");}
if (month==6){tft.print ("Jun");}
if (month==7){tft.print ("Jul");}
if (month==8){tft.print ("Aug");}
if (month==9){tft.print ("Sep");}
if (month==10){tft.print ("Oct");}
if (month==11){tft.print ("Nov");}
if (month==12){tft.print ("Dec");}
tft.print("/");
tft.print(year+2000);
if (day==1){tft.print (" Sun.");}
if (day==2){tft.print (" Mon.");}
if (day==3){tft.print (" Tue.");}
if (day==4){tft.print (" Wed.");}
if (day==5){tft.print (" Thu.");}
if (day==6){tft.print (" Fri.");}
if (day==7){tft.print (" Sat.");}
}
//====================================================
//=========== Обработка Таймеров
//====================================================
void timer(){ //Включаем/выключаем освещение аквариума и СО2
//========== Таймер №1
int fullMinutes = hours * 60 + minutes; //Переводим часы + минуты к полным минутам
int fullMinutesOn1 = hrOn_r1e * 60 + mnOn_r1e; //Переводим часы + минуты включения 1 реле к полным минутам
int fullMinutesOff1 = hrOff_r1e * 60 + mnOff_r1e; //Переводим часы + минуты выключения 1 реле к полным минутам
int fullMinutesOn2 = hrOn_r2e * 60 + mnOn_r2e; //Переводим часы + минуты выключения 2 реле к полным минутам
int fullMinutesOff2 = hrOff_r2e * 60 + mnOff_r2e; //Переводим часы + минуты выключения 2 реле к полным минутам
if (fullMinutesOn1 > fullMinutesOff1) {isNight = 1;} //Если ночное время
if (isNight == 0) { //Если день
if (fullMinutes >= fullMinutesOn1 && fullMinutes < fullMinutesOff1) {isLght1 = 1;} //Проверяем интервал
else {isLght1 = 0;} //Если необходимо включить свет
} else { //Если ночь
if(fullMinutes - fullMinutesOn1 >= 0) {isLght1 = 1;} //Если больше или равно верхнему значению, то необходимо включить свет
else { //Если необходимо включить свет
if(fullMinutes < fullMinutesOff1) {isLght1 = 1;} //Если меньше нижнего значения, то необходимо включить свет
else {isLght1 = 0;} //Если необходимо включить свет
}
}
if((isLght1 == 1) && (lghtStat1 == 0)){ //Если свет еще не включен и выставлен флаг необходимости включить
digitalWrite(ledPin1, LOW); lghtStat1 = 1;
} else {
lghtStat1 = 0;
}
//========== Таймер №2
if (fullMinutesOn2 > fullMinutesOff2) {isNight = 1;} //Если ночное время
if (isNight == 0) { //Если день
if (fullMinutes >= fullMinutesOn2 && fullMinutes < fullMinutesOff2) {isLght2 = 1;} //Проверяем интервал
else {isLght2 = 0;} //Если необходимо включить свет
} else { //Если ночь
if(fullMinutes - fullMinutesOn2 >= 0) {isLght2 = 1;} //Если больше или равно верхнему значению, то необходимо включить свет
else { //Если необходимо включить свет
if(fullMinutes < fullMinutesOff2) {isLght2 = 1;} //Если меньше нижнего значения, то необходимо включить свет
else {isLght2 = 0;} //Если необходимо включить свет
}
}
if((isLght2 == 1) && (lghtStat2 == 0)){ //Если свет еще не включен и выставлен флаг необходимости включить
digitalWrite(ledPin1, LOW); lghtStat2 = 1;
} else {
lghtStat2 = 0;
}
tft.setTextSize(1);
tft.setTextColor(ST7735_WHITE, ST7735_BLACK);
tft.setCursor(50, 140);
tft.print(fullMinutesOn1/60);
tft.print(" ");
tft.print(fullMinutesOff1%60);
tft.setCursor(50, 150);
tft.print(fullMinutesOn2/60);
tft.print(" ");
tft.print(fullMinutesOff2%60);
}
void eEPROMread() {
hrOn_r1e = EEPROM.read(1);
mnOn_r1e = EEPROM.read(2);
hrOff_r1e = EEPROM.read(3);
mnOff_r1e = EEPROM.read(4);
hrOn_r2e = EEPROM.read(5);
mnOn_r2e = EEPROM.read(6);
hrOff_r2e = EEPROM.read(7);
mnOff_r2e = EEPROM.read(8);
hrOn_r3e = EEPROM.read(9);
mnOn_r3e = EEPROM.read(10);
hrOff_r3e = EEPROM.read(11);
mnOff_r3e = EEPROM.read(12);
hrOn_lcde = EEPROM.read(13);
mnOn_lcde = EEPROM.read(14);
hrOff_lcde = EEPROM.read(15);
mnOff_lcde = EEPROM.read(16);
}
//***********************************************************************************************************
void setOnOff(){
byte pos = 0;
setHorClockOn = EEPROM.read(win*4+1); //Считываем записанные значения таймеров
setMinClockOn = EEPROM.read(win*4+2); //Адрес определяется как номер таймера*4+четыре ячейки
setHorClockOff = EEPROM.read(win*4+3);
setMinClockOff = EEPROM.read(win*4+4);
// lcd.clear();
// lcd.blink();
tft.fillScreen(ST7735_BLACK); // Clear screen
while(key() != 1) {//Крутим цикл пока не будет Setup
// if (irrecv.decode(&results)){
byte KEY = key(); // читаем состояние кнопок
// Serial.println(key(),DEC); delay(500);
delay(200); //Если убрать, не работает подсветка уст.позиции
// lcd.setCursor(1, 1);
tft.setCursor(5,75);
tft.setTextColor(ST7735_WHITE,ST7735_BLACK);
tft.setTextSize(1);
tft.print("set to save");
tft.setCursor(5, 55);
tft.print(win+1,DEC); //Печатаем номер прогр.таймера.
tft.setCursor(35, 55); // выводим инфу
if (setHorClockOn < 10) tft.print("0");
tft.print(setHorClockOn,DEC);
tft.print(":");
if (setMinClockOn < 10) tft.print("0");
tft.print(setMinClockOn,DEC);
tft.print(" ");
if (setHorClockOff < 10) tft.print("0");
tft.print(setHorClockOff,DEC);
tft.print(":");
if (setMinClockOff < 10) tft.print("0");
tft.print(setMinClockOff,DEC);
tft.setCursor(pos, 0); // устанавливаем курсор согласно позиции
if (KEY == 5 && pos < 11) pos += 3; // крутим позицию право-лево
else if (KEY == 2 && pos > 3) pos -= 3;
else if (pos == 3 && KEY == 3) setHorClockOn++; // крутим значения
else if (pos == 3 && KEY == 4) setHorClockOn--;
else if (pos == 6 && KEY == 3) setMinClockOn++;
else if (pos == 6 && KEY == 4) setMinClockOn--;
else if (pos == 9 && KEY == 3) setHorClockOff++;
else if (pos == 9 && KEY == 4) setHorClockOff--;
else if (pos == 12 && KEY == 3) setMinClockOff++;
else if (pos == 12 && KEY == 4) setMinClockOff--;
if (setHorClockOn > 23) setHorClockOn = 0; //Ограничиваем значения
else if (setMinClockOn > 59) setMinClockOn = 0;
else if (setHorClockOff > 23) setHorClockOff = 0;
else if (setMinClockOff > 59) setMinClockOff = 0;
// irrecv.resume(); }
}// конец цикла
// lcd.noBlink();
// lcd.clear();
tft.fillScreen(ST7735_BLACK); // Clear screen
EEPROM.write(win*4+1, setHorClockOn);
EEPROM.write(win*4+2, setMinClockOn); //Записываем значения
EEPROM.write(win*4+3, setHorClockOff);
EEPROM.write(win*4+4, setMinClockOff);
tft.print(" Saved");
// delay(1500);
}
//***********************************************************************************************************
void menu(){
//Массив с наименованиями для экрана
char menuTxt[5][15] = {"set Timer-1 >>", "set Timer-2 >>","set menu-3 >>","set menu-4 >>","set menu-5 >>"};
byte pos = 0;
byte KEY;
while(1) {//Бесконечный цикл
// if (irrecv.decode(&results)){
KEY=0;
if (temp[1]<millis()) KEY = key(); //Если прошел интервал, читаем код
// Serial.println(key(),DEC); delay(500);
tft.setCursor(5,55);
tft.print(pos+1); //Печатаем номер.
tft.print(". ");
tft.print(menuTxt[pos]); //Печатаем название
// Уменьшить увеличить + блокировка кнопки
if (KEY == 3 && pos > 0) {pos--; temp[1]=millis()+50;}
if (KEY == 4 && pos < 4) {pos++; temp[1]=millis()+50;}
win=pos; //Переменная номера таймера
// Здесь переходим на подменю. Если останется как сейчас, то достаточно
// if (KEY == 5) setOnOff();
// Сейчас можно перейти на разные подменю.
if (KEY == 5 && pos == 0) setOnOff();
if (KEY == 5 && pos == 1) setOnOff();
if (KEY == 5 && pos == 2) setOnOff();
if (KEY == 5 && pos == 3) setOnOff();
if (KEY == 5 && pos == 4) setOnOff();
//Выход из меню с проверкой и установкой блокировки от возврата
if (KEY ==1 && temp[0]<millis())
{
temp[0]=millis()+200;
tft.fillScreen(ST7735_BLACK); // Clear screen
break;}
// irrecv.resume(); }
}
}
//************************************************************
void keyM(){
// tft.fillScreen(ST7735_BLACK); // Clear screen
byte KEY=key(); //ВХОД В МЕНЮ и проверка блокировки от возврата.Принимаем код клавиши
if (KEY==1 && temp[0]<millis()) {
temp[0]=millis()+2000;
menu(); } //Если setup идем в меню
}
byte key(){
if (irrecv.decode(&results))
{irrecv.resume();}
Serial.println(results.value,HEX);
if (results.value == 0x41BEB04F) return 5;
if (results.value == 0x41BE609F) return 4;
if (results.value == 0x41BED02F) return 3;
if (results.value == 0x41BE40BF) return 2;
if (results.value == 0x41BEC03F) return 1;
else return 0;
}
//************************************************************
void loop() {
eEPROMread();
timeRtc();
keyM();
}
Почти 22 кб собака в таком виде, Значит сечас разберусь с обновлениями экрана, также нужно флажок типа (нужен\ненужен таймер) придумать и время автоматического выхода из меню, основной то цикл неработает и ничего невыполняется, даже кнопки :) хороший урок для меня.
1. стр.30-31 Можем сделать вход в меню по Setup, а запись значений и выход по Enter. Тогда исчезает проблема нажатой клавиши и автовозврат.
2. стр71-87 Бессмысленно кушают ресурсы. Эти значения уже существуют в конкретных ячейках EPROM, а самое главное до перезагрузки они будут старыми, как ни меняй их в меню. Правильнее a=EEPROM.read(x)*60. x можно указывать как прямо, так и косвенно по типу ка win в меню.
3. стр221-238 - пункт.2
4. стр.308 Если убираете ее, то тогда и предыдущую, все равно ничего не увидите.
5. стр.344 и 357. Если делаем как п.1, то эту логику можно всю выбросить.
6. Флажок нужности таймера по идее лишний, если время вкл.=время откл. таймер не нужен. Это условие и проверяйте.
7. Возврату в loop я боюсь вам препятствует 344 строка. Вы за 0,2 секунды просто не успеваете среагировать. У меня выход был четкий. Или читаем п.1.
Т.Е фактически получается как кнопка с фиксацией. Хоть палец убран, она все равно нажата?
Мдя... чуток отходил от кода... понедельник всёже :). Все верное таке ощёщение что кнопка с фиксацией несмотря на IR... счас зашел в menu - дале в set Timer-1 (он же set menu1) по вашему старому и чт овы думаете блинк я невижу, однако курсок сразу ушёл на минуты выкл (они-жеЕПРОМ(4)) и елси я нажимаю(up или sown то значения сами меняются в ту или иную сторону).
1. стр.30-31 Можем сделать вход в меню по Setup, а запись значений и выход по Enter. Тогда исчезает проблема нажатой клавиши и автовозврат.
Можно, кнопок в пульте сами знаете, это не физические манстырить, тут определил и готово. Хотя вариант с 5-ю кнопками тоже ничего такой, очень классный вышел. Просто я когда на if-ах писать пробовал то имеено о 6-т кнопках и думал влево\вправо|вверх\вниз|вход в меню|принятие значения и выход - так и думал.
bwn пишет:
2. стр71-87 Бессмысленно кушают ресурсы. Эти значения уже существуют в конкретных ячейках EPROM, а самое главное до перезагрузки они будут старыми, как ни меняй их в меню. Правильнее a=EEPROM.read(x)*60. x можно указывать как прямо, так и косвенно по типу ка win в меню.
Это я видимо по аналогии из какого то кода и его работы с ЕПРОМ брал. Счас понимаю что слишком длинно получилось и занимается каждый байт, И да формула полных минут не просто *60 а ещё и прибавляем сами МИНУТЫ тоесть chas*60+min
3. стр221-238 - пункт.2
4. стр.308 Если убираете ее, то тогда и предыдущую, все равно ничего не увидите.
bwn пишет:
5. стр.344 и 357. Если делаем как п.1, то эту логику можно всю выбросить.
Попробую сам описать, неполучится спрошу, ок? НО после того как сейчашнее меню будет нормуль отрабатывать и нажатия и обновления экранчика. :)
bwn пишет:
6. Флажок нужности таймера по идее лишний, если время вкл.=время откл. таймер не нужен. Это условие и проверяйте.
Я так понял проверки именно в функции таймера будет? Там и проверять.
7. Возврату в loop я боюсь вам препятствует 344 строка. Вы за 0,2 секунды просто не успеваете среагировать. У меня выход был четкий. Или читаем п.1.
Вроде все сказал.
[/quote]
Вот вроде все и понял, как теперь побороть "Удержание" кнопки, которая и неудерживается.
//====================================================
249 //========== Обработка IR-кнопок, ручное управление реле и диммером
250 //====================================================
251 void ir_manual_key(){
252 if (irrecv.decode(&results)){ //Если пришел пакет и этот пакет не FF сохраняем правильный пакет в переменную
253 if (results.value != 0xFFFFFFFF){ //Если пришел FF, соответственно пропускаем.
254 val = results.value; //Сверяем значение из переменной val.. если пришла команда повтора (пакет с FF)
255 } //в переменной останется прошлый, правильный, пакет и код выполнится повторно.
Посмотрел по вашему коду, такая конструкция работает без resume - в чем назначение этой команды?
byte key(){
if (irrecv.decode(&results)){
irrecv.resume();
if (results.value == 0x41BEB04F) return 5;
if (results.value == 0x41BE609F) return 4;
if (results.value == 0x41BED02F) return 3;
if (results.value == 0x41BE40BF) return 2;
if (results.value == 0x41BEC03F) return 1;
else return 0;
}
}
Однако теперь перестали работать именно работать (в serial они возвращаются) но ни поменять время ни позицию нельзя.
Срабатывания на нажатия ОЧЕНЬ чёткие, даже сначала и неповерил - ранее какая то замыленность, то среагирует то нет, а тут чётко, обновляется корректно всё и вход и выход и сохранение... ПОПРАВИТЬ параметры нельзя - ну несмех ли..
//====================================================
249 //========== Обработка IR-кнопок, ручное управление реле и диммером
250 //====================================================
251 void ir_manual_key(){
252 if (irrecv.decode(&results)){ //Если пришел пакет и этот пакет не FF сохраняем правильный пакет в переменную
253 if (results.value != 0xFFFFFFFF){ //Если пришел FF, соответственно пропускаем.
254 val = results.value; //Сверяем значение из переменной val.. если пришла команда повтора (пакет с FF)
255 } //в переменной останется прошлый, правильный, пакет и код выполнится повторно.
Посмотрел по вашему коду, такая конструкция работает без resume - в чем назначение этой команды?
P.S.погорячился, оно у вас в 302 строке.
Да это код ШИКАРНО обрабатывает именно"удержание" кнопки, очень классно и точно обрабатывет на диммировании, вот бы его и прикрутить в устновку времени - чтобы нежмакать минуты каждый раз, а нажал и держиш...
//====================================================
249 //========== Обработка IR-кнопок, ручное управление реле и диммером
250 //====================================================
251 void ir_manual_key(){
252 if (irrecv.decode(&results)){ //Если пришел пакет и этот пакет не FF сохраняем правильный пакет в переменную
253 if (results.value != 0xFFFFFFFF){ //Если пришел FF, соответственно пропускаем.
254 val = results.value; //Сверяем значение из переменной val.. если пришла команда повтора (пакет с FF)
255 } //в переменной останется прошлый, правильный, пакет и код выполнится повторно.
Посмотрел по вашему коду, такая конструкция работает без resume - в чем назначение этой команды?
P.S.погорячился, оно у вас в 302 строке.
Да это код ШИКАРНО обрабатывает именно"удержание" кнопки, очень классно и точно обрабатывет на диммировании, вот бы его и прикрутить в устновку времени - чтобы нежмакать минуты каждый раз, а нажал и держиш...
По нормальному, на мех.кнопках это и происходит с интервалом в 0,3 секунды.
Почти ка ки в моем варианте, все корректно обрабатывается пока ненужно параметры поменять времени (минут и часов).
Однако в моем варианет если нет нажатия то нет и возврата в вашем случае если нет нажатия возвращается "0" если еть то HEX адрес кнопки с межеванием "0" (я так понял это и есть return 0)
Жаль но мой предлженный ни ваш неизменят параметра. внутри setmenu-1
По нормальному, на мех.кнопках это и происходит с интервалом в 0,3 секунды.
Понимаю, только я пульт выбрал непотому чт олень кнопи манстырить было а по другим причинам. ВО первых мобильность некая, далее кнопки у кадого СВОИ кто то так ктото эдак ктото вообще потнциометромих пользует (переменными резиорами, где поворот часов/24 а минут на /60). А пульт у каждого, взяли наш с вами код, подставили СВОИ HEX-кнопки и всё. Ну и само собой у меня контроллер это маааленькая чать в светильнике акариума и довольно высоко вот лазать туда жмакать хоть и нечасто но надо. Да и вообще IR - же намного интереснее, выже сами видите уже :)
у категорически непонмаю ничего КАК могут возвращаться НАЖАТЫЕ кнопки и НИЧЕГО неделать? Есч ораз промониторил serial.Print всё нажимается, а изменения нет.
Так я и не могу понять почему не так. Сейчас выходит: если клавиша нажата, key() возвращает что то от 1 до 5. Если отпустили, идет 0. То есть полностью соответствует мех.клавишам. При этом первый экран меню работает корректно или нет?
В loop у меня это было, чтобы понять где нахожусь. Как там будет это не принципиально за исключением куска входа в меню. А он получается отрабатывает корректно или что то изменяли?
Да и непосредственно вход в функции key() промониторить. Попадаем ли мы туда?
И еще, что делает вот этот кусочек у вас в коде? Если его закоментить мы будем значения с IR получать?
if
(irrecv.decode(&results)){
В loop у меня это было, чтобы понять где нахожусь. Как там будет это не принципиально за исключением куска входа в меню. А он получается отрабатывает корректно или что то изменяли?
Да и непосредственно вход в функции key() промониторить. Попадаем ли мы туда?
В loop я добавил лиш работу с кнопками IR и если не окмментить очистку то надпись cikl перерисовывается циклически. Вот такой у меня loop
Тогда добавьте после 132 строки переменную KEY на экран, посмотреть какие значения она принимает. У меня на обычных кнопках все срабатывало нормально.
Сделал, всё отлично обрабатывает, вход в меню и возврат нажатой кнопки 1 select. Тоесть все корректно, далее 5 сек и снова возварт в cikl
И еще, что делает вот этот кусочек у вас в коде? Если его закоментить мы будем значения с IR получать?
if
(irrecv.decode(&results)){
Ежели это убрать то мои IR нажатия вообще остаются незамеченными. Это я так понял стандартный код для работы с IR:
От, тогда получается, что этот кусок надо добавить в функцию key().
Мы уходя в меню перестаем взаимодействовать с loop, на все время работы с меню. Соответственно и не получаем никаких данных с IR (у вас опрос в loop). Надо его продублировать в функции.
"Сделал, всё отлично обрабатывает, вход в меню и возврат нажатой кнопки 1 select. Тоесть все корректно, далее 5 сек и снова возварт в cikl" - а вот это неправильно. Возврат должен был быть только при повторном нажатии select через две секунды. Получается, что у вас остается запомненным предыдущее состояние KEY и оно возвращает в loop. (кстати на 5 секунд зря меняли, это задержка, чтобы сразу не вернутся - вход и выход из первого меню по одной и той же клавише, автовозврата я сюда не писал, усложнить никогда не поздно.)
P/S примерно понял, почему происходит возврат - мы прекратили опрос и results.value == 0x41BEC03F остался в том же состоянии.
От, тогда получается, что этот кусок надо добавить в функцию key().
Мы уходя в меню перестаем взаимодействовать с loop, на все время работы с меню. Соответственно и не получаем никаких данных с IR (у вас опрос в loop). Надо его продублировать в функции.
Хехе всё пучком, наконецто вошли в menu?z же вот одним местом чуял что неспроста в старом коде где всё висело - ничего невисело ПРОСТО там необрабатывались кнопки IR - я то лол совсем забыл что когда мы в menu то loop НЕРАБОТАЕт и цикла по нему НЕТ.ВОт сюда продублировал:
Рано обрадовался :( - висит у меня счас первый таймер вида:
1 10:00 11:00
set to save
(значения видимо из моих СТАРЫХ проб записи в ЕПРОМ)
... и всё, видимо надо ещё кудато добавлять обработку кнопок . И вот ещё что, вы писали... "P/S примерно понял, почему происходит возврат - мы прекратили опрос и results.value == 0x41BEC03F остался в том же состоянии." ежели выводить в serial.print кнопки ТО именно 1-ка и возвращалась (setup) после того как я НTвошёл в menu, меня выкидывало в cikle а 1-ка - продолжала возвращаться!!! Так что всё верное вы догадались.
Отнюдь отнюдь, это должно быть в функции key(). Иначе вы начнете плодить эти строки во всех циклах, а это неправильно, хоть и будет работать.
Вот меня смущает что немогу в tft обрабатывать blink курсором - я так понял после входа в меню сначала курсор становится на часы и начинает мигать?
Вот меня смущает что немогу в tft обрабатывать blink курсором - я так понял после входа в меню сначала курсор становится на часы и начинает мигать?
Да, сперва мигает разряд единиц часов, потом минут и т.д. Как у вас в библиотеке и есть ли он там, тут уже не помогу. А без него не понять что устанавливаем.
На сегодня меня выгоняют из компьютера с ардуинкой :( . Доброй ночи.
Я всё-же вставил обработку IR аналогично с функции key в функцию void setOnOff() - ну чтоб наверняка. Вобщем тепреь заработали кнопки однако любое нажатие вызывает saved и всё, снова зависон - видимо кнопки IR работают иначе физических.
Завтра на работе буду отлаживать - главное знать где и мы с вами знаем :)
А я все таки настоятельно рекомендую делать это в key(), в том числе и из loop убрать. Когда что то происходит в одной функции, отладка намного проще становится, вы получили на выходе функции стабильный результат и больше к ней не возвращаетесь. А так вам приходится лазать по всему коду и ловить мелких блох.
Еще вопрос, что делает вот эта строка irrecv.resume();? Я так подозреваю, что дает разрешение на следующее считывание. Если так, то делает это с очисткой results.value или без?
Приветы. Сегодня на работе заметил... при входе в setup я кнопками (up - down) могу выбирать номер расписания от 1 до 5, однако они прорисовываются в одной строке поверх и собственно сами понимаете - нечитабельно, счас покурю где мне надо очищать дисплей перед выбором следующего расписания.
Далее я вхожу в расписание и всё, тут уже ничего непроисходит и кнопки необрабатываются. Работу с IR убрал пока отовсюду кроме loop и KEY.
Следуя вашему совету я счас уберу из loop? однако боюсь тогда несмогу войти в setup (кнопки то обрабатыватсья до него небудут).
Ну вот как я и думал из loop IR убирать НЕЛЬЗЯ, можно к примеру если работа с IR есть в функции которая запускается из loop, у меня так в моем акваконтроллере если вы помните в loop()
eEPROMread();
// program_clock();
timeRtc();
timer();
ir_manual_key();
auto_key_dimmer();
dallas(); //flagDallas==0;
tempRelay();
voltM();
bar();
bluetooth();
}
и как раз IК содержится в ir_manual_key();
а вот irrecv.resume(); сильно влияет своим положение в конце какой либо функции, либо перестают отвечать кнопки либо зацикливается выбор.
Когда я нахожусь в (setup) оно же char menuTxt[5][14] = {"set menu1 >>", "set menu2 >>","set menu3 >>","set menu4 >>","set menu5 >>"};
то Serial.println(key(),DEC); delay(500); - невозвращает мне НИЧЕГО хотя я спокойно выбираю set menu1 >> стрелками (up - down) как уже писал выше - чудес небывает я так понял снова пресловутый loop не лупицца и надо serial.Print дописат mb в KEY
Убрать отовсюду я имел в виду - перенести в key() и обращатся только к нему по мере надобности. Сейчас у вас уже пять мест где происходит это обращение (loop, dimmer и три меню), дальше будет больше. irrecv.resume(); думаю должно стоять перед каждым return в функции key(). Функцию key() переписать, чтобы она возвращала как KEY№ , так и от 0 до 5. Тогда вы сможете к ней обращатся из любого места, а брать нужное вам значение.
Экран на LCD у меня сам затирался, очистку не делал, лекарство - напечатать сперва пустую строку (можете ее даже в массив внести для тренировки.)
Ага интеренсная картинка вырисовывается. Вот с такой функцией menu() и кнопок KEY:
я получаю нажатые кнопки ДО собственно моента входа в set menu1 >> и тп. Ка ктолько вошёл всё снова кнопки IR необрабатываются. И кстаи снова навернео какието задержки потмоу как невсегда СРАЗУ я могу пробежаться по char menuTxt[5][14] = {"set menu1 >>", "set menu2 >>","set menu3 >>","set menu4 >>","set menu5 >>"};
чаще serial.Print мне вывел нажатую кнопку а собственно строка несменилась, Ну а далее если и сменилась то прорисовав поверх старой название
А куда вы этот Serial прописывали?
Убрать отовсюду я имел в виду - перенести в key() и обращатся только к нему по мере надобности. Сейчас у вас уже пять мест где происходит это обращение (loop, dimmer и три меню), дальше будет больше. irrecv.resume(); думаю должно стоять перед каждым return в функции key(). Функцию key() переписать, чтобы она возвращала как KEY№ , так и от 0 до 5. Тогда вы сможете к ней обращатся из любого места, а брать нужное вам значение.
Экран на LCD у меня сам затирался, очистку не делал, лекарство - напечатать сперва пустую строку (можете ее даже в массив внести для тренировки.)
Про то думал, но у меня на самом деле IR кнопки обрабатываются ТОЛЬКО один раз имеено в функции работы с диммированием (удержанием кнопки и отключение релюшек). Там пока тьфу три раза всё работает как часики. А тут да - меню штука своебразная. Счас подправлю согласн овашим рекомендациям irrect.resume
Если по вашему коду, он и не должен работать. Если лепить таким образом, то 37 строка должна быть после 10. Иначе вы производите инициацию после того, как уже ушли из меню.
А куда вы этот Serial прописывали?
Serial в самом начале loop ()
void loop() {
Serial.println(key(),DEC); delay(100);
if (irrecv.decode(&results)){
...
}
и в menu(), код выше
А куда вы этот Serial прописывали?
Serial в самом начале loop ()
void loop() {
Serial.println(key(),DEC); delay(100);
if (irrecv.decode(&results)){
...
}
и в menu(), код выше
А в меню, добавлять в 10 строку после KEY=key() и мониторить KEY. delay() не нужен. Когда вы вызываете конструкцией (key(),DEC) вы обращаетесь к функции и печатаете ее результат, а нас интересует переменная.
Если по вашему коду, он и не должен работать. Если лепить таким образом, то 37 строка должна быть после 10. Иначе вы производите инициацию после того, как уже ушли из меню.
Здесь немного вас обманул, работать будет, но возможно некорректная обработка при переходе на следующее меню.
не ничево неполучается, двигаю irrecv.resume(); } - меняется но не в лучьшую сторону, добавил перед return но уже в виде irrecv.resume();
Всё потмоу что для мнея сложно понимание массива и его переменных
byte pos = 0;
byte KEY;
if (temp[1]<millis()) KEY = key();
if (KEY == 3 && pos > 0) {pos--; temp[1]=millis()+300;}
вот этого всего :(((
не ничево неполучается, двигаю irrecv.resume(); } - меняется но не в лучьшую сторону, добавил перед return но уже в виде irrecv.resume();
Всё потмоу что для мнея сложно понимание массива и его переменных
byte pos = 0;
byte KEY;
if (temp[1]<millis()) KEY = key();
if (KEY == 3 && pos > 0) {pos--; temp[1]=millis()+300;}
вот этого всего :(((
Так массив это та же переменная - уберите из него квадратные скобки и получите temp0, temp1 и т.д. все остальные действия как с обычными переменными. В данном коде - задержка 0,3сек иначе у вас цифры будут лететь со скоростью цикла.
П О Л У Ч И Л О С Ь !!
Правда "раком" стопроцентов, именно как вы НЕСОВЕТОВАЛИ. Всётаки дело в "непотребном" коде при работе с кнопками. Значит вот как у меня и всё работает и нажимается, весь код:
а именно как только вставил в void setOnOff() работу с IR, немного подвигал irrecv.resume(); } и всё завелось. То что невидно настраиваемого параметра в меню (нет блинка) небеда для отладки сойдёт, а вот то что НЕВСЕГДА каждое нажатие обрабатывает строку char menuTxt[5][14] = {"set menu1 >>", "set menu2 >>","set menu3 >>","set menu4 >>","set menu5 >>"}; - весьма напрягает.
Ну и немного замыленно (с запозданием после нажатия) обрабатываются
else if (pos == 3 && KEY == 3) setHorClockOn++; // крутим значения
else if (pos == 3 && KEY == 4) setHorClockOn--;
Как я понял нужно ВОВСЕ теперь отказатья от множествафункций, запускающих работу с IR - верно? Чтоб невозник коллапс :)
Но результат на сейчас уже РАДУЕТ.
Вам задержку 90 и 155 строки дают, возможно пропускает значение во время delay().
В key() я имел в виду как то так:
Но здесь меня смущает синтаксис, после decode до resume получается должно быть обернуто в фигурные скобки. Во втором варианте включил промониторить, обнуляется results.value или нет. Надо как то таким способом находить решение.
ПО первому варианту пробовал - неработает. ПО второму начинаются проблеммы с обновлениями экранов, НО это так навскидку. Счас заместто теста "cikl" вывел часики и кусок отображаемого кода с температурой.
Замечено что после установки времени к примеру и так как я сейчас невижу обновления экранчика блинком то нужно нажиать любую клавишу пульта чтобы обновить показания, иначе нажатие кнопки setup одновременно обновляет и записывает показания, которые на 1 ед. больше :)
Блин и размер - огромный матье го етить выходит. У меня всего на НАНО осталось 5-6кб (неоптимизированных) коненчое, но имеется ввиду то то сейчас работает, ка кбы непришлось отказываться от чего то в виде лишнего таймера или термо-реле :(
Счас поколдую ваш вариант KEY 2(вариант)
ПО первому варианту пробовал - неработает. ПО второму начинаются проблеммы с обновлениями экранов, НО это так навскидку. Счас заместто теста "cikl" вывел часики и кусок отображаемого кода с температурой.
Замечено что после установки времени к примеру и так как я сейчас невижу обновления экранчика блинком то нужно нажиать любую клавишу пульта чтобы обновить показания, иначе нажатие кнопки setup одновременно обновляет и записывает показания, которые на 1 ед. больше :)
Блин и размер - огромный матье го етить выходит. У меня всего на НАНО осталось 5-6кб (неоптимизированных) коненчое, но имеется ввиду то то сейчас работает, ка кбы непришлось отказываться от чего то в виде лишнего таймера или термо-реле :(
Счас поколдую ваш вариант KEY 2(вариант)
Я думаю это ваш дисплей кушает с душой. Да и потом повторяющиеся куски можно будет в функции завернуть. Кстати скиньте, что сейчас получилось, когда обновления экрана нет.
Чёрт побери - да вы гений. Убрал отовсюду работу с кнопками. Кнопки поменял на ваш вариант 2 (первый я делал - безрезультатно то синтаксис то неработают). Вынес в отдельную функцию ваш старый loop(), стало так ну неззаю мне чт ото работать с каждой по отдеьности приятнее чтоли:
Остались небольшие грабельки, после сохранения настроек на дисплейчик выводится вся инфа которая периодическ и прорисовывается. Если убрать коммент с очистки экрана в keyM9 то само собой экран начинает переисовыватсья после запуска скетча. И если войти в setup и потом нажать ОДЯИН раз up\down то меню САМО листается от 1 до 5 смотря куда жмакнуть :(
А вот так выглядит сейчас мой цикл():
где Епромчтение -это от старого, нынедействующего таймера и сам таймер. Счас покажу чего вышло когда есть часики и таймер :)
ПО дисплейчикам, разница в скетчах около 7 кб. НАНО имеет всего 30кб - счас у меня свободно как раз 6-7,
По уму, перед выходом из меню , самое правильное давать команду lcd.clear. Эта информация уже не нужна. А следующий блок уже должен выводить свою информацию.
Вот, тут косок с часиками простыми на ds1307, таймер и нагрузка в виде леидков. Весь код:
Почти 22 кб собака в таком виде, Значит сечас разберусь с обновлениями экрана, также нужно флажок типа (нужен\ненужен таймер) придумать и время автоматического выхода из меню, основной то цикл неработает и ничего невыполняется, даже кнопки :) хороший урок для меня.
Я понял почему постоянно обновляется экранчик подсказал принт
byte key(){
if (irrecv.decode(&results))
{irrecv.resume();}
Serial.println(results.value,HEX);
несмотря на то, что нажата однажды кнопка setup ОН её возвращает ПОТСОЯННО пока нежмакнеш что иное, вот...
Я понял почему постоянно обновляется экранчик подсказал принт
byte key(){
if (irrecv.decode(&results))
{irrecv.resume();}
Serial.println(results.value,HEX);
несмотря на то, что нажата однажды кнопка setup ОН её возвращает ПОТСОЯННО пока нежмакнеш что иное, вот...
Т.Е фактически получается как кнопка с фиксацией. Хоть палец убран, она все равно нажата?
Тяк, начну критиковать сверху вниз.
1. стр.30-31 Можем сделать вход в меню по Setup, а запись значений и выход по Enter. Тогда исчезает проблема нажатой клавиши и автовозврат.
2. стр71-87 Бессмысленно кушают ресурсы. Эти значения уже существуют в конкретных ячейках EPROM, а самое главное до перезагрузки они будут старыми, как ни меняй их в меню. Правильнее a=EEPROM.read(x)*60. x можно указывать как прямо, так и косвенно по типу ка win в меню.
3. стр221-238 - пункт.2
4. стр.308 Если убираете ее, то тогда и предыдущую, все равно ничего не увидите.
5. стр.344 и 357. Если делаем как п.1, то эту логику можно всю выбросить.
6. Флажок нужности таймера по идее лишний, если время вкл.=время откл. таймер не нужен. Это условие и проверяйте.
7. Возврату в loop я боюсь вам препятствует 344 строка. Вы за 0,2 секунды просто не успеваете среагировать. У меня выход был четкий. Или читаем п.1.
Вроде все сказал.
Т.Е фактически получается как кнопка с фиксацией. Хоть палец убран, она все равно нажата?
Мдя... чуток отходил от кода... понедельник всёже :). Все верное таке ощёщение что кнопка с фиксацией несмотря на IR... счас зашел в menu - дале в set Timer-1 (он же set menu1) по вашему старому и чт овы думаете блинк я невижу, однако курсок сразу ушёл на минуты выкл (они-жеЕПРОМ(4)) и елси я нажимаю(up или sown то значения сами меняются в ту или иную сторону).
Теперь перечитываю вашу критику к коду.....
Тяк, начну критиковать сверху вниз.
1. стр.30-31 Можем сделать вход в меню по Setup, а запись значений и выход по Enter. Тогда исчезает проблема нажатой клавиши и автовозврат.
Можно, кнопок в пульте сами знаете, это не физические манстырить, тут определил и готово. Хотя вариант с 5-ю кнопками тоже ничего такой, очень классный вышел. Просто я когда на if-ах писать пробовал то имеено о 6-т кнопках и думал влево\вправо|вверх\вниз|вход в меню|принятие значения и выход - так и думал.
2. стр71-87 Бессмысленно кушают ресурсы. Эти значения уже существуют в конкретных ячейках EPROM, а самое главное до перезагрузки они будут старыми, как ни меняй их в меню. Правильнее a=EEPROM.read(x)*60. x можно указывать как прямо, так и косвенно по типу ка win в меню.
Это я видимо по аналогии из какого то кода и его работы с ЕПРОМ брал. Счас понимаю что слишком длинно получилось и занимается каждый байт, И да формула полных минут не просто *60 а ещё и прибавляем сами МИНУТЫ тоесть chas*60+min
3. стр221-238 - пункт.2
4. стр.308 Если убираете ее, то тогда и предыдущую, все равно ничего не увидите.
5. стр.344 и 357. Если делаем как п.1, то эту логику можно всю выбросить.
Попробую сам описать, неполучится спрошу, ок? НО после того как сейчашнее меню будет нормуль отрабатывать и нажатия и обновления экранчика. :)
6. Флажок нужности таймера по идее лишний, если время вкл.=время откл. таймер не нужен. Это условие и проверяйте.
Я так понял проверки именно в функции таймера будет? Там и проверять.
7. Возврату в loop я боюсь вам препятствует 344 строка. Вы за 0,2 секунды просто не успеваете среагировать. У меня выход был четкий. Или читаем п.1.
Вроде все сказал.
[/quote]
Вот вроде все и понял, как теперь побороть "Удержание" кнопки, которая и неудерживается.
Посмотрел по вашему коду, такая конструкция работает без resume - в чем назначение этой команды?
P.S.погорячился, оно у вас в 302 строке.
А давайте из чистой злобы, так попробуем
Похоже я избавился от "зажатой" кнопки так:
Однако теперь перестали работать имеено рабоать (в serial они возвращаются) но ни поменять время ни позицию нельзя.
А давайте из чистой злобы, так попробуем
сначчаал вам написал свой вариант потмо попробовал ваш, синтакси ругается
389: error: 'else' without a previous 'if'
Похоже я избавился от "зажатой" кнопки так:
Однако теперь перестали работать именно работать (в serial они возвращаются) но ни поменять время ни позицию нельзя.
Срабатывания на нажатия ОЧЕНЬ чёткие, даже сначала и неповерил - ранее какая то замыленность, то среагирует то нет, а тут чётко, обновляется корректно всё и вход и выход и сохранение... ПОПРАВИТЬ параметры нельзя - ну несмех ли..
Посмотрел по вашему коду, такая конструкция работает без resume - в чем назначение этой команды?
P.S.погорячился, оно у вас в 302 строке.
Да это код ШИКАРНО обрабатывает именно"удержание" кнопки, очень классно и точно обрабатывет на диммировании, вот бы его и прикрутить в устновку времени - чтобы нежмакать минуты каждый раз, а нажал и держиш...
А если так?
По val я возможно погорячился, посмотрите что она в HEX возвращает.
Посмотрел по вашему коду, такая конструкция работает без resume - в чем назначение этой команды?
P.S.погорячился, оно у вас в 302 строке.
Да это код ШИКАРНО обрабатывает именно"удержание" кнопки, очень классно и точно обрабатывет на диммировании, вот бы его и прикрутить в устновку времени - чтобы нежмакать минуты каждый раз, а нажал и держиш...
По нормальному, на мех.кнопках это и происходит с интервалом в 0,3 секунды.
Почти ка ки в моем варианте, все корректно обрабатывается пока ненужно параметры поменять времени (минут и часов).
Однако в моем варианет если нет нажатия то нет и возврата в вашем случае если нет нажатия возвращается "0" если еть то HEX адрес кнопки с межеванием "0" (я так понял это и есть return 0)
Жаль но мой предлженный ни ваш неизменят параметра. внутри setmenu-1
По нормальному, на мех.кнопках это и происходит с интервалом в 0,3 секунды.
Понимаю, только я пульт выбрал непотому чт олень кнопи манстырить было а по другим причинам. ВО первых мобильность некая, далее кнопки у кадого СВОИ кто то так ктото эдак ктото вообще потнциометромих пользует (переменными резиорами, где поворот часов/24 а минут на /60). А пульт у каждого, взяли наш с вами код, подставили СВОИ HEX-кнопки и всё. Ну и само собой у меня контроллер это маааленькая чать в светильнике акариума и довольно высоко вот лазать туда жмакать хоть и нечасто но надо. Да и вообще IR - же намного интереснее, выже сами видите уже :)
у категорически непонмаю ничего КАК могут возвращаться НАЖАТЫЕ кнопки и НИЧЕГО неделать? Есч ораз промониторил serial.Print всё нажимается, а изменения нет.
Так я и не могу понять почему не так. Сейчас выходит: если клавиша нажата, key() возвращает что то от 1 до 5. Если отпустили, идет 0. То есть полностью соответствует мех.клавишам. При этом первый экран меню работает корректно или нет?
Так как насчет первого экрана, где выбираем таймер?