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

[ATMega162][Bascom]Odczyt z 1wire w przerwaniu.

sundayman 22 Kwi 2010 19:08 3981 34
  • #1 22 Kwi 2010 19:08
    sundayman
    Poziom 24  

    Mam tutaj na Atmedze162 taki problem.

    Zrobiłem odczyt z DS18B20, wykorzystując taką funkcję :

    Code:

    Function Ds_read(byref Sensor As Byte) As Integer
    1wreset
    1wwrite &H55
    1wwrite Sensor , 8
    1wwrite &HBE
    Ds_val = 1wread(2)
    Ds_val = Ds_val * 10
    Ds_val = Ds_val / 16
    Ds_read = Ds_val
    End Function


    i wszystko jest ok, o ile wykonuję pomiar wywołując tą funkcję z pętli do...loop w normalnym programie.
    Ale chciałem przenieść wykonywanie pomiaru do przerwania, i zaczęły się schody.
    Ogólnie, przeniosłem do przerwania (timer0) całą procedurę odczytu, w tym wywołanie funkcji. I ku mojemu zaskoczeniu nie działa.
    Najpierw myślałem, że problem jest w przekazywaniu parametrów z/do funkcji pod przerwaniem. ALe potem przeniosłem całą procedurę odczytu do przerwania ;

    Code:

    ' PRZERWANIE /////////////////////////////////////////////////////////////////////
    Przerwanie:
    Disable Timer0

    ' miganie ledem
    Incr Czas
    If Czas = Tempo Then
       Toggle Led_online
       Czas = 0
    End If

    'pomiar temperatury
    If Ds_count > 0 Then

       1wreset
       1wwrite &HCC
       1wwrite &H44
       Wait 2

       ' to zamiast funkcji
    1wreset
    1wwrite &H55
    1wwrite Ds_id1(1) , 8
    1wwrite &HBE
    Ds_val = 1wread(2)
    Ds_val = Ds_val * 10
    Ds_val = Ds_val / 16

    Print "wynik=" ; Ds_val

    End If
    Enable Timer0
    Return
    ' KONIEC PRZERWANIA //////////////////////////////////////////////////////////////


    przy czym:
    DS_count to liczba czujników wykryta wcześniej (w tym przypadku=1)
    DS_ID1 to identyfikator czujnika

    I teraz jest tak, że przy pierwszym wywołaniu przerwania ds_val zawiera prawidłowy pomiar , a następne są już równe 0.

    Na początku obsługi przerwania timer0 jest wyłączany, na końcu włączany.
    "Normalny" program nic nie robi (pusta pętla do...loop), żeby nie byłą wątpliwości, że coś tam miesza.

    W czym może być problem ?

    Poprawiłem tytuł.
    [zumek]

    0 29
  • Arrow Multisolution Day
  • #2 24 Kwi 2010 08:35
    jousto
    Poziom 16  

    Nie wiem jak wyliczasz DS_count ale na moje oko to właśnie problem pojawia się, że za następnymi wywołaniami przerwania właśnie DS_count jest różne od 1 i pomiar nie jest dokonywany.
    Poza tym nie wiem jak to ma działać, analizując po kolei to co robi funkacja w przerwaniu.
    1. Reset
    2. Skip ROM
    3. Polecenie konwersji
    4. Czekaj 2sek
    5. Reset
    i tu zaczyna się coś dziwnego:
    najpierw funkcja działa tak jakby na magistrali był tylko jeden czujnik, a teraz jakby ich było więcej. Musisz być konsekwentny jak korzystaz z funkcji Skip ROM to nie przeskakuj na Match ROM, niby nie ma różnicy ale pewnie nie działa.

    6. Match ROM
    7. Zaadresuj czujnik
    8. Polecenie odczytu scratchpad
    9. Odczyt 2 pierwszych bajtów
    itd

    Po mojemu ta funkcja mogłaby wyglądać tak:

    Code:

      1wreset
      1wwrite &HCC
      1wwrite &H44
      Waitms 200    'w zależności od wybranej rozdzielczości, tu 9bit
      1wreset
      1wwrite &HCC
      1wwrite &HBE

      Lsb = 1wread():
      Msb = 1wread():
      Ds_val = Msb * 256
      Ds_val = Ds_val + Lsb
      Ds_val = Ds_val / 16

      Print "wynik=" ; Ds_val
     

    0
  • #3 24 Kwi 2010 11:13
    piotr5000
    Poziom 21  

    Nigdy w przerwaniu nie użyłem "wait" i nie użyje.

    0
  • Arrow Multisolution Day
  • #4 24 Kwi 2010 11:29
    netsecurite.pl
    Poziom 13  

    piotr5000 napisał:
    Nigdy w przerwaniu nie użyłem "wait" i nie użyje.


    Od tego są timery w AVR aby z nich korzystać ;)

    0
  • #5 24 Kwi 2010 11:31
    janbernat
    Poziom 38  

    Miałem coś podobnego ale tylko dla 1 DS:
    https://www.elektroda.pl/rtvforum/viewtopic.php?t=1623781&highlight=
    Dla większej ilości jeszcze nie obliczyłem i nie sprawdziłem.
    Ostatni program jest dobry i działa- przerwanie co 4ms.
    Może spróbuj iść w tym kierunku- ale czas odczytu DS sprawdzałem na oscyloskopie- dla większej ilości DS- trzeba sprawdzić.

    0
  • #6 24 Kwi 2010 12:07
    piotr5000
    Poziom 21  

    netsecurite.pl - czytaj uważnie . Nie napisałem , że nie korzystam z timer'ów , ale jaki jest sans obsługi przerwania przez 2 sekundy (WAIT 2) gdy timer wywołuje przerwanie co np. 2milisekundy ?

    0
  • #7 24 Kwi 2010 13:09
    mirekk36
    Poziom 42  

    W ogóle gigantycznym nieporozumieniem jest próba "gadania" z czujnikami DSxxxx w przerwaniach. Jak zwykle pojawia się temat flagi, którą wystarczy ustawiać w przerwaniu a w pętli głównej korzystać z tej flagi i co odpowiedni interwał czasowy "prowadzić" rozmowę z czujnikami - inaczej to bez sensu.

    A już nie wspomnę jak niektórzy mówili żeby do przerwania wstawiać choćby Waitms - to już jest masakra ;)

    0
  • #8 24 Kwi 2010 14:22
    janbernat
    Poziom 38  

    Bo są timery sprzętowe- i dobrze że są.
    A z nich można zrobić przerwania programowe- wystarczy obliczyć ile razy timer sprzętowy się odezwie.
    A wstawianie Waitms albo _delay w przerwaniu- to jak napisał mirekk36- masakra.
    Ale wstawianie tego w główną pętlę- też.

    0
  • #9 24 Kwi 2010 15:44
    sundayman
    Poziom 24  

    hmm... przyznam, że opierałem się na przykładach, które znalazłem tutaj, i prawdę mówiąc, z braku czasu nie zagłębiałem się w protokół 1wire, dlatego pewnie wyszły mi głupoty. Oczywiście, funkcja powinna odczytywać temperaturę z termometru o zadanym DS_id.

    Co do przerwania - pomyślałem o tym , ponieważ w głównym programie korzystam z input na Rs232, no i program mi się zatrzymuje. A chciałem, żeby wyniki pomiarów były "gotowe" do przesłania via RS.

    Zatem, jak powinna ta funkcja wyglądać, zakładając że ma mi pobrać temperaturę z czujnika numerze DS_ID ?

    0
  • #10 24 Kwi 2010 16:03
    asembler
    Poziom 32  

    mirekk36 napisał:
    W ogóle gigantycznym nieporozumieniem jest próba "gadania" z czujnikami DSxxxx w przerwaniach. Jak zwykle pojawia się temat flagi, którą wystarczy ustawiać w przerwaniu a w pętli głównej korzystać z tej flagi i co odpowiedni interwał czasowy "prowadzić" rozmowę z czujnikami - inaczej to bez sensu.

    A już nie wspomnę jak niektórzy mówili żeby do przerwania wstawiać choćby Waitms - to już jest masakra ;)


    A ja znowu nie wyobrazam sobie tego abym muial angazowac program głowny który przewaznie słuzy w innym celu jak tylko pomiar temp. W przerwaniu to wychodzi elegancko a ilosc czujników jak moze byc obsłuzona jest dowolna. W programie głownym umieszczam tylko procedure odczytu uzyskanych wartosci z przerwan i ewentualne sprawdzenie CRC co zajmuje ułamiki msek. Dodatkowo sprawa siekomplikuje gdy mamy zasialnie dwuprzewodowe to i tak trzeba zastosowac jakis timer bo nie wyobrazam sobie aby czekac na odczyt ponad 750mS

    0
  • #11 24 Kwi 2010 16:23
    mirekk36
    Poziom 42  

    asembler napisał:

    A ja znowu nie wyobrazam sobie tego abym muial angazowac program głowny który przewaznie słuzy w innym celu jak tylko pomiar temp. W przerwaniu to wychodzi elegancko a ilosc czujników jak moze byc obsłuzona jest dowolna. W programie głownym umieszczam tylko procedure odczytu uzyskanych wartosci z przerwan i ewentualne sprawdzenie CRC co zajmuje ułamiki msek. Dodatkowo sprawa siekomplikuje gdy mamy zasialnie dwuprzewodowe to i tak trzeba zastosowac jakis timer bo nie wyobrazam sobie aby czekac na odczyt ponad 750mS


    Asmbler - no panie kochany, sam nick i wypowiedzi na temat tego jak to lubisz asmblera powodowały u mnie wrażenie, że bardzo sprawnie się poruszasz w oprogramowaniu, tymczasem jakieś herezje tu kolega wypisuje.

    Ja obsługuję czujniki DSxxxx czy to w trypie Parasite czy w normalnym 3-żyłowym , obojętnie czy jeden czy całe stado. Dodatkowo wykonuję tysiąc innych rzeczy w tym samym czasie i jeszcze nigdy nie się nic nie komplikowało przez to. Pisanie programu głównego w przerwaniu..... hmmmm czasem się stosuje, gdy np robimy pilota na podczerień, który jedyną rzeczą jaką ma robić to emitować kody.

    Ale pisanie obsługi jakichkolwiek czujników a w tym szczególnie DSxxxx to nieporozumienie, no chyba, że tak jak piszesz znowu twój procek nic nie robi poza pomiarami. Ale to nie opowiadaj o tym, że to normalna praktyka i to jeszcze w asemblerze. Bo to jest raczej stawianie sprawy do góry nogami i niestety jednak trochę pachnie brakiem zrozumienia działania przerwań.

    Myślałem, że ktoś dobrze znający asembler nie ma problemu z implementacją tzw timerów programowych, zdarzeń itp..... aczkolwiek rozumiem dobrze, że pisanie czegoś takiego w samym asm to męczarnia. Warto panie kolego pomyśleć w końcu o C ;)

    Żeby nie być gołosłownym, bierzesz sobie jeden timer sprzętowy i przeznaczasz go na obsługę tzw "tyknięć" systemowych z jakąś stałą częstotliwością np 100Hz. A w oparciu o to w pętli głównej robisz sobie programowe timere i to tyle ile ci się żywnie spodoba. Dzięki temu w pętli głównej nie musisz UŻYĆ ani jednego polecenia jak Wait czy Waitms w Bascomie. W ogóle takie opóźnienia są niepotrzebne - wszystko z dużą prcecyzją odmierzasz timerami programowymi w tym twoje nieszczęsne 750ms.

    0
  • #12 24 Kwi 2010 16:37
    asembler
    Poziom 32  

    No cóż moj sposob pomiaru wcale nie angazuje calego procesora bo własnie po to napisałem to w przerwaniu że tak było wygodniej juz nie wiek kiedy tak to musialem rozwiazac ale skoro tak zrobilem to pewnie tak musialo byc (dawne czasy) Według mnie zaleta jest takze to ze moge w dowolnej chwili zawiesic odczyt z DS co np przy programowym generowaniu np dzwieków na głosnik mialo znaczenie. Faktem jest jak ktos wykorzystuje procesor w 10% to najlepiej to zrobic w programie głownym. Co by nie mówic ja pozostane przy swoim rozwiazanu a spierac mie mozna na kazdy temat jak co lepiej napisac.

    0
  • #13 24 Kwi 2010 17:29
    sundayman
    Poziom 24  

    koledzy, zlitujcie się :)
    Zamiast dyskutować akademicko, może byście poratowali po prostu
    prawidłową funkcją :)

    Pewnie,że sam powinienem się wgryźć w ten 1wire, ale nie mam teraz czasu na to. Przejrzałem wszystko co się dało znaleźć na elektrodzie, i nie znalazłem łopatologicznego wyjaśnienia, dlatego po prostu zrobiłem jak mi się wydawało ok.
    No ale w tych przerwaniach nie działa i tyle.

    Jak kolega napisał wcześniej, zapodałem tam najpierw polecenia pominięcia adresu (chyba?), potem podania tego adresu - czyli bez sensu. Powiedzcie proszę, jak to powino wyglądać poprawnie ?

    0
  • #14 24 Kwi 2010 17:41
    asembler
    Poziom 32  

    Przeciez ci radzimy (no moze nie ja) zebys nie robił tego w przerwaniach a szczegolnie w ten sposób. Przerwania stosuje sie dla zaoszczedzenia czasu procesora, a czy to ma sens w BASIC-u to nie sądze.

    0
  • #15 24 Kwi 2010 18:55
    sundayman
    Poziom 24  

    No ale pisałem, że chodzi o to, że główny program korzysta z komendy input, która odbiera polecenia via RS232. I w tym czasie nie ma możliwości "równoległego" odczytu z termometrów. A chodzi mi o to, żeby po odebraniu zapytania o temperatury pomiary były już "gotowe", co można zrobić tylko odczytując je w przerwaniu.

    Jest tylko kwestia prawidłowej obsługi 1wire, przy założeniu, że chcę odczytać konkretny układ, podając adres w zmiennej DS_ID. I to wszystko.
    Czyli - jaka powinna być sekwencja odczytu ? Nie znam poleceń, które wykonują układy DS, i te przykładowe "1wwrite &HCC" mi nic nie mówi...

    0
  • #16 24 Kwi 2010 19:08
    asembler
    Poziom 32  

    No to raczej odwróc założenia gdzyz bardziej prawidłowo bedzie jak umiescisz transmisje szeregową w przerwaniu a DS włozysz w główny program

    0
  • #17 24 Kwi 2010 19:28
    sundayman
    Poziom 24  

    Człowieku... :)
    Nie musi być bardziej prawidłowo :) Ma działać.
    Cały program jest gotowy. Pominąłem odczyt DSów w przerwaniach, bo nie działało, i zrobiłem po prostu, po zapytaniu przez RS. I tak może być.

    Trzeci raz piszę, że odczytuję komendy z RS poprzez input. No przecież to nie będzie działać w przerwaniu. A przerabianie tego na jakieś inne procedury to jest dopiero sięganie lewą reką do prawego ucha...


    Wolałbym mieć odczytane w przerwaniu. Ale przerabianie programu, który jest ok, jest bez sensu. Dla mnie nie jest istotne ideologiczne "uzasadnienie" czy w przerwaniu jest cacy czy be. Odczyt w przerwaniu załatwia moje potrzeby i to wszystko. Jeśli to jest możliwe (technicznie, że tak powiem) to ok. Jeśli nie, to trudno.

    Przypuszczam, że do tego celu wystarczy prawidłowa sekwencja odczytu.
    Jeśli z jakiegoś powodu bascomowa procedura odczytu 1wire nie działa w przerwaniu, to trudno, zostanie tak jak jest.

    0
  • #18 24 Kwi 2010 19:41
    asembler
    Poziom 32  

    Technicznie jest mozliwe przynajmniej w ASM a ty zeby to zrobic w bascomie to nie ma rady musisz sie zapoznac z protokołwem 1-wire ktory nawiasem mowiac jest prosry ja (1 -wir)
    J

    0
  • #19 24 Kwi 2010 19:44
    janbernat
    Poziom 38  

    Czy to jest przerwanie czy odwołanie się do podprogramu?
    Jeśli przerwanie- to jakie zdarzenie je wywołuje?
    Po co w przerwaniu- jeśli jest to przerwanie- blokujesz przerwanie od przepełnienia Timera?
    Przecież i tak jest zablokowane.
    Funkcja jest zdeklarowana?

    0
  • #20 24 Kwi 2010 20:04
    sundayman
    Poziom 24  

    Mówimy cały czas o przerwaniu z timer0, ustawionym na jak najdłuższy czas (1024).
    Samo przerwanie działa ok, i funkcja, którą skąd zapożyczyłem też działa ok, o ile jest wywoływana nie z przerwania a z głównego programu. Funkcja jest oczywiście zadeklarowana.

    A po co blokuję przerwania ? No widocznie bez sensu, na wszelki wypadek, bo nie wiedziałem, czy nie nastąpi kolejne wywołanie (no ale jak rozumiem, nie).
    Ale to przecież nie jest powodem problemu z odczytem chyba.

    0
  • #21 24 Kwi 2010 20:10
    asembler
    Poziom 32  

    Jezeli ty chcesz całą procedure odzcytu z DS-a zmiescic w jednym przerwaniu to to jest bez sensu bo to tak jakbys umiescil odczyt w programie głownym. Tu nie ma zadnego zysku ani czasowego ani tez innego. Jesli tak zrobisz to jest wysoce prawdopodone ze wypadna ci bajty odbierane po rs-sie.

    0
  • #22 24 Kwi 2010 20:23
    janbernat
    Poziom 38  

    no to tak:
    Przerwanie od timer0 jest wywoływane zbyt często- podaj jaki jest zegar.
    W przerwaniu robisz tak- incr temp_0.
    I tylko to- nic więcej.
    A w pętli głównej:
    if temp_0>=x then 'tak aby było > niż 750ms
    temperatura=funkcja()
    temp_0=0
    end if

    0
  • #23 24 Kwi 2010 20:58
    utak3r
    Poziom 25  

    Powiem tak: obsługa przerwania powinna trwać tak krótko, jak to tylko możliwe. Np. ustawianie jakichś flag, zliczanie wartości itp. Komunikacja z użyciem jakiegokolwiek protokołu ciężko podchodzi pod tę zasadę... Niby działa - ale stwarza ogromne problemy.
    A już użycie "wait"... jak wspomniał kolega - to jest "no no". Tego się nie powinno robić.

    0
  • #24 24 Kwi 2010 22:50
    sundayman
    Poziom 24  

    Heh, no już się powtarzam... :)

    W głównej pętli programu jest instrukcja ;

    Input Rs_data

    Czyli, że nic mi nie pomoże żadne odliczanie czasu, bo przez 99% czasu program nic nie robi stojąc na instrukcji input, i czekając na dane z rs232.
    I właśnie dlatego wymyśliłem to przerwanie, żeby - kiedy przyjdzie zapytanie o temperaturę, były te dane już gotowe.
    Skoro zaś nie można tego zrobić w przerwaniu, to musi być tak jak jest, czyli PO odebraniu tego zapytania.

    Tak, że zostawmy to już, bo skoro nie można w przerwaniu odczytać danych z DS, to sprawa nie ma sensu :)

    0
  • #25 24 Kwi 2010 23:10
    utak3r
    Poziom 25  

    Powiem więcej - zauważyłem, że DS odpytywany co chwilę, lubi zwracać jakieś idiotyczne wyniki, z kosmosu wzięte. Tak że lepiej jest, jak odpytujemy go tylko na żądanie :)

    0
  • #26 24 Kwi 2010 23:16
    mirekk36
    Poziom 42  

    sundayman --> poczytaj sobie o poleceniu Ischarwaiting to sprawa nabierze sensu, poobserwuj inne programy, idź dalej do przodu - bo wszystko da radę zrobić - i to nie w przerwaniu i wcale nie trzeba czekać na INPUT ;)

    utak3r --> skoro DS zwraca wyniki z kosmosu wzięte to świadczy tylko o jednym, że jest źle oprogramowany a nie że to jest kwestią jakichś obserwacji itp. Wszystko da się zrobić żeby było normalnie z odczytami i to nawet bardzo szybkimi. Ale trzeba też co nieco o sprawdzaniu sum kontrolnych poczytać no i prawidłowo soft napisać - wtedy wszystko będzie zawsze działać dobrze tak jak powinno.

    0
  • #27 24 Kwi 2010 23:50
    janbernat
    Poziom 38  

    Odpytywanie pojedynczego DS trwa ok. 3.5ms.
    Jeśli w tym czasie przyjdzie przerwanie to pokaże błędny odczyt.
    Taki odczyt można pominąć sprawdzaniem CRC - jak napisał mirekk36.
    Po odczycie ustawiamy DS na pomiar i sprawdzamy wynik np. po 1s.
    Po odczycie mamy prawie 1s na wysłanie danych przez RS.

    0
  • #28 25 Kwi 2010 00:12
    mirekk36
    Poziom 42  

    janbernat --> jak się napisze własną procedurę obsługi DS'a to może sobie przychodzić przerwanie w trakcie odczytu "do" czy też odczytu "z" .... a i tak nic się nie stanie ;). Tyle że trzeba w najbardziej krytycznych momentach wyłączać przerwania. Wtedy czasy wyłączenia przerwań są drastycznie krótsze niż taki kawał czasu jak 3,5ms - przecież to "wieczność". W bascomie o tyle kiepsko to się sprawdza, że właśnie można co najwyżej wyłączać przerwania na czas całej procedury odczytu/zapisu, która trwa długo i przez to może przeszkadzać w pracy innym przerwaniom - wtedy kicha :(

    0
  • #29 25 Kwi 2010 09:52
    janbernat
    Poziom 38  

    mirekk36- wiem że bascom jest wolny.
    Ale DS też.
    Sam reset to jest 2x480us- prawie 1ms.
    Przesyłanie 64 bitów adresu- 120usx64 =7680us czyli 7.7ms minimum.
    Pomiędzy tymi komendami można włączać przerwania- ale w trakcie chyba nie.
    A odczyt można zrobić potem- ale to też ponad 1ms.
    Tak że nie wiem jak to robisz.

    0
  • #30 25 Kwi 2010 10:50
    mirekk36
    Poziom 42  

    janbernat --> Wystarczy przerwania wyłączać na czas przesyłania poszczególnych bitów w odpowiednich pętlach, które wysyłają całość. Pewnie, że to też co nieco zabiera ale o niebo krócej niż gdy wyłączać przerwania na całe te czasy które tu przytoczyłeś.

    Druga sprawa to oczywiście jak się wykorzystuje w ogóle przerwania, bo jeśli w tym sposobie o którym piszę napisałbym jakieś procedury obsługi przerwań jak co niektórzy, gdzie wrzuciłbym polecenia Wait czy Waitms to ten sposób też byłby do kitu.

    Koniec końców, i w takim sposobie jak ja opisuję mogą się co jakiś czas pojawić zakłócenia jednak - to nie uniknione , ale ........... no ale wtedy za każdym razem sprawdza się jeszcze CRC co w 100% eliminuje przykry efekt jak wyświetlanie "wyników z kosmosu"

    0