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

Woltomierz cyfrowy - prośba o sprawdzenie

AsKeR 14 Sty 2010 18:24 2761 0
  • #1 7535416
    AsKeR
    Poziom 11  
    Przerobiłem trochę program z książki "Mikrokontrolery Avr W Praktyce" (Doliński) w taki sposób, by napięcie mierzone było wyświetlane na wyświetlaczu LCD. Używałem modułu uruchomieniowego ZL3AVR wyposażonego m.in. w mikrokontroler Atmel ATMEGA32 16PU, wyświetlacz LCD HD444780 2x16 oraz 16-sto przyciskową klawiaturę. Układ podłączyłem jak na rysunku:
    Woltomierz cyfrowy - prośba o sprawdzenie

    Do obsługi wyświetlacza użyto uniwersalnej biblioteki tAvrLib.

    Cykl pomiarowy rozpoczyna się od ustawienia stanu wysokiego na wyjściu PD4, w wyniku czego kondensator C zaczyna się ładować przez opornik R na do napięcia zasilającego Vcc. W tym samym czasie mikrokontroler uruchamia pomiar czasu. W momencie, gdy napięcie na kondensatorze osiągnie wartość mierzonego napięcia wejściowego, na wyjściu komparatora nastąpi zmiana stanu, co powoduje zatrzymanie pomiaru czasu (zatrzaśnięcie wyniku w rejestrach ICR1H i ICR1L), który jest proporcjonalny do napięcia wejściowego (błąd jest niewielki). Cykl pomiarowy kończy się podaniem stanu niskiego na wyjściu PD4,
    w wyniku czego kondensator jest rozładowywany przez rezystor R i niewielką oporność wyjściową portu PD4 w tym stanie.
    Napięcie wejściowe woltomierza będące jednocześnie napięciem w stanie ustalonym na kondensatorze wylicza się z zależności:
    $$U_{c}=\frac{I*t}{C}=\frac{V{cc}-U_{BEP}}{R_{1}}*\frac{t}{C}$$
    Założono spadek napięcia na złączu baza-emiter w stanie przewodzenia 0,7 V.
    Otrzymany wynik jest przysłany na wyświetlacz LCD.
    Na początku programu deklaruje się wartości pojemności C oraz rezystancji rezystora R1.
    Do wyliczenia napięcia referencyjnego zastosowano procedurę kalibracyjną. Jest ona uruchamiana gdy zaraz po restarcie mikrokontrolera zostanie wykryte wciśnięcie klawisza S5 (bit_is_clear(PIND,1)). W pętli do...while jest realizowany cykliczny pomiar napięcia wejściowego. Wyjście z pętli jest możliwe po naciśnięciu klawisza S1. Powoduje to wyliczenie współczynnika kalibracyjnego i zapisanie go w pamięci EEPROM mikrokontrolera.
    Do pisania i kompilowania programu użyto środowiska AVR Studio 4.18 połączone z WinAVR-20090313 natomiast do przesyłania skompilowanego programu (pliku HEX) używano ISP Programmer 1.2.0.52.

    
     Konfiguracja połączeń:
     - PORTA4-PORTA7 - piny DATA4-DATA7 kontrolera HD44780
     - PORTA1 - pin RS
     - PORTA2 - pin E
     - PORTB2 - wejście nieodwracające komparatora +
     - PORTB3 - wejście odwracające komparatora -
     - PORTD4 - wejście służące do rozładowywania kondensatora
     - PORTD0 - wejście z podciąganiem z klawiatury
     - PORTD1 - wejście z podciąganiem z klawiatury
    
     Należy zadać wartości:
    - pojemności C
    - rezystora R1
    - napięcie zasilania Vcc
    */
    
    float rezystorR1=1; //1 Ohm
    float kondensatorC=0.001; //1 mF
    float napieciezasilania = 5; //5 V
    double prad;
    
    #define F_CPU 16000000 //częstotliwość taktowania
    #define HD44780_DATA_GPIO A // pod którym portem jest szyna danych 
    #define HD44780_DATA_HIGHHALFBYTE 1
    #define HD44780_RS_GPIO A
    #define HD44780_RS_BIT 1
    #define HD44780_E1_GPIO A
    #define HD44780_E1_BIT 2
    #define HD44780_WIDTH 16 //liczba kolumn wyświetlacza
    #define HD44780_HEIGHT 2 //liczba wierszy wyświetlacza
    #define HD44780_CHARSET HD44780_CHARSET_PL
    #define HD44780_CODEPAGE HD44780_CODEPAGE_UTF8
    
    #include <tAvrLib/hd44780.h> 		//biblioteka do obsługi wyświetlacza
    #include <avr/io.h> 			//biblioteka plikowych operacji wejścia - wyjścia
    #include <avr/signal.h> 		//biblioteka umożliwiająca obsługę sygnałów
    #include <avr/eeprom.h> 		//biblioteka umożliwiająca korzystanie z pamięci EEPROM
    #include <compat/deprecated.h> 	//biblioteka umożliwiająca kompatybilność z starszymi wersjami kompilatora
    
    
    unsigned char liczt0;
    volatile unsigned char pomiar;   	//flaga dokonania pomiaru
    union{
          unsigned int wspkal;        	//współczynnik kalibracji
          unsigned char wspkalb[2];
         } uwspkal;
    
    
    void czekaj(unsigned long zt) 	//procedura wytracania czasu
    {
    	#define tau 10.38
    	unsigned char zt1;
     	for(;zt>0;zt--)
     	{
      		for(zt1=255;zt1!=0;zt1--);
     	}
    }
    
    
    SIGNAL (SIG_INPUT_CAPTURE1)  		//obsługa przerwania od przechwycenia
    {
     	union {
    		unsigned int czas;
    		unsigned char czasb[2];
     		} uczas;
    
     	uczas.czasb[0]=ICR1L;       	//zatrzaśnij rejestry przechwytywania
     	uczas.czasb[1]=ICR1H;
    
     	float WYNIK=(uczas.czas/uwspkal.wspkal)*(prad/kondensatorC);
    	int cyf0 = WYNIK;		// wyznacz cyfrę przy pozycji 1V 
    	int cyf1 = (WYNIK-cyf0)*100;	// pozycja po przecinku 
    
    	// początek kodu odpowiedzialnego za wyświetlenie dolnego napisu
    	hd44780_goto(1, 1);
    	HD44780_PUTPSTR("    ");
    	hd44780_putInt(cyf0, 10, 0);
    	hd44780_putChar('.');
    	hd44780_putInt(cyf1, 10, 0);
    	HD44780_PUTPSTR(" V");;
    	// koniec kodu odpowiedzialnego za wyświetlenie dolnego napisu
    
     	pomiar=1;                   //pomiar dokonany (zapal flagę)
     	sbi(PORTD,4);               //zacznij rozładowywać kondensator pomiarowy
    }
    
    
    int main(void)
    {
    
    	hd44780_init(); 			//inicjacja wyświetlacza
    	HD44780_BIND_STREAM(stdout);		//powiązanie wyświetlacza ze standardowym wyjściem
    	hd44780_goto(0, 0); 			//przejście do początku górnej linii wyświetlacza
    	HD44780_PUTPSTR("Napiecie wynosi:"); //wyświetlenie górnego napisu
    
    	DDRD=0x13;	//PORTD we oprócz PD4, PD1 i PD0 - wy
     	PORTD=0xff;	//z podciąganiem
     	PORTB=0x04;	//PB2 z podciąganiem
    	DDRB=0xF3;	//PORT B0,B1,B4-B7 - wy, PORTB2 i PORTB3-0 - we
     	TCCR1A=0;	//funkcje porównania i PWM wyłączone
     	TCCR1B=0x41;	//preskaler XTAL/1 dla TC1, przechwytywanie na narastającym zboczu
    	TIMSK=0x08;	//zezwolenie na przerwania od przechwytywania
     	ACSR=1<<ACIC;	//zezwolenie na wyzwalanie przechwytywania komparatorem
     	czekaj(10*tau);
     	TIFR=0xff;	//kasuj przerwania od timerów
     
     
    
     	if(bit_is_clear(PIND,1)) //wciśnięty S5 - kalibracja
     		{      
    		hd44780_goto(1, 1);
    		HD44780_PUTPSTR("  KALIBRACJA");	//wyświetl napis „KALIBARCJA”
    			do
      				{
    prad=((napieciezasilania-(0.7))/(rezystorR1));
       				cbi(PORTD,4);	 //ładuj kondensator pomiarowy (stan wysokiej impedancji na PD4
    	   			TCNT1H=0;	 //zeruj licznik 1 pomiar czasu ładowania
       				TCNT1L=0;
     				sbi(TIFR,ICF1); //ustawienie bitu ICF1 w rejestrze TIFR
    	   			while(bit_is_clear(TIFR,ICF1));   	//czekaj aż napięcie mierzone zrówna się
        	//z napięciem wejściowym
    uwspkal.wspkalb[0] = ICR1H; //zapisanie do zmiennej 16 bitowej wspkal wartość 16 bitowego rejestru przechwytywania (ICR1H do starszej części 16 bitowej danej)
    uwspkal.wspkalb[1] = ICR1L;	// ICR1L do młodszej części 16 bitowej danej
    	            	//uwspkal.wspkal=(ICR1L+256*ICR1H); // inny sposób zapisania powyższych operacji
    
    					sbi(PORTD,4); 		//zacznij rozładowywać kondensator pomiarowy
       					czekaj(1*tau);        //opóźnienie związane z częstotliwością odświeżania
      				} while(bit_is_set(PIND,0));
      		uwspkal.wspkal = uwspkal.wspkal / 64; 
    
      		eeprom_write_byte(1,uwspkal.wspkalb[0]);	//zapisz współczynnik kalibracji 
      		eeprom_write_byte(2,uwspkal.wspkalb[1]);	//do pamięci EEPROM
      		sbi(TIFR,ICF1); 				//ustawienie bitu ICF1 w rejestrze TIFR
     		}
     	else
     		{
     		uwspkal.wspkal=eeprom_read_byte(1);  //odczytaj współczynnik kalibracji z EEPROM-u
     		}
     	sei();		//odblokuj globalne przerwania
     	while(1)	//główna pętla pomiarowa
     	{
     		cbi(PORTD,4);        //ładuj kondensator pomiarowy
     		TCNT1H=0;            //zeruj licznik 1 - pomiar czasu ładowania
     		TCNT1L=0;
     		pomiar=0;
     		while(pomiar==0);    //czekaj aż napięcie mierzone zrówna się z napięciem
      		                     //na kondensatorze pomiarowym
      		czekaj(23*tau);      //opóźnienie związane z częstotliwością odświeżania LCD
    	}
    }
    


    Czy mógłby ktoś sprawdzić czy to w ogóle ruszy? Płytkę miałem pożyczoną więc teraz już nie mam jak samemu? W załączniku biblioteka tAvrLib oraz program wraz z HEXem
REKLAMA