Skocz do zawartości

Rysowanie menu po kliknieciu


piottrr

Pomocna odpowiedź

Witam.

dostosowalem kod menu ktory znalazłem w sieci. Chciałem dodać opcję rysowania menu dopiero po kliknieciu przycisku ( pojawieniu sie stanu wysokiego e.w wykrycie bita? na styku)

#include <LiquidCrystal.h>

LiquidCrystal lcd(2, 3, 4, 5, 6, 7); //Informacja o podłączeniu nowego wyświetlacza
#define BTN_BACK  13
#define BTN_NEXT  9
#define BTN_PREV  1
#define BTN_OK    0




typedef struct {
 String label;
 int minVal;
 int maxVal;
 int currentVal;
 void (*handler)();
} STRUCT_MENUPOS;

typedef enum {
 BACK, NEXT, PREV, OK, NONE
} ENUM_BUTTON;


STRUCT_MENUPOS menu[4];

int currentMenuPos = 0;
int menuSize;
bool isInLowerLevel = false;
int tempVal;

void setup() {
// pinMode(10, INPUT); 

 Serial.begin(9600);
 lcd.begin(16, 2);

 pinMode(BTN_NEXT, INPUT_PULLUP);
 pinMode(BTN_PREV, INPUT_PULLUP);
 pinMode(BTN_BACK, INPUT_PULLUP);
 pinMode(BTN_OK, INPUT_PULLUP);

 menu[0] = {"Wilgotnosc", 0, 90, 5, NULL};
 menu[1] = {"Temperatura", 10, 1000, 15, NULL};
     menu[2] = {"Alarm Wilg", 0, 90, 0, NULL};
     menu[3] = {"Alarm Temp", 0, 90, 0, NULL};

int zadana_wilg = (menu[0].currentVal);
int zadana_temp = (menu[1].currentVal);
int alarm_wil = (menu[2].currentVal);
int alarm_temp = (menu[3].currentVal);

 menuSize = sizeof(menu)/sizeof(STRUCT_MENUPOS);
}

void loop() {




drawMenu();



}
ENUM_BUTTON getButton() {
 if(!digitalRead(BTN_BACK)) return BACK;
 if(!digitalRead(BTN_NEXT)) return NEXT;
 if(!digitalRead(BTN_PREV)) return PREV;
 if(!digitalRead(BTN_OK)) return OK;

 return NONE;
}

void drawMenu() {
 static unsigned long lastRead = 0;
 static ENUM_BUTTON lastPressedButton = OK;
 static unsigned int isPressedSince = 0;
 int autoSwitchTime = 500;

 ENUM_BUTTON pressedButton = getButton();

 if(pressedButton == NONE && lastRead != 0) {
   isPressedSince = 0;
   return;
 }
 if(pressedButton != lastPressedButton) {
   isPressedSince = 0;
 }

 if(isPressedSince > 3) autoSwitchTime = 70;
 if(lastRead != 0 && millis() - lastRead < autoSwitchTime && pressedButton == lastPressedButton) return;

 isPressedSince++;
 lastRead = millis();
 lastPressedButton = pressedButton;

 switch(pressedButton) {
   case NEXT: handleNext(); break;
   case PREV: handlePrev(); break;
   case BACK: handleBack(); break;
   case OK: handleOk(); break;
 }

 lcd.home();
 lcd.clear();

 if(isInLowerLevel) {
   lcd.print(menu[currentMenuPos].label);
   lcd.setCursor(0, 1);
   lcd.print(F("> "));

   if(menu[currentMenuPos].handler != NULL) {
     (*(menu[currentMenuPos].handler))();
   } else {
     lcd.print(tempVal);
   }
 } else {

   lcd.print(F("Menu glowne"));
   lcd.setCursor(0, 1);
   lcd.print(F("> "));

   lcd.print(menu[currentMenuPos].label);

}
}

void handleNext() {
 if(isInLowerLevel) {
   tempVal++;
   if(tempVal > menu[currentMenuPos].maxVal) tempVal = menu[currentMenuPos].maxVal;
 } else {
   currentMenuPos = (currentMenuPos + 1) % menuSize;
 }
}

void handlePrev() {
 if(isInLowerLevel) {
   tempVal--;
   if(tempVal < menu[currentMenuPos].minVal) tempVal = menu[currentMenuPos].minVal;
 } else {
   currentMenuPos--;
   if(currentMenuPos < 0) currentMenuPos = menuSize - 1;
 }
}

