Elektroda.pl
Elektroda.pl
X
BotlandBotland
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

Termostat z timerem Arduino, LCD i enkoder

13 Lut 2019 23:38 1398 34
  • Poziom 8  
    Witam serdecznie
    Jestem początkującym użytkownikiem Arduino.
    Chciałem napisać program termostatu z timerem, LCD, i enkoderem ale niestety nie mam zupełnie pojęcia o enkoderach. Wiec znalazłem jakiś przykład na działanie enkodera (który wydal mi się najlepiej działający i prosty) i dorobiłem do niego troszkę :). Niestety nie pamiętam kto był autorem tego przykładu za co przepraszam. Jestem prawie na końcu osiągnięcia swojego celu w związku z czym chciałem podpytać doświadczonych użytkowników.
    Czy tylko mój przykład wykorzystania enkodera muli trochę cały program i czy da się coś z tym zrobić?
    Wygląda to tak ze czas, mimo kilku potknięć przy wyświetlaniu (sekundy chodzą nie równo) wydaje się być dobrze mierzony ale przyciski trzeba czasem trochę przytrzymać.
    Ogólnie to działa, tylko zastanawiam się czy lepiej nie zrobić tego na 4 przyciskach pomijając enkoder i czy by to pomogło. Wydaje też mi się że czasem przy odpowiednim ustawieniu enkodera miedzy przeskokami potrafi się zawiesić.
    Do Arduino jest podłączony wyświetlacz LCD 20x4 na I2C, enkoder do pinów 2,3,4), buzer do 7,termometr ds18b20 do 6 , przycisk do pinu 9 (do startu odliczania czasu i programu docelowo) i dioda do 13. Enkoder jest w wersji z rezystorami PullUp i przycisk tez jest podciągnięty rezystorem.
    Kod wygląda następująco:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    Myślę ze wielu początkującym może się to przydać bo jest napisany bardzo prosto i łatwy do przerobienia. Niestety nie jest jeszcze dokończony a wszelkie sugestie mile widziane.
    A tak to wygląda : Termostat z timerem Arduino, LCD i enkoder Termostat z timerem Arduino, LCD i enkoder
    Darmowe szkolenie: Ethernet w przemyśle dziś i jutro. Zarejestruj się za darmo.
  • BotlandBotland
  • Pomocny post
    Poziom 17  
    Weź pod uwagę takie problemy:
    1. zminimalizuj drgania styków przycisków (tzw. debouncing) programowo lub sprzętowo używając kondensatorów
    2. przerwanie od enkodera wywołuj stanem FALLING lub RISING (Ty masz LOW co jest bardziej podatne na drgania przycisku zwieranego do masy)
    3. zmienna globalna "time" użyta w przerwaniu powinna być typu volatile (Ty masz unsigned long)
    4. obsługa DS18B20 ma w bibliotece zdefiniowane opóźnienia, które są różne (od 94 do 750 ms) w zależności od wymaganej rozdzielczości wyniku pomiaru
    To powoduje, że na taki czas program się "wiesza" gdy jest umieszczony w pętli głównej.
    5. chyba też jest tak, że w ISR nie działa poprawnie millis() ale mogę się mylić

    Dobrą praktyką jest sterowanie buzera poprzez tranzystor.
    Ogólnie to pochwała za samodzielną próbę napisania kodu bez użycia nieszczęsnych delay()
    Napisz jednak jaki cel ma spełniać ten termostat.
  • Poziom 38  
    jaclew napisał:
    chyba też jest tak, że w ISR nie działa poprawnie millis() ale mogę się mylić

    Nie działa poprawnie tzn. kolejne jej wywołania w danym przerwaniu zwracają te same wartości czasu, jak w momencie wywołania tego przerwania.

    jaclew napisał:
    obsługa DS18B20 ma w bibliotece zdefiniowane opóźnienia, które są różne (od 94 do 750 ms) w zależności od wymaganej rozdzielczości wyniku pomiaru
    To powoduje, że na taki czas program się "wiesza" gdy jest umieszczony w pętli głównej.

    Jak będzie umieszczony w przerwaniu, to wydłuży czas obsługi tego przerwania. Najlepiej byłoby, gdy odczyt DS18B20 podzielić na dwa odrębne zadania: najpierw tylko wysłać żądanie odczytu temperatury (które może się wykonywać po stronie sensora nawet do 750ms tak, jak napisałeś), wrócić do programu głównego, a później odczytać temperaturę (o ile wcześniejsze żądanie odczytu się powiodło). Zła wiadomość jest taka, że jeszcze nie natknąłem się na bibliotekę DS18B20 dla Arduino, która by w ten sposób to robiła :)

    jaclew napisał:
    przerwanie od enkodera wywołuj stanem FALLING lub RISING (Ty masz LOW co jest bardziej podatne na drgania przycisku zwieranego do masy)

    Jak będzie FALLING to RISING to będzie praktycznie tak samo podatne na drgania :) Sensownym rozwiązaniem jest tylko debouncing.
  • Poziom 32  
    khoam napisał:
    Jak będzie umieszczony w przerwaniu, to wydłuży czas obsługi tego przerwania. Najlepiej byłoby, gdy odczyt DS18B20 podzielić na dwa odrębne zadania: najpierw tylko wysłać żądanie odczytu temperatury (które może się wykonywać po stronie sensora nawet do 750ms tak, jak napisałeś), wrócić do programu głównego, a później odczytać temperaturę (o ile wcześniejsze żądanie odczytu się powiodło).

    Ta tu użyta tak, robi, wystarczy ładnie poprosić: setWaitForConversion KEYWORD2, tylko wtedy samemu trzeba pilnować by pytać o temperaturę nie wcześniej niż po czasie konwersji dla danej rozdzielczości.
  • Poziom 38  
    kaczakat napisał:
    Ta tu użyta tak, robi, wystarczy ładnie poprosić: setWaitForConversion KEYWORD2, tylko wtedy samemu trzeba pilnować by pytać o temperaturę nie wcześniej niż po czasie konwersji dla danej rozdzielczości.

    No jak, już cytujesz komentarze z kodu, to do końca :)
    Kod: c
    Zaloguj się, aby zobaczyć kod

    To drugie jest równie ważne.
  • Poziom 32  
    Tu nie ma za bardzo nic do tłumaczenia, ta funkcja jest opisana w bibliotece i wyłącza oczekiwanie na konwersję, temperaturę można odczytać po 750ms, lub po 10s, można też sprawdzać kompletność konwersji okresowo, po prostu będzie to ta temperatura z chwili zlecenia pomiaru. Nie wiem o co chodzi z tym cytatem, może nie znam dobrze języka, ale nie widzę tu niczego, czego nie napisałem.
    Przykład skądś tam:
    Kod: c
    Zaloguj się, aby zobaczyć kod
  • Poziom 8  
    Bardzo dziękuje wszystkim za pomoc.
    Okazało się ze najbardziej muli ds18b20 wiec postanowiłem przenieść odczyt temperatury do oddzielnego void wykonywanego co 1 sekundę to dało pewne efekty ale co jakiś czas nadal się zawiesza :( i teraz pojawił się problem debouncingu :) za to naprawiło się wyświetlanie odliczanego czasu :) ale efekt jest taki ze raz działa i to super szybko a od czasu do czasu trzeba przytrzymać przycisk lub ruszyć enkoderem żeby przyciski działały :(
    odpowiedzi do Kolegi "jaclew"
    Niestety nie wiele wiem o funkcji volatile
    Program czasem się wiesza od enkodera a czasem od ds18b20
    Cel to będzie urządzenie do Sous-vide (oczywiście pod nadzorem :) ) lub do sterowania wedzarką jak popsuje mi się obecne sterowanie :)
    Do "khoam" i "kaczakat"
    Czy mogli byście rozwinąć temat sprawdzania temperatury z oczekiwaniem na zwrot temperatury? Potrzebuje przykładu gdyż jestem amatorem Arduino i muszę zrozumieć jak to działa żeby coś napisać :)
    Mysle też ze zastąpił bym ten enkoder na rzecz takiego innego, którego nie mogę znaleźć bo nie wiem jak go nazwać :)

    Termostat z timerem Arduino, LCD i enkoder

    Chodzi mi o coś takiego co przekręca się 25 stopni w prawo i to jest 1 SW,
    25 stopni w lewo, 2 SW i wciśniecie 3 SW
  • BotlandBotland
  • Poziom 38  
    florek1882 napisał:
    odczyt temperatury do oddzielnego void wykonywanego co 1 sekundę to dało pewne efekty ale co jakiś czas nadal się zawiesza

    Trochę się nie dziwię ;) Skorzystaj z funkcji isConvertionComplete() przed odczytem temperatury. Funkcję tę wywołujesz po każdym requestTemperatures(), jeżeli zwróci wartość true, możesz dokonać odczytu temperatury. Nie ma większego znaczenia z jakim interwałem czasowym będziesz wywoływał wiele isConvertionComplete() po ostatnim requestTemperatures(), ale powinieneś sprawdzać również przy okazji, czy nie został przekroczony maksymalny czas konwersji dla danej rozdzielczości sensora. Wtedy dopiero też możesz skorzystać z ustawienia setWaitForConversion(0), o którym pisał kolega @kaczakat.

    florek1882 napisał:
    Niestety nie wiele wiem o funkcji volatile

    Słowo kluczowe volatile stosuje się w odniesieniu do tych zmiennych, które będą używane zarówno przez program główny, jaki i w procedurach obsługi przerwań.
  • Poziom 32  
    Wrzuciłem Ci przykład, wyłączasz oczekiwanie na konwersję, zlecasz konwersję raz w setup, korzystając z millis uczysz się zarządzać czasem, odczytujesz temperaturę i zlecasz ponowną konwersję. Każde "zagadanie" do DS18B20 to kilka -kilkadziesiąt ms, można przeżyć, ale jak jeszcze czekasz 750ms na konwersje to już lipa. Są inne sposoby komunikacji z DS prawie niezależne dla kodu programu ale nie widziałem biblioteki dla Arduino. Jak masz więcej czujników temperatury to też nie pytasz wszystkie o temperaturę po kolei, bo każdy taki odczyt to 30ms, 4 to już 120ms, możesz to zrobić jak w przykładzie miganie led, w pierwszej sekundzie czytasz 1 czujnik, w drugiej drugi itd do czwartego, w piątej zlecasz konwersje wszystkim temperatury i zaczynasz cykl od nowa, wtedy z każdej sekundy tracisz kilkadziesiąt ms na DS. Zależy jeszcze czego jest to temperatura, w pokoju sprawdzanie co 1 czy 5s nie ma sensu, można to robić np. co 1minutę. Wtedy pomiar sprzed minuty nie ma sensu, jest zbyt stary, zlecasz pomiar w 55s, czyli if(sekundy%55==0), w kolejnych po kolei odczytujesz czujniki. Bawić się z millis można na wiele sposobów, np.:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    Zależy co chcesz robić, tik 10ms z DS może szybko się rozjechać, bo jak program gdzieś zajrzy na 30ms to te 2 dziesiątki zostaną zgubione, na zegarek to się nie nada, ale używam takiej funkcji do rozłożenia zdarzeń w czasie. To coś prostego, jak nie wystarcza to są jeszcze timery sprzętowe.
  • Poziom 8  
    Myślałem że to trochę prostsza sprawa, czyli wysyłam komedę zapytaj a potem po millis + 750 wysyłam odpytaj :)
  • Poziom 38  
    florek1882 napisał:
    Myślałem że to trochę prostsza sprawa, czyli wysyłam komedę zapytaj a potem po millis + 750 wysyłam odpytaj

    W zasadzie to tak jest z mała poprawką: wysyłam, sprawdzam czy gotowe, czytam :)
  • Poziom 8  
    A możesz przedstawić Komedy do tego ds18b20 na wysyłam, sprawdzam,czytam?
  • Poziom 38  
    florek1882 napisał:
    A możesz przedstawić Komedy do tego ds18b20 na odczytam, sprawdzam,czytam?

    requestTemperature()
    isConversionComplete() [zwraca true, jak sensor gotowy jest do odczytu]
    getTempC() lub inna z tej biblioteki do odczytywania temperatury
  • Poziom 8  
    niestety "isConversionComplete()" nie działa dla mojej biblioteki lub nie wiem ze trzeba zadeklarować to jako zmienna :(
  • Poziom 38  
    florek1882 napisał:
    niestety "isConversionComplete()" nie działa dla mojej biblioteki lub nie wiem ze trzeba zadeklarować to jako zmienna

    A co to znaczy konkretnie "nie działa"?
  • Poziom 8  
    Próbowałem coś takiego if (isConversionComplete()== true)

    exit status 1
    'ConversionComplete' was not declared in this scope
  • Poziom 38  
    florek1882 napisał:
    Próbowałem coś takiego if (ConversionComplete()== true)

    Bez obrazy, ale sądzę, że powinieneś zacząć od nauki języka C ...

    Powinno być:
    Kod: c
    Zaloguj się, aby zobaczyć kod
  • Poziom 8  
    exit status 1
    'isConversionComplete' was not declared in this scope
    :(
    Może mam starą bibliotekę?
  • Poziom 32  
    isConversionComplete jest metodą do obiektu sensors, wszystkie funkcje/metody dla sensors wywołujesz sensors.metoda(); Jakbyś sobie zrobił na początku: DallasTemperature czujniki(&oneWire); to potem wszystkie funkcje wywoływałbyś czujniki.funkcjezbibliotekiDallasTemperature();.
  • Poziom 8  
    Jak mówiłem jestem amatorem :(
    Zaktualizowałem biblioteki one wire i Dallas i nadal ten sam błąd :(

    Dodano po 4 [minuty]:

    Co robię nie tak?

    Kod: c
    Zaloguj się, aby zobaczyć kod
  • Poziom 8  
    exit status 1
    'class DallasTemperature' has no member named 'isConversionComplete'
    :(
  • Poziom 8  
    nie wiem :( to było dawno temu :) i mam pytanie czy te biblioteki jak zainstaluje to nie wywalą mi innych projektów zrobionych na starych bibliotekach?

    Dodano po 9 [minuty]:

    zainstalowalem i nic sie nie zmienilo :(
  • Poziom 32  
    DallasTemerature najlepiej pobierz z managera, jak nie ma funkcji isConversionComplete to zresztą mała strata, bo i tak niewłaściwie ją wywołujesz, chodziło przecież o to by samemu odliczać czas, w tym czasie robić inne ważne rzeczy w programie, a o temperaturę zapytać po czasie co najmniej 750ms. isConversionComplete jest dalej wolną funkcją na magistrali oneWire, jak masz millis() wywoływaną w każdym loop i coś do one wire to ich długość jest 1:1000. Czyli w każdej sekundzie zapytasz o stan czujnika ze 20 razy i będzie to 99.9 czasu pracy procesora. A, i w mojej bibliotece jest isConversionComplete, tak że nie wiem co masz za wynalazek.
    Jak nie rozumiesz dlaczego można wywołać funkcję sensors.requestTemperatures(); po sensors.getTempCByIndex(0) to pomyśl o czymś takim: wstajesz rano, nic nie jadłeś i nic nie piłeś a idziesz do kibelka.
  • Poziom 8  
    Dziękuje za podpowiedzi
    Niestety zauważyłem ze po każdym wywołaniu funkcji sensors.requestTemperatures() następuje opóźnienie mimo ze wywoływane jest 1 raz na sekundę. Bibliotekę juz zaktualizowałem i mam funkcje sensors.isConversionComplete() ale to tez niewiele daje :( Pewnie nie da się tak zrobić żeby sensors.requestTemperatures() zapytał i nie blokował kodu aż termometr odpowie?
    Ponowie jeszcze pytanie o ten przełącznik który opisałem wyżej może ktoś wie jak nazwać takie coś żeby znaleźć to w internecie?
  • Poziom 8  
    Przepraszam za śmietnik ale próbowałem chyba wszystkich możliwości i trochę kombinowałem :)


    Kod: c
    Zaloguj się, aby zobaczyć kod
  • Pomocny post
    Poziom 32  
    W poście #6 pokazałem Ci sposób użycia sensors.setWaitForConversion(0); by nie czekać na wynik, nie użyłeś tego i zdziwiony że nie działa? Dopiero jak wyłączysz czekanie na wynik sens ma okresowe sprawdzanie czy przypadkiem wynik się nie pojawił, inaczej jest dostępny natychmiast po wywołaniu funkcji sensors.requestTemperatures();. Na razie idziesz po omacku, zrób jakiś kurs, poczytaj, poanalizuj kod w ciekawych projektach.
  • Poziom 8  
    Dzięki za podpowiedź ale czy nie łatwiej było napisać : "dopisz sensors.setWaitForConversion(0); w setup " ? :) teraz śmiga wszystko jak należy :) Pytanie o przełącznik nadal aktualne :)