Mikrokontrolery - Jak zacząć?

... czyli zbiór praktycznej wiedzy dot. mikrokontrolerów.

wtorek, 1 marca 2011

ADC - Wstęp i uruchomienie

Autor: drzasiek
Redakcja: dondu


Drzaśkowy pamiętnik: Spis treści


Mając już za sobą zabawę z diodami, zmianę częstotliwości i źródła zegara przyszła pora zatrudnić uC do czegoś poważniejszego. Bo przecież mruganie diodami, to żadna atrakcja. Czas coś zmierzyć!!!

Większość wielkości w przyrodzie zmienia się w sposób ciągły-analogowy. Światło, temperatura, ciśnienie, wilgotność, prąd, napięcie, rezystancja, pojemność, indukcyjność itd. Wszystkie te wielkości przyjmują pewną wartość w danej chwili czasu. Zmieniają się, albo narastają, albo maleją, albo też utrzymują się na pewnym poziomie przez jakiś czas.


Jak więc wielkość analogową przetworzyć do postaci cyfrowej?
Tutaj z pomocą przychodzi Przetwornik Analogowo-Cyfrowy (ADC - ang. Analog to Digital Converter)
Przetwornik ogólnie mierzy napięcie i przedstawia je w postaci cyfrowej. Każdą wielkość w przyrodzie można przedstawić w postaci napięciowej, a zatem zmierzyć przetwornikiem A/C.

Większość mikrokontrolerów AVR ma na swoim pokładzie ADC. Co prawda nie są to jakieś super szybkie i dokładne przetworniki, ale do większości amatorskich zastosowań w zupełności wystarczają.


Jak skorzystać z wbudowanego przetwornika?
Jak zwykle w przypadku uruchamiania nowych peryferii najlepszym i najpewniejszym źródłem wiedzy jest datasheet. ATmega8, z której korzystałem do tej pory, posiada przetwornik ADC więc pora na lekturę noty katalogowej mojego mikrokontrolera: ATmega8 datasheet

Dobrym źródłem bardziej ogólniejszej wiedzy jest także dokument firmy Atmel o symbolu AVR120:
AVR120: Characterization and Calibration of the ADC on an AVR


Na samym początku rozdziału dotyczącego ADC (w datasheet Atmegi) jest ogólny opis parametrów przetwornika:

Rys. 1 - Parametry przetwornika ADC ATmega8


Wychwyciłem najważniejsze informacje:
  • max 10 bitowa rozdzielczość
  • czas konwersji 13-260us 
  • max częstotliwość próbkowaniu przy 10 bitach rozdzielczości to 15 kHz
  • 6 lub 8 multipleksowanych wejść, w zależności od typu obudowy 


Które to wejścia i ile ich jest?
Najlepiej widać to na samym początku datasheet-a, gdzie przedstawiony jest zarys poszczególnych typów obudów wraz z opisem pinów (nóżek):

Rys. 2 - "Pinologia" ATmega8

ATmega8 w obudowie DIP, którą zastosowałem, jak widać posiada 6 multipleksowanych wejść na pinach 0-5 portu C:

Rys. 3 - Wyprowadzenia ATmega8 dla obudowy typu DIP.




Kolejna ważna informacja to zakres napięć wejściowych wynoszący 0-VCC.
Jednym słowem NIE WOLNO mierzyć za pomocą ADC sygnałów przekraczających napięcie zasilania mikrokontrolera.


Możliwe jest uruchomienie przetwornika w jednym z dwóch trybów pracy:
  • Single Conversion – jak sama nazwa wskazuje jest to pojedyncza konwersja (pomiar).
  • Free Running- ciągła konwersja (pomiary jeden po drugim)


Skoro znam już możliwości ADC w Atmega8 to pora spróbować go uruchomić.
Skorzystałem z tego samego układu który stosowałem do tej pory, czyli ATmega8, 16MHz kwarc, 2 diody i klawisz jako interfejs.

Pozostała kwestia zasilania części analogowej mikrokontrolera oraz podłączenia źródła napięcia mierzonego. Warto więc zajrzeć co datasheet, mówi o podłączeniu zasilania do ADC:

Rys. 4 - Zasilanie części analogowej ATmega8.
Tu wprawdzie pokazany jest przypadek obudowy TQFP, ale zasady są takie same niezależnie od jej rodzaju.


Pora więc zaprojektować schemat:

Rys. 5 - Schemat mojego projektu.


Pobierz schemat w wersji Eagle: schemat.rar


