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

[ATmega 644p][C] ADC próbkowanie

Fir3man 19 Sie 2010 13:41 1926 3
REKLAMA
  • #1 8415205
    Fir3man
    Poziom 10  
    Witam
    Mam problem tego rodzaju iż potrzebuje napisać program który będzie pobierał 3 próbki z jednego kanału i przeskakiwał na następny i tak do końca. Następnie te próbki zebrane trzeba uśrednić.Za bardzo nie wiedziałem jak się za to zabrać więc przekopałem forum w poszukiwaniu cennych informacji i skleciłem mniej więcej coś takiego :

    
    void pomiar(void)
    {
    ISR(TIMER1_COMPA_vect){ 
    #define VREF 5
    int i;
    int c;
    char kanal[3];
    char aBytes[i];
    for (i = 0; i < 8; ++i) {
        ADMUX &= ~0x07; /* zeruj 3 najmłodsze bity ADMUX */
        ADMUX |= i; /* w i mogą być ustawione tylko 3 najmłodsze bity */
        ADCSRA |= _BV(ADSC); /* rozpocznij konwersję */
        loop_until_bit_is_set(ADCSRA, ADIF);
        ADCSRA |= _BV(ADIF); /* wyzeruj bit */
    	while(c<3){
    	aBytes[i] = (float)(ADCL | (ADCH<<8))/1024*VREF; /* zapisz wynik */
        kanal[c]=aBytes[i];
    	c++;
    	}
    
    }
    }
    }
    


    Nie miałem pomysłu jakby to zrobić żeby 3 próbki pobierał z jednego kanału więc dałem pętle bo nic innego nie przychodziło mi na myśl. Jakby ktoś mógłby rzucić okiem i sprawdzić czy to ma sens to byłbym wdzięczny.
  • REKLAMA
  • #2 8415291
    Samuraj
    Poziom 35  
    Początek masz dobry tyle tylko że w tablicy za każdym razem będziesz mieć ten sam wynik.
    Przerzuć start konwersji do pętli razem ze sprawdzaniem bitu ADIF.
    I na koniec należało by wyciągnąć jakąś średnią z tych pomiarów.
    Jest jeszcze mały błąd w definicji tablicy aBytes. Nie można jako wielkość tablicy podać zmienną. Na etapie kompilacji zmienna ta ma wartość 0 gdyż dwie linijki wyżej ją inicjujesz.
  • REKLAMA
  • #3 8415412
    dziechu
    Poziom 27  
    Ja w swoim urządzeniu zastosowałem taki algorytm:

    unsigned char ilpom; // licznik ilości pomiarów.

    dla każdego kanału wykonuję w pętli ilpom pomiarów.
    Najpierw zeruję tablicę - np. kanal[3] = {0, 0, 0};
    potem uruchamiam pętlę z pomiarem w której np. kanal[0] = kanal[0] + ADCW;

    czyli mam sumę ilpom pomiarów, po pętli robię kanal[0] = kanal[0] / ilpom; i mam srednią z ilpom pomiarów. Wszytsko da się zrobić w dwóch (jedna w drugiej) pętlach - jedna dla kolejnych kanałów, druga dla ilpom pomiarów każdego kanału. ilpom możesz ustawiać dowolnie np. od 1 do 16 lub wiecej.
    i oraz c powinno być chyba unsigned char, z kolei kanal raczej insigned int.

    A jeśli masz tą funkcję jako void pomiar(void), czyli bez wartości wej/wyj. to np. int kanal[3]; powinno być zadeklarowane jako tablica globalna a nie w funkcji, wtedy inne części programu będą miały dostęp do wartości pomiaru.

    Dodano po 7 [minuty]:

    
    unsigned int pomcal(char kanal, char licznik)			// funkcja pomiaru ADC
    {
    	uint16_t pomiar(uint8_t);					// deklaracja typu funkcji dla pomiar
    	unsigned int liczba = 0;					// tu bedzie wynik pomiaru
    	char i;
    
    	for (i=0; i<licznik; ++i)					// 'licznik' pomiarów sumowanych w liczba
    
    		{
         		liczba = liczba + pomiar(kanal);	// 'licznik' x dodać do 'liczba' pomiar kanału 'kanal'
    	 		_delay_us(200);
    		}
    	return (liczba);
    }
    
    uint16_t pomiar(uint8_t kanal) 
    
    {    
       ADMUX = kanal & 0x07 | 0x40;   				// ustaw kanal 
        
       ADCSRA |= _BV(ADSC);    						//rozpocznij konwersje 
       while(ADCSRA & _BV(ADSC));    				//czekaj az skonczy 
       return ADCW;  								//zmierzona wartosc 
           
    } 


    Dodano po 2 [minuty]:

    wywołując funkcję pomcal podajesz nr kanłu i ilość pomiarów, np. costam = pomcal(0,3); - czyli costam będzie równe sumie trzech pomiarów kanału 0, a średia będzie costam = pomcal(0,3) / 3; - oczywiście zamiast 3 lepiej podstawić zmienną.
  • #4 8415477
    Fir3man
    Poziom 10  
    Bardzo dziękuję wam za pomoc. Zaraz to wszystko przeanalizuje i napisze czy mi coś z tego wyszło. Wiem jeszcze że to wszystko będzie musiało być zawarte w przerwaniu ponieważ te dane z każdego kanału będą wyświetlane na HD44780, którego obsługę już udało mi się opanować.
REKLAMA