Felgrip Napisano Listopad 12, 2022 Udostępnij Napisano Listopad 12, 2022 Dzien dobry, Mam pewien problem z budowa menu, ogólnie chciałem zrobić menu które wyświetla mi dane na wyświetlaczu LCD, parametry z czujników i możliwość dodania daty, godziny z klawiatury. Problem polega na tym ze przy dodawaniu np dnia program dodaje mi tylko pierwszy znak który nacisnę na klawiaturze, po następnym naduszeniu klawisza zmienia wartość, a chciałbym żeby zapisywało poprzednie znaki. void ustawienieDnia(String a,String b,int c,char klawisz) { if (klawisz && klawisz != 'A' && klawisz != 'B' && klawisz != 'C' && klawisz != 'D' && klawisz != '#' && klawisz != '*'){ lcd.print(klawisz); a = String(klawisz); //b.concat(a); a.length(); c = a.toInt(); Serial.println(c); } } Próbowałem cos zakombinować z komenda length, lecz nie za bardzo wiem jak to ugryźć ;/ Cytuj Link do komentarza Share on other sites More sharing options...
Treker (Damian Szymański) Listopad 14, 2022 Udostępnij Listopad 14, 2022 @Felgrip witam na forum 🙂 Każdy klawisz wciskany na klawiaturze jest odczytywany niezależnie. Układ "nie wie", że to pierwsza z dwóch cyfr itd. W najprostszej wersji musisz samodzielnie dorobić taki mechanizm. Zakładając, że chodzi o liczby dwucyfrowe mógłbyś to zrobić następująco (to tylko ogólna idea, bo jest tam kilka haczyków): Jeśli wciśnięto klawisz i zmienna pomocnicza równa się 0 to: Odczytujesz cyfrę i zapisujesz ją jako wynik Zwiększasz zmienną pomocniczą o 1 Jeśli wciśnięto klawisz i zmienna pomocnicza równa się 1 to: Wcześniejszy wynik mnożysz razy 10 (aby przesunąć wartość z jedności na dziesiątki) Odczytujesz cyfrę i dodajesz ją do wyniku (otrzymujesz wtedy liczbę dwucyfrową) Zwracasz dwucyfrową wartość 1 Cytuj Link do komentarza Share on other sites More sharing options...
SzpondeRR Listopad 14, 2022 Udostępnij Listopad 14, 2022 Próbowałem zrobić według tego co mi na pisałeś, lecz napotkałem problem taki że po po wciśnięciu przycisku widzi mi pierwszego ifa, po czym zamiast się zatrzymać i poczekać na następne wciśnięcie klawisza leci dalej i wpisuje mi liczbę np. 11, 33 itd. możliwe jest jest to przez moją nieuwagę nie jestem za dobry w programowaniu i pewnie nie rozumiem pewnych rzeczy.😄 Próbowałem to zrobić jeszcze na switchu ale tu znowu nie widziało mi naciśniętego klawisza. Myślałem jeszcze nad zrobieniu tablic dla wyboru danego dnia, miesiąc ale myślę ze problem leży gdzie indziej. Nie mam pomysły na to. Jeżeli maci jakieś poradniki czy kursy gdzie mógłbym się podszkolić, chętnie skorzystam.😀 Cytuj Link do komentarza Share on other sites More sharing options...
Treker (Damian Szymański) Listopad 15, 2022 Udostępnij Listopad 15, 2022 @SzpondeRR czy jesteś tą samą osobą, która założyła ten temat? Pytam, ponieważ pierzesz z jakiegoś innego konta. Jeśli tak, to daj znać, które konto ma zostać aktywne - połączę je. Wracając do tematu - pokaż swój kod, to łatwiej będzie pomóc 🙂 Cytuj Link do komentarza Share on other sites More sharing options...
Polecacz 101 Zarejestruj się lub zaloguj, aby ukryć tę reklamę. Zarejestruj się lub zaloguj, aby ukryć tę reklamę. 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
Felgrip Listopad 15, 2022 Autor tematu Udostępnij Listopad 15, 2022 (edytowany) Konto Felgrip może zostać, do tego drugiego zapomniałem hasła już jakiś czas temu dlatego założyłem drugie, w sumie nawet nie wiem dlaczego post został napisany z tego starego konta , Jeżeli chodzi o kod wrzucę całości, możliwe ze problem leży w innym miejscu. #include <LiquidCrystal.h> #include <Keypad.h> LiquidCrystal lcd(2, 3, 4, 5, 6, 7); const byte ROWS = 4; //four rows const byte COLS = 4; //three columns char keys[ROWS][COLS] = { {'1','2','3' , 'A'}, {'4','5','6' , 'B'}, {'7','8','9' , 'C'}, {'*','0','#' , 'D'} }; byte rowPins[ROWS] = {50, 51, 52, 53}; //Piny, do których podłączamy wyprowadzenia od rzędów byte colPins[COLS] = {46, 47, 48 , 49}; //Piny, do których kolumn wyprowadzenia od rzędów Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS ); bool lock = 1; bool lock1 = 1; int A = 0; int B = 0; int C = 0; String string1 = String(); String string2 = String(); String string3 = String(); String string4 = String(); String string5 = String(); String cyfra1,cyfra2,cyfra3,cyfra4,cyfra5; int dzien, miesiac, rok, godzina, minuta; void setup() { Serial.begin(9600); lcd.begin(16, 2); lcd.setCursor(0, 0); lcd.print("Projekt Trakera"); } void loop() { char klawisz = keypad.getKey(); switch (A) { case 0: // poruszanie do góry if(lock == 1) { lcd.clear(); lcd.home(); lock = 0; lcd.print("projekt trakera"); lcd.setCursor(0, 1); lcd.print("BY Rafal & Damian"); } if (klawisz == 'A'){ A++; } break; case 1: // poruszanie do dołu if (lock == 0){ lcd.clear(); lcd.home(); lock = 1; lcd.print("Ustawienie czasu"); } switch (C) // posaczefolne parametry { case 0: if (lock1 == 1){ lock1 = 0; } if(klawisz == 'C'){ C++; } break; case 1: if (lock1 == 0){ lcd.clear(); lcd.print("Dzien :"); lcd.setCursor(0,1); lock1 = 1; } ustawienieDnia(dzien,klawisz); if(klawisz == 'C') C++; if (klawisz == 'D') C--; break; case 2: if(lock1 == 1){ lcd.clear(); lcd.print("Miesiac :"); lcd.setCursor(0,1); lock1 = 0; } ustawienieDnia(cyfra2,string2,miesiac,klawisz); if(klawisz == 'C'){ C++; } if (klawisz == 'D') C--; break; case 3: if(lock1 == 0){ lcd.clear(); lcd.print("Rok :"); lcd.setCursor(0,1); lock1 = 1; } ustawienieDnia(cyfra3,string3,rok,klawisz); if(klawisz == 'C'){ C++; } if (klawisz == 'D') C--; break; case 4: if(lock1 == 1){ lcd.clear(); lcd.print("Godzina :"); lcd.setCursor(0,1); lock1 = 0; } ustawienieDnia(cyfra4,string4,godzina,klawisz); if(klawisz == 'C'){ C++; } if (klawisz == 'D') C--; break; case 5: if(lock1 == 0){ lcd.clear(); lcd.print("Minuta :"); lcd.setCursor(0,1); lock1 = 1; } ustawienieDnia(cyfra5,string5,minuta,klawisz); if (klawisz == 'D') C--; if(klawisz == '*') break; } // koniec switcha C if (klawisz == 'A') A++; if (klawisz == 'B') A--; break; case 2: if(lock == 1){ lcd.clear(); lcd.print("parametry"); lock = 0; } if (klawisz == 'A') A++; if (klawisz == 'B') A--; break; case 3: { lcd.clear(); lcd.print("3"); } break; case 4: { break; } case 5: { break; } } } void ustawienieDnia(int c,char klawisz) { String liczba1,liczba2; String cyfra, cyfra1; int liczbaWpisana; bool pomocnicza = 0; if (pomocnicza == 0) pomocnicza++; if(klawisz && klawisz != 'A' && klawisz != 'B' && klawisz != 'C' && klawisz != 'D' && klawisz != '#' && klawisz != '*'){ lcd.print(klawisz); liczba1 = String(klawisz); cyfra.length(liczba1); liczbaWpisana = cyfra.toInt(); Serial.println(liczbaWpisana); } if (pomocnicza == 1) pomocnicza = 0; if ( klawisz && klawisz != 'A' && klawisz != 'B' && klawisz != 'C' && klawisz != 'D' && klawisz != '#' && klawisz != '*'){ lcd.print(klawisz); liczba2 = String(klawisz); cyfra1.concat(liczba2); c = cyfra1.toInt()+(liczbaWpisana*10); Serial.println(c); } } Nie wiem dlaczego po wpisaniu pierwszej liczby program nie czeka na podanie następnej liczby tylko leci dalej, próbowałem również zamiast ifa, na switchu zrobić podobny warunek ale efekt był jeszcze gorszy bo nie widziało żadnego wciśniętego przypisku, program pisany na szybko dlatego może być kapkę nieczytelny Edytowano Listopad 15, 2022 przez Felgrip Źle dodany kod programu. Cytuj Link do komentarza Share on other sites More sharing options...
Treker (Damian Szymański) Listopad 16, 2022 Udostępnij Listopad 16, 2022 12 godzin temu, Felgrip napisał: program pisany na szybko dlatego może być kapkę nieczytelny No faktycznie, lepiej chyba usiąść do tego na spokojnie. Na początek stwórz nowy szkic i spróbuj w nim napisać tylko ten jeden fragment, który będzie zmieniał jedną wartość - pomiń na razie całe menu. Skup się na ustawianiu wartości. Tak będzie łatwiej naprawiać kod. Jak całość zadziała to dopiero będzie sens obudowywać to resztą kodu i całym menu - przy okazji wyjdą pewnie również jakieś inne problemy, ale będzie wiadomo, że podstawowa część działa poprawnie 🙂 Cytuj Link do komentarza Share on other sites More sharing options...
kaczakat Listopad 17, 2022 Udostępnij Listopad 17, 2022 Bardzo sobie komplikujesz tymi cyferkami na klawiaturze. Do zmiany opcji menu w aucie wystarcza 1 przycisk. Co ciekawe w czasie obsługi menu komputer pokładowy dalej obsługuje wszystkie elementy samochodu, nie jest odcinany zapłon, wtrysk paliwa, czy możliwość otwarcia blokady drzwi, bo wszedłeś ustawić zegarek. Kocioł mi nie przestaje sterować wentylatorem, bo wszedłem w menu sprawdzić temperaturę zewnętrzną. Nie ma co się umartwiać jednym przyciskiem, jak już masz ich 16, ale prościej byłoby ograniczyć ich funkcje do IN/OUT/+/-. Na pewno w czasie obsługi menu program nie powinien się tu zatrzymywać, to tylko tak może wyglądać na ekranie. Można np. w loop podzielić sobie całość na 3 sekcje, obsługa odczytów i wyjść A, wyświetlanie wartości na ekranie B, wyświetlanie menu C. Normalnie program powinien działać po drodze AB. Jeśli jakikolwiek przycisk zostanie dotknięty to przełączasz zmienną z 0 na 1 i dzięki niej nie wchodzisz w sekcję B, a zamiast tego wchodzisz w C. Oczywiście program tu nie stoi, wchodzi tu, robi coś lub niewiele, wychodzi, przechodzi przez sekcję A, pomija wyświetlanie wartości B i wchodzi w C. I tak w kółko drogą AC. W menu zlicza czas od ostatniego dotknięcia klawiatury, jeśli minie np. 20s to znaczy, że ktoś zasłabł, zszedł, ma coś pilniejszego do robienia i nie ma sensu tu dłużej wchodzić, przełącza zmienną z 1 na 0 i program działa dalej lecąc drogą AB. Oczywiście ani w B ani w C program nie drukuje nic na LCD częściej niż to jest potrzebne. Jeśli jest jakaś nowa informacja do wyświetlenia, albo minęła 1s od ostatniego wydruku to można wydrukować, a inaczej to po co, program się zapoci ciągłym wysyłaniem danych niepotrzebnie zabierając czas. Więc tu najważniejszy jest pomiar czasu. Żeby nie było, że w A ciągle coś robi, tu też powinno być ustalone dla każdej czynności, jak często jest niezbędne robienie czegoś, robienie tych rzeczy tak często jak trzeba i nie częściej, by jak najszybciej ponownie wykonać te pilne rzeczy. Więc przede wszystkim mierzenie czasu, czy już trzeba coś zrobić. Jeśli program wszedł w C to oczywiście drukuje nowy stan i przy pierwszym wejściu tylko sobie zanotuje czasy, ustawi się na pierwszym elemencie menu i wychodzi, przy drugim sprawdzi czy wciśnięto jakiś przycisk, jak tak to coś zrobi, jak nie to tylko sprawdzi czy upłynęła sekunda, jak upłynęła sekunda to ją zliczy++, jak zliczy++>20, to wszystko tu wyzeruje i przełączy na B. Jak jednak zauważy przycisk IN to w kontekście miejsca gdzie jest, np. na menu0 wejdzie w edycję zmiennej menu0, przy następnych wejściach będzie wiedział, że tu jesteś bo sobie zapisał w zmiennej lokalnej static, że jest na pozycji menu0 i w drugiej że menu jest aktywne, wczyta do zmiennej pomocniczej int wartość menu0, jak przy kolejnym wejściu zauważy wciśnięcie + lub - to wyzeruje zliczanie czasu bezczynności w menu i zrobi akcję zmienna++ albo zmienna--, jak program będzie umiał obsługiwać długie wciśnięcie przycisku to nawet zmienna+=10 albo zmienna-=10, a potem i o 100. Jak znowu ktoś wciśnie IN, to te zmiany zapisze do menu0, jak ktoś jednak wciśnie OUT to program to porzuci zwalniając aktywność menu, a jak w ogóle zaniecha dalszych działań na 20s to program się wycofa, wyzeruje menu i przejdzie na drogę AB. Tak samo jak nie jest aktywna żadna pozycja menu wciśnięcie OUT spowoduje wyzerowanie zmiennych menu i powrót na drogę AB. Większość rzeczy można w menu zapisać w int, godzina i minuty dnia, można je zliczać 0-23, 0-59, albo w jednym int jako 0-1439, bo tyle jest różnych minut w ciągu doby (1440). Ktoś potrzebuje wyświetlić potem liczbę h:m to wystarczy minuty/60:minuty%60, sprintf to ładnie sformatuje by był to napis typu 00:00. sprintf(napis,"%02d:%02d ",minuty/60,minuty%60,); - napis to powinna być cała linia do wyłania na LCD, nie będzie problemu jakiś artefaktów. Jak + - zostanie wciśnięty w kontekście nieaktywnego menu to program przesunie pozycję menu. Z kalendarzem można zrobić podobnie, jest prosty algorytm do wyguglania by ustalić czy rok jest przestępny, można sobie zapisać start na rok 2020, bo po co się bardziej cofać w czasie, rok ma 365 lub 366 dni, miesiąc ma 28, 29, 30 lub 31 dni, zmienna int wystarczy na zapis daty przez kolejnych 40 lat. I tak trzeba mieć tablicę z miesiącami by nie ustawić 31 listopada czy 30 luty, ale może tu faktycznie byłaby zbyt duża gimnastyka i prościej zrobić rok w bajcie, a tylko dni i miesiące w int. Temperaturę z dokładnością do 0.01 (+/-160,00oC, większy zakres też, tylko już w int32_t) też można zapisać w int, histerezę. Ty to możesz pokazać na menu jako 14.45oC, ale w zmiennej to będzie 1445 tylko wydrukowane sprintf tuż przed pokazaniem na ekran jako temp/100.temp%100. A jak już ogarniesz, że wszystko (prawie) może być int to jako menu zrobisz sobie tablice int, przez index tablicy wczytasz tekst danej pozycji z tablicy tekstów i zmienną do jej przechowywania z tablicy int -proste menu jednopoziomowe. Można mieć też tablice funkcji jeśli zmienne w menu muszą być obsługiwane w bardziej finezyjny sposób niż ++/--. No i sekcja B, jak jeszcze nie wiesz co tu przede wszystkim trzeba robić, to tak, trzeba mierzyć czas, by nie robić nic częściej niż jest to niezbędne. No i jak teraz patrzę na twój program, to nigdzie nie mierzysz czasu. Z Google znajdziesz pewnie gotowce do tworzenia menu. Pierwsze co robię to test migania led, jeśli po wejściu w opcje menu moja testowa led przestaje migać co 100ms to taka biblioteka leci do kosza. Są menu na tablicach, w strukturach i inne wynalazki. Super jak jeszcze całość jest we flash. Wg mnie jest to jeden z trudniejszych tematów w Arduino. Dużo prościej jest wysłać wszystkie parametry do programu linijką tekstu z terminala przez USB, albo z telefonu przez Bluetooth. 1 Cytuj Link do komentarza Share on other sites More sharing options...
Felgrip Listopad 17, 2022 Autor tematu Udostępnij Listopad 17, 2022 Udało mi się znaleźć znaleźć pośrednie rozwiązanie Wystarczyło dodać kolejne casy aby wpisać pierwsza i druga liczbę. Pytanie czy jest możliwość wpisania wartości dnia w jednym case ? #include <LiquidCrystal.h> #include <Keypad.h> LiquidCrystal lcd(2, 3, 4, 5, 6, 7); const byte ROWS = 4; //four rows const byte COLS = 4; //three columns char keys[ROWS][COLS] = { {'1','2','3' , 'A'}, {'4','5','6' , 'B'}, {'7','8','9' , 'C'}, {'*','0','#' , 'D'} }; byte rowPins[ROWS] = {50, 51, 52, 53}; //Piny, do których podłączamy wyprowadzenia od rzędów byte colPins[COLS] = {46, 47, 48 , 49}; //Piny, do których kolumn wyprowadzenia od rzędów Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS ); bool lock = 1; bool lock1 = 1; int A = 0; int B = 0; int C = 0; int dzien, miesiac, rok, godzina, minuta; int liczba_Wpisana; // zmienna potrzeba wyliczenia dnia void setup() { Serial.begin(9600); lcd.begin(16, 2); lcd.setCursor(0, 0); lcd.print("Projekt Trakera"); } void loop() { // lcd.setCursor(9, 1); //lcd.print(millis() / 1000); //lcd.setCursor(0, 1); char klawisz = keypad.getKey(); switch (A) { case 0: // if(lock == 1) { lcd.clear(); lcd.home(); lock = 0; lcd.print("projekt trakera"); lcd.setCursor(0, 1); lcd.print("BY Rafal & Damian"); } if (klawisz == 'A'){ A++; } break; case 1: // if (lock == 0){ lcd.clear(); lcd.home(); lock = 1; lcd.print("Ustawienie czasu"); } switch (C) // wybór opcji z menu { case 0: if (lock1 == 1){ lock1 = 0; } if(klawisz == 'C'){ C++; } break; case 1: //"dzien" pierwsza liczba if (lock1 == 0){ lcd.clear(); lcd.print("Dzien pierwsza liczba :"); lcd.setCursor(0,1); lock1 = 1; } ustawienieDnia(klawisz); if(klawisz == 'C') C++; if (klawisz == 'D') C--; break; case 2: //"dzien" druga liczba if (lock1 == 1){ lcd.clear(); lcd.print("Dzien druga liczba :"); lcd.setCursor(0,1); lock1 = 0; } ustawienie_Dnia1(klawisz,dzien); if(klawisz == 'C') C++; if (klawisz == 'D') C--; break; } // switch C } // switch A } // loop void ustawienieDnia(char klawisz) { String liczba1; String cyfra; if(klawisz && klawisz != 'A' && klawisz != 'B' && klawisz != 'C' && klawisz != 'D' && klawisz != '#' && klawisz != '*'){ lcd.print(klawisz); liczba1 = String(klawisz); cyfra.concat(liczba1); liczba_Wpisana = cyfra.toInt()*10; Serial.println(liczba_Wpisana); // liczba wpisana return liczba_Wpisana; } } void ustawienie_Dnia1(char klawisz, int b) { String liczba; String cyfra; if ( klawisz && klawisz != 'A' && klawisz != 'B' && klawisz != 'C' && klawisz != 'D' && klawisz != '#' && klawisz != '*'){ lcd.print(klawisz); liczba = String(klawisz); cyfra.concat(liczba); b = cyfra.toInt() + liczba_Wpisana; // b - liczba dnia zapisana jako dziesiątka Serial.println(b); Cytat No i jak teraz patrzę na twój program, to nigdzie nie mierzysz czasu. Ogólnie to piszę prace automatyzacji stacji fotowoltaicznej i potrzebna jest mi możliwość ustawiania daty aby zaprezentować ze w dany dzień i o danej godzinie panele będą się ustawiały prostopadle do słońca, a do mierzenia czasu mam dołożony moduł czasu rzeczywistego według którego panele w trybie automatycznym będą się poruszały. Dzięki za post, trochę rozjaśniło mi to sytuację i możliwe ze za jakiś czas jeszcze poprawie menu Cytuj Link do komentarza Share on other sites More sharing options...
Treker (Damian Szymański) Listopad 18, 2022 Udostępnij Listopad 18, 2022 8 godzin temu, Felgrip napisał: Wystarczyło dodać kolejne casy aby wpisać pierwsza i druga liczbę. Pytanie czy jest możliwość wpisania wartości dnia w jednym case ? Zanim pójdziesz dalej to poświęć trochę czasu, aby uporządkować formatowanie w tym programie - jak tego nie zrobisz to za jakiś czas sam się pogubisz. Nawet tutaj wyżej brakuje na końcu program się "urywa". Jak nie chcesz robić tego ręcznie to skorzystaj chociaż z opcji automatycznego formatowania w edytorze. Zastanów się też ogólnie ile jeszcze rzeczy będzie później chciał tam ustawiać, bo może się okazać, że te klawiatura (w obecnej formie) będzie tylko utrudnieniem - gdybyś zdecydował się na 5 przycisków (typu zwiększ/zmniejsz/dalej/wstecz/zatwierdź) zamiast klawiatury to te programy byłyby właściwie dużo prostsze. Cytuj Link do komentarza Share on other sites More sharing options...
Pomocna odpowiedź
Dołącz do dyskusji, napisz odpowiedź!
Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!