Na początek uruchomiłem przetwornik ADC z wewnętrznym napięciem referencyjnym (dla Atmega8 jest to 2.56V) dlatego pin AREF pozostał podłączony przez kondensator do masy.

W celu eliminacji zakłóceń zasilanie przetwornika (AVCC) zgodnie z DS zostało podłączone (zgodnie z rys. 4) przez filtr LC(10µH/100nF). Więcej szczegółów w tej sprawie znalazłem tutaj: ADC - Dokładność vs podłączanie

Jako źródło napięcia mierzonego użyłem potencjometr 10k w szeregu z rezystorem 10k.
Potencjometr z rezystorem będący dzielnikiem napięcia w takiej konfiguracji będzie regulował napięcie wejściowe dla ADC na Pinie 5 Pirtu C w zakresie 0-2.5V.

Dlaczego tak?
Ponieważ napięcie może być mierzone z zakresu 0-VREF i bezwzględnie nie może przekraczać VCC Stąd dodałem rezystor 10K w szeregu z potencjometrem, by nie tracić na rozdzielczości potencjometru.

Każda wartość napięcia w zakresie VREF-VCC podana na wejście ADC będzie odczytywana jako wartość max dla danej rozdzielczości przetwornika, czyli dla 10 bitów będzie to 1023, a więc 0x3FF.

Przy doborze takiego dzielnika napięcia na wejściu należy stosować nie duże wartości rezystancji, aby wynik konwersji był jak najlepszy. Cytat z noty Atmel-a: Atmel AVR120:



Dlatego przy dzielnikach napięcia lub źródłach napięcia o dużej impedancji wyjściowej dobrym przyzwyczajeniem jest stosowanie buforów wejściowych o niskiej impedancji wyjściowej, np wtórnik napięcia na WO. Jednak dla tak prostego doświadczenie jakie tutaj chciałem wykonać, dzielnik na takich rezystorach wystarczy.

Następnie musiałem podjąć decyzję z jaką częstotliwością ma ADC dokonywać pomiaru. Z dokumentacji dowiedziałem się, że zegar "napędzający" przetwornik ADC ma pewne ograniczenia:



Ponieważ mój mikrokontroler jest taktowany przez zewnętrzny kwarc 16MHz, stąd musiałem użyć prescalera ADC (patrz. rys. 6). Musiałem więc się dowiedzieć coś na ten temat i znalazłem to:
Prescaler, postscaler - Co to takiego?

Postanowiłem użyć największego prescalera ADC czyli 128. Po policzeniu:


okazało się, że mieszczę się w prawidłowym zakresie 50-200kHz dla 10 bitowej dokładności pomiaru.


Start konwersji (pomiaru)
Do projektu dodałem klawisz na pinie 0 portu C (PC0), który posłużył mi do wyzwalania pojedynczej konwersji (pomiaru). Diody wyświetlać będą zdeklarowane w programie poziomy napięcia.


Teraz przyszła pora na wydawać, by się mogło najtrudniejszą część zabawy z przetwornikiem - napisanie programu. :-)

Strasznie to tylko wyglądało na początku. Nie trzeba jednak korzystać nawet z żadnych gotowców, wszystko jest bardzo jasno i czytelnie wyjaśnione w datasheet.

Rzut okiem na schemat blokowy:


Rys. 6 - ADC w ATmega8



Jak widać ADC posiada 3 rejestry:
  • 8 bitowy rejestr ADMUX jak widać ze schematu oraz nazwy służy do ustawiania multiplekserów,
  • 8 bitowy rejestr ADCSRA – ADC Control and Status Register A,
  • 16 bitowy rejestr ADC (ADCH/ADCL) - The ADC Data Register, w którym przechowywana jest zmierzona wartość napięcia. 
Rejestry te są bardzo dobrze opisane w datasheet. Przyszła więc pora przystąpić do pisania procedury konfiguracji ADC.

Zacząłem od rejestru ADCSRA:




W opisie pod tabelką znalazłem informację, że:

  • dla preskalera 128 powinienem ustawić jedynkę na bitach ADPS2, ADPS1 i ADPS0.
  • ustawić jedynkę na bicie ADEN, by włączyć przetwornik ADC.

ADCSRA = (1<<ADEN) //ADEN=1 włączenie przetwornika ADC)
         |(1<<ADPS0) // ustawienie preskalera na 128
         |(1<<ADPS1)
         |(1<<ADPS2)


Następnie przyszła kolej na rejestr ADMUX.



ADMUX  =    (1<<REFS1) | (1<<REFS0) // REFS1:0: wybór napięcia odniesienia ADC
                           //na wewnętrzne źródło 2,56V
                           //z zewnętrznym kondensatorem na pinie AREF

          |(1<<MUX2) | (1<<MUX0);// wybór kanału ADC5 na pinie PC5

