lewwus Napisano Styczeń 2, 2021 Udostępnij Napisano Styczeń 2, 2021 Cześć, chce zrobić termostat, który będzie oparty na dwóch rożnych ekranach które będą przełączane jednym guzikiem. Część, kodu mam napisane jednak doszedłem do momentu w którym nie wiem co może być nie tak. Przyjmę każda pomoc w ruszeniu z miejsca 🙂 Wiem, że podobny wątek był poruszany na forum jednak nie chce zmieniać pierwotnego problemu innego uzytkownika. Poniżej załączam kod na jakim działam. Część kodu jest napisana prze zemnie a część zapożyczona z gotowego. #include <Wire.h> #include <LiquidCrystal_I2C.h> #include "dht.h" LiquidCrystal_I2C lcd(0x3F,20,4); dht DHT22; #define DHT22PIN 13 int menu =1; // This variable stores the current Screen number boolean hasChanged = true; const int buttonPin = 10; // the number of the pushbutton pin int buttonState; // the current reading from the input pin int lastButtonState = LOW; // the previous reading from the input pin unsigned long lastDebounceTime = 0; // the last time the output pin was toggled unsigned long debounceDelay = 50; // the debounce time; increase if the output flickers unsigned long aktualnyCzas = 0; // Przypisanie long temperatury i willgotnosci unsigned long zapamietanyCzas = 0; unsigned long roznicaCzasu = 0; void setup() { lcd.init();// initialize the lcd lcd.backlight(); pinMode(buttonPin, INPUT_PULLUP); } void loop() { if (hasChanged == true) { switch(menu) { case 1: { secondScreen(); } break; case 2: { fourthScreen(); //temperatura } break; case 3: { fifthScreen(); // wilgotnosc } break; case 0: { } break; } } //------------------------------- // BEGIN of the switch debouncing code int reading = digitalRead(buttonPin); if (reading != lastButtonState) { // reset the debouncing timer lastDebounceTime = millis(); } if ((millis() - lastDebounceTime) > debounceDelay) { // whatever the reading is at, it's been there for longer // than the debounce delay, so take it as the actual current state: // if the button state has changed: if (reading != buttonState) { buttonState = reading; // only toggle the LED if the new button state is HIGH if (buttonState == HIGH) { hasChanged = true; menu++; } } else { hasChanged = false; } } lastButtonState = reading; // END of the switch Debouncing code // -------------------------------------- if (menu > 3){ menu = 1; } } /////////////////////////////////////////////////////// WIDOK GŁÓWNY ///////////////////////////////////////////////// void secondScreen() { lcd.clear(); lcd.setCursor(0,0); // Column, line lcd.print(" Ekran nr 1 "); lcd.setCursor(0,1); lcd.print(" na moim menu !! "); } /////////////////////////////////////////////////////// TEMPERATURA ////////////////////////////////////////////////// void fourthScreen() { aktualnyCzas = millis(); roznicaCzasu = aktualnyCzas - zapamietanyCzas; if (roznicaCzasu >= 1000UL) { int chk = DHT22.read(DHT22PIN); zapamietanyCzas = aktualnyCzas; lcd.clear(); lcd.setCursor(0,0); lcd.print("Temperatura (C): "); lcd.setCursor(0,1); lcd.print((float)DHT22.temperature, 2); } } /////////////////////////////////////////////////////// WILOGTNOSC //////////////////////////////////////////////////// void fifthScreen() { aktualnyCzas = millis(); roznicaCzasu = aktualnyCzas - zapamietanyCzas; if (roznicaCzasu >= 1000UL) { int chk = DHT22.read(DHT22PIN); zapamietanyCzas = aktualnyCzas; lcd.clear(); lcd.setCursor(0,0); lcd.print("Wilgotnosc: "); lcd.setCursor(0,1); lcd.print((float)DHT22.humidity, 2); } } Główne problemy to: 1. Menu przełącza się miedzy ekranami, jednak zmienne (temperatury oraz wilgotności) nie są aktualizowane na bieżąco, widać tylko jakby jedną "klatkę" danego odczytu. Dopiero po powrocie do tego samego ekranu wartości jakby się aktualizowały. Chciałbym, żeby dane aktualizowały się na bieżąco. No i jak za szybko kliknę to czasami przeskakuje o 2 ekrany. 2. Chciałbym dodać do tego termostatu, dwoma kolejnymi przyciskami, funkcje regulacji temperatury, by przekaźniki wyłączały się po osiągnięciu założonych wartości. 3. Punkt na którym zależy mi póki co najmniej, optymalizacja kodu oraz ewentualnie dodanie dodatkowych funkcji. Jestem mega amatorem pod względem optymalizacji, a wiem ze wiele spraw można uprościć, dodając biblioteki. Kurs na Arduino przerobiony, przynajmniej pierwsza część w 100 %, część druga w około 40%. Dziękuje bardzo za wszelką pomoc. 🙂 Cytuj Link do komentarza Share on other sites More sharing options...
ethanak Styczeń 2, 2021 Udostępnij Styczeń 2, 2021 (edytowany) Tak krótko. Problem pierwszy - program robi dokładnie to co chciałeś, czyli wyświetla nowy ekran tylko wtedy, gdy zmieniła się zmienna menu. Na początek usuń po prostu tego ifa przed switchem i zobacz co się stanie. Wyniknie z tego oczywiście inny problem, ale to już musisz sam zaobserwować. Czyli nie: if (hasChanged) { switch(cośtam) { // tu jakieś case i inne mądre wynalazki } // koniec switcha } // koniec ifa a raczej po prostu: switch(cośtam) { // tu jakieś case i inne mądre wynalazki } // koniec switcha Jeśli nic sensownego nie zobaczysz na ekranie - wrzuć po prostu (prowizorycznie) delay(100) na końcu loop. Co do przeskakiwania o dwa - patrz problem trzeci. Problem drugi: najpierw zrób działający program (oczywiście rozumiejąc jak on działa), potem będziemy sobie coś do niego dodawać. Problem trzeci: przerzucenie na biblioteki własnego (czyli w tym przypadku zapożyczonego) kodu to bardzo dobry pomysł. Rozumiem sytuację, kiedy piszesz np. własną funkcję do debouncingu aby zrozumieć jak ona działa - w tym przypadku jest po prostu przekopiowana z innego i wcale nie stanowi szczytowego osiągnięcia sztuki programistycznej (vide przeskakiwanie). Zapoznaj się z biblioteką Bounce2, zastosuj w programie (przy kilku przyciskach kod pozostanie prosty, bez tego będzie się komplikować), wtedy pogadamy o rozbudowie. A przy okazji najprawdopodobniej przestanie przeskakiwać 🙂 A co do kursu - przejrzyj sobie pobieżnie przynajmniej tytuły pozostałych 60%, być może gdzieś tam jest rozwiązanie któregoś z Twoich problemów? No, do roboty, czekam na problem czwarty wynikły z rozwiązania problemu pierwszego 🙂 Edytowano Styczeń 2, 2021 przez ethanak 2 Cytuj Link do komentarza Share on other sites More sharing options...
lewwus Styczeń 3, 2021 Autor tematu Udostępnij Styczeń 3, 2021 Okej, problem pierwszy, częściowo zażegnany. Po usunięciu "ifa" ekrany się zmieniają i aktualizują na bieżąco wartości, jednak pojawił się problem czwarty, który przewidziałeś niczym z magicznej kuli 🙂 . Problemem jest mruganie lub zanikanie tekstu. W momencie dodania delay'u na końcu, tekst z pierwszego ekranu mruga, bez tego delay'a zanika. Co do biblioteki Bounce2, pobrana i staram się z nią zapoznać na podstawie gotowych przykładów jakie znajdują się w tej bibliotece, jednak wszystkie opierają się na ledzie i nie wiem do końca który z tych przykładów może mieć zastosowanie w moim problemie ? No i dodatkowo część kodu znajdującą sie w loop ma być umieszczona za switchem czy przed ? 🤷♂️ Cytuj Link do komentarza Share on other sites More sharing options...
ethanak Styczeń 3, 2021 Udostępnij Styczeń 3, 2021 8 minut temu, lewwus napisał: Problemem jest mruganie lub zanikanie tekstu Tak, to było przewidziane 🙂 Wyobraź sobie funkcję rysowania ekranu: void fourthScreen() { aktualnyCzas = millis(); roznicaCzasu = aktualnyCzas - zapamietanyCzas; // jeśli menu zostało zmienione, czyścimy ekran i przygotowujemy do wyświetlania if (hasChanged) { lcd.clear(); lcd.setCursor(0,0); lcd.print("Temperatura (C): "); } // wypisujemy temperaturę albo od razu po wyświetleniu menu, albo co sekundę if (roznicaCzasu >= 1000UL || hasChanged) { int chk = DHT22.read(DHT22PIN); zapamietanyCzas = aktualnyCzas; lcd.setCursor(0,1); lcd.print((float)DHT22.temperature, 2); } } Zauważ: nie będzie migać i znikać, bo czyścimy ekran tylko raz na początku wejścia w nową pozycję menu Nie jest potrzebny żaden delay, bo odczyt i wyświetlenie temperatury jest tylko wtedy kiedy trzeba, nie ma czyszczenia całego ekranu, a pętla loop może się kręcić Pozostaje tylko zmuszenie wyświetlacza, aby czyścił śmieci po poprzednim wyświetleniu temperatury... ale to zadanie domowe 🙂 A co do Bounce2: Załóżmy, że masz w programie jakiś "przycisk", ładnie zdeklarowany i zainicjalizowany. Czyli możesz napisać np: void loop() { przycisk.update(); hasChanged = przycisk.fell(); if (hasChanged) { menu++; if (menu > COUNT_MENU) menu = 1; } // dalej reszta kodu Przy okazji - lepiej pozycje menu liczyć od zera, wtedy kod się upraszcza: if (hasChanged) menu = (menu + 1) % COUNT_MENU; Może być? Mam nadzieję, że to zrozumiałe... 2 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
lewwus Styczeń 6, 2021 Autor tematu Udostępnij Styczeń 6, 2021 Kod poprawiony, troszkę uporządkowany, wygląda on następująco #include <Wire.h> // dodanie bibliotek #include <LiquidCrystal_I2C.h> #include "dht.h" #include <Bounce2.h> LiquidCrystal_I2C lcd(0x3F,20,4); //przypisanie wspołrzednyc ekranu LCD dht DHT22; #define DHT22PIN 13 // zdefiniowanie podłączeń #define BUTTON_PIN 10 int menu = 1; Bounce przycisk = Bounce(); boolean hasChanged = true; int COUNT_MENU = 3; unsigned long aktualnyCzas = 0; // Przypisanie long temperatury i willgotnosci unsigned long zapamietanyCzas = 0; unsigned long roznicaCzasu = 0; void setup() { lcd.init(); // inicjacja ekranu lcd.backlight(); przycisk.attach(BUTTON_PIN,INPUT_PULLUP); // przypisanie przysku przycisk.interval(25); // określenie interwałow przycisku } void loop() { przycisk.update(); // wywolanie funkcji przycisku hasChanged = przycisk.fell(); if (hasChanged) { menu++; if (menu > COUNT_MENU) menu = 1; } switch(menu) { case 0: { menu = 1; } break; case 1: { secondScreen(); // widok głowny } break; case 2: { fourthScreen(); // temperatura } break; case 3: { fifthScreen(); // wilgotnosc } break; } delay(100); } /////////////////////////////////////////////////////// WIDOK GŁÓWNY ///////////////////////////////////////////////// void secondScreen() { if (hasChanged) { lcd.clear(); lcd.setCursor(4,0); lcd.print("STACJA METEO"); lcd.setCursor(0,2); lcd.print("Temperatura -> 1"); lcd.setCursor(0,3); lcd.print("Wilgotnosc -> 2"); } } /////////////////////////////////////////////////////// TEMPERATURA ////////////////////////////////////////////////// void fourthScreen() { aktualnyCzas = millis(); roznicaCzasu = aktualnyCzas - zapamietanyCzas; // jeśli menu zostało zmienione, czyścimy ekran i przygotowujemy do wyświetlania if (hasChanged) { lcd.clear(); lcd.setCursor(0,0); lcd.print("Temperatura (C): "); lcd.setCursor(17,3); lcd.print("(1)"); } // wypisujemy temperaturę albo od razu po wyświetleniu menu, albo co sekundę if (roznicaCzasu >= 2000UL || hasChanged) { int chk = DHT22.read(DHT22PIN); zapamietanyCzas = aktualnyCzas; lcd.setCursor(0,1); lcd.print((float)DHT22.temperature, 2); } } /////////////////////////////////////////////////////// WILOGTNOSC //////////////////////////////////////////////////// void fifthScreen() { aktualnyCzas = millis(); roznicaCzasu = aktualnyCzas - zapamietanyCzas; // jeśli menu zostało zmienione, czyścimy ekran i przygotowujemy do wyświetlania if (hasChanged) { lcd.clear(); lcd.setCursor(0,0); lcd.print("Wilgotnosc (RH): "); lcd.setCursor(17,3); lcd.print("(2)"); } // wypisujemy wilgotność albo od razu po wyświetleniu menu, albo co sekundę if (roznicaCzasu >= 2000UL || hasChanged) { int chk = DHT22.read(DHT22PIN); zapamietanyCzas = aktualnyCzas; lcd.setCursor(0,1); lcd.print((float)DHT22.humidity, 2); } } Temperatura oraz wilgotność aktualizują się prawidłowo co 2 sekundy. Biblioteka Bounce2, również skróciła oraz "rozjaśniła" cały kod. 🙂 Jedynym mankamentem, który domyślam się jest błahy, jest czysty ekran po załadowaniu programu, dopiero po pierwszym kliknięciu przyciskiem pojawia się temperatura i dalej wszystko funkcjonuje prawidłowo. Próbowałem z dodatkiem default do swatcha oraz podpowiedzianym odliczaniem pozycji menu od zera, jednak nie chciało dobrze to zagrać. Cytuj Link do komentarza Share on other sites More sharing options...
ethanak Styczeń 6, 2021 Udostępnij Styczeń 6, 2021 34 minuty temu, lewwus napisał: Jedynym mankamentem, który domyślam się jest błahy, jest czysty ekran po załadowaniu programu, Przerzuć wywołanie przycisk.fell() za switcha - wtedy przy pierwszym obrocie pętli dostanie wartość którą mu nadajesz przy inicjalizacji, a dopiero przy następnym będzie reagował na wciśnięcie. A, przy okazji, ten delay na końcu miał być prowizoryczny, nie powinien być więcej potrzebny! 1 Cytuj Link do komentarza Share on other sites More sharing options...
lewwus Styczeń 8, 2021 Autor tematu Udostępnij Styczeń 8, 2021 Wszystko działa prawidłowo, delay usunięty. 🙂 (przepraszam za brak rozgarnięcia). Dziękuję pięknie za pomoc ! Chciałbym się też dowiedzieć (jeśli możesz wiedzieć), bo nie wiem czy to wina kodu czy samego czujnika DHT22, ale momentami odczyt wilgotności wskazuje -999, jednak po 2 sekundach kiedy ma być wykonany nowy odczyt błąd ten znika. Dodatkowo wspomniałem na początku, że chciałbym dodać do tego rozwiązania możliwość regulacji temperatury np. w pomieszczeniu poprzez podłączenie przekaźnika, który będzie załączał się i wyłączał w odpowiednim momencie. Myślę, że to jest dobry moment. 🙂 Dodatkowe przyciski zostały zdefiniowane, przekaźnik też. Tak wygląda kod w aktualnej postaci. #include <Wire.h> // dodanie bibliotek #include <LiquidCrystal_I2C.h> #include "dht.h" #include <Bounce2.h> LiquidCrystal_I2C lcd(0x3F,20,4); //przypisanie wspołrzednyc ekranu LCD dht DHT22; #define DHT22PIN 13 // zdefiniowanie podłączeń #define BUTTON_PIN 10 #define BUTTON_PIN_1 9 #define BUTTON_PIN_2 8 #define RELAY_PIN 7 int menu = 1; Bounce przycisk = Bounce(); //okreslenie przycisków Bounce przyciskPlus = Bounce(); Bounce przyciskMinus = Bounce(); boolean hasChanged = true; int COUNT_MENU = 3; int zmiennaTemp = 20; unsigned long aktualnyCzas = 0; // Przypisanie long temperatury i willgotnosci unsigned long zapamietanyCzas = 0; unsigned long roznicaCzasu = 0; void setup() { lcd.init(); // inicjacja ekranu lcd.backlight(); pinMode(RELAY_PIN, OUTPUT); // przypisanie modułu przekaznika pinMode(BUTTON_PIN_1,INPUT_PULLUP); // przycisk do wzrostu temperatury przyciskPlus.attach(BUTTON_PIN_1); przyciskPlus.interval(25); //interwal pinMode(BUTTON_PIN_2,INPUT_PULLUP); // przycisk do zmniejszania temperatury przyciskMinus.attach(BUTTON_PIN_2); przyciskMinus.interval(25); przycisk.attach(BUTTON_PIN,INPUT_PULLUP); // przypisanie przysku przycisk.interval(25); } void loop() { switch(menu) { case 1: { secondScreen(); // widok głowny } break; case 2: { fourthScreen(); // temperatura } break; case 3: { fifthScreen(); // wilgotnosc } break; } przycisk.update(); // wywolanie funkcji przycisku hasChanged = przycisk.fell(); if (hasChanged) { menu++; if (menu > COUNT_MENU) menu = 1; } // załączenie sie przekaznika if (DHT22.temperature >= zmiennaTemp){ digitalWrite(RELAY_PIN, HIGH); } else if (DHT22.temperature <= zmiennaTemp){ digitalWrite(RELAY_PIN, LOW); } } /////////////////////////////////////////////////////// WIDOK GŁÓWNY ///////////////////////////////////////////////// void secondScreen() { if (hasChanged) { lcd.clear(); lcd.setCursor(4,0); lcd.print("STACJA METEO"); lcd.setCursor(0,2); lcd.print("Temperatura -> 1"); lcd.setCursor(0,3); lcd.print("Wilgotnosc -> 2"); } } /////////////////////////////////////////////////////// TEMPERATURA ////////////////////////////////////////////////// void fourthScreen() { aktualnyCzas = millis(); roznicaCzasu = aktualnyCzas - zapamietanyCzas; // jeśli menu zostało zmienione, czyścimy ekran i przygotowujemy do wyświetlania if (hasChanged) { lcd.clear(); lcd.setCursor(0,0); lcd.print("Temperatura (C): "); lcd.setCursor(17,3); lcd.print("(1)"); lcd.setCursor(0,2); lcd.print("Ustawiona"); // wpisanie zmienianej temperatury lcd.setCursor(0,3); lcd.print(zmiennaTemp); } // wypisujemy temperaturę albo od razu po wyświetleniu menu, albo co 2 sekundy if (roznicaCzasu >= 2000UL || hasChanged) { int chk = DHT22.read(DHT22PIN); zapamietanyCzas = aktualnyCzas; lcd.setCursor(0,1); lcd.print((float)DHT22.temperature, 2); } // zmiana wartosci załączania sie przekażnika przyciskPlus.update(); // przyciski do regulacji temperatury przyciskMinus.update(); int wzrostTemp = przyciskPlus.fell(); // zdefiniowanie przycisków int spadekTemp = przyciskMinus.fell(); if (wzrostTemp){ zmiennaTemp++; zmiennaTemp = constrain (zmiennaTemp, 10, 50); lcd.setCursor(0,3); lcd.print(zmiennaTemp); } else if (spadekTemp){ zmiennaTemp--; zmiennaTemp = constrain (zmiennaTemp, 10, 50); lcd.setCursor(0,3); lcd.print(zmiennaTemp); } // załączenie sie przekaznika /*if (DHT22.temperature >= zmiennaTemp){ digitalWrite(RELAY_PIN, HIGH); } else if (DHT22.temperature <= zmiennaTemp){ digitalWrite(RELAY_PIN, LOW); }*/ } /////////////////////////////////////////////////////// WILOGTNOSC //////////////////////////////////////////////////// void fifthScreen() { aktualnyCzas = millis(); roznicaCzasu = aktualnyCzas - zapamietanyCzas; // jeśli menu zostało zmienione, czyścimy ekran i przygotowujemy do wyświetlania if (hasChanged) { lcd.clear(); lcd.setCursor(0,0); lcd.print("Wilgotnosc (RH): "); lcd.setCursor(17,3); lcd.print("(2)"); } // wypisujemy wilgotność albo od razu po wyświetleniu menu, albo co 2 sekundy if (roznicaCzasu >= 2000UL || hasChanged) { int chk = DHT22.read(DHT22PIN); zapamietanyCzas = aktualnyCzas; lcd.setCursor(0,1); lcd.print((float)DHT22.humidity, 2); } } Jako komentarz mam dodane załączanie się przekaźnika w fifthScreen bo zauważyłem, że będąc tylko w nim przekaźnik działa. Przerzuciłem to do loopa, tylko nie wiem do końca czy taka forma jest prawidłowa ? Czy może zamiast // załączenie sie przekaznika if (DHT22.temperature >= zmiennaTemp){ digitalWrite(RELAY_PIN, HIGH); } else if (DHT22.temperature <= zmiennaTemp){ digitalWrite(RELAY_PIN, LOW); } Zdefiniować jakaś zmienną lub voidem ? Bo w momencie dodania tam kolejnego przekaźnika do wilgotności, to może nie wyglądać estetycznie. Może istnieje jeszcze inna metoda uporządkowania tego ? 🙄 Cytuj Link do komentarza Share on other sites More sharing options...
ethanak Styczeń 8, 2021 Udostępnij Styczeń 8, 2021 26 minut temu, lewwus napisał: Zdefiniować jakaś zmienną lub voidem CZYM??? Marsz do kursu (albo gdziekolwiek gdzie piszą coś o podstawach C/C++) i zgłosisz się jak będziesz wiedział co znaczy słowo "void". Wybacz, ale bez znajomości podstawowej terminologii po prostu nie jestem w stanie czegokolwiek wyjaśnić. Przy okazji - w sieci (i na tym forum też) jest od metra przykładów jak się robi termostat. Poczytaj co to histereza, przeanalizuj przykłady i wyciągnij wnioski. Cytuj Link do komentarza Share on other sites More sharing options...
Treker (Damian Szymański) Styczeń 10, 2021 Udostępnij Styczeń 10, 2021 Ja jednak dopytam z ciekawości. @lewwus, a co dokładnie miałeś na myśli pisząc o tym voidzie? Może to tylko jakieś językowe nieporozumienie 😉 Cytuj Link do komentarza Share on other sites More sharing options...
lewwus Styczeń 10, 2021 Autor tematu Udostępnij Styczeń 10, 2021 Wybaczcie za mój błąd z voidem lub zmienna, nie jestem programista, a to co robię wykonuje hobbystycznie poza godzinami regularnej pracy. Wiem, że mam braki (i to nie małe!), jednak dziękuje za zwrócenie uwagi i odesłanie do dalszej nauki 🙂. @Treker zgadza się to co miałem na myśli to była osobna funkcja tak jak w przykładzie poniżej. void loop() { . . . // kod własciwy regulacjaTemp(); } void regulacjaTemp() { // wykonanie czynnosci/ zadania } Na przyszłość będę pamiętał i zabieram się za dalsze kształcenie 😉 Cytuj Link do komentarza Share on other sites More sharing options...
ethanak Styczeń 10, 2021 Udostępnij Styczeń 10, 2021 @lewwus i pamiętaj jeszcze: void do typ (tak jak int, float, bool czy różne inne). Czyli void costam() {...} int cosinnego() {...} oznaczają odpowiednio "funkcja costam która nie zwraca wyniku" i "funkcja cosinnego która zwraca wynik typu int". Ja doskonale rozumiem skąd to się bierze: po prostu jak ktoś patrzy na kod, widzi "void setup" i "void loop" i dochodzi do wniosku, że są tam jakieś dwa voidy co się nazywają setup i loop. I tak to jest jak ktoś z kursów czyta tylko ciekawsze kawałki 🙂 [1] Wracając do tematu: o histerezie poczytałeś? Wyrzucenie regulacji temperatury do oddzielnej funkcji (np. typu void) to wielce zacny pomysł, poprawia czytelność, zmniejsza prawdopodobieństwo zrobienia błędu i ułatwia poprawki... zaproponujesz funkcję? [1] Chyba że w kursach o tym nie mówią? Cytuj Link do komentarza Share on other sites More sharing options...
lewwus Styczeń 11, 2021 Autor tematu Udostępnij Styczeń 11, 2021 Zanotowane 🙂 Tak, poczytałem o histerezie i dodałem funkcje regulacji temperatury pomiędzy dwoma rożnymi wartościami. Jednak nie jestem do końca co do niej przekonany. 🤷♂️ Dokładniej to stany w ktorych włącza lub wyłącza się przekaźnik są odwrotne niż w innych rozwiązaniach, nie wiem czy jest to duży błąd. Dodatkowo przekaźnik włącza się ponownie po załadowaniu temperatury maksymalnej na ekranie. Wersja z jedną temperaturą (bez histerezy) działa nie ważne jaki ekran wyświetlacz pokazuję. #include <Wire.h> // dodanie bibliotek #include <LiquidCrystal_I2C.h> #include "dht.h" #include <Bounce2.h> LiquidCrystal_I2C lcd(0x3F,20,4); //przypisanie wspołrzednyc ekranu LCD dht DHT22; #define DHT22PIN 13 // zdefiniowanie podłączeń #define BUTTON_PIN 10 #define BUTTON_PIN_1 9 #define BUTTON_PIN_2 8 #define RELAY_PIN 7 int menu = 1; Bounce przycisk = Bounce(); //okreslenie przycisków Bounce przyciskPlus = Bounce(); Bounce przyciskMinus = Bounce(); boolean hasChanged = true; int COUNT_MENU = 4; int minTemp = 20; // przypisanie wartosci temperatur int maxTemp = 40; unsigned long aktualnyCzas = 0; // Przypisanie long temperatury i willgotnosci unsigned long zapamietanyCzas = 0; unsigned long roznicaCzasu = 0; void setup() { lcd.init(); // inicjacja ekranu lcd.backlight(); pinMode(RELAY_PIN, OUTPUT); // przypisanie modułu przekaznika pinMode(BUTTON_PIN_1,INPUT_PULLUP); // przycisk do wzrostu temperatury przyciskPlus.attach(BUTTON_PIN_1); przyciskPlus.interval(25); //interwal pinMode(BUTTON_PIN_2,INPUT_PULLUP); // przycisk do zmniejszania temperatury przyciskMinus.attach(BUTTON_PIN_2); przyciskMinus.interval(25); przycisk.attach(BUTTON_PIN,INPUT_PULLUP); // przypisanie przycisku do zmiany menu przycisk.interval(25); } void loop() { switch(menu) { case 1: { menuGlowne(); // widok głowny } break; case 2: { temperaturaMin(); // temperatura min } break; case 3: { temperaturaMax(); // temperatura max } break; case 4: { wilgotnoscOdczyt(); // wilgotnosc } break; } przycisk.update(); // wywolanie funkcji przycisku hasChanged = przycisk.fell(); if (hasChanged) { menu++; if (menu > COUNT_MENU) menu = 1; } // załączenie sie przekaznika regulacjaTemperatury(); } /////////////////////////////////////////////////////// WIDOK GŁÓWNY ///////////////////////////////////////////////// void menuGlowne() { if (hasChanged) { lcd.clear(); lcd.setCursor(4,0); lcd.print("STACJA METEO"); lcd.setCursor(0,2); lcd.print("Temperatura -> 1"); lcd.setCursor(0,3); lcd.print("Wilgotnosc -> 2"); } } /////////////////////////////////////////////////////// TEMPERATURA MIN ////////////////////////////////////////////////// void temperaturaMin() { aktualnyCzas = millis(); roznicaCzasu = aktualnyCzas - zapamietanyCzas; // jeśli menu zostało zmienione, czyścimy ekran i przygotowujemy do wyświetlania if (hasChanged) { lcd.clear(); lcd.setCursor(0,0); lcd.print("Temperatura (C): "); lcd.setCursor(17,3); lcd.print("(1)"); lcd.setCursor(0,2); lcd.print(">Min.Temp"); // wpisanie zmienianej temperatury lcd.setCursor(0,3); lcd.print(minTemp); } // wypisujemy temperaturę albo od razu po wyświetleniu menu, albo co 2 sekundy if (roznicaCzasu >= 2000UL || hasChanged) { int chk = DHT22.read(DHT22PIN); zapamietanyCzas = aktualnyCzas; lcd.setCursor(0,1); lcd.print((float)DHT22.temperature, 2); } // zmiana wartosci załączania sie przekażnika przyciskPlus.update(); // przyciski do regulacji temperatury przyciskMinus.update(); int minTemp1 = przyciskPlus.fell(); // zdefiniowanie przycisków int minTemp2 = przyciskMinus.fell(); if (minTemp1){ minTemp++; minTemp = constrain (minTemp, 10, 50); lcd.setCursor(0,3); lcd.print(minTemp); } else if (minTemp2){ minTemp--; minTemp = constrain (minTemp, 10, 50); lcd.setCursor(0,3); lcd.print(minTemp); } } /////////////////////////////////////////////////////// TEMPERATURA MAX ///////////////////////////////////////////////// void temperaturaMax() { aktualnyCzas = millis(); roznicaCzasu = aktualnyCzas - zapamietanyCzas; // jeśli menu zostało zmienione, czyścimy ekran i przygotowujemy do wyświetlania if (hasChanged) { lcd.clear(); lcd.setCursor(0,0); lcd.print("Temperatura (C): "); lcd.setCursor(17,3); lcd.print("(1)"); lcd.setCursor(0,2); lcd.print(">Min.Temp"); // wpisanie zmienianej temperatury lcd.setCursor(0,3); lcd.print(minTemp); lcd.setCursor(10,2); lcd.print(">Max.Temp"); lcd.setCursor(10,3); lcd.print(maxTemp); } // wypisujemy temperaturę albo od razu po wyświetleniu menu, albo co 2 sekundy if (roznicaCzasu >= 2000UL || hasChanged) { int chk = DHT22.read(DHT22PIN); zapamietanyCzas = aktualnyCzas; lcd.setCursor(0,1); lcd.print((float)DHT22.temperature, 2); } // zmiana wartosci załączania sie przekażnika przyciskPlus.update(); // przyciski do regulacji temperatury przyciskMinus.update(); int maxTemp1 = przyciskPlus.fell(); // zdefiniowanie przycisków int maxTemp2 = przyciskMinus.fell(); if (maxTemp1){ maxTemp++; maxTemp = constrain (maxTemp, 10, 50); lcd.setCursor(10,3); lcd.print(maxTemp); } else if (maxTemp2){ maxTemp--; maxTemp = constrain (maxTemp, 10, 50); lcd.setCursor(10,3); lcd.print(maxTemp); } } /////////////////////////////////////////////////////// WILOGTNOSC //////////////////////////////////////////////////// void wilgotnoscOdczyt() { aktualnyCzas = millis(); roznicaCzasu = aktualnyCzas - zapamietanyCzas; // jeśli menu zostało zmienione, czyścimy ekran i przygotowujemy do wyświetlania if (hasChanged) { lcd.clear(); lcd.setCursor(0,0); lcd.print("Wilgotnosc (RH): "); lcd.setCursor(17,3); lcd.print("(2)"); } // wypisujemy wilgotność albo od razu po wyświetleniu menu, albo co 2 sekundy if (roznicaCzasu >= 2000UL || hasChanged) { int chk = DHT22.read(DHT22PIN); zapamietanyCzas = aktualnyCzas; lcd.setCursor(0,1); lcd.print((float)DHT22.humidity, 2); } } /////////////////////////////////////////////////////// REGULACJA TEMP ////////////////////////////////////////////////// void regulacjaTemperatury() { if ((DHT22.temperature <= minTemp) && (DHT22.temperature <= maxTemp)){ // właczenie sie przkaznika gdy temp otoczenia jest mniejsza od minmalnej temp oraz mniejsza od maksymalnej digitalWrite(RELAY_PIN, LOW); } else if (DHT22.temperature >= maxTemp){ // wylączenie sie przekaznika gdy jest rowna lub wieksza maksymalnej digitalWrite(RELAY_PIN, HIGH); } } Cytuj Link do komentarza Share on other sites More sharing options...
ethanak Styczeń 11, 2021 Udostępnij Styczeń 11, 2021 if ((DHT22.temperature <= minTemp) && (DHT22.temperature <= maxTemp)){ I w tym momencie całą histerezę diabli biorą. Masz wyłączyć grzanie jeśli temperatura opadnie poniżej minTemp i włączyć, jeśli wzroście powyżej maxTemp. Jeśli jest pośrodku to nie robisz nic. Cytuj Link do komentarza Share on other sites More sharing options...
Elvis Styczeń 11, 2021 Udostępnij Styczeń 11, 2021 Przecież ten kod dokładnie to robi... chociaż trochę niepotrzebnie sprawdza maxTemp, bo pewnie minTemp <= maxTemp. 1 Cytuj Link do komentarza Share on other sites More sharing options...
ethanak Styczeń 11, 2021 Udostępnij Styczeń 11, 2021 Oj, fakt, zwracam honor. 1 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!