Voltmetrs ir mērierīce, ar kuras palīdzību ir iespējams izmērīt gan līdzspriegumu, gan maiņspriegumu. Vispārīgi voltmetri var būt gan analogi, gan digitāli, kur analogie voltmetri pārvieto rādītāju (adatu) pa skalu proporcionāli nomērītajam spriegumam, bet digitālie voltmetri rāda skaitlisku sprieguma vērtību, kuru nosaka, izmantojot analogais-ciparu pārveidotāju.
Zemāk redzamajā attēlā (skatīt 1.1.att.) ir izveidota samērā vienkārša digitālā voltmetra elektriskā principiālā shēma, kuras darbības princips ir balstīts uz analogais-ciparu pārveidotāja. Analogais-ciparu pārveidotājs jeb ACP ir iebūvēts mikrokontrollerī (ATmega328P).
1.1.att. Digitālais voltmetrs 0-100 V
Sprieguma mērīšana tiek veikta, izmantojot sprieguma dalītāju (R3=100 kΩ un R2=1 kΩ), vēlāk nodalītais spriegums tiek nolasīts, izmantojot mikrokontrollera PC0 izvadu jeb ACP 0. kanālu, tālāk tiek iegūta ACP vērtība, kura var būt robežās no 0 līdz 1023. Šīs robežas nosaka tas, kāda ir ACP izšķirtspēja jeb bitu skaits (2^10 = 1024 dažādas vērtības).
Rezultātā, veicot visus nepieciešamos aprēķinus un darbības, mikrokontrolleris uz LCD izvada izmērīto spriegumu voltos.
#define F_CPU 16000000UL // 16 MHz takts signals
#include<avr/io.h> // Tiek pievienotas nepieciesamas bibliotekas #include<util/delay.h> #include <avr/interrupt.h> #define LCD_datu_ports PORTD // Ports D tiek definets ka LCD datu ports #define LCD_vadiba PORTB // Ports B tiek definets ka LCD vadibas ports #define en PB2 // Takts signals #define rw PB1 // Lasit/rakstit #define rs PB0 // Registra izvele /* ----------- ---------- | ATmega328 | | LCD | | | | | | PD7|---------------->|D7 | | PD6|---------------->|D6 | | PD5|---------------->|D5 | | PD4|---------------->|D4 | | PD3|---------------->|D3 | | PD2|---------------->|D2 | // 8 bitu rezims | PD1|---------------->|D1 | | PD0|---------------->|D0 | | | | | | PB2|---------------->|E | | PB1| GND------>|RW | | PB0|---------------->|RS | ----------- ---------- */ void LCD_cmd(unsigned char cmd); // Funkciju prototipi void LCD_inicializacija(); void LCD_izvade(unsigned char dati); void ADC_inicializacija(); int nolasa_ADC(); void LCD_teksta_izvade(unsigned char *str,int index,int pozicija); void LCD_datu_izvade(int ADC_vertiba); int vieni, desmiti, simti ; // Globalie mainigie int main() { int ADC_rezultats; DDRB=0x07; // B porta jaunakie tris biti jeb PB0,PB1 un PB2 tiek iestatiti uz izeju --> LCD vadibaiDDRD=0xff; // Viss D ports ka izeja --> LCD datiem LCD_inicializacija(); // Tiek veikta LCD inicializesana ADC_inicializacija(); // Tiek veikta ADC inicializesana _delay_ms(100); // Aizture 100 ms LCD_teksta_izvade(" V",2,9); // Funkcija teksta izvadei uz LCD, kur tiek padots teksts un koordinatas attelojumam uz ekrana LCD_teksta_izvade("Spriegums",1,4); // Funkcija teksta izvadei uz LCD, kur tiek padots teksts un koordinatas attelojumam uz ekrana while(1) { ADC_rezultats = nolasa_ADC(); _delay_ms(20); LCD_datu_izvade(ADC_rezultats); // Izvada uz LCD LCD_cmd(0x80|0x45); _delay_ms(10); } return 0; } void ADC_inicializacija() { ADMUX=(1<<REFS0); // Iestata atbalsta sprieguma vertibu (Vcc jeb +5 V) ADCSRA=(1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); // Iespejo ADC izmantosanu// Atlauj ADC ar frekvences dalitaju128 } /* ADC takts frekvence = 16000000/128 = 125000 =125KHz */ void LCD_inicializacija() { _delay_ms(100); LCD_cmd(0x30); // LCD tiek izmantots 8 bitu rezima // Tiek inicializets _delay_ms(10); LCD_cmd(0x30); _delay_ms(200); LCD_cmd(0x30); _delay_ms(200); LCD_cmd(0x38); // Izvelas 8 bitu rezimu _delay_ms(50); LCD_cmd(0x08); // Izsledz LCD _delay_ms(80); LCD_cmd(0x08); // Izsledz LCD _delay_ms(50); LCD_cmd(0x01); // Tiek notirits LCD _delay_ms(5); LCD_cmd(0x06); // Entry mode _delay_ms(80); LCD_cmd(0x0C); // Iesledz displeju _delay_ms(80); LCD_cmd(0x80); // 8 norada uz pirmo liniju, bet 0 uz pirmo poziciju (nulles pozicija) --> 0x80 _delay_ms(50); } void Izsledz_LCD() { LCD_cmd(0x01); // Tiek notirits LCD _delay_ms(1); LCD_cmd(0x08); // Izsledz LCD _delay_ms(1); } void LCD_cmd(unsigned char cmd) { LCD_datu_ports = cmd; LCD_vadiba = (0<<rs)|(0<<rw)|(1<<en); _delay_ms(1); LCD_vadiba = (0<<rs)|(0<<rw)|(0<<en); _delay_ms(50); } void LCD_izvade(unsigned char dati) { LCD_datu_ports = dati; LCD_vadiba = (1<<rs)|(0<<rw)|(1<<en); _delay_ms(1); LCD_vadiba = (1<<rs)|(0<<rw)|(0<<en); _delay_ms(50); } void LCD_teksta_izvade(unsigned char *str,int index, int pozicija)// Saglaba un izvada tekstu { int i=0; if(index == 2) { LCD_cmd((0x80+pozicija)|0x40); _delay_ms(1); // Ja indekss bus 2, tad LCD sapratis, ka jaizvada lietotaja izveidots simbols } if(index == 1) { LCD_cmd(0x80+pozicija); // 8 norada uz pirmo liniju, bet 0 uz pirmo poziciju (nulles pozicija) --> 0x80 _delay_ms(1); } while(str[i] != '\0') // Dati tiek izvaditi tik ilgi, kamer nonak pie masiva beigam, kuras nosaka ar '\0' { LCD_izvade(str[i]); // Datu izvade uz LCD, izmantojot WHILE ciklu i++; } } void LCD_datu_izvade(int ADC_vertiba) { int Uie, Uiz, R1=100,R2=1, dalitajs; LCD_cmd(0x80|0x40|6); if(ADC_vertiba<205 && ADC_vertiba>190) { dalitajs=204; } else if(ADC_vertiba<190 && ADC_vertiba>180) { dalitajs=203; } else if(ADC_vertiba<180 && ADC_vertiba>170) { dalitajs=203; } else if(ADC_vertiba<170 && ADC_vertiba>150) { dalitajs=203; } else if(ADC_vertiba<150 && ADC_vertiba>50) { dalitajs=202; } else { dalitajs=202; } Uiz=ADC_vertiba; Uie=(Uiz*R1+Uiz*R2)/(R2*dalitajs); // Aprekina nolasito spriegumu _delay_ms(1); vieni = (Uie%10); desmiti = (Uie/10)%10; simti = (Uie/100)%10; // Pareizai attelosanai uz LCD vieni = vieni + 0x30; desmiti = desmiti + 0x30; simti = simti + 0x30; ; LCD_izvade(simti); Uie++; LCD_izvade(desmiti); Uie++; LCD_izvade(vieni); Uie++; LCD_cmd(0x40); // Adrese datu saglabasanai } int nolasa_ADC() { ADMUX|=0x00; // Tiek izvelets 0.kanals ADCSRA|=(1<<ADSC); _delay_ms(1); while(!(ADCSRA&(1<<ADSC))); // Gaida, kamer pabeidz konvertesanu ADCSRA|=(1<<ADIF); return ADCW; // Tiek atgriezta ADC vertiba }