void handleBack() {
 if(isInLowerLevel) {
   isInLowerLevel = false;
 }
}

void handleOk() {
 if(menu[currentMenuPos].handler != NULL && menu[currentMenuPos].maxVal <= menu[currentMenuPos].minVal) {
   (*(menu[currentMenuPos].handler))();
   return;
 }
 if(isInLowerLevel) {
   menu[currentMenuPos].currentVal = tempVal;
   isInLowerLevel = false;
 } else {
   tempVal = menu[currentMenuPos].currentVal;
   isInLowerLevel = true;
 }
}







Aby zrobić moje założenie wywnioskowałem że dołożenie ifa przed drawMenu();

powinno załatwić sprawę.

A więc

if (digitalRead(11) == HIGH)
{
drawMenu();
}
else
{
lcd.clear();
lcd.print("Wilgotnosc ");
}

(..)

Kompletnie nie działa mi to. Po starcie arduino i tak widać menu ale nie da się w nim nawigować. Dopiero po podaniu wysokiego stanu na pin 11, mozna się poruszać w menu. Bo pojawieniu się LOW na pinie 11, pojawia się napis Wilgotność ale "miga". Jakby coś innego chciało się tam pojawić

Proszę o pomoc bo siędze nad tym już pare dobrych godzin i nie mam pomysłu 🙁

Pozdrawiam

EDIT:

zauważyłem jeszcze jeden problem.

