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

Arduino + DS18B20 - zaniki pomiarów

30 Cze 2020 08:34 348 20
  • Poziom 11  
    Witam
    Zrobiłem sterownik podgrzewacza ciśnieniowego wody wykorzystując Arduino Nano + DS18B20
    W trakcie odczytu temperatury następują chwilowe zaniki odczytu.
    Temperatura jest odczytywana z termometru w sposób ciągły. Cały czas wynik jest wyświetlany na LCD a w zależności od wartości pomiaru są uruchamiane odpowiednie przekaźniki sterujące osobnymi urządzeniami.
    Problemem jest to że raz na minutę, dwie następuje krótki zanik odczytu temperatury ( dosłownie na 0,5 sek) później znów wszystko wraca do normalnej pracy. Te zaniki powodują chwilowe uruchomienie przekaźnika.
    Termometr jest podłączony na kablu długości ok. 15 m (3x0.75). Rezystor podciągający 4,7K
    Myślałem że problemem jest uszkodzony termometr ale wymieniłem go na nowy i problem dalej jest ten sam.
    Czy kto miał podobny problem?
  • HelukabelHelukabel
  • Poziom 30  
    Stawiam na zbyt dużą prędkość odczytu przez co przygotowana ramka danych jest niepełna. Zmniejsz ją i zobacz.
  • Poziom 11  
    A podpowiedz mi jeszcze jak to zrobić - nie jestem zbyt biegły z arduino, to mój pierwszy projekt
  • HelukabelHelukabel
  • Poziom 39  
    Witam,
    jak sie komunikujesz z DS1820? czy czekasz odpowiedni czas na konwersje danych?
    Moze pokasz kod, zapewne uzywasz standardowych bibliotek.
    Jaki to kabel? moze masz zaklucenia? czy problem jest zawsze w tym samym momencie czy przypdakowo?
    Moze taka uwaga, kod powinien byc odporny na takie problemy, zawsze moze sie zdarzyc blado dczytu czy zaniki.
    Pozdrawiam
  • Poziom 11  
    1. Komunikacja po OneWire - tylko jeden termometr
    2. Odczyt jest bezpośredni - nie mam żadnego opóźnienia odczytu danych
    3. Nie mam teraz w pracy kodu - wrzucę go po południu
    4. Biblioteki standardowe
    5. Kabel zwykły trzyżyłowy, nieekranowany - kurcze może tutaj jest problem
    6. Problem występuje w bardzo losowych momentach - czasem zdarza się 2 razy w ciągu minuty a czasem jest 5 minut OK
    Nie mam doświadczenia w pisaniu kodów więc trudno mi stworzyć kod odporny - to mój pierwszy program i na pewno ma wiele wad, ale rzeźbię jak potrafię :)
  • Poziom 11  
    Nie mam zdefiniowanego co ile ma być odczyt temperatury
    Tutaj jest fragment kodu:

    #include <DallasTemperature.h> //biblioteka czujnika temp
    #include <OneWire.h> //biblioteka interfejsu
    #include <LiquidCrystal_I2C.h> //biblioteka wyświetlacza 2004
    #define ONE_WIRE_BUS2 //definiowanie pinu ONE-WIRE
    OneWire oneWire(ONE_WIRE_BUS);
    DallasTemperature sensors(&oneWire);
    int Grzalka =4; //definiowanie pinu grzałki
    int LED_G =5; //definiowanie pinu LED grzałki
    int Pompa =6; //definiowanie pinu pompy
    int LED_P =7; //definiowanie pinu LED pompy
    int Temperatura =2; //definiowanie pinu termometru
    int TD =37; //temperatura dolna - włączenie grzałki
    int TG =93; //temperatura górna - właczenia pompy
    int Histereza =2; //ustawienie histerezy
    int Manual =12; //ustawienie przycisku Manual
    int Grzanie =8; //ustawienie przycisku grzałka
    int Chlodzenie =10; //ustawienie przycisku pompa
    boolean SG =false; //definiowanie zmiennej grzania
    boolean SC =false; //definiowanie zmiennej chłodzenia
    boolean flaga =true; //definiowanie zniennej trybu pracy
    LiquidCrystal_I2C lcd(0x27,20,4); //Konfiguracja wyświetlacza - Adres

    void setup() {
    pinMode(Grzalka, OUTPUT); //grzałka
    pinMode(LED_G, OUTPUT); //LED grzałki
    pinMode(Pompa, OUTPUT); //pompa
    pinMode(LED_P, OUTPUT); //LED pompy
    pinMode(Temperatura, INPUT); //czujnik temperatury
    sensors. Begin(); //uruchomienie termometru
    lcd. Begin(); //inicjalizacja wyświetalcza
    pinMode(Manual, INPUT_PULLUP); //definiowanie przełącznika AUTO / MANUAL
    pinMode(Grzanie, INPUT_PULLUP); //definiowanie przycisku Grzanie
    pinMode(Chlodzenie, INPUT_PULLUP); //definiowanie przycisku Chłodzenie

    }
    void loop()
    {
    {
    sensors.requestTemperatures(); //odczyt temperatury
    float tempC = (sensors.getTempCByIndex(0));
    lcd.setCursor(0,0); //ustaw kursor w pozycji 0,0
    lcd.print("Temperatura: "); //wyswietl "Temperatura: "
    lcd.print(sensors. getTempCByIndex(0)); //wyswietl wartosc z czujnika 0
    lcd. print((char)0xDF); //wyswietl znak stopnia
    lcd. print("C"); //wyswietl znak C

    nie potrafię inaczej wstawić więc metoda kopiuj/wklej
  • Poziom 33  
    Czyli w pętli bez interwału, to słabe jest. Czy tak częste odczyty sa kluczowe w tym projekcie ? sugerowałbym max kilka na sekundę, a bardziej 2, czyli co 500ms.

    Pozdr
  • Poziom 11  
    Nie - nawet wystarczy co kilka sekund.
    Sterownik ma za zadanie sprawdzanie temperatury wody w zasobniku i w przypadku zbyt niskiej temperatury (np. poniżej 35 st) ma włączyć grzałkę i w przypadku osiągnięcia temperatury pow. 93-95 st ma wlączyć pompę która przepompuje część gorącej wody do innego zasobnika.
    Można założyć że nawet co 15 sek jest wystarczająco jak sprawdzi temperaturę
  • Poziom 33  
  • Poziom 11  
    Bardzo możliwe że tak
    Czyli mam wprowadzić jakieś opóżnienie typu "Delay" czy jakoś inaczej ?
  • Poziom 33  
    Nie, nie, delay to porażka, wykorzystaj funkcję millis()

    np. tak :

    Kod: c
    Zaloguj się, aby zobaczyć kod


    To samo możesz zrobić dla wyświetlania danych na LCD, bo nie ma potrzeba pakowania danych bez sensu cały czas.
    Można też zrobić tak, że do LCD sa wysyłane dane tylko jak się zmienią, czyli np. tak :

    Kod: c
    Zaloguj się, aby zobaczyć kod
  • Poziom 11  
    Ok - spróbuje tak zastosować
    Dzięki - dam znać czy zadziałało
  • Poziom 32  
    Niestety problemu musisz szukać gdzie indziej. Biblioteka DallasTemperature sama wprowadza opóźnienie, o którym wspomina kolega Sławek. Robiąc odczyt sama pauzuje program na 750ms (lub mniej dla niższej rozdzielczości odczytu czujnika). W niej odwrotnie, jak się nie chce tego odczekiwać trzeba użyć metody wyłączającej oczekiwanie na konwersję - sensors.setWaitForConversion(0); - dodaj to w setup i zobacz różnicę. Co oczywiście zwykle robię, bo blokowanie loop na 750ms to wieczność, już po tym zabiegu 1-wire blokuje na 20ms, co jest kłopotliwe. Oczywiście lepiej robić to z millis, odczyt może być wtedy robiony równo co 1s: włączasz czas = 0, robisz zlecenie pomiaru, czekasz 1s, wchodzisz do loop, robisz odczyt, zlecasz pomiar i wracasz do tego punktu pomiaru za 1s zgodnie z pomiarami z millis(). Natomiast trzeba pominąć wszystkie operacje jeśli temperatura nie została odczytana prawidłowo, zliczyć ilość błędnych pomiarów i po bezpiecznym czasie wyłączyć całą zabawkę. Trzeba się upewnić, że grzałka ma zabezpieczenie termiczne, wyłączające całość układu powyżej 90oC, można dodać też własny termostat mechaniczny wyłączający zasilanie grzałek już przy 80oC, a jak nie ma zaworu mieszającego na wyjściu już przy 65oC.
    W uproszczeniu dla podgrzewacza CWU możesz przyjąć, że każdy pomiar z wynikiem spoza zakresu między 5 a 80 oC jest błędny, że przez 60s nic strasznego się nie wydarzy i czekać na prawidłowy odczyt, potem wyłączyć. Użyj też WDT i ustaw na 8s. Przewód powinien mieć małą pojemność, super by był w ekranie, np. jakaś skrętka komputerowa, przewód telefoniczny, nie powinien być ułożony blisko obok przewodu zasilającego grzałkę.
  • Poziom 33  
    Kolego @StaruchPl, zobacz jak wygląda wykres temperatury kolektora słonecznego ciśnieniowego 200l napędzanego dodatkowo 1kWp paneli fotowoltaicznych, przy odczytach temperatury z DS18B20 co 60s.

    Arduino + DS18B20 - zaniki pomiarów

    Wykres jest łagodny, spokojnie wystarczy taki interwał, nie ma sensu częściej.
  • Poziom 11  
    Dzięki za podpowiedzi. Wypadł mi wczoraj pilny wyjazd na kilka dni i nie miałem możliwości przetestowania Waszych podpowiedzi. Wracam w przyszłym tygodniu więc dam znać czy sobie poradziłem
    Sławek K. masz rację że wystarczy co minutę odczytywać temperaturę - nie przewidziałem takiej opcji w trakcie pisania kodu, więc w pierwszej kolejności spróbuję zrobić właśnie tak jak podpowiadasz
    Pozdrawiam
  • Poziom 36  
    StaruchPl napisał:
    1. Komunikacja po OneWire - tylko jeden termometr
    2. Odczyt jest bezpośredni - nie mam żadnego opóźnienia odczytu danych
    3. Nie mam teraz w pracy kodu - wrzucę go po południu
    4. Biblioteki standardowe
    5. [b]Kabel[/b] zwykły trzyżyłowy, nieekranowany - kurcze może tutaj jest problem
    6. Problem występuje w bardzo losowych momentach - czasem zdarza się 2 razy w ciągu minuty a czasem jest 5 minut OK
    Nie mam doświadczenia w pisaniu kodów więc trudno mi stworzyć kod odporny - to mój pierwszy program i na pewno ma wiele wad, ale rzeźbię jak potrafię :)


    Odległość 15m os sensora to troche dużo... Próbuj obniżyć wartość rezystoa 4.7k na mniejszy, lecz nie mniej niż 1.5K
    Zakłucenia w wyświetlaniu wyniku pomiaru temperatury mogą być powodowane różnymi przyczynami, na przyklad resetowanie processora, czego nie zaobserwujesz bezpośrednio na LCD.
    Cała dyskusja stoczyła się do sposobu pomiaru i określania interwałów czasu pomiędzy odczytami temperatury z DS, gdy tymczasem 'de facto' taka specyficzna konieczność nie występuje.

    Zasilasz ten DS w formie trzy-żyłowej, czyli 'pełnej'; wiec niezależnie od ustawionej rozdzielczości pomiaru (9, 10, 11, czy 12-bits), nie musisz formalnie mierzyć czasu odczekania na dokonanie konversji. Przy tym rodzaju zasilania możesz korzystać z opcji wbudowanej w DS18B20 , która powiadomi cię że konversja została ukończona, a wtedy już tą temperaturę odczytasz kiedykolwiek przyjdzie na to potrzeba.
    Po odczycie, mozesz wydać komendę kolejnej konversji.
    Ta opcja jest uwzględniona w bibliotecew formie:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Przy zasilaniu 'pasożytniczym' ta opcja nie jest dostępna.
    Jeżeli pomiar temperatury nie wymaga wysokiej rozdzielczości (12-bit jako default; 0.0625°C) to możesz to zmniejszyć stosownie do wymogu projektu (na 9, 10, 11-bits; odpowiednio 0.5°C, 0.25°C, 0.125°C).
    Funkcja ta też jest zawarta w bibliotece..
    Kod: c
    Zaloguj się, aby zobaczyć kod

    Skoro mowa jest o zasilaniu, to byłby dobrze gdyby ten kabel zasilający DS, był jakąś komputerową lub telefoniczną skrętką, o czym już wcześniej pisano.

    e marcus
  • Poziom 4  
    kaczakat napisał:
    Przewód powinien mieć małą pojemność, super by był w ekranie

    Jeśli w ekranie to przeważnie ma dużą pojemność. Dla DS sprawdza się skrętka komputerowa.

    emarcus napisał:
    Zakłucenia w wyświetlaniu wyniku pomiaru temperatury mogą być powodowane różnymi przyczynami, na przyklad resetowanie processora, czego nie zaobserwujesz bezpośrednio na LCD.

    Przyczynę resetu można odczytać z rejestru procesora.

    StaruchPl napisał:
    4. Biblioteki standardowe

    Pewnie nie sprawdzają CRC z DS i jak są jakieś zakłócenia to zwracany jest błędny wynik. Popraw bibliotekę tak aby sprawdzała CRC.
  • Poziom 38  
    kaczodp napisał:
    Popraw bibliotekę tak aby sprawdzała CRC.

    W bibliotece DallasTemperature, w funkcjach odczytu temperatury są sprawdzane CRC dla odczytanego scratchpada.

    @StaruchPl Funkcja getTempCByIndex() zwraca wartość DEVICE_DISCONNECTED_C (-127), kiedy jest problem z odczytem DS. Nie jest to wtedy wartość temperatury.
  • Poziom 4  
    khoam napisał:
    W bibliotece DallasTemperature, w funkcjach odczytu temperatury są sprawdzane CRC dla odczytanego scratchpada.

    Tą która mam odczytuje tylko dwa bajty, bez crc.
  • Poziom 38  
    kaczodp napisał:
    Tą która mam odczytuje tylko dwa bajty, bez crc.

    Aktualna wersja biblioteki DallasTemperature znajduje się pod linkiem:
    https://github.com/milesburton/Arduino-Temperature-Control-Library