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

Problem z ADC - odczyt z kilku wejść A/C

Faber33 29 Wrz 2010 15:11 2472 19
REKLAMA
  • #1 8564352
    Faber33
    Poziom 16  
    Witam. Mam problem z ustawieniem z tego co zauważyłem rejestrów ADMUX i odczytem z właściwego ADC. Głównie chodzi mi o ADC4. Bo zamiast wyniku z ADC4 pojawia mi się w miejscu tego pomiaru wynik z ADC0 :/

    Oto kod:

     
    int main(void)
    {
        while(1)
        {
    
            prad = 0;
            napiecie = 0;
            temperatura = 0;                
            ADC_temp = 0;
            ADC_temp_sr = 0;
            Uin = 0;
            pradogr = 0;
            ogran = 0;
    
               // pomiar wartości ADC0 
               for(i = 0 ; i < 20 ; i++)
            {
                ADCSRA|= _BV(ADSC);             //start pojedynczej konwersji
                   while(bit_is_set(ADCSRA,ADSC)){};   
                   ADC_L = ADCL;
                   ADC_H = ADCH;
                ADC_temp  = ADC_H*256+ADC_L;
                ADC_temp_sr = ADC_temp_sr + ADC_temp;    
                if(i==19)            
                {
                    ADC_temp = ADC_temp_sr/20;
                    Uin = (Uref/1024)*ADC_temp;
                    napiecie = ((R1+R2)/R2)*Uin;
                    
                    napiecie_int = napiecie;
                    napiecie_float = (napiecie*100)-(napiecie_int*100);
                        
                }
              }
    
            temperatura = 0;                
            ADC_temp = 0;
            ADC_temp_sr = 0;
            Uin = 0;
            //prad = 0;
    
               // pomiar wartosci ADC1
               ADMUX |= _BV(PC0);             
               for(i = 0 ; i < 20 ; i++)
            {
                ADCSRA|= _BV(ADSC);             //start pojedynczej konwersji
                   while(bit_is_set(ADCSRA,ADSC)){};   
                   ADC_L = ADCL;
                   ADC_H = ADCH;
                ADC_temp  = ADC_H*256+ADC_L;
                ADC_temp_sr = ADC_temp_sr + ADC_temp;    
                if(i==19)            
                {
                    ADC_temp = ADC_temp_sr/20;
                    Uin = (Uref/1024)*ADC_temp;
                    prad = Uin/Rpom;
                    
                    prad_int = prad;
                    prad_float = (prad*100)-(prad_int*100);
                }
              }
    
    
            temperatura = 0;                
            ADC_temp = 0;
            ADC_temp_sr = 0;
            Uin = 0;
    
              ADMUX &= ~_BV(PC0);
    
               // pomiar wartosci ADC2
               ADMUX |= _BV(PC1);             
               for(i = 0 ; i < 20 ; i++)
            {
                ADCSRA|= _BV(ADSC);             //start pojedynczej konwersji
                   while(bit_is_set(ADCSRA,ADSC)){};   
                   ADC_L = ADCL;
                   ADC_H = ADCH;
                ADC_temp  = ADC_H*256+ADC_L;
                ADC_temp_sr = ADC_temp_sr + ADC_temp;    
                if(i==19)            
                {
                    ADC_temp = ADC_temp_sr/20;
                    Uin = (Uref/1024)*ADC_temp;
                    temperatura = Uin*90;
                }
              }
            ADMUX &= ~_BV(PC1);
     
            
            ADC_temp = 0;
            ADC_temp_sr = 0;
            Uin = 0;
            //prad = 0;
    
               // pomiar wartosci ADC4
               ADMUX |= _BV(PC3);           
               for(i = 0 ; i < 20 ; i++)
            {
                ADCSRA|= _BV(ADSC);             //start pojedynczej konwersji
                   while(bit_is_set(ADCSRA,ADSC)){};   
                   ADC_L = ADCL;
                   ADC_H = ADCH;
                ADC_temp  = ADC_H*256+ADC_L;
                ADC_temp_sr = ADC_temp_sr + ADC_temp;   
                if(i==19)           
                {
                    ADC_temp = ADC_temp_sr/20;
                    pradogr = (Imax/1024)*ADC_temp;
                    ogran = pradogr;
                   
                    pradogr_int = ogran;
                    pradogr_float = (ogran*100)-(pradogr_int*100);
                }
             } 
    
            ADMUX &= ~_BV(PC3);

    return 0;

    }


    Dodaję że niejest to mój kod...i chciałbym się dowiedzieć jak prawidłowo ustawiać ADMUX do konkretnego ADC żeby nie mieszało mi wyników????
  • REKLAMA
  • #2 8564377
    dj_west
    Poziom 17  
    Karta katalogowa mikrokontrolera w łapkę, a tam wszystko czarno na białym opisane, wraz z tabelką możliwych kombinacji :)
  • REKLAMA
  • #3 8564647
    Faber33
    Poziom 16  
    tylko tabelka mi nie powie jak mam te konkretne bity ustawić w języku C:P może by ktoś podał jak to w łatwy sposób i czytelny zapisać poprawnie???
  • #4 8564741
    janbernat
    Poziom 38  
    Do rejestru ADMUX wstaw bity MUX0-3 albo 4 (zależy od procesora) a nie stany portów.
  • #5 8564818
    Faber33
    Poziom 16  
    czyli naprzykład dla odczytu z ADC0 mam ustawić ADMUX:

    ADMUX |= _BV(0);

    czy w postaci binarnej??

    np. dla ADC4

    ADMUX |= _BV(0100);

    ??

    Proszę używać znaczników code!
    Robak
  • #6 8564977
    janbernat
    Poziom 38  
    A jak chcesz.
    Ja wstawiam nazwę bitu np tak:
    
    ADMUX = _BV(REFS0)|_BV(REFS1)
    

    Inni numer bitu a jeszcze inni przesuwają << bit na określone miejsce.
    Możesz sobie zrobić też
    
    #define KANAL_0 0 itd.
    

    Najfajniej jest tak:
    
    ADMUX=0b11000110;
    
  • #7 8565275
    Faber33
    Poziom 16  
    w tym ostatnim sposobie też musi być przesunięte o 1 bit??
  • #8 8565486
    janbernat
    Poziom 38  
    No chyba żartujesz.
    Po prostu wstawiasz do rejestru.
    Ten ostatni sposób podałem tylko dlatego że tak też można.
    Ale tylko z nosem w DS danego procesora.
    No i po miesiącu jak ktoś to czyta (nawet Ty sam) to bez DS nie dojdzie co tam jest.
    W pierwszej części Swojego programu nic nie wstawiasz do ADMUX.
    Na pewno tak ma być?
    Masz wtedy zewnętrzne napięcie odniesienia.
    Jak masz- to w porządku.
  • #9 8566293
    Faber33
    Poziom 16  
    źle to ująłem ale zapytam tak...dla ADC0 nie ustawia się wogóle ADMUXA?????...bo z tego co zauważyłem teraz jak pozmieniałem według tego sposobu co podałeś wszystkie inne niż ADC0 to jakby pomiar z tego adc pomieszał z innymi oprócz pomiaru temperatury :/

    PS. Jeśli dobrze rozumiem to chodzi Ci o inicjalizację ADC...mam ją ustawioną tylko że w innym pliku
  • REKLAMA
  • #10 8566414
    janbernat
    Poziom 38  
    Po resecie cały ADMUX==0
    Załóżmy że korzystasz z zewn. napięcia odniesienia i nie ustawiasz bitu ADLAR.
    No to nic nie ustawiasz i masz pomiar z kanału 0 z zewn nap. odniesienia.
    Ale jak masz konfigurację w innym pliku do podaj jaką.
    No i w końcu- jaki procesor?
    No i co ty wstwiasz w końcu do ADMUX?
    najpierw- nic.
    Potem PC0- jaki PinC- przecież to stan wejścia a nie konfiguracja kanału do odczytu.
    Potem- znowu PC0
    Potem- PC1 a potem PC3.
    A powinno być:
    kanal_0- ADMUX taki jaki jest- nie wiem jaki.
    kanal_1 ADMUX|=_BV(MUX0);
    kanal_2 ADMUX|= _BV(MUX1);
    kanal_3 ADMUX|=_BV(MUX0)|_BV(MUX1);
    Trzema bitami można ustawić 8 kanałów a czwarty jest dla bardziej tajemniczych operacji.
    DS Mega8 str.206
    Mega32 str.215
  • #11 8568194
    Faber33
    Poziom 16  
    Ok.Chodzi o Amegę8

    a tu jest ta konfiguracja:

    void ADC_init(void)
    {
        
    // Wybranie wewnętrznego żródła napięcia odniesienia    
        ADMUX |= _BV(REFS0);        
        ADMUX |= _BV(REFS1);
    
        //ADMUX |= _BV(ADLAR);         
    // Zezwolenie na konwersję    
        ADCSRA |= _BV(ADEN);        
    
        ADCSRA |= _BV(ADPS0);     
        ADCSRA |= _BV(ADPS1);        
        
    }
    
  • #12 8568539
    janbernat
    Poziom 38  
    No to jest dobrze dla 1MHz.
    Jak wpiszesz odpowiednie MUX do ADMUX tak jak podałem wyżej to powinno działać.
  • REKLAMA
  • #13 8568785
    Faber33
    Poziom 16  
    ok. a co z kanałem 0??? należy tu wpisać jakiś MUX????
  • #14 8569304
    janbernat
    Poziom 38  
    Str. 206 DS ATmega8
    Table 75. Input Channel Selections
    MUX3..0 Single Ended Input
    0000 ADC0
    0001 ADC1
    0010 ADC2
    0011 ADC3
    0100 ADC4
    0101 ADC5
    0110 ADC6
    0111 ADC7
    1000
    1001
    1010
    1011
    1100
    1101
    1110 1.23V (VBG)
    1111 0V (GND)
    faber- Twoja odporność na wiedzę staje się niepokojąca.
    W tej tabeli masz jak wół napisane że dla odczytu kanału 0 wszystkie MUX są zero.
    A ponieważ po resecie(po starcie programu) jest tam 0 to nic nie wpisujemy. [/b]
  • #15 8572634
    Faber33
    Poziom 16  
    DZIĘKUJĘ koledze za wyoślenie sprawy ( wiem że jestem strasznie tępy ale co mogę na to poradzić )
  • #16 8572890
    janbernat
    Poziom 38  
    A działa?
    Bo to dopiero wtedy jest dobre wyoślenie.
  • #17 8573522
    Faber33
    Poziom 16  
    no teraz działa jak należy :)... tylko mam małe problemy z dokładnością pomiaru...ponieważ wynik przeważnie skacze o 3-4 setki w górę i w dół...może by jakoś uśrednić kilka pomiarów...chodź nie jestem pewnie czy nie jest to już robione:

    ADC_temp = ADC_temp_sr/20; 
  • #18 8573599
    janbernat
    Poziom 38  
    Pewnie tak- to może być próba uśrednienia.
    Ale to nie jest Twój kod i problem może być w wyświetlaniu.
    Ale skoki o 3/100V mogą być równie dobrze spowodowane działaniem zasilacza.
    Żaden prosty zasilacz nie da napięcia z dokładnością do 1/100V.
    Wyświetlanie powinno działać po uśrednieniu- a nie wiadomo co ile wyświetla.
    Daj raczej cały kod- może da się to sprawdzić.
    No i może schemat- bo ATmega8 nie ma wejść różnicowych i przy pomiarze prądu może być coś nie tak.
  • #19 8574899
    Faber33
    Poziom 16  
    Zasilacz to: https://www.elektroda.pl/rtvforum/topic1560889-0.html

    Tu jest cześć odpowiadająca za wyświetlanie:

    
    #include <avr/io.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    #include "naglowkowy.h"
     
    /************************ #include<LCD_init.h> ***************************************************/
    
    #define LCD      PORTD
    #define E          3                                    
    #define RS      2                                     
    
    #define SET_E   LCD |=     _BV(E)                        
    #define CLR_E   LCD &= ~_BV(E)
    
    #define SET_RS  LCD |=     _BV(RS)
    #define CLR_RS  LCD &= ~_BV(RS)
    
    #define PORT_AD PORTC                // Port z wejściami analogowymi 
    #define DDR_AD DDRC
    
    char bufor1[10];
    
    //**********************************************************************************************/
    
    void write_to_lcd(char x)
        {
        SET_E;                                             
        LCD = ((LCD & 0x0F) | (x & 0xF0));                 
        CLR_E;                                             
        SET_E;                                             
        LCD = ((LCD & 0x0F) | ((x & 0x0F) << 4));         
        CLR_E;                                             
        Waitms(1);                                         
        }
    
    //**********************************************************************************************/
    
    void write_command(char x)
        {
        CLR_RS;                                         
        write_to_lcd(x);                                 
        }
    
    //**********************************************************************************************/
    
    void write_char(char x)
        {
    
        SET_RS;                                         
        write_to_lcd(x);                                 
        }
    
    //**********************************************************************************************/
    
    void write_text(char *s)
        {
        while(*s)                                         
              {
              //tu by sie cos przydalo atoi np
              write_char(*s);                             
              s++;                                         
              }
        }
    
    
    //**********************************************************************************************/
    
    void write_data(int s)
        {
        
            itoa (s , bufor1, 10); 
            write_text(bufor1);
        }
    
    
    //**********************************************************************************************/
    
    void pierwsza(void)
        {
        write_command(0x80);
        }
    
    void druga(void)
        {
        write_command(0xC0);
        }
        
    void trzecia(void)
        {
        write_command(0x90);
        }
        
    void czwarta(void)
        {
        write_command(0xD0);
        }        
    //**********************************************************************************************/    
    
    void LCD_init (void)
        {
        Waitms(15);             // czekaj 15ms na ustabilizowanie się napięcia zasilającego
        CLR_E;                     // E = 0
        CLR_RS;                 // RS = 0
        char i;                 // zmianna licznikowa
        for(i = 0; i < 3; i++)     // trzykrotne powtórzenie bloku instrukcji
              {
              SET_E;                 // E = 1
              LCD &= 0x3F;         //
              CLR_E;                 // E = 0
              Waitms(5);             // czekaj 5ms
              }
        SET_E;                     // E = 1
        LCD &= 0x2E;             //
        CLR_E;                     // E = 0
        Waitms(1);                 // czekaj 1ms
        
        write_command(0x28);     // interfejs 4-bity, 2-linie, znak 5x7    
        write_command(0x08);     // wyłącz LCD, kursor i miganie
        write_command(0x01);     // czyść LCD
        write_command(0x06);     // bez przesuwania w prawo
        write_command(0x0C);     // włącz LCD, bez kursora i mrugania
        
        
        }
        
                
    //**********************************************************************************************/
    void czysc(void)
    {
        pierwsza();
        write_text("        ");    
        druga();
        write_text("        ");    
        pierwsza();
    }    
    
    //**********************************************************************************************/
    
    void lcd_def_char(char dane[], char numer)
    {
        
    
        char x;    
        write_command(0x40);
        for (x = 0; x < 8; x++)
        {    
            write_command(0b01000000 | (numer<<3) | x);;
            write_char(dane[x]);
    
    
        }
        write_command(0x80);
        
        
    }
    
    


    A schemat miernika tutaj:

    https://obrazki.elektroda.pl/71_1197553996.jpg
  • #20 8583072
    Faber33
    Poziom 16  
    I co kolega na to powie?? :)
REKLAMA