Jesli po void loop() { dam polecenie np lcd.print("s"); to zamiast wyświetlić na lcd "s" wyrzuca same s na ekranie w kazdym miejscu obu lini( poradzilem sobie z tym... wystarczyło ustawić kursor :/ )

Link do komentarza
Share on other sites

A jak masz ten przycisk na pinie 11 podłączony? I czy to w ogóle jest przycisk?

Wszystko działa tak jak napisałeś: jeżeli na pinie 11 jest stan wysoki to wywoływana jest funkcja do rysowania menu, jeżeli nie (else) to wyświetlacz jest czyszczony, a następnie wrzucany jest na niego napis wilgotność - dlatego miga.

Po pierwsze pokazywałbym kod po modyfikacjach.

wprowadziłbym zmienną typu boolean:

 boolean rysujMenu = false;

w funckji setup() zadeklarowałbym pin 11 jako wejście z włączonym rezystorem podciągającym (skoro nie wiem, jak ty to robisz, zrobię po swojemu):

void setup() {
...
pinMode(11, INPUT_PULLUP);
...
} 

i teraz w funkcji loop(), jeżeli na pinie 11 pojawi się stan niski to zmienię wartość zmiennej rysujMenu z false na true lub na odwrót:

void loop() {
..
if (digitalRead == LOW) {
 delay(100); //odczekaj 0.1s taki pseudo-debaounce
   if (digitalRead == LOW) {
     delay(400); już można puścić przycisk :)
       if (rysujMenu == True) {
          rysujMenu = False;
 } else {
   rysujMenu = True;
}
}
..

i od zmiennej rysujMenu uzależniłbym Menu tak jak pisałeś już wcześniej:

if (rysujMenu) { 
drawMenu(); 
} 
else 
{ 
lcd.clear(); 
lcd.print("Wilgotnosc "); 
} 

Czysto teoretycznie powinno działać - wnioskuję po stwierdzeniu, że możesz poruszać się po menu, gdy na pinie 11 jest stan wysoki.

Weź też poprawkę, że funkcja loop wykonuje się bez przerwy - mikrokontroler nie czeka na wciśnięcie przycisku.

Kodu nie sprawdzałem i pisałem z głowy, więc trzeba brać poprawkę, że potrzebne będą jeszcze poprawki.

  • Lubię! 1
Link do komentarza
Share on other sites

A jak masz ten przycisk na pinie 11 podłączony? I czy to w ogóle jest przycisk?

Wszystko działa tak jak napisałeś: jeżeli na pinie 11 jest stan wysoki to wywoływana jest funkcja do rysowania menu, jeżeli nie (else) to wyświetlacz jest czyszczony, a następnie wrzucany jest na niego napis wilgotność - dlatego miga.

Po pierwsze pokazywałbym kod po modyfikacjach.

(...)

dziękuje Zero za poświecenie mi czasu i pochylenie się nad moim problemem. Dodałem Twój kod( z małymi poprawkami literówek itp 🙂 ale to dlatego ze szybko pisałes z "palca")

całość wygląda teraz tak

#include <LiquidCrystal.h>

LiquidCrystal lcd(2, 3, 4, 5, 6, 7); //Informacja o podłączeniu nowego wyświetlacza
#define BTN_BACK  13
#define BTN_NEXT  9
#define BTN_PREV  8
#define BTN_OK    0

boolean rysujMenu = false;



typedef struct {
 String label;
 int minVal;
 int maxVal;
 int currentVal;
 void (*handler)();
} STRUCT_MENUPOS;

typedef enum {
 BACK, NEXT, PREV, OK, NONE
} ENUM_BUTTON;


STRUCT_MENUPOS menu[4];

int currentMenuPos = 0;
int menuSize;
bool isInLowerLevel = false;
int tempVal;

void setup() {

 // pinMode(10, INPUT);
 pinMode(10, INPUT_PULLUP); 

 Serial.begin(9600);
 lcd.begin(16, 2);

 pinMode(BTN_NEXT, INPUT_PULLUP);
 pinMode(BTN_PREV, INPUT_PULLUP);
 pinMode(BTN_BACK, INPUT_PULLUP);
 pinMode(BTN_OK, INPUT_PULLUP);

 menu[0] = {"Wilgotnosc", 0, 90, 30, NULL};
 menu[1] = {"Temperatura", 10, 1000, 15, NULL};
 menu[2] = {"Alarm Wilg", 0, 90, 0, NULL};
 menu[3] = {"Alarm Temp", 0, 90, 0, NULL};



 menuSize = sizeof(menu) / sizeof(STRUCT_MENUPOS);
}

void loop() {

 if (digitalRead(10) == LOW) { 
 delay(100); //odczekaj 0.1s taki pseudo-debaounce 
   if (digitalRead(10) == LOW) { 
     delay(400); //już można puścić przycisk :) 
       if (rysujMenu == true) { 
          rysujMenu = false; 
          lcd.clear();
       }


 else { 
   rysujMenu = true; 
}

 }
 }

 int zadana_wilg = (menu[0].currentVal);
 int zadana_temp = (menu[1].currentVal);
 int alarm_wil = (menu[2].currentVal);
 int alarm_temp = (menu[3].currentVal);



if (rysujMenu == true) {
 drawMenu();

}
else{





lcd.setCursor(0,0);

lcd.print("Wilgotnosc "); 
lcd.setCursor(0,1);
lcd.print(rysujMenu);

}



}

ENUM_BUTTON getButton() {
 if (!digitalRead(BTN_BACK)) return BACK;
 if (!digitalRead(BTN_NEXT)) return NEXT;
 if (!digitalRead(BTN_PREV)) return PREV;
 if (!digitalRead(BTN_OK)) return OK;

 return NONE;
}

void drawMenu() {
 static unsigned long lastRead = 0;
 static ENUM_BUTTON lastPressedButton = OK;
 static unsigned int isPressedSince = 0;
 int autoSwitchTime = 500;

 ENUM_BUTTON pressedButton = getButton();

 if (pressedButton == NONE && lastRead != 0) {
   isPressedSince = 0;
   return;
 }
 if (pressedButton != lastPressedButton) {
   isPressedSince = 0;
 }

 if (isPressedSince > 3) autoSwitchTime = 70;
 if (lastRead != 0 && millis() - lastRead < autoSwitchTime && pressedButton == lastPressedButton) return;

 isPressedSince++;
 lastRead = millis();
 lastPressedButton = pressedButton;

 switch (pressedButton) {
   case NEXT: handleNext(); break;
   case PREV: handlePrev(); break;
   case BACK: handleBack(); break;
   case OK: handleOk(); break;
 }

 lcd.home();
 lcd.clear();

 if (isInLowerLevel) {
   lcd.print(menu[currentMenuPos].label);
   lcd.setCursor(0, 1);
   lcd.print(F("> "));

   if (menu[currentMenuPos].handler != NULL) {
     (*(menu[currentMenuPos].handler))();
   } else {
     lcd.print(tempVal);
   }
 } else {

   lcd.print(F("Menu glowne"));
    lcd.print(rysujMenu);
   lcd.setCursor(0, 1);
   lcd.print(F("> "));

   lcd.print(menu[currentMenuPos].label);

 }
}

void handleNext() {
 if (isInLowerLevel) {
   tempVal++;
   if (tempVal > menu[currentMenuPos].maxVal) tempVal = menu[currentMenuPos].maxVal;
 } else {
   currentMenuPos = (currentMenuPos + 1) % menuSize;
 }
}

void handlePrev() {
 if (isInLowerLevel) {
   tempVal--;
   if (tempVal < menu[currentMenuPos].minVal) tempVal = menu[currentMenuPos].minVal;
 } else {
   currentMenuPos--;
   if (currentMenuPos < 0) currentMenuPos = menuSize - 1;
 }
}



void handleBack() {
 if (isInLowerLevel) {
   isInLowerLevel = false;
 }
}

void handleOk() {
 if (menu[currentMenuPos].handler != NULL && menu[currentMenuPos].maxVal <= menu[currentMenuPos].minVal) {
   (*(menu[currentMenuPos].handler))();
   return;
 }
 if (isInLowerLevel) {
   menu[currentMenuPos].currentVal = tempVal;
   isInLowerLevel = false;
 } else {
   tempVal = menu[currentMenuPos].currentVal;

   isInLowerLevel = true;
 }
}

działa ale jak wejde do menu i je opuszczę i chcę znowu wejść niestety nie wpuszcza mnie. Dodałem sobie wyswietlenie stanu rysujMenu i zmienia zmienna prawidłowo. Siędze już chwile dodaje ify, inne sprawdzenia stanu i nie mogę wpaść na to co może być przyczyną takiego stanu rzeczy. Dodatkowo lcd.clear(); w momencie wyświetlenia napisu wilgotność robi na wyświetlaczu niezłą animację przeniosłem moment czyszczenia do funkcji sprawdzającej stan zmiennej

btw: jak ja lubie te fora postawione na Przemku, kawał dobrego skryptu nie to co teraz wszystko przechodzi na fejsbuki 🙁

Edit kolejny,

zauważyłem że po kolejnej probie wejścia do menu gdy jak twierdzilem menu się nie wyświetla wystarczy wcisnąć przycisk do nawigowania prawo lewo np na pinie 8 i menu się pojawia. Hmm czyżby jakiś problem z brakiem czyszczenia menu przy ponownej próbie wejscia ?

dodałem

if (rysujMenu == true) {

lcd.print("test");

drawMenu();

}

wciskanie przycisku od rysowania menu pokazuje napis test, ukrywa i ponownie go pokazuje więc funkcja działa.

Link do komentarza
Share on other sites

Fajnie, że trochę Cię naprowadziłem, a kod pisałem "z głowy, czyli z niczego" 😉 {jak zwał tak zwał}

Powiem szczerze, że nie zagłębiałem się w ten kod odpowiedzialny za menu, bo mam jeszcze spore braki.

Ale przypominają mi się pierwsze podejścia i "sklejki" mojego kodu z kodem z netu, oczywiście zawsze coś nie działało.

Czy to Twoje urządzenie już działa? Jeżeli nie, to jak ma działać? Ciężko oceniać po dwóch postach, ale można odnieść wrażenie, że zaczynasz od wodotrysków... 😕 (może uda mi się odwrócić uwagę od mojej niekompetencji tymi "chytrymi" pytaniami ) 😳

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

a wiec urządzenie ma być dość proste. Czujnik DHT11, pomiar temperatury i wilgotności, odpalenie przekaźników gdy reguła będzie spełniona, do tego jeszcze parę pierdół zabezpieczających jak badanie czy czujnik działa prawidłowo itp. Sama cześć kodu działała ok ale panował w nim wielki bajzel ( z natury jestem bałaganiarzem a w kodzie to nie przejdzie) postanowiłem że zrobię wszystko schludnie na nowo no i przy okazji wymyśliłem sobie menu 🙂

Planuje wyciągać podane przez użytkownika zmienne, zapisywać do eprom oraz podmieniać domyślne ustawienia w menu danymi z epromu ( z tym będzie też coś czuje spory problem bo owe menu operuje na "tymczasowej" zmiennej no ale zoabcze- uczę się wiec też jestem nastawiony że będzie trzeba szukać innej drogi )

Link do komentarza
Share on other sites

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.