Elektroda.pl
Elektroda.pl
X

Search our partners

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

atMega16 - Wyświetlanie temp z ADC

paweciu 19 May 2016 23:16 3408 63
  • #31
    BlueDraco
    MCUs specialist
    Zmienne dziesiatki i jedności, służące do komunikacji z przerwaniem, mają zakres od 0 do 9. W jaki niby sposób brak "atomowości" miałby wpływać na ich rzekomo błędne wartości?

    To, co Kolega nazywa "atomowością" miałoby znaczenie, gdyby te zmienne miały zakres i typ wykraczający poza jeden bajt.

    Prooblem leży w fatalnej jakości kodu, w tym w wielokrotnym czytaniu ADC.
  • MetalworkMetalwork
  • #32
    paweciu
    Level 10  
    Witam ponownie,
    Nie pokazałem całego kodu nie ze względu na to że ktoś mi go może ukraść jak to napisał kolega ale właśnie z racji tego że jest on napisany przez amatora.
    Jest to mój pierwszy projekt z mikro kontrolerem oraz językiem C. Wcześniej trochę bawiłem się z PHP oraz HTML i nić po za tym. Dlatego nie chciałem abyście po mnie pojechali...

    Wracając do tematu to niestety ale nie mogę sobie nadal poradzić z tym wyświetlaniem dlatego też zamieszczam cały kod i proszę o pomoc. Możecie na mnie wieszać psy za jego styl i formę.

    Z góry dzięki za pomoc.



    Code: c
    Log in, to see the code


    Code: c
    Log in, to see the code
  • #33
    grko
    Level 33  
    Kod nadal jest niesformatowany. Jeżeli używasz Eclipse to użyj sekwencji klawiszy Ctrl+A oraz Ctrl+I. Jeżeli w Twoim środowisku nie ma formatowania to użyj strony:

    http://format.krzaq.cc/

    Oszczędzi to nam/tobie czasu.
  • #35
    BlueDraco
    MCUs specialist
    No to zacznijmy od początku main():
    Code: c
    Log in, to see the code

    I mamy poustawiane porty.
  • #37
    User removed account
    User removed account  
  • #38
    Pokey
    Level 17  
    Przerwanie wyświetlacza masz co 10 ms (czy tak ?), więc jedna cyfra "trwa" na wyświetlaczu przez 20ms. Napisz jeszcze, jak długo utrzymuje się na wyświetlaczu ten "fenomen" że po 29 zamiast 30, pokazuje się 20. Czy ten czas po którym 20 zmieni się na 30 to jest ułamek sekundy, mrugnięcie oka, czy jest to jednak wyraźnie zauważalny czas, rzędu kilkuset ms, lub więcej ? Może wrzucisz jakiś AVI ?
  • MetalworkMetalwork
  • #39
    paweciu
    Level 10  
    To nie sarkazm tylko na prawdę chcę ten kod poprawić żeby był ok a przy tym poznać styl w jakim powinienem pisać inne kody.

    Filmik zrobię i wrzucę jak wrócę do domu teraz nie mam jak.

    A ten efekt utrzymuje się długo. Tzn jak ustawię potenciometr w przejściu miedzy 29 a 30 to pojawi się wartość 20 dopuki nie przekrece potencjometru.
  • #40
    BlueDraco
    MCUs specialist
    Już pisałem, jak masz poprawić kod. Zamiast sekwencji if() sprawdzających bez sensu kolejne wartości zmiennej użyj if - else albo switch. Zwiększ częstotliwość przerwania wyświetlacza - proponowałbym min. 400 Hz. Nie poprawiłeś błędu w obsłudze wyświetlacza - masz duchy, bo zmieniasz segmenty przy włączonej cyfrze.
  • #41
    User removed account
    User removed account  
  • #43
    grko
    Level 33  
    Zmienną aktualna_temp modyfikujesz w wielu miejscach i tak naprawdę trudno wymyślić co się w programie dzieje. Zacznij od prostego przypadku: ustawiasz ta zmienna w jednym miejscu oraz odczytujesz w przerwaniu. Dodatkowo zmienną tr_wysw powinieneś ustawić po zapisie do zmiennej aktualna_temp (przynajmniej tak mi się wydaje). Programowanie to proces iteracyjny. Odnoszę wrażenie, że nie zastosowałeś się do tego i napisałeś cały program i okazało się, że nie działa.

    BTW: nie definiuj zmiennych w nagłówkach
  • #44
    Pokey
    Level 17  
    Zmienna tr_wysw - używasz jej do blokowania aktualizacji zmiennych wyświetlacza. Z tego co widzę jeśli jest 1 - to jest blokada, jeśli jest 0 - zmienne są aktualizowane.
    Code: c
    Log in, to see the code

    Bo masz tam negację. Ja bym jednak nie polecał tej metody, bo masz tam 2 razy dzielenie, które wykonujesz w przerwaniu - a to dość czasochłonna operacja. Ale ok, załóżmy że się wyrabia.

    W miejscu gdzie jest ten odczyt z przetwornika masz:

    Code: c
    Log in, to see the code


    Czyli zezwalasz na wyświetlanie zmiennych w przerwaniu i jednocześnie je modyfikujesz cały czas. Spróbuj zrobić tak
    Code: c
    Log in, to see the code

    Czyli czekaj w tej pętli while ale nie czytaj cały czas tego przetwornika. Bo przecież to jest wynik z pojedynczej konwersji (jak wynika z tego co jest powyżej), więc wartość z ADC i tak się nie zmieni.


    Dlaczego pierwsza cyfra świeci Ci jaśniej, masz inne rezystory anodach tych wyświetlaczy ? A może coś się dzieje z przerwaniem - zwróć na to uwagę. Może przez te dzielenia i inne operacje trwa dłużej niż okres wywołania i tracisz niektóre jego wywołania. Możesz sprawdzić czas jego wykonania w programowym debugerze.
  • #45
    User removed account
    User removed account  
  • #46
    Pokey
    Level 17  
    Piotrus_999 wrote:
    Pokey wrote:
    bo masz tam 2 razy dzielenie, które wykonujesz w przerwaniu - a to dość czasochłonna operacja.

    Nieprawda.To integery. Nie ma nic wspólnego z niewyrabianiem się przerwania.
    Powinien to przepisać, bo poprawianie takiego śmietnika mija się z celem. Łatwiej, szybciek i bardziej edukacyjnie, majac wszystkie uwagi, jak przemysli i jeszcze raz napisze.


    No i co z tego że integery. Czy to znaczy, że dzielenie wykona się w jednym lub kilku cyklach ? Sądzę, że kompilator i tak zrobi te dwa dzielenia w jednym, ale przecież to 8-bitowy procesor i nie ma sprzętowego dzielenia. Takie dzielenie zajmuje nawet kilkaset cykli.
    Czas wykonywania przerwania powinno się minimalizować na ile to tylko możliwe, a program ten da się przerobić tak, żeby tego dzielenia nie było tutaj. Nie mówię, że na pewno mu to zakłóca przerwanie (napisałem przecież, że "załóżmy, że się wyrabia" i dlatego pytam, czy może ma różne wartości rezystorów) ale jak mu się zbierze trochę takich rzeczy, to w końcu będzie gubił przerwania.
  • #47
    BlueDraco
    MCUs specialist
    Nie ma powodu, by cokolwiek w tym programie nie było robione w przerwaniach, trzeba tylko sensownie zaprojektować całość. Cały program można zgrabnie sprowadzić do jednego przerwania timera, w którym następuje wyświetlanie, odczyt ADC, filtrowanie wyników ADC, przygotowanie wartości do wyświetlenia i wystartowanie następnej konwersji - w takiej właśnie kolejności. Obsługa takiego przerwania zajmie < 1 ms, a ich częstotliwość powinna wynosić 400..800 Hz, a więc bez problemu ze wszystkim się wyrobimy - z dzieleniem też.
  • #48
    grko
    Level 33  
    @BlueDraco Nie ma również powodu aby wszystko było robione w przerwaniach. Po prostu kwestia podejścia do rozwiązania problemu.
  • #49
    BlueDraco
    MCUs specialist
    Na razie jest mowa o JEDNYM przerwaniu, w którym wszystko da się zrobić, więc po co dzielić to na dwa kawałki kodu z problemami komunikacyjnymi - volatile, pisanie 16 bitów po kawałku?
  • #50
    User removed account
    User removed account  
  • #51
    paweciu
    Level 10  
    Witam ponownie,
    Poszedłem za radą większości z was i postanowiłem napisać program od nowa.
    W załączniku zamieszczam kod.

    Teraz nie mam już problemu z przejściem ADC z np.: 29 na 30 i też nie ma problemu z jego wyświetlaniem ale mam inny problem. Właściwie dwa.

    1. Wyświetlenie ADC pomimo uśredniania jest niestabilne - ciężko jest ustawić stabilną wartość np. 47. - nie wiem czy to wina tego że mam to na płytce stykowej czy niedkoładności potencjometru - czy może z kodem jest coś nie tak. - później wrzucę filmik,

    2. To problem z odliczaniem czasu - chciałbym odmierzyć np.: aby co np.: 10 s mrygneła dioda oraz zabuczał buzzer - ale wychodzi ze buzzer i dioda załączają się co około (równo) 8,5 s. - mierzone stoperem (kilka prób pod rząd)

    ustawienia mam takie - kwarc zewnętrzny 8MHz, preskaler 1024, OCR2 = 6 - z tego z noty wyczytałem że przerwanie będzie generowane co 1ms,
    a więc jeśli programowy timer ustawię na załączanie co 1000 cykli przerwania to powinno co 10 s załaczyć buzzer i diodę - jednak wychodzi tak jak napisałem co około 8,5 s,

    Prośba o pomoc

    Code: c
    Log in, to see the code
  • #52
    BlueDraco
    MCUs specialist
    1. Zapomniałeś o filtrowaniu pomiarów, o czym pisałem parę dni temu. Pomnożenie wyniku przez jakąś liczbę, a nestępnie podzielenie go przez tę samą liczbę raczej nie daje filtracji.

    2. W jakiej to nocie prezeczytałeś, że wynik dzielenia 8000000 przez 1024 i przez 7 wynosi 1000? Zwykle parametry czasowe wylicza się podczas pisania programu, a nie "wyczytuje w nocie".

    Oczywiście jesteś świadomy tego, że przerwanie rozsypie odczyt DS18B20?
  • #53
    paweciu
    Level 10  
    1. Możesz mi podać przykład takiej filtracji wyników adc. Znalazłem coś na podstawie pętli for i sumowaniu wyników i późniejszym dzieleniu przez ilość. Ale czy wstawienie pętli w przerwanie nie spowoduje jego opóźnienia. Po za tym już to próbowałem i efekt jest taki sam jak z tym co mam w kodzie. Nie wiem jak inaczej to zrealizować. Prośba o podpowidz

    2. Poradzilem sobie z tym czasem. Wstawiłem preskaler 64 i ocr 125 i wszystko śmiga jak trzeba. Taka zmiana nie rozwalila ds18x20. Wszystko z tym jest ok.
    Teraz mam przerwanie co 1ms i w miarę dokładne odliczanie czasu.
    Dzięki za podpowiedź .
  • #55
    BlueDraco
    MCUs specialist
    Prosty filtr:

    suma = suma - suma / 8 + ADC;
    srednia = suma / 8;

    8 jest umowną stałą, którą dobiera się w zależności od potrzeb (moożna spróbować np. 4).

    UW jaki sposób uzasadnisz tezę, że wydłużenie o nieznany, dość losowy czas rzędu kilkunastu..kilkudziesięciu us krytycznego odstępu czasowego wynoszącego kilkanaście us nie zakłóca transmisji? Przykładowe możliwe uzasadnienia, to:
    - "nie zauważyłem błędu odczytu temperatury, pomimo, że taki błąd był"
    - "5 razy się udało, więc wnioskuję, że uda się zawsze"
    - "czasem dostaję bzdury, ale to na pewno czujnik się myli".
  • #56
    User removed account
    User removed account  
  • #57
    BlueDraco
    MCUs specialist
    Ja tylko nie wiem, po co przerwanie ADC. Od początku piszę - odczytywać Wynik ADC i startować nową konwersję w przerwaniu timera. Jedno przerwanie może zawierać całą funkcjonalność (poza DS18B20, który kłóci się ze wszystkim - może by go tak UARTem potraktować?)
  • #58
    User removed account
    User removed account  
  • #59
    paweciu
    Level 10  
    Nie rozumiem dlaczego odczyt z adc będzie pwowodowal problemy z czujnikiem. Przecież czujnik nie jest uruchamiany w przerwaniu. W przerwaniu jest tylko wyświetlenie Led.

    Odczytu adc chcę dokonywać i wyświetlać wtedy gdy nie będzie wyświetlana wartość z czujnika. Na razie w kodzie tego nie ma ale adc ma pracować tylko w jednym trybie - gdy nie jest wyświetlana temp z czujnika.

    Czy w takim wypadku błędy też mogą wystąpić.

    Nie za pardzo rozumiem tego filtrowania zaproponowanego przez bluedraco

    Prośba o wyjaśnienie jak to zaadaptować
  • #60
    rajszym
    Level 20  
    paweciu wrote:
    Nie za pardzo rozumiem tego filtrowania zaproponowanego przez bluedraco

    To jest uśrednianie. Proste, szybkie i skuteczne.
    Jeśli chcesz filtrować wartości, to musisz odrzucać te, które wykraczają poza określony przedział.
    Przedział oczekiwanych wartości można ustawić "na sztywno", w zależności od obliczonej średniej, ostatnio odczytanej wartości itp.