Цикл в цикле
- Войдите на сайт для отправки комментариев
Пнд, 16/09/2019 - 22:30
Задание: В одном из пунктов главного меню организовать установку времени посредством энкодера (d2,d3,d4), поворачивая меняются часы, при нажатии на энкодер настрйока перескакивает на установку минут. И организовать выход из установки часов и минут посредством длинного тапа.
Проблема: Часы с минутами устанавливаются одновременно, то по очереди. )))
Кусок кода прилагаю. Заранее благодарю за помощь.
void action1() { // ----------- Выполнение 1 пункта меню ---------------------------------
if (millis() - lasttime > 1000) {
lasttime = millis();
tft.setTextColor(ST77XX_YELLOW, ST77XX_BLACK);
tft.setCursor (20, 20);
tft.print(rtc.getTimeStr()); }
do {
switch (tset) {
case 0:
tset =1;
break;
case 1:
tft.setTextColor(ST77XX_RED, ST77XX_BLACK);
tft.setCursor (20, 40);
if (hsetON < 10) tft.print('0');
tft.print(hsetON);
tft.setTextColor(ST77XX_MAGENTA, ST77XX_BLACK);
tft.setCursor (55, 40);
tft.print(msetON);
if (enc1.isRight()) {
hsetON++;
if (hsetON >=24) hsetON=0; }
if (enc1.isLeft()) {
hsetON--;
if (hsetON <=0) hsetON=0; }
if (enc1.isPress()){
tset++;
break; }
case 2:
tft.setTextColor(ST77XX_MAGENTA, ST77XX_BLACK);
tft.setCursor (20, 40);
tft.print(hsetON);
tft.setTextColor(ST77XX_RED, ST77XX_BLACK);
tft.setCursor (55, 40);
if (msetON < 10) tft.print('0');
tft.print(msetON);
if (enc1.isRight()) {
msetON++;
if (msetON >=60) msetON=0; }
if (enc1.isLeft()) {
msetON--;
if (msetON <=0) msetON=0; }
if (enc1.isPress()){
tset--;
break;
}
case 3:
tset = 1;
break;
}
}
while (enc1.isHolded() !=1 );
tft.fillScreen(ST77XX_BLACK);
}
void action2() { // ----------- Выполнение 2 пункта меню ---------------------------------
Что то ересь какая то...
Вот целый код.
#include "SPI.h" #include "Adafruit_GFX.h" #include <Adafruit_ST7735.h> #include <Adafruit_INA219.h> #include <BH1750.h> #include <DS3231.h> #define TFT_DC 9 #define TFT_CS 10 #define TFT_RST -1 #define CLK 2 #define DT 3 #define SW 4 #include <Wire.h> #include <AT24CX.h> AT24CX mem; byte luxset; byte hsetON =12; byte msetON =45; unsigned long lasttime; Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST); Adafruit_INA219 ina219; DS3231 rtc(SDA, SCL); BH1750 lightMeter; #include "GyverEncoder.h" Encoder enc1(CLK, DT, SW); int menu = 1; int tset = 1; void setup() { lightMeter.begin(); ina219.begin(); rtc.begin(); tft.initR(INITR_BLACKTAB); tft.setRotation(3); tft.fillScreen(ST77XX_BLACK); // tft.setTextSize(2); enc1.setType(TYPE1); enc1.setTickMode(AUTO); float busvoltage = 0; updateMenu(); } void loop() { if (enc1.isRight()) { menu++; updateMenu(); while (enc1.isRight()); } if (enc1.isLeft()) { menu--; updateMenu(); while (enc1.isLeft()); } if (enc1.isPress()) { tft.fillScreen(ST77XX_BLACK); tft.setTextColor(ST77XX_MAGENTA, ST77XX_BLACK); executeAction(); updateMenu(); delay(50); while (enc1.isPress()); } } void updateMenu(){ tft.setTextSize(2); switch (menu) { case 0: menu = 1; break; case 1: tft.setCursor(20, 10); tft.setTextColor(ST77XX_YELLOW, ST77XX_RED); tft.print("Set Time "); tft.setCursor(20, 30); tft.setTextColor(ST77XX_YELLOW, ST77XX_BLACK); tft.print("Luxometer "); tft.setCursor(20, 50); tft.setTextColor(ST77XX_YELLOW, ST77XX_BLACK); tft.print("Battery "); tft.setCursor(20, 70); tft.setTextColor(ST77XX_YELLOW, ST77XX_BLACK); tft.print("Exit "); break; case 2: tft.setCursor(20, 10); tft.setTextColor(ST77XX_YELLOW, ST77XX_BLACK); tft.print("Set Time "); tft.setCursor(20, 30); tft.setTextColor(ST77XX_YELLOW, ST77XX_RED); tft.print("Luxometer "); tft.setCursor(20, 50); tft.setTextColor(ST77XX_YELLOW, ST77XX_BLACK); tft.print("Battery "); tft.setCursor(20, 70); tft.setTextColor(ST77XX_YELLOW, ST77XX_BLACK); tft.print("Exit "); break; case 3: tft.setCursor(20, 10); tft.setTextColor(ST77XX_YELLOW, ST77XX_BLACK); tft.print("Set Time "); tft.setCursor(20, 30); tft.setTextColor(ST77XX_YELLOW, ST77XX_BLACK); tft.print("Luxometer "); tft.setCursor(20, 50); tft.setTextColor(ST77XX_YELLOW, ST77XX_RED); tft.print("Battery "); tft.setCursor(20, 70); tft.setTextColor(ST77XX_YELLOW, ST77XX_BLACK); tft.print("Exit "); break; case 4: tft.setCursor(20, 10); tft.setTextColor(ST77XX_YELLOW, ST77XX_BLACK); tft.print("Set Time "); tft.setCursor(20, 30); tft.setTextColor(ST77XX_YELLOW, ST77XX_BLACK); tft.print("Luxometer "); tft.setCursor(20, 50); tft.setTextColor(ST77XX_YELLOW, ST77XX_BLACK); tft.print("Battery "); tft.setCursor(20, 70); tft.setTextColor(ST77XX_YELLOW, ST77XX_RED); tft.print("Exit "); break; case 5: menu = 4; break; } } void executeAction() { switch (menu) { case 1: action1(); break; case 2: action2(); break; case 3: action3(); break; case 4: action4(); break; } } void action1() { // ----------- Выполнение 1 пункта меню --------------------------------- if (millis() - lasttime > 1000) { lasttime = millis(); tft.setTextColor(ST77XX_YELLOW, ST77XX_BLACK); tft.setCursor (20, 20); tft.print(rtc.getTimeStr()); } do { switch (tset) { case 0: tset =1; break; case 1: tft.setTextColor(ST77XX_RED, ST77XX_BLACK); tft.setCursor (20, 40); if (hsetON < 10) tft.print('0'); tft.print(hsetON); tft.setTextColor(ST77XX_MAGENTA, ST77XX_BLACK); tft.setCursor (55, 40); tft.print(msetON); if (enc1.isRight()) { hsetON++; if (hsetON >=24) hsetON=0; } if (enc1.isLeft()) { hsetON--; if (hsetON <=0) hsetON=0; } if (enc1.isPress()){ tset++; break; } case 2: tft.setTextColor(ST77XX_MAGENTA, ST77XX_BLACK); tft.setCursor (20, 40); tft.print(hsetON); tft.setTextColor(ST77XX_RED, ST77XX_BLACK); tft.setCursor (55, 40); if (msetON < 10) tft.print('0'); tft.print(msetON); if (enc1.isRight()) { msetON++; if (msetON >=60) msetON=0; } if (enc1.isLeft()) { msetON--; if (msetON <=0) msetON=0; } if (enc1.isPress()){ tset--; break; } case 3: tset = 1; break; } } while (enc1.isHolded() !=1 ); tft.fillScreen(ST77XX_BLACK); } void action2() { // ----------- Выполнение 2 пункта меню --------------------------------- byte luxset = mem.read(19); do { if (millis() - lasttime > 1000) { lasttime = millis(); float lux = lightMeter.readLightLevel(); tft.setCursor (10, 30); tft.print(lux); } tft.setCursor (10, 10); tft.print(luxset); if (enc1.isRight()) { luxset++; if (luxset >=100) luxset=99; } if (enc1.isLeft()) { luxset--; if (luxset <=0) luxset=1; } } while (enc1.isHolded() !=1); mem.write(19, luxset); tft.fillScreen(ST77XX_BLACK); } void action3() { // ----------- Выполнение 3 пункта меню --------------------------------- float minvoltage = mem.readFloat(24); do { if (millis() - lasttime > 1000) { lasttime = millis(); tft.setCursor (10, 30); tft.print(ina219.getBusVoltage_V()); } tft.setCursor (10, 10); tft.print(minvoltage); if (enc1.isRight()) { minvoltage=minvoltage+0.1; if (minvoltage >=25.1) minvoltage=25.0; } if (enc1.isLeft()) { minvoltage=minvoltage-0.1; if (minvoltage <=4.9) minvoltage=5.0; } } while (enc1.isHolded() !=1); mem.writeFloat(24, minvoltage); tft.fillScreen(ST77XX_BLACK); } void action4() { // ----------- Выполнение 4 пункта меню --------------------------------- tft.setTextSize(1); byte luxset = mem.read(19); float minvoltage = mem.readFloat(24); do { if (millis() - lasttime > 1000) { lasttime = millis(); tft.setCursor (5, 5); tft.print(rtc.getTimeStr()); tft.print(" / "); tft.print(rtc.getTemp()); tft.print(" C"); float lux = lightMeter.readLightLevel(); tft.setCursor (5, 30); tft.print(lux); tft.print(" / "); tft.print(luxset); tft.setCursor (5, 55); tft.print(ina219.getBusVoltage_V()); tft.print(" / "); tft.print(minvoltage); } } while (enc1.isHolded() !=1); tft.fillScreen(ST77XX_BLACK); }нажатие и удержание кнопки энкодера в несколько секунд.
Если кнопка не нажата, то после case 1 срезу же выполняется case2 - там брейка нет. После case 2 брейка, кстати, тоже нет. Так и должно быть? Думаю именно поэтому всё одновременно устанавливается.
Alex178, меня уже забодало это. Ну почему вы не организовываете меню как цифровой автомат с лямда функциями для управления. А потом в вашей ереси посторонним искать ошибки.
Если кнопка не нажата, то после case 1 срезу же выполняется case2 - там брейка нет. После case 2 брейка, кстати, тоже нет. Так и должно быть? Думаю именно поэтому всё одновременно устанавливается.
Строка 209 и 233. При нажатии должен быть брейк и переход на след. кейс. При повороте брейка нет.
И что это за название case 1,case 2 . Ну зачем так шифроваться . назовите clock, setHour,setMin,setSec.
И что это за название case 1,case 2 . Ну зачем так шифроваться . назовите clock, setHour,setMin,setSec.
А как? там по флажку tset, при нажатии 1 раз плюсует, при повторном отнимает.
Выпилил все ненужное.
#include "Adafruit_GFX.h" #include <Adafruit_ST7735.h> #define TFT_DC 9 #define TFT_CS 10 #define TFT_RST -1 #define CLK 2 #define DT 3 #define SW 4 byte hsetON =12; byte msetON =45; Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST); #include "GyverEncoder.h" Encoder enc1(CLK, DT, SW); int tset = 1; void setup() { tft.initR(INITR_BLACKTAB); tft.setRotation(3); tft.fillScreen(ST77XX_BLACK); tft.setTextSize(2); enc1.setType(TYPE1); enc1.setTickMode(AUTO); do { switch (tset) { case 0: tset =1; break; case 1: tft.setTextColor(ST77XX_RED, ST77XX_BLACK); tft.setCursor (20, 40); if (hsetON < 10) tft.print('0'); tft.print(hsetON); tft.setTextColor(ST77XX_MAGENTA, ST77XX_BLACK); tft.setCursor (55, 40); tft.print(msetON); if (enc1.isRight()) { hsetON++; if (hsetON >=24) hsetON=0; } if (enc1.isLeft()) { hsetON--; if (hsetON <=0) hsetON=23; } if (enc1.isPress()) { tset++; break; } case 2: tft.setTextColor(ST77XX_MAGENTA, ST77XX_BLACK); tft.setCursor (20, 40); tft.print(hsetON); tft.setTextColor(ST77XX_RED, ST77XX_BLACK); tft.setCursor (55, 40); if (msetON < 10) tft.print('0'); tft.print(msetON); if (enc1.isRight()) { msetON++; if (msetON >=60) msetON=0; } if (enc1.isLeft()) { msetON--; if (msetON <=0) msetON=59; } if (enc1.isPress()){ tset--; break; } } } while (enc1.isHolded() !=1 ); tft.fillScreen(ST77XX_BLACK); } void loop() { // put your main code here, to run repeatedly: }Ну если вам нравится гайвер с библиотеками, то почему не организовать так #63
Добавьте нужное и поиск косяков в меню упростися.
Ну если вам нравится гайвер с библиотеками, то почему не организовать так #63
Добавьте нужное и поиск косяков в меню упростися.
Мне понравилось, что у него в библиотеке есть нажатие и долгое нажатие. Что вполне инктуитивно. Если есть у Вас другая аналогичная, буду рад попробовать. И с меню у меня проблем нет. Есть проблема цикла в цикле. Внешний do пока долго не удерживать кнопку энкодера, и внутренний switch с флажком, для установки часов и минут. Внешний работает, а внутренний запускает оба блока одновременно при повороте энкодера, сразу меняет значение часов и значение минут.
Вынеси брейки 2 и 3 кейсов за операторные скобки условий.
63 строка и 87-я
Вы решили поспорить?
Брейк - это не переход на следующий кейс, а выход из свич целиком. А вот отсутствие брейка - как раз переход на следующий кейс.
А если еще и форматировать код, то его и читать удобнее и ошибки находить )))
Чем отличается?
Это:
switch (tset) { case 0: tset =1; break; case 1: tft.setTextColor(ST77XX_RED, ST77XX_BLACK); tft.setCursor (20, 40); if (hsetON < 10) { tft.print('0'); } tft.print(hsetON); tft.setTextColor(ST77XX_MAGENTA, ST77XX_BLACK); tft.setCursor (55, 40); tft.print(msetON); if (enc1.isRight()) { hsetON++; if (hsetON >=24) hsetON=0; } if (enc1.isLeft()) { hsetON--; if (hsetON <=0) { hsetON=23; } } if (enc1.isPress()) { tset++; break; } case 2: tft.setTextColor(ST77XX_MAGENTA, ST77XX_BLACK); tft.setCursor (20, 40); tft.print(hsetON); tft.setTextColor(ST77XX_RED, ST77XX_BLACK); tft.setCursor (55, 40); if (msetON < 10) { tft.print('0'); } tft.print(msetON); if (enc1.isRight()) { msetON++; if (msetON >=60) { msetON=0; } } if (enc1.isLeft()) { msetON--; if (msetON <=0) { msetON=59; } } if (enc1.isPress()){ tset--; break; } }От этого:
switch (tset) { case 0: tset =1; break; case 1: tft.setTextColor(ST77XX_RED, ST77XX_BLACK); tft.setCursor (20, 40); if (hsetON < 10) { tft.print('0'); } tft.print(hsetON); tft.setTextColor(ST77XX_MAGENTA, ST77XX_BLACK); tft.setCursor (55, 40); tft.print(msetON); if (enc1.isRight()) { hsetON++; if (hsetON >=24) hsetON=0; } if (enc1.isLeft()) { hsetON--; if (hsetON <=0) { hsetON=23; } } if (enc1.isPress()) { tset++; } break; case 2: tft.setTextColor(ST77XX_MAGENTA, ST77XX_BLACK); tft.setCursor (20, 40); tft.print(hsetON); tft.setTextColor(ST77XX_RED, ST77XX_BLACK); tft.setCursor (55, 40); if (msetON < 10) { tft.print('0'); } tft.print(msetON); if (enc1.isRight()) { msetON++; if (msetON >=60) { msetON=0; } } if (enc1.isLeft()) { msetON--; if (msetON <=0) { msetON=59; } } if (enc1.isPress()){ tset--; } break; }???
Всем спасибо. Разобрался. Все прекрасно заработало одним циклом.
Я все еще охреневаю от того, что в названии темы и что в итоге решали....
Alex178, меня уже забодало это. Ну почему вы не организовываете меню как цифровой автомат с лямда функциями для управления. А потом в вашей ереси посторонним искать ошибки.
а, шо такоэ лямбда функции?
Клапа, это новая секта такая, в которую Пух попал, не разбираясь
а, шо такоэ лямбда функции?
Пятнадцать лет он не был дома (с).))))
А можно пример такого меню на всём этом и во всей красе (простенькое)? Хочу понять как это реализовано, а то представить или возраст или уровень знаний не позволяют. Собаки этакие...
Ну вот под гайверовкие кнопки и простой вариант меню
/**/ template <typename T> inline Print & operator << (Print &s, T n) { s.print(n); return s; } typedef void (*pDo)(); #include <GyverButton.h> //github.com/AlexGyver/GyverLibs/blob/master/GyverButton/GyverButton.h GButton btnS(/*пин*/2);//кнопка селект GButton btnU(/*пин*/3);//кнопка вверх int var1 = 0, var2 = 0, var3 = 0; //некие переменные pDo Do_btnS_Click = [] {}; pDo Do_btnU_Click = [] {}; const byte page0 = 0;//главный экран const byte page1 = 10;// 1-я страница const byte page2 = 20;// 2-я страница const byte page3 = 30;// 3-я страница byte page; void goPage(byte p) { page = p; switch (page) { case page0: { Serial << "\npage0 var1:" << var1 << " var2:"<< var2 << " var3:" << var3; } Do_btnS_Click = [] {goPage(page1);}; Do_btnU_Click = [] {}; break; case page1: { Serial << "\npage1 var1:" << var1; } Do_btnS_Click = [] {goPage(page2);}; Do_btnU_Click = [] { var1++; if (var1 > 59)var1 = 0; goPage(page1); }; break; case page2: { Serial << "\npage2 var2:" << var2; } Do_btnS_Click = [] {goPage(page3);}; Do_btnU_Click = [] { var2++; if (var2 > 59)var2 = 0; goPage(page2); }; break; case page3: { Serial << "\npage2 var3:" << var3; } Do_btnS_Click = [] {goPage(page0);}; Do_btnU_Click = [] { var3++; if (var3 > 59)var3 = 0; goPage(page3); }; break; } } void init_menu() { goPage(page0); } void run_menu() {} //-------------------------------------- void setup() { Serial.begin(9600); init_menu(); } void loop() { btnS.tick(); btnU.tick(); if (btnS.isClick()) Do_btnS_Click(); if (btnU.isClick()) Do_btnU_Click(); run_menu(); }Управление двумя кнопками - Селект и Верх. Вывод в Сериал.