Меню
- Войдите на сайт для отправки комментариев
Пт, 27/02/2015 - 17:29
Привет всем. Требуется небольшая помощь. Пишу меню и столкнулся с проблемой. Пока оно написано лишь частично и некоторые вещи в коде лишние. проблема вот в чем: есть кусок кода "установка времени простоя" (строки 111-128), и в нем не выполняется присваивание переменной menu значение 4. Причем в "установке времени работы"(93-110) все работает, и если эти блоки поменять местами, то "время простоя" работает (присваивает menu 4), а "время работы" - нет. Смотрел переменные через serial: item и menu совпадают по условиям. Получается 3 пункта меню, в каждом из них установка параметра, и вот в установку последнего параметра не заходит, непонятно почему. Заранее благодарю за помощь.
#include <Wire.h>
#include <EEPROM.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);
#define pump 8
#define heat 9
#define ok 4 // кнопка возврата
#define up 3 // увеличение значения
#define down 2 // уменьшение значения
byte okstate = 0;
byte upstate = 0;
byte downstate = 0;
byte menu = 0;
byte item = 1;
byte temp = 15;
void setup(){
lcd.init(); // инициализация LCD
lcd.backlight(); // включаем подсветку
pinMode(down, INPUT);
pinMode(up, INPUT);
pinMode(ok, INPUT);
pinMode(pump, OUTPUT);
pinMode(heat, OUTPUT);
pinMode(13,OUTPUT);
}
void filt(){ }
void loop(){
if (menu == 0){
filt();
}
// кнопка ОК вход в главное меню
if (menu == 0 && okstate == 0 && digitalRead(ok) == HIGH){
menu = 1;
okstate = 1;
}
if (okstate == 1 && digitalRead(ok) == LOW)
okstate = 0;
// главное меню
if (menu == 1){
// кнопка ВВЕРХ
if (upstate == 0 && digitalRead(up) == HIGH){
item ++;
upstate = 1;
}
if (upstate == 1 && digitalRead(up) == LOW)
upstate = 0;
if (item > 4){
item = 1;
}
// кнопка ВНИЗ
if (downstate == 0 && digitalRead(down) == HIGH){
item--;
downstate = 1;
}
if (downstate == 1 && digitalRead(down) == LOW)
downstate = 0;
if (item < 1){
item = 4;
}
// выход
if (item == 4 && okstate == 0 && digitalRead(ok) == HIGH){
lcd.clear();
menu = 0;
item = 1;
okstate = 1;
}
if (okstate == 1 && digitalRead(ok) == LOW)
okstate = 0;
}
// установка температуры
if (menu == 1 && item == 1){
if (okstate == 0 && digitalRead(ok) == HIGH){
menu = 2;
lcd.clear();
okstate = 1;
}
if (okstate == 1 && digitalRead(ok) == LOW)
okstate = 0;
}
if (menu == 2 && okstate == 0 && digitalRead(ok) == HIGH)
{
lcd.clear();
menu = 1;
okstate = 1;
}
if (okstate == 1 && digitalRead(ok) == LOW){
okstate = 0;
}
// установка времени работы
if (menu == 1 && item == 2){
if (okstate == 0 && digitalRead(ok) == HIGH){
lcd.clear();
menu = 3;
okstate = 1;
}
if (okstate == 1 && digitalRead(ok) == LOW)
okstate = 0;
}
if (okstate == 0 && digitalRead(ok) == HIGH){
lcd.clear();
menu = 1;
okstate = 1;
}
if (okstate == 1 && digitalRead(ok) == LOW){
okstate = 0;
}
// установка времени простоя
if (menu == 1 && item == 3){
if (okstate == 0 && digitalRead(ok) == HIGH){
lcd.clear();
menu = 4;
okstate = 1;
}
if (okstate == 1 && digitalRead(ok) == LOW)
okstate = 0;
}
if (okstate == 0 && digitalRead(ok) == HIGH){
lcd.clear();
menu = 1;
okstate = 1;
}
if (okstate == 1 && digitalRead(ok) == LOW){
okstate = 0;
}
// вывод меню
if (menu == 0){
lcd.setCursor(3,0);
lcd.print("filter ");
}
if (menu == 1){
lcd.setCursor(3,0);
lcd.print("main menu");
if (item == 1){
lcd.setCursor(3,1);
lcd.print("set temp");
}
else if (item == 2){
lcd.setCursor(3,1);
lcd.print("set on ");
}
else if (item == 3){
lcd.setCursor(3,1);
lcd.print("set off ");
}
else if (item == 4){
lcd.setCursor(3,1);
lcd.print("exit ");
}
}
if (menu == 2){
lcd.setCursor(3,1);
lcd.print("temp set ");
}
else if (menu == 3){
lcd.setCursor(3,1);
lcd.print("ON time ");
}
else if (menu == 4){
lcd.setCursor(3,1);
lcd.print("OFF time ");
}
}
в допВкладке есть галочка - свернуть код ( нумеровать - тоже очень хорошо )
исправьте - пока никто не ругается.... моя покушал, добрый просто :)
Что-то я не могу свое сообщение открыть для редактирования. Как удалить тему?
upd: во 2 посте есть ссылка "изменить", а в 1 нет.
Что-то я не могу свое сообщение открыть для редактирования. Как удалить тему?
Уже никак, и тебя сосчитали(((
тему нельзя удалить.... сообщения нежелательно править позднее минут 1.......5 - вытекает из постулатов энштейновых, неоднозначность :(
Тогда так.
#include <Wire.h> #include <EEPROM.h> #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x27,16,2); #define pump 8 #define heat 9 #define ok 4 // кнопка возврата #define up 3 // увеличение значения #define down 2 // уменьшение значения byte okstate = 0; byte upstate = 0; byte downstate = 0; byte menu = 0; byte item = 1; byte temp = 15; void setup(){ lcd.init(); // инициализация LCD lcd.backlight(); // включаем подсветку pinMode(down, INPUT); pinMode(up, INPUT); pinMode(ok, INPUT); pinMode(pump, OUTPUT); pinMode(heat, OUTPUT); pinMode(13,OUTPUT); } void filt(){ } void loop(){ if (menu == 0){ filt(); } // кнопка ОК вход в главное меню if (menu == 0 && okstate == 0 && digitalRead(ok) == HIGH){ menu = 1; okstate = 1; } if (okstate == 1 && digitalRead(ok) == LOW) okstate = 0; // главное меню if (menu == 1){ // кнопка ВВЕРХ if (upstate == 0 && digitalRead(up) == HIGH){ item ++; upstate = 1; } if (upstate == 1 && digitalRead(up) == LOW) upstate = 0; if (item > 4){ item = 1; } // кнопка ВНИЗ if (downstate == 0 && digitalRead(down) == HIGH){ item--; downstate = 1; } if (downstate == 1 && digitalRead(down) == LOW) downstate = 0; if (item < 1){ item = 4; } // выход if (item == 4 && okstate == 0 && digitalRead(ok) == HIGH){ lcd.clear(); menu = 0; item = 1; okstate = 1; } if (okstate == 1 && digitalRead(ok) == LOW) okstate = 0; } // установка температуры if (menu == 1 && item == 1){ if (okstate == 0 && digitalRead(ok) == HIGH){ menu = 2; lcd.clear(); okstate = 1; } if (okstate == 1 && digitalRead(ok) == LOW) okstate = 0; } if (menu == 2 && okstate == 0 && digitalRead(ok) == HIGH) { lcd.clear(); menu = 1; okstate = 1; } if (okstate == 1 && digitalRead(ok) == LOW){ okstate = 0; } // установка времени работы if (menu == 1 && item == 2){ if (okstate == 0 && digitalRead(ok) == HIGH){ lcd.clear(); menu = 3; okstate = 1; } if (okstate == 1 && digitalRead(ok) == LOW) okstate = 0; } if (okstate == 0 && digitalRead(ok) == HIGH){ lcd.clear(); menu = 1; okstate = 1; } if (okstate == 1 && digitalRead(ok) == LOW){ okstate = 0; } // установка времени простоя if (menu == 1 && item == 3){ if (okstate == 0 && digitalRead(ok) == HIGH){ lcd.clear(); menu = 4; okstate = 1; } if (okstate == 1 && digitalRead(ok) == LOW) okstate = 0; } if (okstate == 0 && digitalRead(ok) == HIGH){ lcd.clear(); menu = 1; okstate = 1; } if (okstate == 1 && digitalRead(ok) == LOW){ okstate = 0; } // вывод меню if (menu == 0){ lcd.setCursor(3,0); lcd.print("filter "); } if (menu == 1){ lcd.setCursor(3,0); lcd.print("main menu"); if (item == 1){ lcd.setCursor(3,1); lcd.print("set temp"); } else if (item == 2){ lcd.setCursor(3,1); lcd.print("set on "); } else if (item == 3){ lcd.setCursor(3,1); lcd.print("set off "); } else if (item == 4){ lcd.setCursor(3,1); lcd.print("exit "); } } if (menu == 2){ lcd.setCursor(3,1); lcd.print("temp set "); } else if (menu == 3){ lcd.setCursor(3,1); lcd.print("ON time "); } else if (menu == 4){ lcd.setCursor(3,1); lcd.print("OFF time "); } }не вчитывался..... линейное программирование в данном случае тупик, кажися :(
....могу быть не правым
Программа слишком сложна, так что далее последуют предположения.
1. Сброс переменных *state при отжатой кнопке [вывод сделан по INPUT вместо INPUT_PULLUP в pinMode()] - видимо защита от многократного срабатывания кнопок. Слишком много мест с этим, так что лучше вытащить в отдельную функцию.
#include <Wire.h> #include <EEPROM.h> #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x27,16,2); #define pump 8 #define heat 9 #define ok 4 // кнопка возврата #define up 3 // увеличение значения #define down 2 // уменьшение значения #define KEY_OK 1 #define KEY_UP 2 #define KEY_DN 3 void setup(){ lcd.init(); // инициализация LCD lcd.backlight(); // включаем подсветку pinMode(down, INPUT); pinMode(up, INPUT); pinMode(ok, INPUT); pinMode(pump, OUTPUT); pinMode(heat, OUTPUT); pinMode(13,OUTPUT); } void loop(){ if (digitalRead(ok) == HIGH){ while(digitalRead(ok) == HIGH){} processKey(KEY_OK); } if (digitalRead(up) == HIGH){ while(digitalRead(up) == HIGH){} processKey(KEY_UP); } if (digitalRead(down) == HIGH){ while(digitalRead(down) == HIGH){} processKey(KEY_DN); } } void processKey(byte key){ }processKey(key) - это будет реакция, то есть нажали кнопку, надо сделать нечто.
Далее, слишком часто пишется в одно и то же место экрана, так что заодно делаем показывание меню:
void menuDisplay(){ lcd.setCursor(3,0); switch(menu){ case 0: lcd.print("main menu"); break; case 1: lcd.print("temp set "); break; case 2: lcd.print("ON time "); break; case 3: lcd.print("filter "); break; case 4: lcd.print("OFF time "); break; } }После этого рисуем на бумаге все возможные варианты меню, и таким образом получаем дерево режимов. Очередное предположение - menu это на самом деле mode, то есть то состояние в котором программа находится в данный момент, а вот item - это menu, то есть собственно пункты меню, то состояние в котором программа будет находиться, если нажмут Ok.
Пишите, что должно делать меню, тогда возможно будет написать нормально. Ещё одно предположение - есть три переменных (on, off, temp) которые можно мотать стрелками.
state нашел в примерах, чтоб избавиться от дребезга и повторов при нажатой кнопке.
В основном цикле крутится функция filt, там будет таймер и термостат. При этом переменная menu = 0. По нажатию ОК входим в меню выбора параметра (menu=1): ontime - период работы насоса, offtime - период простоя насоса, temp set - уставка термостата. Здесь выбираем item и по нажатию ОК входим в пункт установки параметра (menu = 2;3;4). Время ставим в часах кнопками up и down, по нажатию ОК сохраняем в eeprom и выходим на пункт выше. То же и с температурой. Дело в том, что там, где menu присваиваем 2 и 3, все нормально, а вот там, где должно присвоить 4, не присваивает, и в этом условии вообще ничего не работает, если туда что-нибудь добавить. item, menu, onstate выводил в порт, все совпадает с условиями и по нажатиям изменяется как надо кроме присвоения menu 4. Загадка какая-то.
Мне в таком плоском цикле вообще невозможно найти, что откуда. Так что предлагаю так:
#include <Wire.h> #include <EEPROM.h> #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x27,16,2); #define pump 8 #define heat 9 #define ok 4 // ok/enter #define up 3 // inc./up #define down 2 // dec./down #define KEY_OK 1 #define KEY_UP 2 #define KEY_DN 3 #define onmax 24 #define offmax 24 #define tempmin 1 #define tempmax 40 byte menu = 0; byte item = 0; byte temp = 15; byte ontime = 1; byte offtime = 1; void setup(){ lcd.init(); lcd.backlight(); pinMode(down, INPUT); pinMode(up, INPUT); pinMode(ok, INPUT); pinMode(pump, OUTPUT); pinMode(heat, OUTPUT); pinMode(13,OUTPUT); ontime = EEPROM.read(0x00); offtime= EEPROM.read(0x01); temp = EEPROM.read(0x02); if(ontime>onmax) ontime=onmax; if(offtime>offmax) offtime=offmax; if(temp>tempmax) temp=tempmax; } void loop(){ if (digitalRead(ok) == HIGH){ while(digitalRead(ok) == HIGH){} processKey(KEY_OK); } if (digitalRead(up) == HIGH){ while(digitalRead(up) == HIGH){} processKey(KEY_UP); } if (digitalRead(down) == HIGH){ while(digitalRead(down) == HIGH){} processKey(KEY_DN); } if(menu==0) filt(); } void menuDisplay(byte str){ /* str: 0 - mode 1 - menu item 2 - both + clear screen */ if(str==2) lcd.clear(); if(mode>=2 && mode<=4){ // parameters edit modes lcd.blink(); // show cursor lcd.cursor(); }else{ // other modes lcd.noBlink(); // hide cursor lcd.noCursor(); } if(str==0 || str==2){ lcd.setCursor(3,0); switch(menu){ case 0: lcd.print("Filter "); break; case 1: lcd.print("Main menu"); break; case 2: lcd.print("ON time: "); break; case 3: lcd.print("OFF time:"); break; case 4: lcd.print("Temp set:"); break; } } if(str==1 || str==2){ lcd.setCursor(3,1); switch(item){ case 2: lcd.print("ON time "); break; case 3: lcd.print("OFF time"); break; case 4: lcd.print("Temp set"); break; case 5: lcd.print("Go back "); break; } } } void processKey(byte key){ switch(key){ case KEY_UP: if(menu==1 && item<5){ // menu navigation item++; menuDisplay(1); } if(menu>=2 && menu<=4) ]cd.setCursor(3,1); // parameter value coords if(menu==2 && ontime<onmax){ // menu=2..4 - edit parameter ontime++; lcd.print(ontime); } if(menu==3 && offtime<offmax){ offtime++; lcd.print(offtime); } if(menu==4 && temp<tempmax){ temp++; lcd.print(temp); } break; case KEY_DN: if(menu==1 && item>2){ // menu navigation item--; menuDisplay(1); } if(menu>=2 && menu<=4) ]cd.setCursor(3,1); // parameter value coords if(menu==2 && ontime>1){ // menu=2..4 - edit parameter ontime--; lcd.print(ontime); } if(menu==3 && offtime>1){ offtime--; lcd.print(offtime); } if(menu==4 && temp>tempmin){ temp--; lcd.print(temp); } break; case KEY_OK: switch(menu){ case 0: // setup mode menu=1; item=2; menuDisplay(2); break; case 1: // select menu=item; menuDisplay(1); break; case 2: // on storeONtime(); menu=1; menuDisplay(2); break; case 3: // off storeOFFtime(); menu=1; menuDisplay(2); break; case 4: // temp storeTEMP(); menu=1; menuDisplay(2); break; case 5: // return to main loop menu=0; menuDisplay(2); break; } break; } } void storeONtime(){ // storage routines if(EEPROM.read(0x00)!=ontime) EEPROM.write(0x00,ontime); } void storeOFFtime(){ if(EEPROM.read(0x01)!=offtime) EEPROM.write(0x01,offtime); } void storeTEMP(){ if(EEPROM.read(0x02)!=temp) EEPROM.write(0x02,temp); }