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

[ATmega8][C] Pobieranie napięcia przez przetwornik A/C

InkER_o 10 Gru 2008 21:24 1667 15
  • #1 5843623
    InkER_o
    Poziom 11  
    Witam,
    czy pomógłby mi ktoś pomóc analizując poniższy program? Chcę aby dokonywał się odczyt napięcia z termopary. Niestety tak się nie dzieje. Przedstawiam w kodzie inicjalizację przetwornika, funkcję która ma odbywać się podczas przerwania oraz FRAGMENT int main().

    
    ISR(TIMER0_OVF_vect)
    {
      uint16_t x,y;
    
      napiecie = ADCH;         // czytaj wartość z przetwornika ADC
      x=napiecie;	             //przypisz odczyt. wart. do x
      y=(-0.057*(x^2) + 25.542*x -3.479)/100+25;//rownanie wyznaczajace charakterystyke
      temp_o=y;	//wartosc obliczona temperatury  
      LCD_Home();
      LCD_putstr_P(itoa(temp_o, temp,10));
    }
    
    void ADC_init(void)
    {
    	ADMUX = 0;       // kanał 0 przetwornika ADC
    	ADMUX |= _BV(REFS0);	        // wybor zrodla napiecia
    	ADMUX |= _BV(REFS1);             //          odniesienia
    	ADMUX |= _BV(ADLAR);   // 8starszych bitów wyniku w rejestrze ADCH)
    	ADCSRA = _BV(ADEN)|_BV(ADIE)|_BV(ADFR)|_BV(ADSC)|_BV(ADPS2)|_BV(ADPS1);
                          // włącz przetwornik ADC w trybie samobieżnym - ADEN
                          // uruchom generowanie przerwań, zezwolenie - ADIE
                          // częstotilwość taktowania F_ADC=F_CPU/64
                          // przy F_CPU=8MHz : F_ADC=125 kHz
    }
    
    void StartADC(void)
    {
    ADCSRA |= _BV(ADSC); // rozpoczecie przetwarzania
    while((ADCSRA & _BV(ADIF))==0) //(bit_is_set (ADCSRA,ADSC)) // Oczekiwanie na zakonczenie przetwarzania
    {};
    ADCSRA |= _BV(ADIF);
    ADCSRA &= ~_BV(ADSC);
    sei(); 
    }
    
    int main(void)
    {
    .
    .
    .
    ADC_init();		//inicjalizacja przetwornika
    
    do
    {
    .
    .
    .
    sei();
    StartADC();
    .
    
    }while(1);
    }
    
    


    Proszę administratorów o nie przenoszenie mojej wiadomości do kosza, jeżeli temat podobny już był. Próbowałam znaleźć posty o podobnej treści niestety po paru minutach wysiłków straciłam cierpliwość. Błąd ogólny
    Cytat:
    Could not obtain search results
    DEBUG MODE
    SQL Error : 2013 Lost connection to MySQL server during query

    pojawiający się po wciśnięciu "Szukaj" potrafi wyprowadzić z równowagi. Za wszelką pomoc z góry dziękuję.

    Skorygowałem tytuł - tagi.
    [zumek]
  • #3 5843826
    kasaidolar
    Poziom 19  
    Chaos. Nie rozumiem tego programu - dlaczego w petli robisz pomiar adc a w przerwaniu od timera to odczytujesz? Napisz konkretnie co chcesz uzyskac. I w czym jest problem. Napisanie ze chcesz zrobic pomiar napiecia z termopary i ze nie dziala moze również swiadczyc ze nie masz zasilania procka ;)
    Napisz konkretnie co i jak.
  • #4 5843835
    InkER_o
    Poziom 11  
    Zatem zmienić na
    SIGNAL(SIG_ADC){ }
    :?:
    Czytałam, że makro ISR(TIMER0_OVF_vect){} definiuje się w nowszych wersjach bibliotek. To jest odpowiednik makra SIGNAL.
    Czy w dalszym kodzie jest wszystko w porządku? Niestety nie uzyskuję wyniku pomiaru po zmianie.
    Wybaczcie, jestem początkująca.
  • #6 5843910
    kasaidolar
    Poziom 19  
    InkER-o - co chcesz uzyskac - co dokładnie program ma robic? Rozumiem ze ma mierzyc napiecie ale 8 bitow czy 10 bitow? Co jaki czas? Co program ma jeszcze robic? Chcesz zeby przetwornik robil przerwanie? Po co?
    Poniżej kilka przydatnych i działających funkcji:

    
    void ADC_init(void)
    {
    	
    // Wybranie wewnętrznego żródła napięcia odniesienia	
    	ADMUX |= _BV(REFS0);		
    	ADMUX |= _BV(REFS1);
    //	Wybranie sposobu zapisu wyniku z wyrównaniem do lewej (osiem starszych bitów wyniku w rejestrze ADCH)
    	//ADMUX |= _BV(ADLAR); // To jest jak jest wyrowanie do lewej a jak tego nie ma to do prawej (ADCH i ADCL)		
    // Zezwolenie na konwersję	
    	ADCSRA |= _BV(ADEN);		
    // Wybranie częstotliwości dla taktowania przetwornika  (1/8 częstotliwosci zegara kontrolera) 
    	ADCSRA |= _BV(ADPS0); 	 
    	ADCSRA |= _BV(ADPS1);		
    	
    }
    


    
    void Pomiar(void)
    {	
    		char ADC_L, ADC_H;
    ADCSRA|= _BV(ADSC); 			//start pojedynczej konwersji
       			while(bit_is_set(ADCSRA,ADSC)){};   
       			ADC_L = ADCL;
       			ADC_H = ADCH;
    }
    


    rozumiem ze ustawilas odpowiednio porty?
  • #7 5843992
    InkER_o
    Poziom 11  
    Ok, już rozumiem. Przyznaję, że zmodyfikowałam książkowe ISR(TIM0_OVF_vect){} na ISR(TIMER0_OVF_vect){}. Dlatego, że kompilator nie wiedział co to jest TIM0. Korzystam z gotowego pliku konfiguracyjnego do ATmegi: iom8.h i tam jest TIMER0 a nie TIM0. Nie wiem czy głupotę zrobiłam. A co tam możecie się śmiać:|

    Działanie programu:
    Robię coś w rodzaju termostatu. Chcę otrzymać na przetworniku napięcie, które będzie zamieniane na temperaturę, a temperatura wyświetlana na LCD. Napięcie ma być pobierane z termopary poprzez układ wzmacniający do portu ADC0. Wartość temperatury ma być co chwila odświeżana, czy tego nie robi się na przerwaniach..?
    Wszystkie porty są ustawione. Korzystam z programu symulacyjnego ISIS Professional. Tam tworząc schemat elegancko można wprowadzić plik .hex, zobaczyć czy porty są ustawione (stan 0 czy 1) oraz sprawdzić poprawność programu - jak na rzeczywistym urządzeniu. Oprócz tego program ma obsługiwać klawiaturę, ale to już mam opanowane.
  • #8 5844030
    Freddie Chopin
    Specjalista - Mikrokontrolery
    no robi sie to w przerwaniach, ale w odpowiednich... ty masz odczyt itp. w przerwaniu od timera, ktory nie wiadomo czy w ogole odpalasz. na pewno zas aktywujesz przerwanie od ADC, za to nigdzie nie widac funkcji obslugi tego przerwania.

    wniiosek:
    wystapienie tego przerwania konczy sie natychmiastowym resetem ukladu.

    P.S. nie dolacza sie naglowkow konkretnych ukladow - wystarczy dolaczyc io.h - on sam wybierze uklad i dolaczy co trzeba.

    4\/3!!
  • #9 5844077
    kasaidolar
    Poziom 19  
    Ok no to ja juz mniej wiecej rozumiem. Nie rozumiem troche o co chodzi Ci z tym Timerem - po co w ogole go uzywasz skoro nie odpalasz timera a odpalasz przerwanie od ADC - to jest zagadka.
    Najprosciej jest to zrobic tak:

    
    #include <avr/io.h>
    #include <util/delay.h>
    
    void main (void)
    {
    char ADC_L, ADC_H;
    int ADC_pomiar;
    
    	DDRC = 0x00;		// ustawienie portu na wejsciowy	
    	PORTC= 0x00;
    
    // === USTAWIENIE ADC - inicjalizacja ===
    
    // Wybranie wewnętrznego żródła napięcia odniesienia	
    	ADMUX |= _BV(REFS0);		
    	ADMUX |= _BV(REFS1);
    //	Wybranie sposobu zapisu wyniku z wyrównaniem do lewej (osiem starszych bitów wyniku w rejestrze ADCH)
    	//ADMUX |= _BV(ADLAR); // To jest jak jest wyrowanie do lewej a jak tego nie ma to do prawej (ADCH i ADCL)		
    // Zezwolenie na konwersję	
    	ADCSRA |= _BV(ADEN);		
    // Wybranie częstotliwości dla taktowania przetwornika  (1/8 częstotliwosci zegara kontrolera) 
    	ADCSRA |= _BV(ADPS0); 	 
    	ADCSRA |= _BV(ADPS1);
    
    
    while(1)
    {
    // === start ADC ===
    
    			ADCSRA|= _BV(ADSC); 			//start pojedynczej konwersji
       			while(bit_is_set(ADCSRA,ADSC)){};   
       			ADC_L = ADCL;
       			ADC_H = ADCH;
    
    ADC_pomiar = ADC_H*255+ADC_L; // tu masz dana z adc 10 bitowa z ktora mozesz robic sobie co chcesz
    
    
    
    
    }
    }
    
    
    


    A ze tak zapytam jesli chodzi o Twoj program... to co wedlug Ciebie jest w zmiennej napiecie - chodzi mi o ten fragmet:
      napiecie = ADCH;         // czytaj wartość z przetwornika ADC
      x=napiecie;                //przypisz odczyt. wart. do x
      y=(-0.057*(x^2) + 25.542*x -3.479)/100+25;//rownanie wyznaczajace charakterystyke
      temp_o=y;   //wartosc obliczona temperatury 
      LCD_Home();
      LCD_putstr_P(itoa(temp_o, temp,10)); 


    bierzesz pod uwage napiecie referencyjne itd?
  • #12 5844223
    InkER_o
    Poziom 11  
    No edukacyjna, edukacyjna! :D Jednak porównuję ze swoim nie kopiując na ślepo. Ale dalej drążę temat jako kobieta.. wiadomo, wolniej łapiąca, itd. Ale to miło, że koledzy wyrozumiali:) Koniec wazeliniarstwa, pytanie brzmi: Żeby odczepić się od tego Timera, czy wystarczy na miejsce ISR(..){} wcisnąć SIGNAL(..){}?? czy w ogóle nie zapisywać tego w przerwaniu tylko wzorować się na przykładzie kolegi :arrow: kasaidolar.
    W zmiennej napięcie jest ustawione 8 starszych bitów wyniku. Chociaż może by lepiej ustawić tam całe ADC? Napięcie odniesienia jest ustawione jako stany wysokie w rejestrach REFS0 i REFS1 (jak w kodzie w pierwszym poście).
  • #13 5844281
    zumek
    Poziom 39  
    InkER_o w kodzie napisał:

    y=(-0.057*(x^2) + 25.542*x -3.479)/100+25;//rownanie wyznaczajace charakterystyke

    Bardzo mnie zaciekawił - zaznaczony na niebiesko - fragment powyższego wzoru :P
    Dlaczego negowany jest bit nr. 1, w zmiennej x :?:
    Bardziej by mi pasowało potęgowanie, choć głowy nie dam :|
    Piotrek
  • #14 5844295
    InkER_o
    Poziom 11  
    Wg mnie to jest potęgowanie, mylę się?
    Negacja to ~.
  • #15 5844306
    Freddie Chopin
    Specjalista - Mikrokontrolery
    InkER_o napisał:
    Koniec wazeliniarstwa, pytanie brzmi: Żeby odczepić się od tego Timera, czy wystarczy na miejsce ISR(..){} wcisnąć SIGNAL(..){}?? czy w ogóle nie zapisywać tego w przerwaniu tylko wzorować się na przykładzie kolegi :arrow: kasaidolar.

    nie nie nie nie nie... ISR czy SIGNAL to w tym rozumowaniu roznica jedynie kosmetyczna...

    chodzi o to, co masz wewnatrz nawiasow - obslugujesz przerwanie od timera 0, ktore nigdy nie wystapi, bo timer 0 nie zostal uruchomiony. wystapi za to przerwanie od ADC, ktorego obslugi nie masz napisanej - przez to wywolywana jest wewnetrzna funkcja bad_isr (albo default_isr), ktora resetuje procka. to nie jest kwestia czy robic to w przerwaniu, czy tak jak ktos ci gotowca podeslal - przerwania sa rozwiazaniem lepszym, ale i bardziej skomplikowanym, problematycznym itp. niemniej jednak u ciebie w kodzie obslugujesz nie to przerwanie co trzeba...

    w C nie ma operacji potegowania, ^ to operator XOR.

    4\/3!!
  • #16 5844328
    zumek
    Poziom 39  
    InkER_o napisał:
    Wg mnie to jest potęgowanie, mylę się?

    Tak , mylisz sie .
    InkER_o napisał:
    Negacja to ~.

    W takim razie, czym jest operacja Exclusive-OR(XOR), której użyłaś zamiast np. pow() lub w tym konkretnym przypadku zwykłego (x*x) :?:

    Piotrek
REKLAMA