Teraz pozostało tylko scalić program i dopisać obsługę ma na celu przetestowanie trybu pojedynczej konwersji na żądanie (wciśniecie klawisza).
Cały kod programu:

#include <avr/io.h>

#define LED1 PB0    //definicja LED1 (do którego pinu podłączony LED1)
#define LED2 PB1    //definicja LED2 (do którego pinu podłączony LED2)
#define KLAWISZ PC0 //definicja KLAWISZ (do którego pinu podłączony klawisz)
#define ADCIN PC5   //definicja ADCIN (wejście ADC)

int main(void)
{
  //Uruchomienie ADC, wewnętrzne napiecie odniesienia, tryb pojedynczej konwersji, preskaler 128, wejście PIN5, wynik do prawej
  ADCSRA =   (1<<ADEN) //ADEN: ADC Enable (uruchomienie przetwornika)

   //ADPS2:0: ustawienie preskalera, preskaler= 128
   |(1<<ADPS0)
   |(1<<ADPS1)
   |(1<<ADPS2); 

  ADMUX  =  (1<<REFS1) | (1<<REFS0) //REFS1:0: Reference Selection Bits 
         //Internal 2.56V Voltage Reference with external capacitor at AREF pin
    |(1<<MUX2) | (1<<MUX0); //Input Channel Selections (ADC5 - Pin 5 )

  //ustawienie wejśc/wyjść
  DDRB  |= (1<<LED1) | (1<<LED2); //Ustawienie pinów sterujących diodami jako wyjścia
  DDRC=0xff;                      //Nieużywane Piny na porcie C jako wyjścia
  DDRC  &=~ (1<<KLAWISZ);         //Ustawienie pinu klawisza jako wejście
  DDRC &=~ (1<<ADCIN);            //Ustawienie Wejścia ADC

  PORTC |=  (1<<KLAWISZ);         //Pull_up klawisz

  for(;;)//pętla główna 
  {
    if(!(PINC & (1<<KLAWISZ)))//jeśli klawisz wciśniety
    {
    ADCSRA |= (1<<ADSC); //ADSC: uruchomienie pojedynczej konwersji
 
    while(ADCSRA & (1<<ADSC)); //czeka na zakończenie konwersji
 
  if(ADC<350)//jeśli wynik ADC mniejszy od 350 gasi obydwie diody
  {
    PORTB  &=~ (1<<LED1);
    PORTB  &=~ (1<<LED2);
  }
  else if(ADC<700)//jeśli 700>ADC>=350 LED1 świeci
  {
    PORTB  |= (1<<LED1);
    PORTB  &=~ (1<<LED2);
  }
  else //jeśli ADC>=700 świecą obydwie diody 
                {
    PORTB  |= (1<<LED1);
    PORTB  |= (1<<LED2);
  }
    }
  }
}
Pobierz program: adc.rar

Program działa w następujący sposób:
Po uruchomieniu programu obydwie diody nie świecą się, ponieważ nie było żadnego uruchomienia konwersji. Naciśnięcie klawisza powoduje porównanie 10 bitowego wyniku z rejestru ADC z zdeklarowanymi wartościami i odpowiednie zapalenie/zgaszenie diod. Konwersja jest pojedyncza za każdym razem, kiedy nastąpi naciśnięcie klawisza.


Przeczytaj także:

Oceń artykuł.
Wasze opinie są dla nas ważne, gdyż pozwalają dopracować poszczególne artykuły.
Pozdrawiamy, Autorzy
Ten artykuł oceniam na:

