logo elektroda
logo elektroda
X
logo elektroda
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

Jak poprawić działanie enkodera w projekcie termostatu Arduino?

florek1882 13 Lut 2019 23:38 4779 34
Najlepsze odpowiedzi LABEL_AI_GENERATED

Jak ograniczyć spowalnianie programu Arduino z enkoderem i czujnikiem DS18B20, żeby termostat działał płynnie i nie blokował przycisków?

Największe spowolnienie w tym projekcie robi DS18B20, a nie sam enkoder, więc najpierw trzeba wyłączyć blokujące oczekiwanie na wynik pomiaru i zrobić odczyt bez czekania. W bibliotece DallasTemperature należy użyć `sensors.setWaitForConversion(0);` w `setup()`, potem wywoływać `sensors.requestTemperatures();`, a temperaturę czytać dopiero później, po czasie konwersji albo po sprawdzeniu gotowości czujnika [#17777673][#17779928] Jeśli obsługujesz enkoder przerwaniami, dodaj debouncing, nie używaj wyzwalania `LOW`, tylko `FALLING` albo `RISING`, i pamiętaj, że zmienne współdzielone z ISR powinny być `volatile` [#17777673] Enkoder w ogóle nie musi działać w przerwaniach — można go obsługiwać w `loop()`, podobnie jak przyciski; dostępne są też biblioteki z trybem `Low Performance`, który nie korzysta z przerwań [#17826728][#17826752]
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
  • #1 17776556
    florek1882
    Poziom 10  
    Posty: 34
    Ocena: 2
    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 / 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 : Jak poprawić działanie enkodera w projekcie termostatu Arduino? Jak poprawić działanie enkodera w projekcie termostatu Arduino?
  • Pomocny post
    #2 17777673
    jaclew
    Poziom 18  
    Posty: 206
    Pomógł: 27
    Ocena: 210
    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.
  • #3 17777850
    Konto nie istnieje
    Poziom 1  
  • #4 17778452
    kaczakat
    Poziom 34  
    Posty: 1748
    Pomógł: 317
    Ocena: 231
    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.
    Pomogłem? Kup mi kawę.
  • #5 17778524
    Konto nie istnieje
    Poziom 1  
  • #6 17778585
    kaczakat
    Poziom 34  
    Posty: 1748
    Pomógł: 317
    Ocena: 231
    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 / C++
    Zaloguj się, aby zobaczyć kod
    Pomogłem? Kup mi kawę.
  • #7 17778799
    florek1882
    Poziom 10  
    Posty: 34
    Ocena: 2
    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ć :)

    Jak poprawić działanie enkodera w projekcie termostatu Arduino?

    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
  • #8 17778821
    Konto nie istnieje
    Poziom 1  
  • #9 17778841
    kaczakat
    Poziom 34  
    Posty: 1748
    Pomógł: 317
    Ocena: 231
    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 / 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.
    Pomogłem? Kup mi kawę.
  • #10 17778869
    florek1882
    Poziom 10  
    Posty: 34
    Ocena: 2
    Myślałem że to trochę prostsza sprawa, czyli wysyłam komedę zapytaj a potem po millis + 750 wysyłam odpytaj :)
  • #11 17778871
    Konto nie istnieje
    Poziom 1  
  • #12 17778874
    florek1882
    Poziom 10  
    Posty: 34
    Ocena: 2
    A możesz przedstawić Komedy do tego ds18b20 na wysyłam, sprawdzam,czytam?
  • #13 17778877
    Konto nie istnieje
    Poziom 1  
  • #14 17778882
    florek1882
    Poziom 10  
    Posty: 34
    Ocena: 2
    niestety "isConversionComplete()" nie działa dla mojej biblioteki lub nie wiem ze trzeba zadeklarować to jako zmienna :(
  • #15 17778884
    Konto nie istnieje
    Poziom 1  
  • #16 17778885
    florek1882
    Poziom 10  
    Posty: 34
    Ocena: 2
    Próbowałem coś takiego if (isConversionComplete()== true)

    exit status 1
    'ConversionComplete' was not declared in this scope
  • #17 17778886
    Konto nie istnieje
    Poziom 1  
  • #18 17778887
    florek1882
    Poziom 10  
    Posty: 34
    Ocena: 2
    exit status 1
    'isConversionComplete' was not declared in this scope
    :(
    Może mam starą bibliotekę?
  • #19 17778889
    kaczakat
    Poziom 34  
    Posty: 1748
    Pomógł: 317
    Ocena: 231
    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();.
    Pomogłem? Kup mi kawę.
  • #20 17778891
    florek1882
    Poziom 10  
    Posty: 34
    Ocena: 2
    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 / C++
    Zaloguj się, aby zobaczyć kod
  • #21 17778894
    Konto nie istnieje
    Poziom 1  
  • #22 17778896
    florek1882
    Poziom 10  
    Posty: 34
    Ocena: 2
    exit status 1
    'class DallasTemperature' has no member named 'isConversionComplete'
    :(
  • #24 17778901
    florek1882
    Poziom 10  
    Posty: 34
    Ocena: 2
    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 :(
  • #25 17779132
    kaczakat
    Poziom 34  
    Posty: 1748
    Pomógł: 317
    Ocena: 231
    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.
    Pomogłem? Kup mi kawę.
  • #26 17779852
    florek1882
    Poziom 10  
    Posty: 34
    Ocena: 2
    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?
  • #28 17779909
    florek1882
    Poziom 10  
    Posty: 34
    Ocena: 2
    Przepraszam za śmietnik ale próbowałem chyba wszystkich możliwości i trochę kombinowałem :)


    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • Pomocny post
    #29 17779928
    kaczakat
    Poziom 34  
    Posty: 1748
    Pomógł: 317
    Ocena: 231
    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.
    Pomogłem? Kup mi kawę.
  • #30 17780008
    florek1882
    Poziom 10  
    Posty: 34
    Ocena: 2
    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 :)

Podsumowanie tematu

LABEL_AI_GENERATED
Użytkownik Arduino, który pracuje nad projektem termostatu z wykorzystaniem enkodera, napotkał problemy z opóźnieniami i zawieszaniem się programu. W odpowiedziach zasugerowano kilka rozwiązań, takich jak minimalizacja drgań styków (debouncing), użycie przerwań w trybie FALLING lub RISING, oraz zastosowanie zmiennej volatile dla zmiennej czasu. Wskazano również na problemy związane z odczytem temperatury z czujnika DS18B20, który może blokować działanie programu. Użytkownik zdecydował się na przeniesienie odczytu temperatury do oddzielnej funkcji, co poprawiło działanie, ale nadal występowały sporadyczne zawieszenia. W końcu zasugerowano użycie funkcji setWaitForConversion(0) w celu uniknięcia blokowania kodu podczas oczekiwania na wynik pomiaru. Użytkownik rozważa również zastąpienie enkodera innym komponentem, takim jak potencjometr lub joystick, aby zminimalizować problemy z przerwaniami.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA