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

atMega16 - Wyświetlanie temp z ADC

paweciu 19 Maj 2016 23:16 3126 63
  • #31 19 Maj 2016 23:16
    BlueDraco
    Specjalista - Mikrokontrolery

    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.

  • #32 23 Maj 2016 17:18
    paweciu
    Poziom 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.



    Kod: c
    Zaloguj się, aby zobaczyć kod


    Kod: c
    Zaloguj się, aby zobaczyć kod

  • #33 23 Maj 2016 17:36
    grko
    Poziom 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 24 Maj 2016 00:06
    BlueDraco
    Specjalista - Mikrokontrolery

    No to zacznijmy od początku main():

    Kod: c
    Zaloguj się, aby zobaczyć kod

    I mamy poustawiane porty.

  • #37 24 Maj 2016 10:12
    2675900
    Użytkownik usunął konto  
  • #38 24 Maj 2016 10:46
    Pokey
    Poziom 16  

    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 ?

  • #39 24 Maj 2016 11:31
    paweciu
    Poziom 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 24 Maj 2016 11:39
    BlueDraco
    Specjalista - Mikrokontrolery

    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 24 Maj 2016 12:00
    2675900
    Użytkownik usunął konto  
  • #43 24 Maj 2016 21:42
    grko
    Poziom 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 25 Maj 2016 00:55
    Pokey
    Poziom 16  

    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.

    Kod: c
    Zaloguj się, aby zobaczyć kod

    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:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Czyli zezwalasz na wyświetlanie zmiennych w przerwaniu i jednocześnie je modyfikujesz cały czas. Spróbuj zrobić tak
    Kod: c
    Zaloguj się, aby zobaczyć kod

    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 25 Maj 2016 01:10
    2675900
    Użytkownik usunął konto  
  • #46 25 Maj 2016 02:38
    Pokey
    Poziom 16  

    Piotrus_999 napisał:
    Pokey napisał:
    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 25 Maj 2016 09:12
    BlueDraco
    Specjalista - Mikrokontrolery

    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 25 Maj 2016 09:40
    grko
    Poziom 33  

    @BlueDraco Nie ma również powodu aby wszystko było robione w przerwaniach. Po prostu kwestia podejścia do rozwiązania problemu.

  • #49 25 Maj 2016 12:37
    BlueDraco
    Specjalista - Mikrokontrolery

    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 25 Maj 2016 13:31
    2675900
    Użytkownik usunął konto  
  • #51 29 Maj 2016 17:27
    paweciu
    Poziom 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

    Kod: c
    Zaloguj się, aby zobaczyć kod

  • #52 29 Maj 2016 18:45
    BlueDraco
    Specjalista - Mikrokontrolery

    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 30 Maj 2016 07:53
    paweciu
    Poziom 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 30 Maj 2016 12:50
    BlueDraco
    Specjalista - Mikrokontrolery

    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 30 Maj 2016 13:07
    2675900
    Użytkownik usunął konto  
  • #57 30 Maj 2016 13:47
    BlueDraco
    Specjalista - Mikrokontrolery

    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 30 Maj 2016 13:55
    2675900
    Użytkownik usunął konto  
  • #59 31 Maj 2016 09:33
    paweciu
    Poziom 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 31 Maj 2016 09:56
    rajszym
    Poziom 20  

    paweciu napisał:
    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.