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

[C] READ ROM 2 x DS18b20 1-wire

qutrit 26 Mar 2010 22:54 11585 39
  • #1 7884460
    qutrit
    Poziom 20  
    Witam,
    czy ktoś z szanownych kolegów mógłby mi rozjaśnić taką kwestie dotyczącą odczytu 64-bitoego kodu z DS-a. Mianowicie wiem (chyba, że źle wiem), że aby to zrobić należy użyć komendy read rom wtedy gdy do linii podłączony jest jeden DS. Następnie aby odczytać kod następnego DS-a należy zmienić układ itd. Poprostu skąd autor fragmentu poniższego kodu (dla 4 układów) zna dokładne adresy Ds-ów :?: Gdzie one zostały mu wyświetlone :?: W jaki sposób trzeba napisać program (ja używam C) aby wyświetlił ten rom kod :?: Jak dobrze rozumuję jeżeli będę miał rom kody moich czujników zamieszczone w tablicy to będę mógł w łatwy sposób je adresować za pomocą MATCH ROM. Chyba że coś źle rozumuję :cry:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Potrzebuję tej informacji ponieważ chciałbym zrobić sobie 2-punktowy termometr wykorzystując 1-wire. Dla jednego Ds-a mój termometr działa poprawnie.

    Pozdrawiam.
  • Pomocny post
    #2 7884653
    michalko12
    Specjalista - Mikrokontrolery
    Wysyłasz komendę READ ROM a potem czytasz 8 bajtów. Co w tym jest nie do zrozumienia? Wysyłać komendy i czytać dane z czujnika potrafisz skoro działasz z jednym czujnikiem.
  • #3 7888315
    qutrit
    Poziom 20  
    Witam,
    tak wiem, tylko jezeli chcę umieścić kody w tablicy w programie to muszę je pierw gdzieś (jakoś) wyświetlić, i na tym polega mój problem ze, nie wiem jak to zrobić.

    Cytat:
    Wysyłasz komendę READ ROM a potem czytasz 8 bajtów

    Oznacza to ze muszę mieć podłączony wyświetlacz do procesora i z niego odczytywać :?:

    Moze ktoś dysponuje fragmentem kodu w C dotyczącym odczytania rom kodu :?:

    Pozdrawiam.
  • Pomocny post
    #4 7889225
    omicronNs
    Poziom 21  
    A po co je wyświetlać? Wpisujesz je chyba do zmiennej a nie do zeszytu :D A pobieranie kodu ROM nie polega tylko na wysłaniu SEARCH ROM i czytaniu 8-miu bajtów. Do tego służy pewien algorytm na bazie drzewa bitowego.

    U mnie wygląda to tak(kod algorytmu nie jest mojego autorstwa):

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Oprócz tego mam zadeklarowaną globalną zmienną tablicową dwuwymiarową rom, wygląda to tak: unsigned char rom[ilość_termometrów][8]. Do niej wpisywane są kody rom, dostępne potem dla każdej funkcji w programie. Jeśli chcesz skopiować kod to musisz pozmieniać nazwy funkcji owire_reset, owire_get_bit, owire_send_byte. Nie muszę chyba ich tłumaczyć co poszczególne robią. I zdefiniować stałą AMOUNT zawierającą ilość termometrów na linii. No i w zależności od tego co zwraca Tobie funkcja restartu linii DQ ewentualnie potrzeba zanegować logicznie warunek w pierwszej pętli while 1-negacja, 0-bez negacji.


    edit//

    Aha! już rozumiem o co ci chodzi z tym zapisywaniem. Ty chcesz zczytać romy, odczytać je sobie i zapisać(do zeszytu :D ) i wpisać je na stałe do programu? To nie jest zbyt dobry pomysł. Czytaj je przy każdym uruchomieniu programu i wpisuj do tablicy tak jak w powyższym kodzie. Bo co jeśli wymienisz termometr? A i dodanie kolejnego w przypadku mojej propozycji będzie łatwiejsze.
  • #5 7891192
    rdyla
    Poziom 12  
    Witam, kolego OmicroNs mógłbyś wrzucić jeszcze jak się tą funkcję w praktyce obsługuje? Chodzi mi o sposób odwoływania się do czujnika którego kod jest zapisany w tej tablicy...
  • #6 7892173
    qutrit
    Poziom 20  
    Witam.

    Cytat:

    Do tego służy pewien algorytm na bazie drzewa bitowego.

    Znam ten algorytm (narazie teoretycznie), który polega na odczytywaniu bitu a następnie bitu komplementarnego itd.


    Cytat:
    Aha! już rozumiem o co ci chodzi z tym zapisywaniem. Ty chcesz zczytać romy, odczytać je sobie i zapisać(do zeszytu Very Happy ) i wpisać je na stałe do programu?

    Dokładnie oto mi chodzi :D . Dlatego pytam jak to zrobić, ponieważ jakoś ten sposób (z wpisaniem do programu do tablicy) wydaje mi się lepszy. Oczywiście ma swoje wady, takie jak np. po zmianie czujnika musiałbym zmienić rom kod w programie.

    Więc skoro już wiadomo oco mi chodzi, to teraz może ktoś mnie oświeci :idea: Nie wiem czy to takie trudne czy coś umknęło mi z dokumentacji DS-a.

    Pozdrawiam.
  • Pomocny post
    #7 7892581
    omicronNs
    Poziom 21  
    Funkcja może przyjąć argument od 0 do AMOUNT-1 i wysyła na linię DQ rom'a z tablicy.

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    qutrit>> jak bardzo chcesz na stałe wpisać rom na stałe do flasha, to podłącz do portu kontrolera diody, do innego portu termometr, sczytaj romy tym co podałem, i wystawiaj kolejne bajty tablicy z opóźnieniami(żebyś zdążył odczytać) na port z diodami. Aczkolwiek odradzam takie rozwiązanie. Taką tablicę z flasha i tak wczyta do sramu więc jeśli zależy ci na oszczędności tej pamięci to kicha.

    //edit Kompilujesz, programujesz megę (8) do portu b pinu 0 podłączasz sczytywanego ds'a, a do portu b i portu c(opcjonalnie) diody. Na porcie d masz dane, na porcie c numer bajtu kodu rom (1-8). I wsio :D

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Na marginesie, to ja dalej nie wiem na czym polega sczytywanie romu z linii, funkcja znaleziona gdzieś na elce. Z resztą od razu widać że ta jedna jest inaczej napisana od pozostałych powyższych. ;)
  • Pomocny post
    #8 7893238
    sepako
    Poziom 14  
    Rozpoznawanie za każdym razem ID ROM może i jest uniwersalne ale ja tez wybrałem prostszy sposób oznaczyłem sobie każdy czujnik i odczytałem jego ID. Aby odcztać ID ROM na magistrali musi być tylko jedno urządzenie na którym wykonujesz np taka operacje:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Odczytany wynik zapisujesz tab[n] w kajecie wraz z numerem przetwornika (np wydrapany igłą na obudowie) i podpinasz następny czujnik do odczytania. Dalej to tylko korzystasz z odczytanych ID ROM adresując potrzebne czujniki.
  • #9 7893780
    qutrit
    Poziom 20  
    Dzięki
    oto mi chodziło.
    Pozdrawiam.
  • #10 7894865
    rdyla
    Poziom 12  
    Witam, mam problem z tą komendą search rom. Wziąłem kod od kolegi OmikronNs, który jest powyżej i wszystko śmiga ale tylko gdy daje komende Skip ROM, a przy probie odczytu kodu ROM i użyciu Match ROM, nie wyswietla temperatury. Tutaj jest mój kod:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Reszta funkcji jak u kolegi OmikronNS.
    Może ktoś pomoże mi znaleść błąd?
  • #11 7901115
    omicronNs
    Poziom 21  
    owire_send_byte(rom[AMOUNT][i])

    To tak na pierwszy rzut oka - nie może być w tablicy stałej z liczbą termometrów AMOUNT, ponieważ tablicę liczy się od zera. Jak masz tylko jeden termometr klepiesz tam 0. W ogóle to nie pisz za każdym razem pętli z wysyłaniem romu tylko wydziel na to odpowiednią funkcję.

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Funkcja przyjmuje wartości od 0 do AMOUNT-1, i jest to numer czujnika.

    Tak na marginesie to zmienne w c powinno się deklarować w jednym miejscu przy klamrze otwierającej funkcji. I jaki ma cel zmienna sprawdz? Bo main się skończył a ona dalej jest 0 i nic z nią nie robisz.

    No i ten float. Potrzebna ci tak duża dokładność temperatury? Ja programuje ds-a na 9bit-ową konwersję i temperaturę mam po niecałych 100ms. a mimo wszystko bit połówki stopnia olewam.
  • #12 7903369
    rdyla
    Poziom 12  
    Witam, już wszystko śmiga:) Powodem nie działania było te odwołanie do tablicy:) nie wiem jak mogłem zrobić taki błąd:) Wielkie dzięki za pomoc.

    Funkcja owire_reset() zwraca do zmiennej "sprawdz" wartość po ktorej wiem czy jest podłączony jakiś czujnik do magistrali, ale w tym kodzie nie jest to zaimplementowane (usunąłem tymczasowo wszystkie zbędne linijki kodu:))

    A jeśli chodzi o floata to nie potrzebuje tak dokładnej temperatury i zmienię to później w kodzie, ale w sumie czemu wszyscy tak narzekają na float'y? u mnie zmienna float zajmuje 4B czyli tyle co long to przecież nie jest za wiele? Chyba, że o coś innego chodzi?
  • #13 7904610
    omicronNs
    Poziom 21  
    Przeglądam mnemoniki assemblera avr i nie widzę instrukcji operacji na zmiennym przecinku, czyli implementacja takich obliczeń zżera sporo czasu jednostki. Niestety :D Dlatego od floatów z daleka się trzymam, zwłaszcza, że póki co jeszcze nie potrzebowałem tego typu. :)

    Pozdrawiam
  • #14 7904678
    rdyla
    Poziom 12  
    No jeśli chodzi o czas to masz racje pewnie zżera trochę czasu :) , ale ja jak na razie nie mam jakich specjalnych rygorów czasowych w programie. Pozdrawiam
  • #15 9118538
    arci123
    Poziom 11  
    Odkopuję stary temat, ale nie mogę sobie poradzić z odczytem temperatury po wykorzystaniu Match ROM. Teoretycznie powinno działać, ale ...
    Tutaj daję kod:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Gdy używam Skip ROM termometry działają bez zastrzeżeń, problem pojawia sie przy wybieraniu konkretnego urządzenia.
  • #16 9118799
    asembler
    Poziom 32  
    Sprawdzales czy tablica adresów czujników dobrze jest zapełniania przez program searchrom?
    Przy czytaniu temperatury nalezy odczytac 72bity i sprawdzic CRC.
  • #17 9118927
    arci123
    Poziom 11  
    Użyłem funkcji Search ROM, która teoretycznie działała u kolegów wyżej. Tylko zmieniłem nazwy funkcji do odczytu bitu, bajtu. Dlaczego mam odczytywać 72bity podczas odczytu temp? Przecież ona zawiera się w dwóch pierwszych bajtach. Przy użyciu skip ROM wszystko działa. Na razie chcę uruchomić choć jeden termometr za pmocą MATCH ROM. Nie jestem pewny co do tego algorytmu przeszukiwania Search ROM. Choć jak przeglądałem wydawało się wszystko OK. W sieci też za wiele gotowych rozwiązań nie ma.
  • #18 9118967
    asembler
    Poziom 32  
    Bo na końcu jes CRC służące do weryfikacji odebranych bajtów. Jezeli przy użyciu skip ROM działa to znaczy że adresy czujników te 8 bajtowe masz nieprawidłowe.
    Spróbuj na poczatek poprostu odczytać i reczne wprowadzic do tablicy adresów.
  • #19 9287375
    qutrit
    Poziom 20  
    Witam.
    Mam takie pytanko do znawców tematu. Robię sobie termometr wielopunktowy na czujnikach DS i Atmegi. Każde naciśnięcie przycisku będzie powodowało przejście do odczytu z kolejnego czujnika. Mogę to zrobić na dwa sposoby:

    1. Połączyć wszystkie DS-y pod jedną linię (równolegle) i adresować je kodami ROM,wcześniej odczytanymi i umieszczonymi w tablicy. Takie rozwiązanie jest może i eleganckie jednak problem może się pojawić gdy zepsuje się jakiś czujnik. Konieczność przeprogramowania atmegi z nowym kodem ROM nowego DS-a. Trochę kłopotliwe i czasochłonne.

    2. Podłączenie DS-ów w ten sposób ze "+" od każdego DS-a będzie podłączony do oddzielnej nóżki atmegi. Przyciśnięcie przycisku będzie powodowało włączenie tylko jednego portu przy wyłączonych pozostałych do których podłączone są czujniki.
    2a. Podobnie jak punkt 2 tylko do osobnej nóżki atmegi podłączamy przewód "data" od DS-a. Czyli "+" i "-" są cały czas podłączone do zasialnia.
    W tych punktach mogę skorzystać z komendy SkipRom.

    Oczywiście w tym przypadku muszę do czujników podłączać osobne przewody, ale ponieważ czujniki będą rozmieszczone w obrębie 1m, to żaden problem. Skłonny był bym zbudować ten termometr na podstawie punktów 2 lub 2a ze względu na szybką wymianę czujnika w razie awarii. W związku z tym który sposób jest lepszy: osobne zasilania czy osobne porty "data" :?: A może jest jakiś inny lepszy sposób :?: Czy w przypadku osobnego zasilania DS-a muszę stosować jakiś tranzystor, czy jakiś czasy opóźnień dłuższe (chodzi mi o _delay). Pytam, bo nie chciałbym na początku czegoś spalić.
  • #20 9651525
    esh0
    Poziom 19  
    Witam.

    Takie pytanie mam: czy DS18S20 różnią się w poszukiwaniu search rom od DS18B20? Nie za bardzo chce mi to działać, kod jak poniżej:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Jako dwa pierwsze bity odczytuje 01, następnie do końca (64 bit) 11. Sprawdziłem oba DSy pobierając ich numery seryjne: 8.247.58.85.0.4.0.221 i 136.156.43.85.0.4.0.192. Jednak już tutaj coś mi się nie zgadza. Według noty producenta, DS18S20 mają ID = 0x10, czyli pierwsze bajty w obu powinny być: 16? A nie są... Pytanie, czy mam coś nie tak z kodem?
  • #21 9663699
    esh0
    Poziom 19  
    Kupiłem DS18B20. Przy okazji zauważyłem, że w funkcji read_rom jest błąd, niepotrzebnie odczytuję jeden bit przed odczytaniem całego SN. Po poprawieniu poprawnie rozpoznaje rodzaj urządzenia (w przypadku B20 - 28h).

    Nie zmienia to faktu, że funkcja search_rom nadal nie działa. Czy ktoś widzi w niej jakiś błąd?
  • #22 12555362
    oookamilooo
    Poziom 11  
    Witam.

    Potrzebuje pomocy, gdyż mam problem z programem. Siedzę nad nim i nie mogę nic wymyślić mądrego. Problem jest chyba już z czytaniem rom ds'ów. Skorzystałem z kodów powyżej i nic nie pomogło.

    Proszę o pomoc i z góry dziękuję.

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #23 12555463
    BlueDraco
    Specjalista - Mikrokontrolery
    Sformatuj kod i napisz jaki dokładnie masz problem. Napisanie "nie działa" nie jest żadną informacją. Co działa, a co nie? Po czym poznajesz, że jest źle?
  • #24 12555549
    oookamilooo
    Poziom 11  
    Program kompiluje się i wgrywa. Wyświetlony zostaje napis "SAPiR Kamil Osinski" następnie w pętli chciałem kontrolnie wyświetlić zawartość tablicy ROM lecz wyświetlane są same "0". Zatem przypuszczam, że nie został w ogóle odczytany kod ROM.

    Po czym program przechodzi po kolei do końca kodu i wyświetla napis "Temp", numer czujnika i temperaturę równą 0.0. Czyli w ogóle nie ma procesu odczytu temperatury z racji tego, że nie ma kodu ROM ds'a.
  • #25 12558208
    Michał93b
    Poziom 13  
    Mam również z tym kłopot, choć ja nie mam pojęcia, czy, w ogóle porównanie, jakie wstawiłem ma prawo bytu. Zarówno uC jak i C dopiero się uczę.
    Zaznaczę, że odczyt z jednego termometru jest poprawny.
    W załączniku dodaję DS1820.h, DS1820.c oraz plik main.c.
    Biblioteki wyświetlacza nie dodaję, bo działa, wyświetla co bym chciał.
    Nie mam również koncepcji, jak sprawdzić, czy w tablicy rom cokolwiek istnieje, nie wiem jak ją wyświetlić na LCD.
    Po ekranie powitalnym na ekranie jest cisza.
  • #26 12558709
    oookamilooo
    Poziom 11  
    To jest fragment mojego kodu który odpowiada za wyświetlanie tablicy ROM

    for(i=0; i<8; i++)
    {
    char fff=0;
    fff=rom[1][i];
    dtostrf(fff,1,0,buf);
    LCD_GoTo(0,0);
    LCD_WriteText(buf);
    _delay_ms(200);
    LCD_Clear;

    }

    Może należałoby zacząć od tego, co tak naprawdę jest prawdziwe. Jedni uważają że nie da się odczytywać kodu ROM gdy na linii 1-Wire jest więcej urządzeń niż jedno. Logicznie myśląc jeżeli wysyłamy na linię komendę "podaj swój adres ROM" to gdy mamy kilka urządzeń to skąd "mają one wiedzieć" z którego urządzenia chcemy ten adres. W takiej sytuacji wysyłają wszystkie zgadza się?

    Inni natomiast uważają, że da się odczytywać ten kod gdy mamy kilka urządzeń na linii, czego przykładem jest kod kolegi powyżej.

    Proszę o odpowiedz na to pytanie i pomoc.
  • #27 12558760
    BlueDraco
    Specjalista - Mikrokontrolery
    Procedura rozpoznawania wielu urządzeń jest dokładnie opisana w dokumentacji Dallas. Zamaist raportować "co uważają jedni, a co drudzy", przeczytaj dokumentację.

    Przy wielu urządzeniach nie można po prostu odczytać kodu ROM, za to można przeprowadzić identyfikację, która w każdej iteracji podaje kod kolejnego urządzenia. Po zebraniu kodów w tablicy możesz następnie adresować poszczególne czujniki i czytać je indywidualnie.
  • #28 12558774
    oookamilooo
    Poziom 11  
    Teraz rozumiem. Dziękuję BlueDraco!

    A czy mógłbyś zerknąć wprawnym okiem w mój kod powyżej. Po prostu patrzę na niego setny raz i już nic nie widzę. :)

    Z góry dzięki.
  • #29 12558809
    Michał93b
    Poziom 13  
    No to dokładnie tak mam. Dataheeta DSa znam prawie na pamięć, rozmyślałem wczoraj nad algorytmem kilka godzin. Dalej ruszyć nie umiem.
    Identyfikację przeprowadzam co reset urządzenia, funkcja search_rom zdaje się być prawidłowa. A mimo to nie ma komunikacji z DSami.
  • #30 12558856
    BlueDraco
    Specjalista - Mikrokontrolery
    Michał93b:

    Adresy czujników masz w rom[0] i rom[1], a w kodzie używasz rom[1] i nieistniejącego rom[2], czyli wysyłasz śmieci zamiast adresu i czujnik nie odpowiada.

    Zauważ, że czynności dla obu czujników są dokładnie takie same - po co rozmnażasz kod dwa razy, skoro jest to ten sam kod, różni się tylko numerem czujnika, który pownien być zmienną przyjmującą na przemian wartości 0 i 1.

    możesz napisać np. w pętli wysyłana adresu
    send_byte(rom[nr][i]);

    Poza tym danych NIE definiuje się w pliku .h.

    Przenieś deklaracje rom[] i buf[] do głównego pliku programu, a w pliku .h zostaw:
    extern unsigned char rom[][8];
REKLAMA