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

[Atmega8][c][WinAVR]Odczyt wartosci ADC0

szpicus 05 Lut 2011 20:07 2580 15
  • #1 9108465
    szpicus
    Poziom 10  
    Witam Mam problem z odczytem wartosci z ADC0
    Mianowicie caly czas odczytywana jest wartosc maksymalna tj 1023 mimo ze powinno byc 0
    Kod z moimi komentarzami:
    
    void InitADC()
    {
    ADMUX=(3<<REFS0);                         // For Aref=2,56 internal;
    ADCSRA=(1<<ADEN)|(1<<ADPS2)|(0<<ADPS1)|(0<<ADPS0); //Rrescalar div factor =16 bo mam ustawione 1mhz
    }
    uint16_t ReadADC(uint8_t ch)
    {
       //Select ADC Channel ch must be 0-7
       ch=ch&0b00000000; // Aby czytac z ADC 0
       ADMUX|=ch;
    
       //Start Single conversion
       ADCSRA|=(1<<ADSC);
    
       //Wait for conversion to complete
       while(!(ADCSRA & (1<<ADIF)));
    
       //Clear ADIF by writing one to it
       //Note you may be wondering why we have write one to clear it
       //This is standard way of clearing bits in io as said in datasheets.
       //The code writes '1' but it result in setting bit to '0' !!!
    
       ADCSRA|=(1<<ADIF);
    
       return(ADC);

    Nastepnie :
    
    uint16_t adc_result;
    InitADC();
    adc_result=ReadADC(0);  // Pobieram wartosc z ADC
    
          
     
    
    InitLCD();
    ClearLCD();
    char* bufor="Hello ";
    char* bufor2=" XXX";
    itoa(adc_result,bufor2,10);  // zamiana Na asci
    //bufor = adc_result;
    Println(bufor, 6);
    Println(bufor2,4);  // wypisywanie
    


    Widzi ktos jakies błędy przez które moj ADC zawsze podaje wartosc Max?
  • #2 9109020
    mgyz
    Poziom 14  
    Jak masz ustawiony pin PC0 (ADC0) czy jako wejście bez pull-up'u?
    Jakie napięcie masz na tym pinie?

    ch=ch&0b00000000; // Aby czytac z ADC 0

    w ten sposób zawsze, niezależnie do wywołania funkcji ch będzie ustawiane na 0
    i nie zmienisz kanału pomiarowego (ale w tym przypadku nie ma to znaczenia bo i tak korzystasz z kanału ADC0)

    
    char* bufor="Hello "; 
    char* bufor2=" XXX";

    mi sie to nie podoba, wskaźnik nie rezerwuje miejsca na tekst, ja bym zadeklarował tablice
    
    char bufor[]={"Hello "}; 
    char bufor2[]={" XXX"};

    nazwa tablicy jest jednocześnie wskaźnikiem do jej początku więc dalszy kod bez zmian.
  • #3 9109053
    szpicus
    Poziom 10  
    Nie ustawialem nic ( w 2 znaczniku CODE jest caly main)
    poprostu czytam z ADC0
    Na wejsciu w typowych sytuacjach jest 0V lub troszke ponad
    w ekstremalnych sytuacjach ponad 2.5 V
  • #4 9109074
    hotdog
    Poziom 26  
       ch=ch&0b00000000; // Aby czytac z ADC 0 
       ADMUX|=ch; 
    


    Chyba nie chciałeś tego napisać co napisałeś. ADMUX się nigdy nie zmieni i zawsze będzie miało taką samą wartość jak przed wejściem do funkcji.

    Więc zapewne mierzysz cały czas na ADC0, niezależnie co podasz do funkcji. Może z tego wynika Twój błąd? Jeżeli nie to sprawdź napięcie na Vbg, tak dla testów i na GND (masz w datasheet jakie wartości wpisać do ADCMUX żeby przełączyć multiplekser na Vbg i na GND).

    Jak zadajesz napięcie na to ADC0? Może masz port ustawiony w programie na wyjście?

    Pamiętam że kiedyś miałem problem z ADC, że musiałem robić 2 pomiary pod rząd. Dopiero w drugim maiłem dobry wynik. Pewnie było to dlatego że coś maiłem źle napisane (zaczynałem zabawę), ale to zawsze jakiś hint.
  • #5 9109098
    mgyz
    Poziom 14  
    No dobra, po resecie piny sa jako wejścia Hi-Z.
    Ustal na wejściu konkretne napięcie (żeby nie wisiało w powietrzu) i sprawdź czy program odpowiada wartością której się spodziewasz (lub coś w okolicach).
    Sprawdź to wykorzystanie tablic jak pokazałem.
  • #6 9109135
    szpicus
    Poziom 10  
    mgyz napisał:
    No dobra, po resecie piny sa jako wejścia Hi-Z.
    Ustal na wejściu konkretne napięcie (żeby nie wisiało w powietrzu) i sprawdź czy program odpowiada wartością której się spodziewasz (lub coś w okolicach).
    Sprawdź to wykorzystanie tablic jak pokazałem.

    z tym problem ze buduje czujnik i spodziewam sie wartosci 0.
    wiec powinno byc 0.
    trudno jutro podepne baterie 1,5 V i sprawdze wtedy

    ch=ch&0b00000111;
    

    takie cos bedzie poprawne ? Jako ch zawsze dostaje parametr 0
    wiec jak bedzie potem ADMUX |= ch to bedzie czytal z adc0?
  • #7 9109357
    mgyz
    Poziom 14  
    szpicus napisał:

    ch=ch&0b00000111;
    

    takie cos bedzie poprawne ?


    tak, teraz multiplekser będzie ustawiał wybrany kanał (parametr wywołania funkcji)

    Weź dwa oporniki i zrób dzielnik napięcia, podłącz do zasilania uC i ustal napięcie ok. 1V. Podłącz to do ADC0. Pomiar powinien pokazywać wartość nieco mniejszą od połowy

    Oczywiście zasilanie analogowe AVCC masz podpięte i AREF odsprzęgnięte do masy kondensatorem 100n?
  • #8 9109379
    szpicus
    Poziom 10  
    Dzieki wielkie :)
    oczywiscie AVCC do 5V przez Cewke
    a AREF do gnd przez kondenstator
  • #9 9117123
    szpicus
    Poziom 10  
    Ok mialem dzis dostep do programatora i sprawdzilem to co pisaliscie
    zmiana
    ch=ch&0b00000000; 

    na
    ch=ch&0b00000111; 

    niec nie dala.
    dalej pokazuje max tj 1023

    sprawdzalem ten dzielnik napiecia z bateria tez zawsze pokazuje 1023

    nawet jak jest pusta nózka tez pokazuje 1023
    jakies pomysly?
  • #10 9120250
    LordBlick
    VIP Zasłużony dla elektroda
    szpicus napisał:
    jakies pomysly?
    Przestać używać wartości numerycznych i zacząć używać symbolicznych z odpowiednimi operatorami bitowymi, takich, jak w plikach nagłówkowych. Nie ma wtedy prawa się nic p... w kodzie... ;)
  • #11 9120466
    szpicus
    Poziom 10  
    Light-I napisał:
    szpicus napisał:
    jakies pomysly?
    Przestać używać wartości numerycznych i zacząć używać symbolicznych z odpowiednimi operatorami bitowymi, takich, jak w plikach nagłówkowych. Nie ma wtedy prawa się nic p... w kodzie... ;)

    Niestety jestem bardzo początkujacy w programowaniu i tych operatorów logicznych nie rozumiem...
    A dajac wartosci liczbowe przynajmniej poczesci rozumiem kod

    Dodano po 2 [godziny] 28 [minuty]:

    Btw Mam pytanie.
    Defaultowo Atmega 8 ma portc jako Pull-Up?
    to by wyjasnialo dlaczego nawet na pustym porcie mam 1023 wynik
  • #12 9124141
    Fredy
    Poziom 27  
    Defaultowo PORT i DDR są wypełnione zerami . Więc masz wejścia i bez podciągania.
    Tylko pamiętaj że rezystancja wejściowa przetwornika jest b.duża więc nie mogą one wisieć w powietrzu. Jeśli zostawisz nie podłączone to się nie zdziw że będą się cuda dziać.
  • #13 9124398
    mgyz
    Poziom 14  
    ch=ch&0b00000111;

    miało być tylko po to abyś w przyszłości mógł używać innych kanałów niż tylko ADC0.

    na końcu funkcji odczytu ADC masz:

    a ja się pytam jak jest zdefiniowane ADC, sprawdź w pliku .h z definicjami rejestrów ATmegi.
    Po konwersji wynik jest zapamiętywany w ADCL i ADCH.

    daj coś takiego:
    return ((ADCH<<8) | ADCL);


    Poza tym, puszczasz maina tylko raz? Zrób pętlę, niech odczytuje cały czas ADC0. Jakby złapało jakieś śmieci to przy kolejnym pomiarze się poprawi.
  • #15 9124527
    mgyz
    Poziom 14  
    A co ze wskaźnikami 'bufor' i 'bufor2', zamieniłeś na tablice?
    Bo jeśli one wskazują na stałe tekstowe we Flash'u to:
    itoa(adc_result,bufor2,10);  // zamiana Na asci

    tak konwertować można sobie do usr... dosc dlugo ;-)

    Ewentualnie wpisz
    itoa(0x123,bufor2,10);  // zamiana Na asci

    żeby zobaczyć czy chodzi. Powinno wyświetlić wynik 291
  • #16 9128332
    szpicus
    Poziom 10  
    Ok poprawione na tablice. Odczyt ADC dziala poprawnie.
    Problem jest gdzies indziej.
    Mam wzmacniacz operacyjny ktory pracuje jako Current TO Voltage converter
    ale niestety zawsze pokazuje max 1023 nie wazne co dostanie na wejscie
REKLAMA