48 komentarzy:

  1. Nie rozumiem. Wynik ADC tutaj zależy od mierzonego napięcia? Np. dioda LED zapali się po osiągnięciu 7v?

    OdpowiedzUsuń
  2. Pisałem, że wartość napięcia mierzonego nie może przekraczać napięcia referencyjnego czyli w powyższym przypadku 2.56V.
    Wartości w warunkach if() są to wartości z rejestru ADC, nie są one wartościami napięcia w Voltach.
    Przetwornik 10 bitowy a więc może zmierzyć 2^10 stanów a więc 1024.
    Czyli od 0 do 1023.
    Wartość max przetwornika a więc 1023 w powyższym przypadku odpowiada napięciu referencyjnemu.
    Jak z otrzymanej wartości z przetwornika obliczyć napięcie jest wyjaśnione w DS ale będę o tym pisał w kolejnych częściach artykułu o ADC.

    OdpowiedzUsuń
  3. Witam. Mam mały problem ;) Korzystam z trybu free run. Program działa tak: po przyłożeniu do pinu ADC napięcia 0,625V zapala się dioda 1, przy 1,25V zapala dwie diody, przy 1,875V zapala trzy diody. Tu program działa ok. Przy zdjęciu napięcia z ADC np dla 1,875V diody gasną po kolei od ostatniej do pierwszej, a chcę uzyskać działanie takie, że po zdjęciu napięcia z ADC mają gasnąć od razu wszystkie.
    Warunki na wartość ADC mam podobnie jak w artykule w if-ach, ale korzystam z przerwania ISR(ADC_vect), w którym mam te warunki.

    OdpowiedzUsuń
  4. Witam.
    Trudno jest cokolwiek doradzić nie widząc kodu programu.

    OdpowiedzUsuń
  5. No tak ;)

    #define F_CPU 1000000UL

    #include
    #include
    #include

    #define led0 (PB0 << 1)
    #define led1 (PB1 << 1)
    #define led2 (PB2 << 1)
    #define led3 (PB3 << 1)
    #define led4 (PB4 << 1)
    #define led5 (PB5 << 1)
    #define led6 (PB6 << 1)
    #define led7 (PB7 << 1)

    float fConvResult;
    uint8_t pomiar;

    ISR(ADC_vect)

    {
    if ((ADC > 240) && (ADC <= 470)) PORTB = 0b00000001; //zmierzone napięcie 0.63V - wartość 252
    else if ((ADC > 470) && (ADC <= 720)) PORTB = 0b00000011; //zmierzone napięcie 1.24V - wartość 496
    else if ((ADC > 720) && (ADC <= 770)) PORTB = 0b00000111; //zmierzone napięcie 1.86V - wartość 744
    else PORTB = 0x00;
    }

    void InitADC(void)
    {
    ADMUX = _BV(REFS0) | _BV(REFS1);
    ADCSR = _BV(ADEN) | _BV(ADIE) | _BV(ADFR) | _BV(ADSC)
    | _BV(ADPS0) | _BV(ADPS1);
    }

    main()
    {
    DDRB = 0xff;
    InitADC();
    sei();
    while(1)
    {
    }
    }

    Tak jak pisałem przykładanie napięcia działa ok. Podczas zdejmowania go z pinu ADC diody gasną po kolei, a chcę aby zgasły wszystkie na raz.

    OdpowiedzUsuń
  6. Witam.
    Po pierwsze, to definicje ledów masz źle napisane.
    Np:
    #define led3 (PB3 << 1)
    wbrew temu co myślisz to nie jest
    00001000
    ale
    00000110
    A dlaczego?
    Bo tak napisałeś.
    PB3 to liczba 3.
    Liczba 3 binarnie to 00000011
    ale ty ją przesuwasz w lewo o 1 więc dlatego masz 00000110.
    Najpierw powinieneś dać 1 czyli 00000001 a potem przesuwać w lewo o x pozycji czyli np:
    #define led3 (1 << PB3)

    Co do tego gaśnięcia powoli, to jaki mniej więcej jest odstęp czasowy między wygaszaniem kolejnych diod?

    Spróbuj wyciągnąć te warunki z przerwania do pętli głównej, a w przerwaniu tylko przepisuj wynik ADC do jakiejś zmiennej.

    OdpowiedzUsuń
  7. Rzeczywiście z tą deklaracją led zrobiłem źle :)

    Pomimo dania warunków do pętli głównej while(1) efekt pozostał taki sam.

    Jeżeli podam 1,875V i zdejmę to diody gasną po kolei w sumarycznym czasie około 1-2 sekund. Wygląda to tak jakby rozładowywał się jakiś kondensator podłączony do diod.
    Jeżeli chodzi o podłączenie to zwarłem przez 100nF AREF z GND oraz AVCC z GND (też przez 100 nF).
    Jak zmienię w warunkach na
    if ((ADC> 240) && (ADC <= 470)) PORTB = 0b00000001;
    else if ((ADC > 470) && (ADC <= 720))PORTB = 0b00000010;
    else if ((ADC > 720) && (ADC <= 770))PORTB = 0b00000100;
    else PORTB = 0x00;
    to po zdjęciu napięcia z pinu ADC gaśnie led2, zapala i gaśnie led1, zapala i gaśnie led0. Trwa to około 1-2 sekund.

    OdpowiedzUsuń
  8. Jak podłączasz to napięcie? Bezpośrednio do nogi procesora, czy przez jakiś dzielnik/bufor?
    I w jaki sposób je odłączasz? Odłączając całkowicie przewód od nogi uC pozostawiając ją wolną?

    OdpowiedzUsuń
  9. Układ mam zbudowany na płytce stykowej. Napięcie podaję bezpośrednio przewodem na nogę ADC z dzielnika napięcia. Dzielę Vcc na 8 rezystorach, czyli mam na jednym 0,625V. Podłączam i odłączam napięcie do ADC przewodem, tzn dotykam bądź nie dotykam pinu ADC. Czyli tak jak piszesz, odłączając zostawiam pin uC wolny.

    OdpowiedzUsuń
  10. Wystarczyło ściągnąć pin ADC do masy przez 100kOhm ;)

    OdpowiedzUsuń
  11. Witam, mam mały problem ponieważ ten program (ani żaden inny do obsługi ADC) mi nie działa :( Posiadam płytkę testową od Kamami ZL2AVR, podłączone jest wszystko ok, kod dosłownie skopiowany żywcem, a mimo to ADC nie pracuje. Jakieś pomysły dlaczego?

    OdpowiedzUsuń
  12. a jak zrobić żeby cały czas mi odczytywało wartość z potencjometru bez przyciskania przyciska?

    OdpowiedzUsuń
  13. Poczytaj następne części pamiętnika.

    OdpowiedzUsuń
  14. Panie Drzaśku zapomniał Pan dodać, jak się wybiera dane porty. Np. że coś mam podłączone pod PC0 a nie pod z góry założony port PC5

    OdpowiedzUsuń
  15. Noto czytaj następne części artykułów, jest tam również wybór wejść.

    OdpowiedzUsuń
  16. Chyba coś jest nie tak z tym kodem, przekopiowałem na ,,żywca'' i nie działa tak jak powinien. W tekście jest napisane: ,,Po uruchomieniu programu obydwie diody nie świecą się''
    u mnie od razu się świecą, a przycisk nie działa (przetestowałem go na innym kodzie czy jest dobrze podłączony, zapalał i gasił diody). Nie ważne, czy mam włożony potek i rezystor, czy nie, one i tak świecą. Przestają jedynie jeśli zmieniam warunki w if'ie. Układ mam zbudowany na Atmedze 8A

    OdpowiedzUsuń
  17. Musisz pokazać kompletny schemat podłączenia. Coś mogłeś pokręcić, uszkodzić uC.Diody nie mogą świecić, jeśli nie zostaje wciśnięty przycisk, bo wartość początkowa rejestru ADC jest 0.

    OdpowiedzUsuń
  18. http://imageshack.us/photo/my-images/138/dscf9313k.jpg/
    http://imageshack.us/photo/my-images/854/dscf9311p.jpg/
    http://imageshack.us/photo/my-images/222/dscf9310h.jpg/
    Proszę, zdjęcia z trzech różnych ujęć.

    OdpowiedzUsuń
  19. Kurcze, straszny bałagan tam masz, ciężko się poznać.
    Masz po obydwu stronach płytki szyny zasilające (czerwona - czyli jak wiadomo +) i niebieska/czarna czyli -/masa itd. A ty używasz jakoś na przemian ich, masz je razem chyba połączone czy coś. Nie wiem, ale ciężko się takie coś analizuje.

    uC daje się bez problemu programować?

    Skompiluj i wgraj następujący program i daj znać o efektach:

    #include

    #define LED1 PB0
    #define LED2 PB1

    void main(void)
    {
    DDRB |= (1<<LED1) | (1<<LED2); for(;;);
    }

    OdpowiedzUsuń
  20. NO procesor bez problemu daje się programować. A ten kod to nic nie robi ;p chyba chodziło Ci o coś takiego?:
    #include

    #define LED1 PB0
    #define LED2 PB1

    void main(void)
    {
    DDRB |= (1<<LED1) | (1<<LED2);
    for(;;){
    PORTB |= (1<<LED1);
    PORTB |= (1<<LED2);
    }
    }

    Diody mi świecą, pisałem już wcześniej, że testowałem też przycisk i działał. Co do masy to zrobiłem ją na szynach, a + mam tak jakby na środku, widać, że wszystkie czerwone(pomarańczowe) kabelki zbiegają się w jednym punkcie za stabilizatorem.

    OdpowiedzUsuń
  21. Tak, program miał nic nie robić.
    Chodziło mi o to, abyś sprawdził, czy diody mimo tego, że nie powinny się zaświecać, się zaświecają.
    Z kodem ma być wszystko w porządku, nie wrzucam tutaj niesprawdzonych programów. Jak widać wyżej w komentarzach, układ zadziałał u innych osób, jedyne problemy to właśnie ich błędy w podłączeniu itd.
    Więc musisz narysować mi dokładnych schemat z wszystkimi elementami jakie masz na płytce. Ale nie przerysowując z mojego schematu, ale patrząc na płytkę po kablach, narysuj tak jak to podłączyłeś. Najprawdopodobniej coś poknociłeś w podłączeniu.

    OdpowiedzUsuń
  22. W czym narysować, np. w Eaglu? Pierw spróbuje połączyć jeszcze raz a jak nie pójdzie, to wtedy narysuję.

    OdpowiedzUsuń
  23. Odpowiem za Drzaśka: Tak w Eaglu.

    OdpowiedzUsuń
  24. Dobra działa ;D Potencjometr zwierał dwiema nóżkami. Należało go obrócić o 90 stopni. W międzyczasie zdążyłem usmażyć już jedną Atmegę ;p

    OdpowiedzUsuń
  25. Witam,
    mam takie pytanie (może lamerskie, ale dopiero zaczynam - to mój pierwszy projekt).
    Chciałbym odczytać rezystancję termistora (podłączonego pod Vcc=5V). Intersuje mnie odczyt z przedziału 10 K Ohm - 900 K Ohm.
    W jaki sposób go podłączyć do mikrokontrolera, i jak dobrać rezystory, tak, żeby otrzymać napięcie z przedziału 0 - 5V (lub 0V - 2.5V)?

    OdpowiedzUsuń
  26. Sposobów jest wiele.
    Możesz dobrać rezystor równy wartości maksymalnej rezystancji termistora czyli 900 kOhm.
    Połącz równolegle rezystor z termistorem. Wolną nogę termistora podłącz do masy a wolną nogę rezystora do 5V. Ustaw napięcie referencyjne 2.56V. Jeśli termistor będzie miał rezystancję 900 kOhm to dostaniesz dzielnik napięcia przez połowę więc napięcie w punkcie połączenia rezystorów wyniesie 2.5V.
    Jeśli termistor będzie zmniejszał swoją rezystancję to napięcie będzie malało.
    Poczytaj jak działa dzielnik napięcia.

    Taki sposób jest prosty i będzie działał, ale wprowadzi pewne błędy w pomiar ADC, bo jest to dzielnik napięcia na dużych rezystorach. W praktyce dobrze byłoby zastosować wtórnik napięcia na jakimś WO.

    OdpowiedzUsuń
  27. Dzięki za odpowiedź!
    Niebawem sprawdzę, czy dokładność jest wystarczająca i ewentualnie kombinował na wtórniku.

    OdpowiedzUsuń
  28. Przymierzam sie do tego projektu. Pytanie czy na Attiny dobrze ustawione bity to:
    1.Prescaler adc na 8 przy 1Mhz czyli 125kzh bo 13.260qs resolution
    czyli ADPS0, ADPS1 ustawić
    2.Właczenie kompaktora
    ustawić ADEN
    3.ADMUX czyli MUX1 ustawic aby wykorzystywac kanal 1 na PB2
    4.Czy REFS0 to wybór napiecia odniesienia, które wybrać aby działało przy tym schemacie?
    VCC used as analog reference.
    Internal Voltage Reference

    OdpowiedzUsuń
  29. Witam, na wstępie wielgachne dzięki za te artykuły. Bardzo pomocne:-)

    A pytanie mam takie, ponieważ rozkręciłem swoje radio RC, a tam atmelek: Mega48PA. Bardzo proste radio, sterowanie tylko serwomechanizmami, bez dodatkowych opcji.
    Przyglądam się podłączenim potencjometrów i o dziwo jest tam dodatkowy opornik wraz z kondesatorem.
    Opornik oznaczony jako 101, czyli 1kOhm podłączony jest w miejscu wyjścia zmiennego napięcia z potencjometru do ADC.
    Kondensator bez opisu, jest on podłączony do linii mierzonego napięcia (ADC) i GND.
    No i teraz nasuwa mi się pytania czy one są tam potrzebne zawsze (bez względu na projekt),
    czy widocznie w tym projekcie są wymagane?
    Przeglądnąłem trochę internetu w poszukiwaniu tej odpowiedzi i zawsze jak coś znalazłem to potencjometr
    był "wprost" podłączony pod mikrokontroler (w szczegółności w przypadku arduino).

    Zygmunt

    OdpowiedzUsuń
    Odpowiedzi
    1. Witaj.

      101 to 10 x 10¹ = 100Ω, a nie 1kΩ

      Jeśli dobrze zrozumiałem to rezystor ten wraz z kondensatorem i potencjometrem tworzy filtr RC, na wejściu pomiarowym ADC. Sądzę, że osoba która zaprojektowała to urządzenie chciała zabezpieczyć się przed sytuacją, gdy potencjometr zostanie ustawiony w takim położeniu, że będzie bez jakiejkolwiek rezystancji zwierał do wyjścia napięcia zmiennego, o którym piszesz.

      Innymi słowy w takiej sytuacji będziesz miał zawsze filtr RC złożony co najmniej z rezystora 101 i kondensatora. To dobrze świadczy o projektancie :-)

      Usuń
    2. > 101 to 10 x 10¹ = 100Ω, a nie 1kΩ
      Racja, coś pomieszałem.

      Dzięki za informacje:-)
      Zygmunt

      Usuń
  30. Witam, mam problem z uruchomieniem pańskiego programu, podobny jak kolega Chwali Chwallus, z tym że po załadowaniu do mojej atmegi (atmega8) programu który pan polecił diody się świecą mimo iż nie powinny czy to ozancza, że mój procesor jest już uszkodzony? czy są jakieś inne powody?

    OdpowiedzUsuń
    Odpowiedzi
    1. Prawdopodobnie robisz jednak coś nie tak. Niestety odpowiadam z wielkim opóźnieniem (przegapiłem Twój post) stąd pewnie już temat jest rozwiązany.

      Usuń
  31. Witam, mam pewien dziwny problem z ADC. Działa 0-1 o_0.
    Mam złożone wszystko według schematu (jedynie potek mam 5k a rezystor 7,5 co daje maks 2v na wejściu ADC. Nie ma reakcji na klawisz, jedynie reset sprzętowy budzi ADC do życia ale i tak tylko albo gasną wszystkie ledy albo świecą. Dodam iż moja atmega przeżyła odwrotną polaryzację. Czy to mogło uszkodzić ADC?

    OdpowiedzUsuń
    Odpowiedzi
    1. Odwrotna polaryzacja niestety mogła uszkodzić spor w mikrokontrolerze.

      Usuń
  32. Witam, podczas realizacji tego projektu pojawił mi się problem z zasilaniem - zmierzyłem napięcie na liniach zasilania i miernik pokazywał 3,3 - 3,4 V, no a powinno być 5. Układ zasilany z programatora USB ASP. Rozmontowałem układ i zostawiłem minimalne podłączenie pinów, tak jak tutaj: http://mikrokontrolery.blogspot.com/2011/04/minimalne-podlaczanie-pinow.html (dostosowane do Atmegi32), problem nie ustąpił. Wpiąłem VCC i GND z programatora poza układ i wtedy dopiero pokazało 5 V. Co może być przyczyną takiego stanu? Zworka w programatorze jest umieszczona prawidłowo, do tej pory programowałem mikrokontroler przy takim samym podłączeniu pinów i nie zwróciłem uwagi, żeby coś takiego wystąpiło.

    OdpowiedzUsuń
    Odpowiedzi
    1. Dobrze byłoby byś pokazał schemat i zdjęcia, stąd najlepiej załóż temat na naszym forum, a tutaj wklej link, bym wiedział gdzie zaglądnąć.

      Usuń
  33. Witam, wykonałem taki sam schemat jedyne co to usunąłem przycisk i wprowadziłem adekwatne do tego zmian w programie. Układ jest dobrze podłączony, sprawdziłem miernikiem na pini PC5 uzyskuję od 0 do 4,3 V kręcąc potencjometrem, a co bym nie zrobił to cały czas palą mi się diody.
    Oto mój kod.
    #include

    #define LED1 PB0
    #define LED2 PB2
    #define ADCIN PC5

    int main(void)
    {
    ADCSRA = (1<<ADEN)|(1<<ADPS1)|(1<<ADPS0);
    ADMUX =(1<<REFS0)|(1<<MUX2)|(1<<MUX0);

    DDRB |= (1<<LED1)|(1<<LED2);

    DDRC &=~ (1<<ADCIN);

    while(1)
    {
    ADCSRA |= (1<<ADSC);
    while(ADCSRA & (1<<ADSC));

    if(ADC<350)
    {
    PORTB &=~ (1<<LED1);
    PORTB &=~ (1<<LED2);

    }

    else if(ADC<700)
    {
    PORTB |= (1<<LED1);
    PORTB &=~ (1<<LED2);

    }

    else
    {
    PORTB |= (1<<LED1);
    PORTB |= (1<<LED2);

    }



    }

    }

    OdpowiedzUsuń
    Odpowiedzi
    1. Twój program wygląda na poprawnie przerobiony. Powinien więc działać. Skoro na PC5 masz poprawne napięcia, to ... hmm, dobrze byłoby rzucić na to okiem. Załóż może temat na forum, a tutaj wklej link, bym wiedział gdzie trafić.

      Na forum zamieść kod, zdjęcia, link do tego tematu i schemat z poprawkami - możesz zrobić je na tej grafice Paint'em.

      Usuń
    2. Proszę bardzo
      http://www.elektroda.pl/rtvforum/viewtopic.php?p=14403119#14403119

      Usuń
    3. ... a przyczyną było podłączenie pinu AREF do masy co powodowało, że napięcie odniesienia wynosuło 0V, i dlatego przetwornik zawsze odczytywał maksymalną wartość. Zdjęcia to potwierdziły ... tak czasami bywa :-)

      Usuń
  34. Zgubiłem się gdzieś podczas czytania tego.Miejsce zapisu odczytanej wartości jest jedno dla wszystkich wejść w i gdy chcemy po sobie zmierzyć kilka wartości musimy zrobić odczyt i potem zapis odczytanej wartości do ustalonej wcześniej zmiennej potem znowu odczyt i zapis do kolejnej zmiennej ... Tak ?

    OdpowiedzUsuń
    Odpowiedzi
    1. Jeśli masz taką potrzebę to tak. Może to być np. zmienna tablicowa.
      Innymi słowy rejestr ADC może przechowywać wartość tylko ostatniego pomiaru.
      Czy teraz jest już jasne?

      Usuń
  35. Witam serdecznie.
    Zacznę od tego, że rozpoczynanie nauki po czterdziestce nie jest łatwe ale bez Was byłoby jeszcze trudniejsze. Wielkie dzięki!
    Od kilku tygodni praktykuję z Arduino i stopniowo zaczynam używać "prawdziwego C" w szkicach.
    A oto pytania:
    Czy po pojedynczej konwersji praktykuje się wyłączenie ADC (wyzerowanie ADEN)?
    Czy wyłączenie ADC spowoduje utratę wyniku konwersji (ADCH/ADCL)?
    Czy zerowanie ADEN po instrukcji return ma sens?

    unsigned int ADCreadPinA0(void)
    {
    ADMUX = (1<<REFS0);
    ADCSRA = (1<<ADEN) |(1<<ADPS0) |(1<<ADPS1) |(1<<ADPS2);
    DIDR0 |= (1<<ADC0D);
    ADCSRA |= (1<<ADSC);
    while(ADCSRA & (1<<ADSC));
    return(256*ADCH +ADCL);
    ADCSRA &= ~(1<<ADEN);
    }

    OdpowiedzUsuń
    Odpowiedzi
    1. Nie, ne ma sensu po konwersji wyłączać ADC, chyba, że chodzi o oszczędzanie energii. Niema też sensu wstawiać instrukcji po return - nie są one wykonywane i kompilator zapewne pisze ostrzeżenie o kodzie, który nie zostanie wykonany. Po wyłączeniu ADC rezultat konwersji njest tracony.

      Usuń
  36. Jak należałoby zmodyfikować program gdy wybraliśmy ZEWNĘTRZNE napięcie odniesienia?
    Uprzejmie proszę o odpowiedź.

    OdpowiedzUsuń
    Odpowiedzi
    1. Należy tylko wybrać zewnętrzne napięcie odniesienia i tyle - zobacz opis rejestru ADMUX.

      Usuń
  37. Fajny artykuł. Szkoda tylko, że autor co chwilę odsyła do angielskiego datashed. Jakbym dobrze znał angielski i potrafił go przeczytać, to bym nie szukał informacji na polskich stronach.

    OdpowiedzUsuń

Działy
Działy dodatkowe
Inne
O blogu




Dzisiaj
--> za darmo!!! <--
1. USBasp
2. microBOARD M8


Napisz artykuł
--> i wygraj nagrodę. <--


Co nowego na blogu?
Śledź naszego Facebook-a



Co nowego na blogu?
Śledź nas na Google+

/* 20140911 Wyłączona prawa kolumna */
  • 00

    dni

  • 00

    godzin

  • :
  • 00

    minut

  • :
  • 00

    sekund

Nie czekaj do ostatniego dnia!
Jakość opisu projektu także jest istotna (pkt 9.2 regulaminu).

Sponsorzy:

Zapamiętaj ten artykuł w moim prywatnym spisie treści.