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

[C] ATMEGA8 - problem z zerowaniem bitu ADSC

metallmaniac 27 Lip 2011 21:34 2246 25
  • #1 9766000
    metallmaniac
    Poziom 10  
    Witam

    mam malenki problemik z ADC na atmega8:

    mianowicie chodzi o to ze nie zeruje mi sie bit ADSC, ktory to sygnalizuje koniec konwersji ADC. Wyniki na LCD sa chaotyczne (wyglada na to ze dziala tu jakis magiczny random).

    Jesli widzicie jakis blad prosze o pomoc

    KOD:

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


    wyswietlam to na LCD za pomoca funkcji:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #3 9766491
    metallmaniac
    Poziom 10  
    kod poprawiłem ponieważ nie wkleiłem wcześniej przygotowanego


    podwójny && to pomyłka oczywiście.

    po tej zmianie programik "ruszył" niestety nie w taki sposób jak w zamierzeniach (wygląda na to, że wgrywałem starego HEX za każdym razem przez AVR STUDIO).
    dziwnym dla mnie jest fakt, że po podłączeniu napięcia ok 1V, do ADC0 na wyświetlaczu wskazania wariują (w ADCW wartości od ok 500 do maximum)
  • #5 9766629
    metallmaniac
    Poziom 10  
    schemacik:

    LCD na PORTD
    potencjometr na ADC0

    [C] ATMEGA8 - problem z zerowaniem bitu ADSC
  • #6 9766865
    Slkkk
    Poziom 14  
    Jeśli kolega używa wewnętrznego generatora napięcia 2,56 V to ostatnią rzeczą, którą powinien zrobić, jest podłączenie nogi AREF do jakiegokolwiek napięcia, chyba że w celu spalenia czegoś. W tym trybie do tej nogi jest podłączone napięcie z generatora (rysunek 90 na stronie 190 noty katalogowej ATmega8) po to, by można było zainstalować tam kondensator łączący nogę z masą w celu poprawy działania przetwornika. Wszystko to jest opisane na dole strony 194 noty katalogowej. Niech kolega odłączy AREF od napięcia zasilania i sprawdzi, czy wtedy działa.
  • #7 9767017
    metallmaniac
    Poziom 10  
    <sikkk> AREF jak na razie nie jest podlaczony do napiecia zasilajacego, byc moze zmylka jest symbol napiecia VCC przy AREF ale zapewniam ze doprowadzone jest ono do zlacza ARK2 na ktorym obecnie wisi kondensator 100nF jedna noga dolaczony do masy.

    wzor PCB:
    [C] ATMEGA8 - problem z zerowaniem bitu ADSC
  • #9 9767328
    metallmaniac
    Poziom 10  
    na AREF jest 2.62V czyli w granicach
  • #11 9770454
    metallmaniac
    Poziom 10  
    Snaap, zrobiłem jak sugerowałeś, ale nic to nie pomogło, pomiary napięcia na samym pinie uC też nic nie wykazały (napięcie jest stabilne).

    Wygląda na to, że uC sam sobie generuje jakieś przypadkowe wartości, dziś po powrocie z pracy podmienię kontroler,żeby sprawdzić czy przypadkiem nie jest uszkodzony.

    Mam przy okazji pytanie: jeśli wejście ADC nie jest wykorzystane, czy napięcie na nim powinno być równe AREF (w moim przypadku 2.62V) ??
  • #13 9772537
    metallmaniac
    Poziom 10  
    Wymiana uC nie dała żadnej zmiany.
    Wahania wskazań zmniejszyły się lecz nadal układ zbiera jakieś śmieci a wynik przy górnym zakresie pomiarowym waha się nawet o 300mV. Kondziorki filtrujące dałem już wszędzie (VCC, PIN_ADC - obecnie ADC1, AREF), w obwód zasilania AVCC wprowadzony jest szeregowo dławik a za nim kondek 100nF dołączony do masy.
    Zastanawiam się czy sama PCB nie zbiera jakiś śmieci...
  • #14 9772586
    Slkkk
    Poziom 14  
    Może niech kolega spróbuje ustawić bit ADLAR w rejestrze ADMUX i użyć przetwornika w trybie ośmiobitowym odczytując wynik tylko z rejestru ADCH. Jeśli nadal będą dziwne wyniki, to powinno wykluczyć możliwość istnienia błędu w programie obsługi przetwornika, gdyż kod będzie banalnie prosty:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Jeśli to nic nie da, to warto jeszcze sprawdzić, czy nie pomoże uśpienie mikrokontrolera w trybie ADC noise reduction.

    PS. Ja osobiście zwykle używam takiego kodu:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #15 9772731
    metallmaniac
    Poziom 10  
    w obu przypadkach przełączenie ze wskazań 1V na 2V następuje przy napięciu wejściowym = 1.4V
  • #16 9772769
    Slkkk
    Poziom 14  
    Co to jest "przełączenie ze wskazań 1V na 2V"?
  • #17 9772813
    metallmaniac
    Poziom 10  
    Chodziło mi oczywiście o zmianę wartości napięcia na wyświetlaczu, niestety wywalając wskazania na DISP , cyferki przeskakują o wartości całkowite, a jest to wynikiem działania kodu poniżej:

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



    oraz

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #18 9772840
    Slkkk
    Poziom 14  
    To dtostrf mi się jakoś nie podoba. LCD_print_int(wyn,3) też wypisuje dziwne liczby?
  • #19 9772850
    metallmaniac
    Poziom 10  
    niestety uC jakby się zawiesza przy użyciu funkcji LCD_print_int(), w tym przypadku dostaje jakieś krzaczki
  • #20 9772871
    Slkkk
    Poziom 14  
    Bo ona jest źle napisana. Proponuję:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #22 9772937
    metallmaniac
    Poziom 10  
    Chyba czas sobie dać spokój z tym programikiem, poczytać i napisać wszystko od nowa.
  • #23 9773781
    percol
    Poziom 12  
    Programowo nie widzę jakiś błędów prócz && miast & w pętli while().
    Na początek spróbuj wyświetlić zaemulowane odczyty z ADC, np.: 1,95V potem 1,62V itp. a między nimi jakąś małą pętlę delay żebyś zdążył zobaczyć wynik - będziesz wiedział że wyświetlacz poprawnie działa, a funkcje konwertują wynik jak należy.
    W razie nieusuwalnych problemów proponuję ominąć wyświetlacz (ze względu na krzaki) i zrobić banalny kontroler poprawności działania ADC:
    Np. do PB1 (czy PB2 lub PB3) dolutowujemy 470R i diodę LED, programowo włączamy PWM na 8 bitów i odczyt z ADC w 8 bitach. Wynik z ADC wpisujemy bezpośrednio do OCR1A (dla pinu PB1), wtedy niewielki obrót potencjometru powoduje natychmiast (jeśli tylko pojemność filtru dolnoprzepustowego do ADC0 nie jest zbyt duża, np. 10nF) zauważalną zmianę intensywności świecenia diody. Oko ludzkie jest bardzo czułe (szczególnie dla barwy zielonej) i wychwyci zmiany intensywności, najlepiej bawić się w okolicach połowy (albo nawet mniej) zakresu między Vref a GND.

    Jeśli nadal byłyby problemy, pozostaje wypróbować Noise Reduction (w sumie od tego jest;), a w ostateczności sklecić na prędce układ testowy na płytce uniwersalnej bez zbędnych peryferiów.

    I jeszcze jedno: skoki wartości odczytanej są możliwe jeśli źle dobrałeś filtr dolnoprzepustowy. Proponuję policzyć go na ok. 1/10 częstotliwości pracy ADC (ze schematu i ADCMUX wnioskuję że jest to 62,5 kHz, wiec filtr na jakieś 6-7kHz), jeśli nie wiesz jak Wikipedia okaże się pomocna...

    P.S.: Na projekcie płytki nie widzę kondków 0,1uF BLISKO NÓŻEK VCC I AVCC UKŁADU!
    Nie wystarczy kondek prz REF pinie, MUSZĄ być przy nóżkach 7 i 20, więcej na str. 196 manuala (http://www.atmel.com/dyn/resources/prod_documents/doc2486.pdf).
    Poczytaj też nieco o zakłóceniach w układach elektronicznych to może przestaniesz badziewić płytki, np.: jak można puścić ścieżkę sygnałową pod kwarcem?? Chodzi o tą z pina 19.
    Jeśli nie wierzysz - pobaw się oscyloskopem. :-)
    Acha, jak do zasilacza masz ponad 15-20 cm przewód to dajesz w pobliżu Atmegi jakiś mały elektrolit np. 10..100 uF - w zależności od obciążenia.
    Jeśli nie chcesz mieć zbyt zaszumionego sygnału rozważył bym zastosowanie przewodu ekranowanego (choć to zależy od odległości do źródła sygnału dla ADC i ilości zakłóceń emitowanych z otoczenia w jakim będzie pracował układ).
    Powodzenia!


    ----

    Coś o zakłóceniach pisałem kiedyś tu:
    https://www.elektroda.pl/rtvforum/topic1946821.html#9306028


    ----

    Zajrzyj na stronę 195 wspomnianej dokumentacji, zwróć uwagę na częstotliwość Nyquista i na obligatoryjność stosowania filtru dolnoprzepustowego (f_filtru = 10*f_ADC w praktyce). Ponadto piszą tam, że ADC jest zaprojektowany dla źródła o impedancji wyjściowej 10k i mniejszej więc rezystor filtru powinien mieć odpowiednią wartość (nie może być dowolnie duży, zresztą wszystko jest w manualu).
  • #24 9779879
    metallmaniac
    Poziom 10  
    WITAM CZCIGODNYCH FORUMOWICZÓW

    Tak tytułem wstępu chciałem podziękować wam za udzieloną pomoc.
    Programik z ADC nareszcie działa (obecnie wykonuję pomiary na 3 kanałach i wywalam wyniki na LCD). Jak się okazało pomimo kilku drobnych błędów związanych z wyświetlaniem (oraz 1 związanego z wybranym kanałem ADC) programik działał - przyczyną wszelakich zakłóceń były przewody doprowadzające napięcie do ADC.
    Zmiana długości z ok. 30cm na 10-12cm spowodowało tylko to, że układzik już "żyje".

    Programik wymaga jeszcze dopracowania:
    - poprawne wyświetlanie części dziesiętnych setnych itp.
    - auto-kalibracja ADC (programowa)

    kod programu w załączniku (jeśli macie czas na przejrzenie kodu będę wdzięczny za wszelkie sugestie odnośnie poprawy jego działania )

    oto fotki obrazujące działanie programu:
    EKRAN STARTOWY
    [C] ATMEGA8 - problem z zerowaniem bitu ADSC

    POMIAR 3 NAPIĘĆ (zakres 0-V_REF)
    [C] ATMEGA8 - problem z zerowaniem bitu ADSC



    Tematu jeszcze nie zamykam , może jeszcze jutro przyjdzie mi do głowy jakieś pytanie do was.
  • #25 9780322
    Slkkk
    Poziom 14  
    Kolega lubi się niepotrzebnie rozpisywać :). Na przykład cały switch w ADC_meassure (swoją drogą zwykle się pisze przez jedno s ;) ) można zamienić na jedną instrukcję:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    _delay_ms przyjmuje argumenty aż do 65535, nie ma potrzeby dzielić tego na kawałki po 1000.

    Z jakiegoś powodu lubi też obfuskować swój kod pisząc:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

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


    A używanie funkcji Lcd_print, która pobiera długość napisu jako argument jest raczej tylko utrudnianiem sobie życia, w C zwykle stosuje się konwencję by napisy kończyć bajtem o wartości 0. Taka funkcja może wtedy po prostu wypisywać wszystkie bajty po kolei na ekran, aż do napotkania zerowego i wtedy się kończyć. Napis z zerowym bajtem na końcu kolega zadeklaruje:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Swoją drogą warto pomyśleć o stworzeniu funkcji Lcd_print_P, która pobiera dane z pamięci programu (flash) i tam umieszczać argumenty. Deklaracja stałych jako zwykłych zmiennych powoduje, że gcc na początku programu umieści kod, który przenosi je wszystkie z flash do SRAM. Może jak tych napisów jest 40 bajtów to nie problem, ale kiedyś w końcu zabraknie pamięci :).
  • #26 9799433
    metallmaniac
    Poziom 10  
    Jeszcze raz chciałbym podziękować za pomoc i wskazówki (zastosowałem się już do ostatnich)

    zamykam temat.
REKLAMA