Выход из меню без перезагрузки
- Войдите на сайт для отправки комментариев
Вс, 28/02/2016 - 18:28
#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7 );
int Ledlcd = 10; //Номер Pin к которому подключена подсветка LCD
int brightnessLCD =0; //Переменная в которой хранится уровень яркости LCD (От 0 до 254)
int ekran = 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 < 550) return 2; // кнопка вперед
else if (val < 800) return 1; // кнопка входа в меню
else return 0;
}
////////// - цикл 1 - /////////////
void Submenu1(){
lcd.clear();
char menuTxt[][20] = {"SET SUNRISE >>", "SET SUNSET >>", "SET POWER >>"};
byte pos = 0;
while(key() != 1){ //Выход из меню
byte KEY = key();
delay(200);
lcd.setCursor(0, 0);
lcd.print(pos+1);
lcd.print(".");
lcd.print(menuTxt[pos]);
if (KEY == 3 && pos != 0) pos--;
else if (KEY == 4 && pos < 2) pos++;
if (KEY == 5 && pos == 0) ;
else if (KEY == 5 && pos == 1) ;
else if (KEY == 5 && pos == 2) ;
}
lcd.clear();
lcd.print(" -EXIT- ");
delay(1000);
}
///////////- цикл 2 -/////////////
void Submenu2(){
lcd.clear();
char menuTxt[][20] = {"SET SUNRISE >>", "SET SUNSET >>", "SET POWER >>"};
byte pos = 0;
while(key() != 1){ //Выход из меню
byte KEY = key();
delay(200);
lcd.setCursor(0, 0);
lcd.print(pos+1);
lcd.print(".");
lcd.print(menuTxt[pos]);
if (KEY == 3 && pos != 0) pos--;
else if (KEY == 4 && pos < 2) pos++;
if (KEY == 5 && pos == 0) ;
else if (KEY == 5 && pos == 1) ;
else if (KEY == 5 && pos == 2) ;
}
lcd.clear();
lcd.print(" -EXIT- ");
delay(1000);
}
void menu(){
lcd.clear();
char menuTxt[][20] = {"Menu-1 >>", "Menu-2 >>"};
byte pos = 0;
while(1){ // вход в меню
delay(200);
byte KEY = key();
lcd.setCursor(0, 0);
lcd.print(pos+1);
lcd.print(".");
lcd.print(menuTxt[pos]);
if (KEY == 3 && pos != 0) pos--;
else if (KEY == 4 && pos < 1) pos++;
if (KEY == 5 && pos == 0) Submenu1();
else if (KEY == 5 && pos == 1) Submenu2();
}
lcd.clear();
lcd.print(" -EXIT- ");
delay(1000);
}
void setup(){
lcd.begin(16, 2);
pinMode(Ledlcd, OUTPUT);
}
void loop()
{
//// - обработка кнопок Экранов - ////
if (key() == 1) menu(); // если не нажат селект
else if (key() == 5) {
ekran++;
delay(200);
if (ekran>2)
{
ekran=0;
}
}
else if (key() == 2) {
ekran--;
delay(200);
if (ekran<0)
{
ekran=2;
}
}
if (ekran == 0){ ////- 1-й ЭКРАН: Печатаем часы и дату -//////
//lcd.clear();
lcd.setCursor(2, 0); // выводим инфу
lcd.print("PROBA MENU 1");
}
if (ekran == 1){ ////- 1-й ЭКРАН: Печатаем часы и дату -//////
//lcd.clear();
lcd.setCursor(2, 0); // выводим инфу
lcd.print("PROBA MENU 2");
}
if (ekran == 2){ ////- 1-й ЭКРАН: Печатаем часы и дату -//////
//lcd.clear();
lcd.setCursor(2, 0); // выводим инфу
lcd.print("PROBA MENU 3");
}
if (key() == 1) menu(); // если не нажата селект
else if (key() == 3) {
brightnessLCD += 5;
}
else if (key() == 4) {
brightnessLCD -= 5;
}
brightnessLCD = constrain(brightnessLCD, 80, 254);
analogWrite(Ledlcd, brightnessLCD); // Устанавливаем состояние яркости для светодиода
delay(10); // Пауза 10 миллисекунд.
}
Вот собственно проблема. Есть шилд 16Х2 с кнопками, есть ардуино уно. При нажатии на селект попадаем в главное меню, и затем в подмен., если так же нажать на селект. Выход из меню так же осуществляется через селек. Но из главного меню без перезагрузки не обойдешься. Вопрос как исправить приведенный выше скетч для того чтоб можно было выйти из главного меню без перезагрузки! Спасибо.
скопировать строку 55 в строку 81
Спасибо, но при таком раскладе, при нажатии на кнопку селект пишет выход из гланого экрана, причем зайти в меню первого уровня невозможно.
Потому что вход в меню и выход из него по одной кнопке... Пока кнопка нажата, программа успевает несколько раз войти в меню и выйти из него. Надо что бы функция key() возвращала результат по отпусканию кнопки, а не по нажатию. Например так:
byte key(){ //// для кнопок ЛСД шилда //// int val = analogRead(0); byte bt; if (val < 50) bt = 5; // кнопка назад else if (val < 150) bt = 3; // кнопка вверх else if (val < 350) bt = 4; // Кнопка вниз else if (val < 550) bt = 2; // кнопка вперед else if (val < 800) bt = 1; // кнопка входа в меню else return 0; while (analogRead(0) < 800); // ждать пока кнопка не отпустится return bt; }Спасибо добрый человек! Всавил ваш кусочек для кнопок, изменил 81-ю строку на "while(key() != 1){"
но выходит в главные экраны тоько если следуйщую строку "delay(200);" закомментировать, но при этом остальные переходы не пашут. Пожалуйста, помогите еще чуть чуть!
Похоже проблема в этом:
while(key() != 1){ //Выход из меню byte KEY = key();Попробуй так, в строках 27-28, 55-56, 81-83:
byte KEY; while((KEY=key()) != 1){ //Выход из менюdelay() не нужны.
Примногоблагодарен Andy. Реально помог. Вся структура вложенных меню работает замечательно! Осталось решить проблему с экранами (128-143) и ручной регулировкой яркости (147-157) дисплея. Хотя это две одинаковые проблемы.
void loop() { lcd.setCursor(3, 0); lcd.print("PROBA MENU"); //byte KEY; //while((KEY=key()) != 1){ if (key() == 1) menu(); else if (key() == 3) { brightnessLCD += 5; } else if (key() == 4) { brightnessLCD -= 5; } brightnessLCD = constrain(brightnessLCD, 20, 254); analogWrite(Ledlcd, brightnessLCD); //delay(10); // Пауза 10 миллисекунд. }Прообовал разные варианты, то меню вновь не пашет, то яркость не меняется. Вобщем мозгов моих не хватило. Andy если не обременительно помоги еще немного!
Попробуй так:
void loop() { byte KEY=key(); switch (KEY) { case 1: menu(); break; case 2: if (--ekran<0) ekran=2; break; case 3: brightnessLCD += 5; break; case 4: brightnessLCD -= 5; break; case 5: if (++ekran>2) ekran=0; break; default: break; } if (KEY==2 || KEY==5) { lcd.setCursor(2, 0); switch (ekran) { case 0: lcd.print("PROBA MENU 1"); break; case 1: lcd.print("PROBA MENU 2"); break; case 2: lcd.print("PROBA MENU 3"); break; } } if (KEY==3 || KEY==4) { brightnessLCD = constrain(brightnessLCD, 80, 254); analogWrite(Ledlcd, brightnessLCD); // Устанавливаем состояние яркости для светодиода } }Поставил часть этого кода! Почти работает. Проблема в следующем:
При сбросе черный экран, яркость на ноль кнопки регулировки яркости работают, но экран пустой. Как только начинаю листать экраны (они появляются с "PROBA MENU 2"). Т.Е со второго экрана, и затем циклично как и задумывалось. Заходит в меню тоже хороше, но выходит из главного меню "плоховато", всмысле виснет с надписью "-EXIT-" Дальше можно опять кнопками экранов щелкать, тогда он выходит в штатный режим. Как то так!
PS/ Убирал строки с 13 по 22 (экраны) вместо них одну надпись оставил, все работает как надо!
В setup() надо добавить несколько строк для установки яркости и вывода первой надписи:
lcd.print("PROBA MENU 1"); brightnessLCD = constrain(brightnessLCD, 80, 254); analogWrite(Ledlcd, brightnessLCD);А тут можно попробовать изменить строку 13 в моем коде:
Сейчас займусь! Подскажите еще, когда кнопки работают в таком редиме (на разъединение) коректную работу блинка можно наладить.
Ато магающий курсор видно только при зажатой кнопе.
В setup() забыл добавить установку позиции курсора lcd.setCursor(2, 0); перед выводом строки.
Блинк можно сделать так (добавить в loop() перед последней закрывающей скобкой):
if (millis()-time > 1000)//раз в секунду { time=millis(); lcd.blink(); }unsigned long time;//надо объявить где-то вне loop()
Все подставил, все работает. С блинком буду разбираться, пока не совсем понял. Спасибо Andy!
Вот кусок кода, который стоит до сетапа:
//*********************************************************************************// //***************** Цикл установки мощности MIN & MAX вентилятора *****************// //*********************************************************************************// void setPower_Fan(){ byte pos = 5; lcd.clear(); lcd.blink(); byte KEY; // читаем состояние кнопок while((KEY=key()) != 1){ // крутим цикл lcd.setCursor(0, 1); lcd.print(" *Set to save!* "); lcd.setCursor(0, 0); // выводим инфу lcd.print("MAX="); if (FANPWM_MAX < 10) lcd.print("0"); if (FANPWM_MAX < 100) lcd.print("0"); lcd.print(FANPWM_MAX); lcd.setCursor(9, 0); lcd.print("MIN="); if (FANPWM_MIN < 10) lcd.print("0"); if (FANPWM_MIN < 100) lcd.print("0"); lcd.print(FANPWM_MIN); lcd.setCursor(pos, 0); // устанавливаем курсор согласно позиции if (KEY == 5 && pos < 14) pos += 9; // крутим позицию else if (KEY == 2 && pos > 5) pos -= 9; else if (pos == 5 && KEY == 3) FANPWM_MAX++; // крутим значения else if (pos == 5 && KEY == 4) FANPWM_MAX--; else if (pos == 14 && KEY == 3) FANPWM_MIN++; else if (pos == 14 && KEY == 4) FANPWM_MIN--; if (FANPWM_MAX > 255) FANPWM_MAX = 0; // устанавливаем макс. значения переменной температуры else if (FANPWM_MIN > 255) FANPWM_MIN = 0; } // конец цикла lcd.noBlink(); lcd.clear(); EEPROM.write(46, FANPWM_MAX); // Зашиваем значение MAX в память EEPROM.write(47, FANPWM_MIN); // Зашиваем значение MIN в память lcd.print(" -SAVING- "); delay(1000); }Подставлял вместо моего блинка - ваш, нет эффекта. Водставлял ваш блинк в цикл программы, он появляется на главном экране- это хороше, но плохо то что он там мне не нужен :) Вот как бы ваш кусочек прикрутить к тому месту, где он нужен. Строка №8
Логично. Блинк нужен там, где нужен ввод с клавиш, стало быть ему место в функции key()
byte key() //// для кнопок ЛСД шилда //// { int val = analogRead(0); byte bt; if (millis()-time > 1000)//раз в секунду { time=millis(); lcd.blink(); } if (val < 50) bt = 5; // кнопка назад else if (val < 150) bt = 3; // кнопка вверх else if (val < 350) bt = 4; // Кнопка вниз else if (val < 550) bt = 2; // кнопка вперед else if (val < 800) bt = 1; // кнопка входа в меню else return 0; while (analogRead(0) < 800); // ждать пока кнопка не отпустится return bt; }Собственно проблема состоит не в том что blink(); отсутствует, а в том что он появляется (мигает) только при зажатой кнопке. Например в подменю где происходит настройка параметров его не видно, пока не нажмешь кнопку, нажал и держишь ее, блинк есть и он мигает, отпустил кнопку- нет блинка! Я так понимаю это из за реверса нажатия
Вот собственно суть проблемы, а так то он был.
Выходит, пока кнопка нажата программа не бегает по циклу, ждет отпускания кнопки, в это время курсор моргает. При отпускании кнопки программа в цикле выводит символы на дисплей и меняет позицию курсора, курсор попросту не успевает моргать.
Вывод на дисплей надо делать однократно, а не в цикле, как-то так:
//*********************************************************************************// //***************** Цикл установки мощности MIN & MAX вентилятора *****************// //*********************************************************************************// void setPower_Fan(){ byte pos = 5; lcd.clear(); lcd.blink(); byte KEY; while(1) // крутим цикл { lcd.setCursor(0, 1); lcd.print(" *Set to save!* "); lcd.setCursor(0, 0); // выводим инфу lcd.print("MAX="); if (FANPWM_MAX < 10) lcd.print("0"); if (FANPWM_MAX < 100) lcd.print("0"); lcd.print(FANPWM_MAX); lcd.setCursor(9, 0); lcd.print("MIN="); if (FANPWM_MIN < 10) lcd.print("0"); if (FANPWM_MIN < 100) lcd.print("0"); lcd.print(FANPWM_MIN); lcd.setCursor(pos, 0); // устанавливаем курсор согласно позиции while ((KEY=key()) == 0);//жду нажатия кнопки if (KEY == 1) break; if (KEY == 5 && pos < 14) pos += 9; // крутим позицию else if (KEY == 2 && pos > 5) pos -= 9; else if (pos == 5 && KEY == 3) FANPWM_MAX++; // крутим значения else if (pos == 5 && KEY == 4) FANPWM_MAX--; else if (pos == 14 && KEY == 3) FANPWM_MIN++; else if (pos == 14 && KEY == 4) FANPWM_MIN--; if (FANPWM_MAX > 255) FANPWM_MAX = 0; // устанавливаем макс. значения переменной температуры else if (FANPWM_MIN > 255) FANPWM_MIN = 0; } // конец цикла lcd.noBlink(); lcd.clear(); EEPROM.write(46, FANPWM_MAX); // Зашиваем значение MAX в память EEPROM.write(47, FANPWM_MIN); // Зашиваем значение MIN в память lcd.print(" -SAVING- "); delay(1000); }Подпишусь. Планирую делать похожее меню для своего TFT дисплея.
Докладываю. Заготовка меню полностью функциональна. Работают кнопки, блинк, выход осуществлен без перезагрузки контроллера! Что я бы без помощи уважаемого Andy скорее всего не сделал бы. Надо учиться! Еще раз скажу - спасибо добрый человек! Может тема кому будет полезна, например для различных термостатов и т.д.
Очень интересно увидеть ваш код, делаю меню для термо-гигрометра сауны.
Код нужно под себя будет заточить!
#include <EEPROM.h> #include <LiquidCrystal.h> LiquidCrystal lcd(8, 9, 4, 5, 6, 7 ); #define FANPWM_PIN 11 //Пин порта, где будет ШИМ Охлаждения int Ledlcd = 10; //Номер Pin к которому подключена подсветка LCD int brightnessLCD =0; //Переменная в которой хранится уровень яркости LCD (От 0 до 254) int ekran=0; unsigned long time; float tempe = 0; byte settempOn; byte settempOff; byte FANPWM_MAX; byte FANPWM_MIN; byte key(){ int val = analogRead(0); byte bt; if (val < 50) bt = 5; // кнопка назад else if (val < 150) bt = 3; // кнопка вверх else if (val < 350) bt = 4; // Кнопка вниз else if (val < 550) bt = 2; // кнопка вперед else if (val < 800) bt = 1; // кнопка входа в меню else return 0; while (analogRead(0) < 800); // ждать пока кнопка не отпустится return bt; } ////////// - цикл 1 - ///////////// void Submenu1(){ lcd.clear(); char menuTxt[][20] = {"SET SUNRISE >>", "SET SUNSET >>", "SET POWER >>"}; byte pos = 0; byte KEY; while((KEY=key()) != 1){ lcd.setCursor(0, 0); lcd.print(pos+1); lcd.print("."); lcd.print(menuTxt[pos]); if (KEY == 3 && pos != 0) pos--; else if (KEY == 4 && pos < 2) pos++; if (KEY == 5 && pos == 0) ; else if (KEY == 5 && pos == 1) ; else if (KEY == 5 && pos == 2) ; } lcd.clear(); lcd.print(" -EXIT- "); delay(500); } //**********************************************************************************// //********************цикл установки границ температурного коридора*****************// //**********************************************************************************// void SetFanOnOff(){ byte pos = 4; lcd.clear(); lcd.blink(); byte KEY; // читаем состояние кнопок while(1) // крутим цикл { lcd.setCursor(0, 1); lcd.print(" *Set to save!* "); lcd.setCursor(1, 0); // выводим инфу lcd.print("L="); if (settempOn < 10) lcd.print("0"); lcd.print(settempOn); lcd.print("*C"); lcd.setCursor(9, 0); lcd.print("H="); if (settempOff < 10) lcd.print("0"); lcd.print(settempOff); lcd.print("*C"); lcd.setCursor(pos, 0); // устанавливаем курсор согласно позиции while ((KEY=key()) == 0); //жду нажатия кнопки if (KEY == 1) break; if (KEY == 5 && pos < 12) pos += 8; // крутим позицию else if (KEY == 2 && pos > 4) pos -= 8; else if (pos == 4 && KEY == 3) settempOn++; // крутим значения else if (pos == 4 && KEY == 4) settempOn--; else if (pos == 12 && KEY == 3) settempOff++; else if (pos == 12 && KEY == 4) settempOff--; if (settempOn > 40) settempOn = 0; // устанавливаем макс. значения переменной температуры else if (settempOff > 40) settempOff = 0; } // конец цикла lcd.noBlink(); lcd.clear(); EEPROM.write(44, settempOn); // Зашиваем значение On в память EEPROM.write(45, settempOff); // Зашиваем значение Off в память lcd.print(" -SAVING- "); delay(1000); } //*********************************************************************************// //***************** Цикл установки мощности MIN & MAX вентилятора *****************// //*********************************************************************************// void setPower_Fan(){ byte pos = 5; lcd.clear(); lcd.blink(); byte KEY; while(1) // крутим цикл { lcd.setCursor(0, 1); lcd.print(" *Set to save!* "); lcd.setCursor(0, 0); // выводим инфу lcd.print("MAX="); if (FANPWM_MAX < 10) lcd.print("0"); if (FANPWM_MAX < 100) lcd.print("0"); lcd.print(FANPWM_MAX); lcd.setCursor(9, 0); lcd.print("MIN="); if (FANPWM_MIN < 10) lcd.print("0"); if (FANPWM_MIN < 100) lcd.print("0"); lcd.print(FANPWM_MIN); lcd.setCursor(pos, 0); // устанавливаем курсор согласно позиции while ((KEY=key()) == 0);//жду нажатия кнопки if (KEY == 1) break; if (KEY == 5 && pos < 14) pos += 9; // крутим позицию else if (KEY == 2 && pos > 5) pos -= 9; else if (pos == 5 && KEY == 3) FANPWM_MAX++; // крутим значения else if (pos == 5 && KEY == 4) FANPWM_MAX--; else if (pos == 14 && KEY == 3) FANPWM_MIN++; else if (pos == 14 && KEY == 4) FANPWM_MIN--; if (FANPWM_MAX > 255) FANPWM_MAX = 0; // устанавливаем макс. значения переменной температуры else if (FANPWM_MIN > 255) FANPWM_MIN = 0; } // конец цикла lcd.noBlink(); lcd.clear(); EEPROM.write(46, FANPWM_MAX); // Зашиваем значение MAX в память EEPROM.write(47, FANPWM_MIN); // Зашиваем значение MIN в память lcd.print(" -SAVING- "); delay(1000); } ///////////- Главное меню -///////////// void menu(){ lcd.clear(); char menuTxt[][20] = {"Menu-1 >>", "Menu-2 >>"}; byte pos = 0; byte KEY; while((KEY=key()) != 1){ lcd.setCursor(0, 0); lcd.print(pos+1); lcd.print("."); lcd.print(menuTxt[pos]); if (KEY == 3 && pos != 0) pos--; else if (KEY == 4 && pos < 1) pos++; if (KEY == 5 && pos == 0) Submenu1(); else if (KEY == 5 && pos == 1) SubmenuFan(); } lcd.clear(); lcd.print(" -EXIT- "); delay(500); } void SubmenuFan(){ // Охлаждение // lcd.clear(); char menuTxt[][20] = {"SET TEMPER. >>", "SET POWER >>"}; byte pos = 0; byte KEY; // читаем состояние кнопок while((KEY=key()) != 1){ // крутим цикл lcd.setCursor(0, 0); lcd.print(pos+1); lcd.print("."); lcd.print(menuTxt[pos]); if (KEY == 3 && pos != 0) pos--; else if (KEY == 4 && pos < 1) pos++; if (KEY == 5 && pos == 0) SetFanOnOff(); else if (KEY == 5 && pos == 1) setPower_Fan(); } lcd.clear(); lcd.print(" -EXIT- "); delay(1000); } void setup(){ lcd.begin(16, 2); lcd.setCursor(2, 0); lcd.print("PROBA MENU 1"); pinMode(Ledlcd, OUTPUT); brightnessLCD = EEPROM.read(2); // Подсветка LCD // analogWrite(Ledlcd, brightnessLCD); analogWrite(FANPWM_PIN, FANPWM_MIN); //Пишем в порт минимальное значение settempOn = EEPROM.read(44); // Охлаждение // settempOff = EEPROM.read(45); FANPWM_MAX = EEPROM.read(46); FANPWM_MIN = EEPROM.read(47); } void loop() { byte KEY=key(); switch (KEY) { case 1: menu(); break; case 2: if (--ekran<0) ekran=2; break; case 3: brightnessLCD += 5; break; case 4: brightnessLCD -= 5; break; case 5: if (++ekran>2) ekran=0; break; default: break; } if (KEY==2 || KEY==5 || KEY==1) { lcd.setCursor(2, 0); switch (ekran) { case 0: lcd.print("PROBA MENU 1"); break; case 1: lcd.print("PROBA MENU 2"); break; case 2: lcd.print("PROBA MENU 3"); break; } } if (KEY==3 || KEY==4) { brightnessLCD = constrain(brightnessLCD, 0, 254); analogWrite(Ledlcd, brightnessLCD); // Устанавливаем состояние яркости для светодиода EEPROM.write(2, brightnessLCD); } }Код нужно под себя будет заточить!
Тезка, прочитай как код убирать в спойлер. Там ничего сложного....
Код нужно под себя будет заточить!
Тезка, прочитай как код убирать в спойлер. Там ничего сложного....
Спасибо за код!
Опишите в краце структуру меню (схему переходов по меню).
У меня два шилда с кнопками, у одного кнопки очень плохие (дребезг контактов)- работает очень плохо. Второй работает нормально. У вас в коде нет подавления антдребезга?
http://arduino.ru/forum/proekty/antidrebezg-dlya-shilda-lcd-knopki Тут я попытался решить проблему для нашего шилда по дребезгу контактов.
Когда выбираем в меню изменение значения параметра, нет режима при удержании кнопки - автоматическое изменение параметра, очень удобная штука.
Еще можно русифицировать наш шилд (заглавными буквами по русски), если нужно могу скинуть код.
Уважаемый Andy подправил код таким образом, чтоб кнопки реагировали на отпускание кнопки, насколько я понимаю в этом случае защита от дребезга не обязательна. Режима удержания кнопки действительно нет, может общими усилиями сможем добавить? За русифицированный код буду признателен, там библиотека нужна специальная, или кодом все правиться?
Структура меню простая: По нажатию селект попадаем в основное меню, выбираем настройку параметров какой то группы, попадаем в настройку индивидуальных параметров в группе. Например В основном меню настройка света и температуры, в подменю света настройки времени включения/выключения, яркости и цветовой температуры. В подменю температуры настраиваем срабатывание реле по определенным параметрам датчика температуры (температурный коридор). Вентиляци. И Т.Д. Ну и все ради чего это заморачивалось выход из меню без перезагрузки ардуинки!
Спасибо добрый человек! Всавил ваш кусочек для кнопок, изменил 81-ю строку на "while(key() != 1){"
но выходит в главные экраны тоько если следуйщую строку "delay(200);" закомментировать, но при этом остальные переходы не пашут. Пожалуйста, помогите еще чуть чуть!
Разбирайся....
// подключение библиотек #include <TM1637.h>// индикатор 4 секции 7сегментов #include <OneWire.h>// считка ТМ ключей #include <EEPROM.h>// работа с паматью #include <pitches.h>// библа на звуки // назначение пинов #define TMread 2//TM key pin #define LEDclk 3//LED 1637 pin CLK #define LEDdio 4//LED 1637 pin DIO #define SoundPin 9//Звук в динамик #define pinKBx1 6 // 1 столбец кнопок #define pinKBx2 7 // 2 столбец кнопок #define pinKBx3 8 // 3 столбец кнопок #define pinKBy1 14 // 1 строка кнопок #define pinKBy2 15 // 2 строка кнопок #define pinKBy3 16 // 3 строка кнопок #define pinKBy4 17 // 4 строка кнопок // x1 x2 x3 //y1 1 2 3 //y2 4 5 6 //y3 7 8 9 //y4 A B C const int melody[] = { NOTE_C4, NOTE_G3, NOTE_G3, NOTE_A3, NOTE_G3, 0, NOTE_B3, NOTE_C4 }; // note durations: 4 = quarter note, 8 = eighth note, etc.: const int noteDurations[] = { 4, 8, 8, 4, 4, 4, 4, 4 }; const long int TimeXX=60000;//делитель миллисекунд int TimeCH=15; //минуты для ЧЕМОДАНА byte Seg_ON=0; //двоеточие на индикаторе byte TMbuffer[8];// буфер приема byte TMlistKEY[20][8];// 5 ключей админских и 15 игровых ключей byte PrevCMD=0;// Предыдущая команда byte NextCMD=0;// следующая команда byte ChCMD=0;// буфер считывания команды byte SetMode=0;// режим - 0 не установлен, 1 кнопки, 2 ключи byte SetTimerMode=1;// режим - 0 таймер выключен, 1 таймер включен unsigned long buffMillis=0;// буфер для расчетов unsigned long PrevMillis=0;// предыдущее время в миилсах unsigned long NextMillis=0;// следующее время в миилсах unsigned long CMDmillis[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};// следующее время в миилсах byte buffTM[8];// буфер приема ТМ-ключей byte ChemodanKey[4]={0,0,0,0}; TM1637 tm1637(LEDclk,LEDdio); OneWire ds(TMread); // выход считывателя на пин TMread void setup() // стартовая инициализация { //Serial.begin(9600); //для отладки //Serial.println("Start..."); //для отладки SoundSET(); SirenaOUT(); /* Инициализация структур */ pinMode(pinKBx1, INPUT); // назначить порт ввода X1 digitalWrite(pinKBx1, HIGH); // включить подтягивающий резистор pinMode(pinKBx2, INPUT); // назначить порт ввода X2 digitalWrite(pinKBx2, HIGH); // включить подтягивающий резистор pinMode(pinKBx3, INPUT); // назначить порт ввода X3 digitalWrite(pinKBx3, HIGH); // включить подтягивающий резистор pinMode(pinKBy1, OUTPUT); // назначить порт вывода Y1 pinMode(pinKBy2, OUTPUT); // назначить порт вывода Y2 pinMode(pinKBy3, OUTPUT); // назначить порт вывода Y3 pinMode(pinKBy4, OUTPUT); // назначить порт вывода Y4 tm1637.init(); tm1637.set(5);//BRIGHT_TYPICAL = 2,BRIGHT_DARKEST = 0,BRIGHTEST = 7; tm1637.display(0,0); //в левом сегменте 0 остальные потушены // Читаем с хранилища ключи - 20 шт 5 админских 0-4 и 15 игровых 5-20 for(byte TM1 = 0; TM1 < 20; TM1++) { for(byte TM2 = 0; TM2 < 8; TM2++) { TMlistKEY[TM1][TM2]=EEPROM.read(TM1*8+TM2); } } } void loop() //Основной цикл { //StartMODE3();//********************************************************************************* PrevMillis=millis();//запоминаем первый миллс while(1){ byte buff=0; if (SetMode==3)//если режим ЧЕМОДАН { StartMODE3(); } if (SetMode>0&&NextCMD>0&&PrevCMD>0)//если режим установлен в 1 или 2. Если 0 - пропускаем { buffMillis=CMDmillis[NextCMD];//вносим в буфер NextMillis=millis();//читаем миллсы if(SetTimerMode) { CMDmillis[NextCMD]+=NextMillis-PrevMillis;//добавляем миллсы в счетчик команды } PrevMillis=NextMillis;//запоминаем время if (buffMillis/TimeXX!=CMDmillis[NextCMD]/TimeXX)//если число минут предыдущей записи отличается от минут текущих - выводим на экран { buffMillis=CMDmillis[NextCMD]/TimeXX; TimeDisplay(NextCMD,buffMillis); } } // чтение ТМ-ключа if(ds.reset()) // если обнаружено устройттво { ds.write(0x33); // отправляем команду "считать ROM" delay(10); // на всякий случай ждем for(int i=0;i<8;i++) { buffTM[i] = ds.read(); // считываем ключ } //проверяем ключ админа buff=ScanTM();//проверяем ключ в базе if(buff) { if(buff<6) {AdminMode();}//если админский ключ идем в режим администрирования if(buff>5)//если есть номер команды { if (!SetMode||ChCMD)//режим не установлен - режим ключей 2 { SetMode=2; PrevMillis=millis(); ChCMD=0; } if(SetMode==2)//если режим ключей 2 запоминаем номер ключа команды { NextCMD=buff-5; } } } } // Чтение кнопок delay(500); buff=KBDread();//проверяем нажатие кнопок if (buff)//если нажата любая кнопка { if (!SetMode||ChCMD)//режим не установлен - режим кнопок 1 { SetMode=1; PrevMillis=millis(); ChCMD=0; } if(SetMode==1)//если режим кнопок 1 запоминаем номер кнопки - команды { NextCMD=buff; } } if (NextCMD!=PrevCMD)//если команда изменилась { PrevCMD=NextCMD;//запоминаем номер новой команды buffMillis=CMDmillis[NextCMD]/TimeXX; TimeDisplay(NextCMD,buffMillis); } delay(200); } } byte KBDread()//опрос клавиатуры { byte KBread=0; byte KBx; byte KBy; for (KBx=0;KBx<3;KBx++)//цикл по столбцам { for (KBy=0;KBy<4;KBy++)//цикл по строкам { digitalWrite(pinKBy1+KBy, LOW);// 0 на столбец if (!digitalRead(pinKBx1+KBx))//читаем строку { KBread=KBy*3+KBx+1;//если 0 определяем кнопку } digitalWrite(pinKBy1+KBy, HIGH);//1 на столбец } } return KBread;//возвращаем 0 или номер кнопки 1-12 } void AdminMode(void) // 1 - чтение ключей из базы, 12 - выход // 2 - стоп таймера // 3 - старт таймера если он был включен // 4 - управление ключами команд, 5 - запись и сл номер, 10 - стирание, 12 - выход, 2с задержка на переключениеключа // 5 - запись ключа и сл номер // 6 - запись ключей админов, 5 - запись и сл номер, 10 - стиранние, 12 - выход, 2с задержка на переключениеключа // 7 - чтение времени команд, 12 - выход, 7 - следующая, 2с задержка на переключениеключа // 8 - ВКЛ/ВЫКЛ свет ????? // 9 - моргание света ????? // 10 (А) - режим КНОПКИ // 11 (В) - режим КЛЮЧИ // 12 (С) - режим ЧЕМОДАН/ВЫХОД { byte KeySave=0; byte numTM=0; byte buff=0; byte buffZ=0; byte buff1=0; byte Rkbd=0; tm1637.clearDisplay(); tm1637.display(0,10); //выводим на дисплей A do{ buff=KBDread(); if (buff){tm1637.display(1,buff);} delay(200); switch(buff){ case 1://чтение ключей по командам, кнопка 12 выход KeySave=1; buff1=1; do { if(ds.reset()) // если обнаружено устройттво { ds.write(0x33); // отправляем команду "считать ROM" delay(10); // на всякий случай ждем for(int i=0;i<8;i++) { buffTM[i] = ds.read(); // считываем ключ } } buffZ=ScanTM(); if(buffZ>5){tm1637.display(2,12);tm1637.display(3,buffZ-5);}//пользовательский ключ, выводим С* if(buffZ>0&&buffZ<6){tm1637.display(2,10);tm1637.display(3,buffZ);}//админский ключ, выводим А* if(!buffZ){tm1637.display(2,0);tm1637.display(3,0);}//админский ключ, выводим А* delay(1000); if(KBDread()==12){buff1=0;} }while(buff1); KeySave=0; break; case 2://стоп таймера SetTimerMode=0; break; case 3://старт таймера SetTimerMode=1; break; case 4://запись/стирание ключей команд, 5- запись, 10-стирание, 12 - выход KeySave=1; numTM=6; Rkbd=0; buffTM[0]=255; do{ buffZ=0; tm1637.display(2,0); tm1637.display(3,numTM-5); if(ds.reset())// если обнаружено устройттво { ds.write(0x33); // отправляем команду "считать ROM" delay(10); // на всякий случай ждем for(int i=0;i<8;i++) { buffTM[i] = ds.read(); // считываем ключ } }else { for(int i=0;i<8;i++) { buffTM[i] = 255; // стираем прошлый ключ в памяти } tm1637.display(2,0);tm1637.display(3,0); } buffZ=ScanTM(); if(buffZ>5){tm1637.display(2,12);tm1637.display(3,buffZ-5);}//пользовательский ключ, выводим С* if(buffZ>0&&buffZ<6){tm1637.display(2,10);tm1637.display(3,buffZ);}//админский ключ, выводим А* Rkbd=KBDread(); if(!buffZ)//если ключ не найден в базе { tm1637.clearDisplay(); tm1637.display(0,10); tm1637.display(1,4); tm1637.display(3,numTM-5); if(Rkbd==5)//если кнопка 5 записываем ключ { if(buffTM[0]!=255) { for(int i = 0; i < 8; i++) { EEPROM.write((numTM-1)*8+i,buffTM[i]); TMlistKEY[numTM-1][i]=buffTM[i]; } buffTM[0]=255; numTM++; }else { numTM++; } tm1637.display(2,5); tm1637.display(3,numTM-5);//пользовательский ключ, выводим S* } } if(Rkbd==10)//если нажата кнопка 10 { EEPROM.write((numTM-1)*8,255);//стираем ключ TMlistKEY[numTM-1][0]=255; tm1637.display(2,12); tm1637.display(3,numTM-5);//выводим подтверждение стирания ключа С* } delay(1000); if(Rkbd==12){numTM=99;}//если нажата кнопка 12 выход }while(numTM<21); KeySave=0; break; // 5 - подтверждение записи и сл номер, 10 - стиранпие записи 12 выход case 6://запись/стирание ключей админа, 5 - запись и сл номер, 10 - стирание 12 выход KeySave=1; numTM=1; Rkbd=0; do{ buffZ=0; tm1637.display(2,0); tm1637.display(3,numTM-1); if(ds.reset())// если обнаружено устройттво { ds.write(0x33); // отправляем команду "считать ROM" delay(10); // на всякий случай ждем for(int i=0;i<8;i++) { buffTM[i] = ds.read(); // считываем ключ } }else { for(int i=0;i<8;i++) { buffTM[i] = 255; //стираем прошлый ключ в памяти } tm1637.display(2,0);tm1637.display(3,0); } buffZ=ScanTM(); if(buffZ>5){tm1637.display(2,12);tm1637.display(3,buffZ-5);}//пользовательский ключ, выводим С* if(buffZ>0&&buffZ<6){tm1637.display(2,10);tm1637.display(3,buffZ);}//админский ключ, выводим А* Rkbd=KBDread(); if(!buffZ)//если ключ не найден в базе { tm1637.clearDisplay(); tm1637.display(0,10); tm1637.display(1,6); tm1637.display(3,numTM); if(Rkbd==5)//если кнопка 5 записываем ключ { if (buffTM[0]!=255) { for(int i = 0; i < 8; i++) { EEPROM.write((numTM-1)*8+i,buffTM[i]); TMlistKEY[numTM-1][i]=buffTM[i]; } buffTM[0]=255; numTM++; }else { numTM++; } tm1637.display(2,5); tm1637.display(3,numTM);//flvbycrbq ключ, выводим S* } } if(Rkbd==10&&numTM>1)//если нажата кнопка 10 и ключ более 1 { EEPROM.write((numTM-1)*8,255);//стираем ключ TMlistKEY[numTM-1][0]=255; tm1637.display(2,10); tm1637.display(3,numTM);//выводим подтверждение стирания ключа С* } delay(1000); if(Rkbd==12) { numTM=99; }//если нажата кнопка 12 выход }while(numTM<21); KeySave=0; break; case 7://чтение времени по командам 5 переключение команд 12 выход KeySave=1; numTM=1; Rkbd=0; buffMillis=CMDmillis[numTM]/TimeXX; TimeDisplay(numTM,buffMillis); while(numTM<16) { Rkbd=KBDread(); if(Rkbd==5)//если нажата кнопка 10 и ключ более 1 { numTM++; buffMillis=CMDmillis[numTM]/TimeXX; TimeDisplay(numTM,buffMillis); } delay(1000); if(Rkbd==12) { numTM=99; }//если нажата кнопка 12 выход } KeySave=0; break; case 8://свет ВКЛ/ВЫКЛ break; case 9://свет ВКЛ моргание break; case 10://режим КНОПКИ SetMode=1; ChCMD=1; tm1637.display(2,5); tm1637.display(3,1);//S1 режим кнопок break; case 11://режим КЛЮЧИ SetMode=2; tm1637.display(2,5); tm1637.display(3,2);//S2 режим ключей break; case 12://Режим ЧЕМОДАН SetMode=3; tm1637.display(2,11); tm1637.display(3,3);//S3 режим ЧЕМОДАН break; } delay(200); }while(ds.reset()||KeySave); delay(200); tm1637.clearDisplay(); tm1637.display(0,0); if(!NextCMD) { PrevMillis=millis();//запоминаем первый миллс } } void StartMODE3(void)// режим ЧЕМОДАН { //при старте выбираем время блокировки //на экране bd (block delay) в пятиминутках //выбор на кнопках от 1 до 12 по 5 минут == от 5 до 60 минут //затем инициализация датчика случайных чисел SE //генерируется 4 цифры кода, выводятся на экран на 2 сек //если нажата неправильная цифра - блокировка на время bd минут и сирена //если все цифры угаданы - звук и переход на новую игру //если найден ключ ТМ - сбрасываем все включая звук, найденные ключи //если с ключем ТМ наата любая кнопка - рестарт игры while(1) { byte EndGAME=0; byte i=1; byte j=0; byte buff=0; byte ChmNM=0;// цифра угадана byte numKey=0;// количество угаданных цифр byte ChemodanRead[4]={0,0,0,0};//буфер //инициализация параметров игры tm1637.clearDisplay();//на экран выводим bd tm1637.display(0,11); tm1637.display(1,13); buff=KBDread(); do//ждем нажатие на кнопку { buff=KBDread();//читаем кнопки TimeCH=buff*5;//устанавливаем тайм-аут для ошибки набора *5 мин tm1637.display(3,buff);// выводим число 5-минуток тайм-аута }while(!buff);//ждем нажатие на кнопку delay(4000); tm1637.clearDisplay();//на экран выводим 5Е tm1637.display(0,5); tm1637.display(1,14); while(!KBDread())//ждем нажатие на кнопку { randomSeed(millis());//инициализируем счетчик рандома delay(200); } ChemodanKey[0]=random(1,13);//из списка 1-12 первая цифра while(i<4)//набираем 4 цифры { buff=random(1,13);//из списка 1-12 следующая цифра ChmNM=1; for(j=0;j<i;j++) { if(ChemodanKey[j]==buff)//Если цифра повторяется { ChmNM=0;//сбрасываем счетчик - идем на повтор } } if (ChmNM)//если цифра новая - запоминаем, ищем следующую { ChemodanKey[i]=buff; i++; } } ChmNM=0; for (i=0;i<4;i++) { tm1637.display(i,ChemodanKey[i]);//выводим установленные цифры Serial.print(ChemodanKey[i],HEX); //для отладки } Serial.println(); //для отладки SirenaOUT;//мявкаем в динамик delay(2000); tm1637.clearDisplay();//стираем все tm1637.display(0,0);//на экран 0 numKey=0; while(!EndGAME)//пока EndGAME==0 крутим цикл { if(ds.reset()) // если обнаружен ключ сбрасываем все в 0 { for(i=0;i<=numKey;i++) { ChemodanRead[i]=0;//сбросили хранилище угаданных ключей } ChmNM=0;//изменили статус на 0 numKey=0;//число угаданных 0 tm1637.clearDisplay();//стираем все tm1637.display(0,0);//на экран 0 if (KBDread())//если нажата кнопка стартуем новую игру { EndGAME=1; } } buff=KBDread();//читаем клавиатуру if(buff)//если кнопка нажата { ChmNM=0; for(i=0;i<4;i++)// проверяем цифру { if(buff==ChemodanKey[i])//если цифра есть в коде { ChmNM=1;//изменили статус на 1 ChemodanRead[numKey]=ChemodanKey[i];//запомнили угаданную цифру SirenaOUT();//мявкнули в динамик tm1637.display(numKey,ChemodanRead[numKey]);//вывели на экран угаданную цифру } } if(!ChmNM)//если не угадали { for(i=0;i<=numKey;i++) { ChemodanRead[i]=0;//сбросили хранилище угаданных ключей } ChmNM=0;//изменили статус на 0 numKey=0;//число угаданных 0 tm1637.clearDisplay();//стираем все for(i=0;i<4;i++) { tm1637.display(i,0);//на экран 0 } Serial.println(" ERROR "); //для отладки PrevMillis=millis();//запоминаем первый миллс while(millis()-PrevMillis<TimeCH*TimeXX)//в течении ХХ минут ревем сиреной { SirenaOUT();//сирена delay(1000); Serial.println(" ERROR 1"); //для отладки if(ds.reset()) // если обнаружен ключ сбрасываем все в 0 { for(i=0;i<=numKey;i++) { ChemodanRead[i]=0;//сбросили хранилище угаданных ключей } PrevMillis=TimeCH*TimeXX+millis(); ChmNM=0;//изменили статус на 0 numKey=0;//число угаданных 0 tm1637.clearDisplay();//стираем все tm1637.display(0,0);//на экран 0 if (KBDread())//если нажата кнопка стартуем новую игру { EndGAME=1; } } } tm1637.clearDisplay();//стираем все tm1637.display(0,0);//на экран 0 }else { numKey++;//если угадали - следующий номер delay(1000); } } if(numKey>3)//если угадали все 4 - гимн { SirenaOUT(); SirenaOUT(); SirenaOUT(); EndGAME=1; } } } } void TimeDisplay (byte Ncmd, unsigned long buffTime)//Вывод на дисплей - 1 цифра номер команды, 2-4 - число минут текущей команды { tm1637.display(0,Ncmd); //выводим на дисплей 1 цифру - команда tm1637.display(1,buffTime/100);//выводим на дисплей 1 цифру - сотни минут tm1637.display(2,buffTime%100/10);//выводим на дисплей 1 цифру - десятки минут tm1637.display(3,buffTime%10);//выводим на дисплей 1 цифру - минуты if(buffTime>999) { Seg_ON=1; }else { Seg_ON=0; } tm1637.point(Seg_ON);//вкл двоеточие между сегментами если минут больше 999 } byte ScanTM(void)//проверка ключей ТМ на наличие в хранилище { byte buff2=0; byte buff1=1; for(int y=0;y<20;y++) { if(TMlistKEY[y][0]!=255)//Если 1й байт ключа FF - ячейка пустая, пропускаем { buff1=1; for(int i=0;i<8;i++) { if(buffTM[i]!=TMlistKEY[y][i]){buff1=0;} // сравниваем ключ с базой } if (buff1){buff2=y+1;} } } return buff2; //Возвращаем номер ключа или 0 если не найден } void SoundSET(void) { /********************************************************* //вывод звука for (int thisNote = 0; thisNote < 8; thisNote++) { // to calculate the note duration, take one second divided by the note type. //e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc. int noteDuration = 1000 / noteDurations[thisNote]; tone(SoundPin, melody[thisNote], noteDuration); // to distinguish the notes, set a minimum time between them. // the note's duration + 30% seems to work well: int pauseBetweenNotes = noteDuration * 1.30; delay(pauseBetweenNotes); // stop the tone playing: noTone(SoundPin); } *********************************************************/ } void SirenaOUT(void) { /********************************************************* //Сирена byte Dlit = 17; int Niz = 500; int Verh = 3000; byte Shag = 70; for (int j = Niz;j<= Verh;j+=Shag) { tone(SoundPin,j, Dlit); delay(Dlit); } for (int j = Verh;j>= Niz;j-=Shag) { tone(SoundPin,j, Dlit); delay(Dlit); } ***********************************************************/ }Меню реализовано в функции AdminMode
Подправил ваш код, добавил РУССКИЙ. Нашел код на просторах инета, суть такая, используются заглавные английские буквы и генерируются недостающие заглавные РУССКИЕ. Перед выводом на экран русского текста указываются недостающие символы, но не более 8 символов. Коряво конечно, но работает. Искал библиотеки русификаторы, ни одна на китайских LCD не работает. Не получилось все перевести, так как используется у вас в коде char menuTxt[][20], как в него впихнуть русские буквы, пока не разобрался.
И еще, почему то у вас 3 основных меню, у каждого 2 подменю, не совсем понял функции основных меню.
По поводу дребезга, дребезг у меня проскакивает и очень сильно на шилде с «плохими» кнопками вообще беда.
Давал ранее ссылку на свой код по антидребезгу, там таких проблем нет и там реализована прокрутка по удержанию кнопки. Если долго нажимать Селект (более 5 секунд) тоже идет срабатывание кнопки. Реализовывал для перехода в режим калибровки датчиков. Все возможности кнопок можно посмотреть на LCD.
#include <EEPROM.h> #include <LiquidCrystal.h> //lcd lib LiquidCrystal lcd(8, 9, 4, 5, 6, 7 ); #define FANPWM_PIN 11 //Пин порта, где будет ШИМ Охлаждения int Ledlcd = 10; //Номер Pin к которому подключена подсветка LCD int brightnessLCD =0; //Переменная в которой хранится уровень яркости LCD (От 0 до 254) int ekran=0; unsigned long time; float tempe = 0; byte settempOn; byte settempOff; byte FANPWM_MAX; byte FANPWM_MIN; byte key(){ int val = analogRead(0); byte bt; if (val < 50) bt = 5; // кнопка назад else if (val < 150) bt = 3; // кнопка вверх else if (val < 350) bt = 4; // Кнопка вниз else if (val < 550) bt = 2; // кнопка вперед else if (val < 800) bt = 1; // кнопка входа в меню else return 0; while (analogRead(0) < 800); // ждать пока кнопка не отпустится return bt; } //////////////////////////////////////////////////////////////////// // инициализировать дисплей // третья строка, содержит необходимые русские буквы от "БГДЖЗИЙЛПУФЦЧШЩЬЪЫЭЮЯ" до 21 букв, // но одновременно рекомендуется использовать не более 8 букв на дисплее, получилось использовать весь набор из 21 буквы //////////////////////////////////////////////////////////////////// static byte addon_letters[16]; void init_rus(const char* letters_use ) { // пользовательские символы static byte letters[][8] = { { B11111, B10000, B10000, B11111, B10001, B10001, B11111, B00000 },//Б { B11111, B10000, B10000, B10000, B10000, B10000, B10000, B00000 },//Г { B01111, B01001, B01001, B01001, B01001, B11111, B10001, B00000 },//Д { B10101, B10101, B10101, B01110, B10101, B10101, B10101, B00000 },//Ж { B01110, B10001, B00001, B00110, B00001, B10001, B01110, B00000 },//З { B10001, B10001, B10011, B10101, B11001, B10001, B10001, B00000 },//И { B10101, B10101, B10011, B10101, B11001, B10001, B10001, B00000 },//Й { B00111, B01001, B10001, B10001, B10001, B10001, B10001, B00000 },//Л { B11111, B10001, B10001, B10001, B10001, B10001, B10001, B00000 },//П { B10001, B10001, B10001, B01111, B00001, B10001, B01110, B00000 },//У { B01110, B10101, B10101, B10101, B01110, B00100, B00100, B00000 },//Ф { B10001, B10001, B10001, B10001, B10001, B10001, B11111, B00001 },//Ц { B10001, B10001, B10001, B01111, B00001, B00001, B00001, B00000 },//Ч { B10101, B10101, B10101, B10101, B10101, B10101, B11111, B00000 },//Ш { B10101, B10101, B10101, B10101, B10101, B10101, B11111, B00001 },//Щ { B10000, B10000, B10000, B11110, B10001, B10001, B11110, B00000 },//Ь { B11000, B01000, B01110, B01001, B01001, B01001, B01110, B00000 },//Ъ { B10001, B10001, B10001, B11101, B10101, B10101, B11101, B00000 },//Ы { B11110, B00001, B00001, B01111, B00001, B00001, B11110, B00000 },//Э { B10111, B10101, B10101, B11101, B10101, B10101, B10111, B00000 },//Ю { B01111, B10001, B10001, B01111, B10001, B10001, B10001, B00000 },//Я }; static char chars[] = {'Б','Г','Д','Ж','З','И','Й','Л','П','У','Ф','Ц','Ч','Ш','Щ','Ь','Ъ','Ы','Э','Ю','Я'}; static byte empty[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; int index = 0, cl = sizeof(chars)/sizeof(char),i,j,symb; memset(addon_letters,0,sizeof(addon_letters)); for( j = 0; j < strlen(letters_use) && j < 21; j++ ) lcd.createChar(j, empty); for( j = 0; j < strlen(letters_use) && j < 21; j++ ) { symb = -1; for( i=0; i < cl; i++ ) if( chars[i] == letters_use[j] ) { symb = i; addon_letters[index] = letters_use[j]; break; } if( symb != -1 ) { lcd.createChar(index, letters[symb]); index++; } } } //////////////////////////////////////////////////////////////////// // печать русских букв //////////////////////////////////////////////////////////////////// void print_rus(char *str) { static char rus_letters[] = {'А','В','Е','Ё','К','М','Н','О','Р','С','Т','Х'}; static char trans_letters[] = {'A','B','E','E','K','M','H','O','P','C','T','X'}; int lcount = sizeof(rus_letters)/sizeof(char), i, j; for( i=0; i<strlen(str); i++ ) { if( byte(str[i]) == 208 ) continue; // 208 игнорировать int found = 0; for(j=0; j < 16; j++) if( addon_letters[j] != 0 && byte(str[i]) == byte(addon_letters[j]) ) { lcd.write(j); found = 1; break; } if(!found) for(j=0; j < lcount; j++) if( byte(str[i]) == byte(rus_letters[j]) ) { lcd.write(trans_letters[j]); found = 1; break; } if(!found) lcd.write(byte(str[i])); } } void print_rus(int x, int y, char *str) { lcd.setCursor(x, y); print_rus(str); } //////////////////////////////////////////////////////////////////// ////////// - цикл 1 - ///////////// void Submenu1(){ lcd.clear(); init_rus("ПМЖЛ"); char menuTxt[][20] = {"SET SUNRISE >>", "SET SUNSET >>", "SET POWER >>"}; byte pos = 0; byte KEY; while((KEY=key()) != 1){ lcd.setCursor(0, 0); lcd.print(pos+1); lcd.print("."); lcd.print(menuTxt[pos]); if (KEY == 3 && pos != 0) pos--; else if (KEY == 4 && pos < 2) pos++; if (KEY == 5 && pos == 0) ; else if (KEY == 5 && pos == 1) ; else if (KEY == 5 && pos == 2) ; } lcd.clear(); init_rus("ВЫХД"); print_rus(0,0," -ВЫХОД- "); delay(500); } //**********************************************************************************// //********************цикл установки границ температурного коридора*****************// //**********************************************************************************// void SetFanOnOff(){ byte pos = 4; lcd.clear(); lcd.blink(); byte KEY; // читаем состояние кнопок while(1) // крутим цикл { //lcd.setCursor(0, 1); init_rus("ЗДЬХИ"); print_rus(0,1,"ЗАДАТЬ,СОХРАНИТЬ"); lcd.setCursor(1, 0); // выводим инфу lcd.print("L="); if (settempOn < 10) lcd.print("0"); lcd.print(settempOn); lcd.print("*C"); lcd.setCursor(9, 0); lcd.print("H="); if (settempOff < 10) lcd.print("0"); lcd.print(settempOff); lcd.print("*C"); lcd.setCursor(pos, 0); // устанавливаем курсор согласно позиции while ((KEY=key()) == 0); //жду нажатия кнопки if (KEY == 1) break; if (KEY == 5 && pos < 12) pos += 8; // крутим позицию else if (KEY == 2 && pos > 4) pos -= 8; else if (pos == 4 && KEY == 3) settempOn++; // крутим значения else if (pos == 4 && KEY == 4) settempOn--; else if (pos == 12 && KEY == 3) settempOff++; else if (pos == 12 && KEY == 4) settempOff--; if (settempOn > 40) settempOn = 0; // устанавливаем макс. значения переменной температуры else if (settempOff > 40) settempOff = 0; } // конец цикла lcd.noBlink(); lcd.clear(); EEPROM.write(44, settempOn); // Зашиваем значение On в память EEPROM.write(45, settempOff); // Зашиваем значение Off в память init_rus("ХЯ"); print_rus(0,0," -СОХРАНЯЕМ- "); delay(1000); } //*********************************************************************************// //***************** Цикл установки мощности MIN & MAX вентилятора *****************// //*********************************************************************************// void setPower_Fan(){ byte pos = 5; lcd.clear(); lcd.blink(); byte KEY; while(1) // крутим цикл { //lcd.setCursor(0, 1); init_rus("ЗДЬХИ"); print_rus(0,1,"ЗАДАТЬ,СОХРАНИТЬ"); //lcd.setCursor(0, 0); // выводим инфу init_rus("Х"); print_rus(0,0,"МАХ="); if (FANPWM_MAX < 10) lcd.print("0"); if (FANPWM_MAX < 100) lcd.print("0"); lcd.print(FANPWM_MAX); //lcd.setCursor(9, 0); init_rus("И"); print_rus(0,1,"МИН="); if (FANPWM_MIN < 10) lcd.print("0"); if (FANPWM_MIN < 100) lcd.print("0"); lcd.print(FANPWM_MIN); lcd.setCursor(pos, 0); // устанавливаем курсор согласно позиции while ((KEY=key()) == 0);//жду нажатия кнопки if (KEY == 1) break; if (KEY == 5 && pos < 14) pos += 9; // крутим позицию else if (KEY == 2 && pos > 5) pos -= 9; else if (pos == 5 && KEY == 3) FANPWM_MAX++; // крутим значения else if (pos == 5 && KEY == 4) FANPWM_MAX--; else if (pos == 14 && KEY == 3) FANPWM_MIN++; else if (pos == 14 && KEY == 4) FANPWM_MIN--; if (FANPWM_MAX > 255) FANPWM_MAX = 0; // устанавливаем макс. значения переменной температуры else if (FANPWM_MIN > 255) FANPWM_MIN = 0; } // конец цикла lcd.noBlink(); lcd.clear(); EEPROM.write(46, FANPWM_MAX); // Зашиваем значение MAX в память EEPROM.write(47, FANPWM_MIN); // Зашиваем значение MIN в память init_rus("ХЯ"); print_rus(0,0," -СОХРАНЯЕМ- "); delay(1000); } ///////////- Главное меню -///////////// void menu(){ lcd.clear(); init_rus("ПМЖЛ"); char menuTxt[][20] = {"Menu-1 >>", "Menu-2 >>"}; byte pos = 0; byte KEY; while((KEY=key()) != 1){ lcd.setCursor(0, 0); lcd.print(pos+1); lcd.print("."); lcd.print(menuTxt[pos]); if (KEY == 3 && pos != 0) pos--; else if (KEY == 4 && pos < 1) pos++; if (KEY == 5 && pos == 0) Submenu1(); else if (KEY == 5 && pos == 1) SubmenuFan(); } lcd.clear(); init_rus("ВЫХД"); print_rus(0,0," -ВЫХОД- "); delay(500); } void SubmenuFan(){ // Охлаждение // lcd.clear(); init_rus("ПМЖЛ"); char menuTxt[][20] = {"SET TEMPER. >>", "SET POWER >>"}; byte pos = 0; byte KEY; // читаем состояние кнопок while((KEY=key()) != 1){ // крутим цикл lcd.setCursor(0, 0); lcd.print(pos+1); lcd.print("."); lcd.print(menuTxt[pos]); if (KEY == 3 && pos != 0) pos--; else if (KEY == 4 && pos < 1) pos++; if (KEY == 5 && pos == 0) SetFanOnOff(); else if (KEY == 5 && pos == 1) setPower_Fan(); } lcd.clear(); init_rus("ВЫХД"); print_rus(0,0," -ВЫХОД- "); delay(1000); } void setup(){ lcd.begin(16, 2); //lcd.setCursor(2, 0); init_rus("ПКМЮ"); print_rus(0,0,"ПРОВЕРКА МЕНЮ 1"); pinMode(Ledlcd, OUTPUT); brightnessLCD = EEPROM.read(2); // Подсветка LCD // analogWrite(Ledlcd, brightnessLCD); analogWrite(FANPWM_PIN, FANPWM_MIN); //Пишем в порт минимальное значение settempOn = EEPROM.read(44); // Охлаждение // settempOff = EEPROM.read(45); FANPWM_MAX = EEPROM.read(46); FANPWM_MIN = EEPROM.read(47); } void loop() { byte KEY=key(); switch (KEY) { case 1: menu(); break; case 2: if (--ekran<0) ekran=2; break; case 3: brightnessLCD += 5; break; case 4: brightnessLCD -= 5; break; case 5: if (++ekran>2) ekran=0; break; default: break; } if (KEY==2 || KEY==5 || KEY==1) { lcd.setCursor(2, 0); switch (ekran) { case 0: init_rus("ПКМЮ");print_rus(0,0,"ПРОВЕРКА МЕНЮ 1"); break; case 1: init_rus("ПКМЮ");print_rus(0,0,"ПРОВЕРКА МЕНЮ 2"); break; case 2: init_rus("ПКМЮ");print_rus(0,0,"ПРОВЕРКА МЕНЮ 3"); break; } } if (KEY==3 || KEY==4) { brightnessLCD = constrain(brightnessLCD, 0, 254); analogWrite(Ledlcd, brightnessLCD); // Устанавливаем состояние яркости для светодиода EEPROM.write(2, brightnessLCD); } }Господа что вы никак switch не изучите! каша блин а не код
Господа что вы никак switch не изучите! каша блин а не код
Москва не сразу строилась! Доберемся и до switch. Спасибо за совет!
http://forum.amperka.ru/threads/Библиотека-для-создания-Меню-на-дисплеях.1815/
Тут как делать Меню, там нужно скачать библиотеку. Выкладываю правленный код под наш шилд. Осталось прикрутить антидребезг и русские буквы.
#include <MyMenu.h> #include <LiquidCrystal.h> LiquidCrystal lcd(8, 9, 4, 5, 6, 7); //инициализация дисплея #define NUM_ITEMS 32 //количество пунктов в меню включая все заголовки всех подменю MItm items[NUM_ITEMS] = { MItm("SHOPPING LIST",0,0), //этот пункт является заголовком подменю с индексом 0 (то есть главного меню) MItm("Fruits",1), //пункт главного меню, который при выборе переходит на подменю с индексом 1 MItm("Veggies",2), //с индексом 2 MItm("Other",3), //и с индексом 3 соответственно MItm("FRUITS LIST",1,0), //это подменю с индексом 1, а ноль - верхнее для него меню MItm("Apple",50), //подменю с индексом 50 нет, поэтому будет вызвана функция (ниже) MItm("Orange",60), MItm("Banana",70), MItm("Pear",80), MItm(" <<BACK",0), //вот так можно создавать кнопку "Назад" MItm("VEGGIES LIST",2,0), //подменю с индексом 2 MItm("Tomato",90), MItm("Potato",100), MItm("Smth else",110), MItm(" <<BACK",0), MItm("Other",3,0), MItm("Meat",4), MItm("Fish",5), MItm(" <<BACK",0), MItm("MEAT",4,3), //здесь уже верхним меню является подменю с индексом 3 MItm("Chicken",6), MItm("Bacon",7), MItm("Beef",8), MItm("SHOWFISH",5), MItm(" <<BACK",3), MItm(" <<MAIN",0), MItm("FISH",5,3), MItm("Clownfish",9), MItm("Shark",10), MItm("SHOW MEAT",4), MItm(" <<BACK",3), MItm(" <<MAIN",0) }; Menu menu(items,NUM_ITEMS,&lcd,menuCallback); //так создается меню (подробнее ниже) void setup() { //настраиваем кнопки pinMode(0,INPUT); lcd.begin(16,2); //запускаем экран menu.goMain(); //отображаем на экране главное меню } void loop() { if(analogRead(0) < 80){ //нажата кнопка "вперед" или "выбрать пункт" menu.goNext(); //функция переходит на новый уровень подменю или вызывает callback delay(100); } if(analogRead(0) < 200){ //нажата кнопка "вверх" menu.goUp(); //функция перемещает курсор на один пункт вверх delay(100); } if(analogRead(0) < 400){ //нажата кнопка "вниз" menu.goDown(); //функция перемещает курсор на один пункт вниз delay(100); } if(analogRead(0) < 600){ //нажата кнопка "назад" menu.goBack(); //функция возвращает на предыдущий уровень меню delay(100); } delay(100); } void menuCallback(int idx){ //эта функция будет вызвана, если подменю с индексом idx нет //и нужно совершить действие, а не уходить на еще один уровень в меню if(idx < 10){ //если idx < 10 делаем одно lcd.clear(); lcd.setCursor(0,0); lcd.print("NO MEAT n FISH!"); delay(1000); }else if(idx == 10){ //если выбран пункт "акула" делаем другое :) int i=16; while(i >= 0){ lcd.clear(); lcd.setCursor(0,0); lcd.print("-^-^-^-^-^-^-^-^-^-^"); lcd.setCursor(i,1); lcd.print("/l"); delay(300); i--; } }else{ //иначе просто пишем что было выбрано lcd.clear(); lcd.setCursor(3,0); lcd.print(String(idx)+" pressed"); delay(1000); } menu.goLast(); //после некоторой паузы вот этой функцией возвращаемся на последнее показанное меню }Здравствуйте! Люди добрые подскажите как в моём случае прописать выход из меню по кнопке select.
#include <DallasTemperature.h> #include <DHT.h> #include <EEPROM.h> #include <OneWire.h> #include <LiquidCrystal.h> #define OUT1 2 // выходы для реле #define OUT2 3 #define DHTPIN 12 // what digital pin we're connected to // Uncomment whatever type you're using! //#define DHTTYPE DHT11 // DHT 11 #define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321 //#define DHTTYPE DHT21 // DHT 21 (AM2301) DHT dht(DHTPIN, DHTTYPE); byte tempOUT1, tempOUT2; LiquidCrystal lcd(8, 9, 4, 5, 6, 7); OneWire ds(11); // 11 вход датчика 18b20 byte gradus[8] = { 0b00110, 0b01001, 0b01001, 0b00110, 0b00000, 0b00000, 0b00000, 0b00000 }; void erorr(){ // останавливает работу программы и сигнализирует ошибку digitalWrite(OUT1, LOW); // выключаем реле digitalWrite(OUT2, LOW); while(1){ // крутим бесконечный цикл digitalWrite(13, !digitalRead(13)); delay(500); } } //// 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 setMenu(){ // установка температуры byte pos; //digitalWrite(OUT1, LOW); // выключаем реле //digitalWrite(OUT2, LOW); lcd.clear(); lcd.setCursor(0, 0); // что нужно отрисовать один раз lcd.print("Garag: "); lcd.setCursor(0, 1); lcd.print("Kotel: "); lcd.setCursor(11, 1); lcd.print("|"); lcd.blink(); while(1){ // крутим бесконечный цикл byte KEY = key(); // читаем состояние кнопок lcd.setCursor(6, 0); // выводим на экран lcd.print(tempOUT1); lcd.write(1); lcd.print("C "); lcd.setCursor(6, 1); lcd.print(tempOUT2); lcd.write(1); lcd.print("C "); ////// обработка кнопок if (pos == 0){ // если в первой позиции lcd.setCursor(5, 0); // устанавливаем курсор if (KEY == 2) { // если нажата кнопка tempOUT1--; // изменяем значение EEPROM.write(1, tempOUT1); // сохраняем в еепром } else if (KEY == 5){ tempOUT1++; EEPROM.write(1, tempOUT1); } } if (pos == 1){ lcd.setCursor(5, 1); if (KEY == 2) { tempOUT2--; EEPROM.write(2, tempOUT2); } else if (KEY == 5){ tempOUT2++; EEPROM.write(2, tempOUT2); } } if (KEY == 3) pos--; // крутим позицию else if (KEY == 4) pos++; if (pos > 1) pos = 0; delay(200); } } float getTemp(){ // возвращает температуру с датчика byte data[12]; // и останавливает программу на секунду byte addr[8]; if (!ds.search(addr)) { lcd.clear(); lcd.print("No sensor."); erorr(); } ds.reset_search(); if (OneWire::crc8(addr, 7) != addr[7]) { lcd.clear(); lcd.print("Sensor CRC erorr"); erorr(); } ds.reset(); ds.select(addr); ds.write(0x44); delay(1000); ds.reset(); ds.select(addr); ds.write(0xBE); for (int i = 0; i < 9; i++) data[i] = ds.read(); int raw = (data[1] << 8) | data[0]; // Переводим в температуру if (data[7] == 0x10) raw = (raw & 0xFFF0) + 12 - data[6]; return raw / 16.0; } unsigned long timing; void setup() { Serial.begin(9600); lcd.createChar(1, gradus); lcd.begin(16, 2); lcd.clear(); dht.begin(); pinMode(13, OUTPUT); pinMode(OUT1, OUTPUT); pinMode(OUT2, OUTPUT); tempOUT1 = EEPROM.read(1); // читаем настройки tempOUT2 = EEPROM.read(2); // из еепром } void loop() { if (key() == 1) setMenu(); // если нажата селект, уходим в меню else if (key() == 4) analogWrite(10, 30); // если вниз, глушим подсветку else if (key() == 3) digitalWrite(10, HIGH); float temperature = getTemp(); // читаем температуру float h = dht.readHumidity(); // Read temperature as Celsius (the default) float t = dht.readTemperature(); // Read temperature as Fahrenheit (isFahrenheit = true) float f = dht.readTemperature(true); getTemp(); //if(t <= tempOUT1){ //if (!digitalRead(OUT1)){ // digitalWrite(OUT1, HIGH); // timing = millis(); // } // if (!digitalRead(OUT2) && millis() - timing > 10000){ // digitalWrite(OUT2, HIGH); //} //} if(t >= tempOUT1 ){ if (digitalRead(OUT1)){ digitalWrite(OUT1, LOW); timing = millis(); } if (digitalRead(OUT2) && millis() - timing > 10000){ digitalWrite(OUT2, LOW); } goto metka1; } if(temperature -1<= tempOUT2){ if (!digitalRead(OUT1)){ digitalWrite(OUT1, HIGH); timing = millis(); } if (!digitalRead(OUT2) && millis() - timing > 10000){ digitalWrite(OUT2, HIGH); } } if(temperature +1>= tempOUT2 ){ if (digitalRead(OUT1)){ digitalWrite(OUT1, LOW); timing = millis(); } if (digitalRead(OUT2) && millis() - timing > 10000){ digitalWrite(OUT2, LOW); } } metka1: lcd.setCursor(0, 0); /// вывод инфы на экран lcd.print("G"); lcd.print("-"); lcd.print(t); lcd.write(1); lcd.print("C"); lcd.setCursor(10, 0); lcd.print(h); lcd.print("%"); //if (digitalRead(OUT1)) lcd.print(" ON "); // показываем состояние выхода //else lcd.print(" OFF"); lcd.setCursor(0, 1); lcd.print("K"); lcd.print("-"); //lcd.setCursor(7, 1); lcd.print(temperature); lcd.write(1); lcd.print("C"); //lcd.write(1); //if (digitalRead(OUT2)) lcd.print(" ON "); //else lcd.print(" OFF"); //lcd.setCursor(9, 0); // показываем температуру с датчика //lcd.print("|"); //lcd.print(h, 1); //lcd.write(1); //lcd.print("C"); //lcd.setCursor(9, 1); //lcd.print("|"); }