Elektroda.pl
Elektroda.pl
X

Search our partners

Find the latest content on electronic components. Datasheets.com
Elektroda.pl
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

[Solved] [ATmega8][C] Termometr ATmega8, DS18B20, LCD - pokazywana temperatura 0,0

traur 30 Apr 2019 11:38 678 19
  • #1
    traur
    Level 7  
    Drugi dzień próbuję wyświetlić na wyświetlaczu LCD 2x16 temperaturę pobraną z czujnika DS18B20.
    Układ używa ATmega8.
    Program piszę w Atmel Studio 7.
    Sprawdzałem różne gotowce, sam próbowałem różnych sposobów ale efekt ten sam - temperatura na wyświetlaczu ciągle to 0,0.
    Proszę o wskazówki co może być przyczyną.
    Czujnik podłączony do portu PD7, rezystor podciągający 4.7k (testowałem też na rezystorze 3,3k).
    Zamieszczam kody biblioteki z dopisaną funkcją 'show()' oraz main.c
    Pisząc ds18b20.c wzorowałem się na PDF'ie pana Cezarego Klimasz (z drobnymi poprawkami).

    main.c
    Code: c
    Log in, to see the code


    ds18b20.h
    Code: c
    Log in, to see the code




    ds18b20.c
    Code: c
    Log in, to see the code
  • #2
    Marico
    Level 20  
    Tak na szybko to kod komunikacji 1w wygląda w miarę poprawnie, podejrzany dla mnie jest dtostrf(), czy to prawidłowo formatuje float na string?
    Sprawdziłbym czy cTemperatureL oraz cTemperatureH zawierają bajt <> 0 przed wywołaniem funkcji formatującej.
    Trwałe zwracanie 0 przy odczycie danych na prawidłowo zaimplementowanej magistrali 1W (zawierającej chociaż pullup) jest dość mało prawdopodobne, Wystąpi tylko, gdy magistrala jest zwarta do masy lub czujnik został podłączony odwrotnie (czym zwiera magistralę).

    Dodano po 45 [minuty]:

    Można się przyczepić do tego, że przy v1Wire_SendBit() nie ma slotu recovery (nie ma go również w v1Wire_SendByte(). Wywołanie DIR_1WIRE_IN i zaraz po tym DIR_1WIRE_OUT w przypadku wysyłania zer po sobie może spowodować brak wymaganego Trec (> 1us) (nie wiem jak szybko przełącza port Twój mcu).

    Dodano po 8 [minuty]:

    uc1Wire_ResetPulse() nie wykrywa sytuacji zwarcia magistrali, co może w takim przypadku błędnie sygnalizować obecność  presence pulse.
    Po drugim _delay_us(480); warto jeszcze raz sprawdzić czy na magistrali jest "1" a nie ciągle '0". Zwracać tylko "1" gdy pierwszy odczyt był 0 a drugi 1. Lub rozbudować tą funkcję tak aby zwracała odpowiednie kody błędu dla "jest puls", "brak pulsu", "zwarcie".
  • #3
    traur
    Level 7  
    Mogę prosić o fragment kodu jak przerobić funkcję uc1Wire_ResetPulse?
  • #4
    Marico
    Level 20  
    Code: c
    Log in, to see the code


    Jeśli uc1Wire_ResetPulse() zwróci 2 to oznacza to zwarcie.
  • #5
    traur
    Level 7  
    Czy ustawienia które mam wprowadzone:
    #define PIN_1WIRE PD7
    #define PORT_1WIRE PORTD
    są prawidłowe? Analizując PDF powinno być:
    #define PIN_1WIRE 7
    #define PORT_1WIRE PIND
  • Helpful post
    #6
    Marico
    Level 20  
    Nie znam się na ATmegach i Atmel Studio jak określa port ale zaprezentowany kod odwołuje się do całego portu:

    #define OUT_1WIRE_LOW PORT_1WIRE &= ~(1 << PIN_1WIRE);

    Konfiguracja (wskazanie) w kodzie prawidłowego portu/pinu 1W jest oczywistą oczywistością, jak mawiał klasyk i szczerze mówiąc wstępnie nie rozważałem takiej sytuacji. Użycie błędnego portu/pinu może zwracać 0.
  • #7
    traur
    Level 7  
    Przyglądając się bibliotece z LCD która działa w Atmel Studio powinno się to określać w ten sposób
    #define LCD_RS_DIR DDRD
    #define LCD_RS_PORT PORTD
    #define LCD_RS (1 << PD5)
    Czyli tak jak w mojej wersji jest dobrze.
    W takiej sytuacji jednak cały czas jest zwarcie.

    Jeżeli ustawię tak jak w PDF:
    #define PIN_1WIRE 7
    #define PORT_1WIRE PIND

    na LCD pokazuje się -0.1 - to zaokrąglona wartość -0.0625
    po odłączeniu czujnika na LCD "zwarcie"

    Dodałem również komunikat w razie gdy dostaje 0 z uc1Wire_ResetPulse() - jednak taka sytuacji nie potrafię zasymulować i komunikat "brak czujnika" nie wyświetla się nigdy


    EDIT:
    Po odłączeniu czujnika wartość z -0,1 zmienia się na 0.0 i po chwili wskakuje komunikat zwarcie.
  • #8
    kaczakat
    Level 33  
    Dobrze jest mieć sprawdzony czujnik DS18B20, bo może być tak, że siedzisz cały dzień, w programie wszystko jest dobrze, tylko czujnik uszkodzony. No i najprościej wydrukować komunikaty na UART, sprawdzonych bibliotek jest dużo. Oczywiście LCD też może być, tylko najpierw testuję wszystkie możliwe inty, floaty, znaki i napisy, a dopiero przechodzę do zabawy z kolejnym komponentem.
    Napisz jaki masz zegar to mogę Ci wrzucić gotowego hexa na wybrany piny z wydrukiem temperatury na UART.
  • #9
    traur
    Level 7  
    Czujniki mam 2 - jeden i drugi pokazuje to samo.

    F_CPU=8000000 ustawione w Properties projektu
  • #10
    kaczakat
    Level 33  
    PC3 jest ustawiony na onewire, PC5 jest podłączone do LED, UART sprzętowy na 9600, też miałem podłączone 2 czujniki ale odczytuje 1 (choć zlicza ile jest na magistrali - to ta wartość DS: 2), po podmianie trzeba zrobić reset.
    Tak powinien wyglądać wydruk na UART:

    Spoiler:
    143 DS: 2 26.18o C
    144 DS: 2 26.44o C
    145 DS: 2 26.81o C
    146 DS: 2 27.25o C
    147 DS: 2 error - tu wypiąłem odczytywany czujnik
    148 DS: 2 error
    149 DS: 2 error
    150 DS: 2 error
    151 DS: 2 error
    152 DS: 2 error
    0 DS: 1 26.12o C
    1 DS: 1 26.12o C
    2 DS: 1 26.6o C
    3 DS: 1 26.0o C
    4 DS: 1 26.0o C
    5 DS: 1 25.93o C
  • #11
    traur
    Level 7  
    Na obecną chwilę trochę pozmieniałem kod.
    Zachowanie czujnika wygląda następująco:
    -przy normalnym podłączeniu pokazuje -0.1 (to zaokrąglone -0.0625)
    -po odłączeniu środkowego pinu od atmega8 - pojawia się napis "zwarcie" a temperatura zmienia swoją wartość na 0.0
    -nie potrafię doprowadzić do sytuacji by wyświetlić napis "brak cz"

    main.c
    Code: c
    Log in, to see the code


    ds18b20.h
    Code: c
    Log in, to see the code


    ds18b20.c
    Code: c
    Log in, to see the code
  • Helpful post
    #12
    Wojtek75
    Level 24  
    traur wrote:
    F_CPU=8000000 ustawione w Properties projektu
    A fuse bity w uc masz ustawione na 8MHz. Jeżeli nic nie ustawiłeś to uc domyślnie pracuje z częstotliwością około 1MHz.
  • #13
    traur
    Level 7  
    Jak przestawić to uc w fusebitach?
    Ewentualnie mogę przestawić F_CPU=10000000 i zmienić czasy oczekiwań odpowiednich dla 1MHz?
  • Helpful post
    #15
    kaczakat
    Level 33  
    traur wrote:
    F_CPU=10000000 i zmienić czasy oczekiwań odpowiednich dla 1MHz?

    Do tego zmień na milion, a nie dziesięć.
    Ściągnij sobie AVR LAB++ czy MK AVR Kalkulator (demo tego działa z Atmega8) i po prostu sobie przestaw na 8MHz.
    Gotowy hex, który Ci tu wrzuciłem zmienia stan led co 1s, jeśli masz zegar prawidłowo ustawiony to na pewno oczami zauważysz czy masz ustawiony procesor na 1MHz czy na 8MHz, jak jest za wolny to led zmienia się znacznie wolniej.
  • #16
    Urgon
    Editor
    AVE...

    Oto kod w wersji dla rodziny PIC, który napisałem do obsługi 1-Wire zgodnie ze specyfikacją protokołu. Kod po angielsku, by więcej osób mogło z tego skorzystać. Tris ustala kierunek pinu: 0 = wyjście, 1 = wejście.
    Code: c
    Log in, to see the code

    Mam nadzieję, że to koledze pomoże...
  • #17
    traur
    Level 7  
    Co mam wrzucać do funkcji jako tris i pin?

    Wstępnie dopisałem do Twojego kodu funkcję wyświetlającą na LCD, efekt: nadal -0.1

    Oto kod dodanej funkcji którą wywołuję w main.c:
    Code: c
    Log in, to see the code


    Pewnie błędnie przekazuję wartość dla pin oraz tris - niestety nie wiem jakie wartości są właściwe.
  • Helpful post
    #18
    Urgon
    Editor
    AVE...

    Do wszystkich funkcji podajesz nazwę bitu w rejestrze portu i nazwę bitu w rejestrze kierunku.
    Przykładowo dla PICa te rejestry to PORTx i TRISx, gdzie x to nazwa portu (A, B, C, etc.). Zatem przykładowo kod dla PIC16F do sprawdzenia obecności dwóch sensorów na dwóch pierwszych pinach portu A i ustawienie stosownych flag w dedykowanej ku temu strukturze oraz inicjalizacja pierwszej konwersji wyglądają tak:

    Code: c
    Log in, to see the code

    AVR ma zapewne inne nazwy rejestrów...
  • #19
    traur
    Level 7  
    TRIS w avr to o ile dobrze znalazłem DDR.
    Przerobiłem kod według tego co mi podałeś - niestety nadal na LCD -0.1
    Czujnik mam podpięty do portu PD7

    Kod wygląda teraz tak:

    Code: c
    Log in, to see the code
  • #20
    traur
    Level 7  
    TRIS w avr to o ile dobrze znalazłem DDR.
    Przerobiłem kod według tego co mi podałeś - niestety nadal na LCD -0.1
    Czujnik mam podpięty do portu PD7

    Kod wygląda teraz tak:

    Code: c
    Log in, to see the code


    Dodano po 4 [minuty]:

    Wróciłem do swojego kodu, przestawiłem w programie mkAVRCalculator w fusebitach uproszczonych wewnętrzny oscylator z 1Mhz na 8MHz, i pokazuje temperaturę!
    Dziękuję wszystkim za pomoc. Zamykam.