Mengukur tegangan dan menampilkan hasil pengukuran pada LCD nama kerennya (DIGITAL VOLT METER) adalah hal yang mudah, apalagi dengan CodeVisionAVR , semuanya jadi lebih mudah. Sebagai contoh, kita akan membuat program yang bisa mengukur tegangan antara 0 – 5V dengan ketelitian tegangan yang dapat diukur sebesar 0.00488V atau 4.88mV. Dalam aplikasi ini kita akan menggunakan ADC internal AVR dengan resolusi maksimal 10bit dengan data mulai dari 0 – 1023 atau 2n-1 dan jumlah total data 1024. Untuk menentukan ketelitian yang akan diperoleh sangat mudah, yaitu dengan membagi nilai tegangan referensi dengan resolusi ADC. Misal tegangan referensi yang kita pakai adalah AVCC yang bernilai 5V maka akan didapatkan resolusi sebesar 0.00488V yang didapat dari 5/1024 = 0.00488V atau 4.88mV. Contoh disini diasumsikan bahwa tegangan AVCC adalah bernilai pas 5V.

Simulasi Proteus (Volt Meter)

Untuk aplikasi riil dengan kepresisian tinggi disarankan untuk melakukan trim tegangan dengan pembagi tegangan yang menggunakan multiturn VR dan buffer DC dan gunakan referensi pada Vref bukan AVCC . Akan tetapi kalau hanya sekedar ingin mengetahui nilai tegangan tanpa kepresisian tinggi, referensi pada AVCC sudah cukup. Dan bila diinginkan mengukur tegangan dengan level yang lebih tinggi, bisa digunakan pembagi tegangan seperti pada voltmeter digital dan tentu saja jangan lupa saklar bwt select range dan lagi.. jangan lupa modifikasi programnya hehe :). Wokey let’s check it out :D

#include <mega8535.h>
#include <delay.h>
#include <stdio.h>
 
// Alphanumeric LCD Module functions
#asm
   .equ __lcd_port=0x18 ;PORTB
#endasm
#include <lcd.h>

Seperti code diatas, tentukan dulu library yang mo dipake.. berhugung kita akan menggunakan LCD, delay dan fungsi sprintf jadi kita include librarinya masing2. Jangan lupa sesuaikan port yang akan digunakan untuk LCD.

#define ADC_VREF_TYPE 0x40 //AVCC

Yang tak kalah pentingnya adalah menentukan referensi untuk ADC. Dalam program ini ane gunakan referensi AVCC.

unsigned char buffer[16]; //Untuk buffer sprintf
float tegangan; //Untuk data perhitungan tegangan (float)
unsigned int temporary; //Untuk temporary data ADC (komparasi)

code diatas berfungsi untuk menentukan variable global yang akan digunakan.. buffer berfungsi untuk buffer sprintf. Berhubung sprintf disini akan digunakan dalam formating LCD jadi cukup dah arraynya cuman 16 char. Sedangkan untuk variabel tegangan berfungsi untuk menampung perhitungan hasil bagi dari (data ADC*(referensi/1024)/1000) tipe datanya adalah float biar presisi hasil pembacaanya :D. nah kalo variabel temporary berfungsi cuman untuk pembanding data ADC yang sebelumnya tersimpan dan data ADC terbaca (bwt update aja biar gk terus kerja LCDnya).

void sett_regs(void); //Fungsi untuk setting register di awal proses
unsigned int read_adc(unsigned char adc_input);//Fungsi baca ADC

code yang tertulis persis diatas tulisan ini adalah cuman untuk function prototype dan digunakan bila fungsi main mau diletakkan dimana saja… termasuk diatas fungsi tersebut.

// Routine baca ADC
unsigned int read_adc(unsigned char adc_input){
ADMUX=adc_input | (ADC_VREF_TYPE &amp; 0xff);
// Delay needed for the stabilization of the ADC input voltage
delay_us(10);
// Start the AD conversion
ADCSRA|=0x40;
// Wait for the AD conversion to complete
while ((ADCSRA &amp; 0x10)==0);
ADCSRA|=0x10;
return ADCW;
}

Fungsi diatas digunakan untuk pengambilan data ADC. Bila dipanggil akan mengembalikan nilai berupa data ADC terbaru dengan tipe unsigned int.

// Function for setting register
void sett_regs(void){
// Port a initialization
PORTA=0x00;DDRA=0x00;
// Port b initialization
PORTB=0x00;DDRB=0x00;
// Port c initialization
PORTC=0x00;DDRC=0x00;
// Port D initialization
PORTD=0x00;DDRD=0x00;
// ADC initialization
// ADC Clock frequency: 1000.000 kHz
// ADC Voltage Reference: AVCC pin
// ADC Auto Trigger Source: Free Running
ADMUX=ADC_VREF_TYPE &amp; 0xff;
ADCSRA=0xA2;
SFIOR&amp;=0x1F;
 
// LCD module initialization
lcd_init(16);
 
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x00;
ACSR=0x80;
SFIOR=0x00;
 
// Watchdog Timer initialization
// Watchdog Timer Prescaler: OSC/2048k
#pragma optsize-
WDTCR=0x1F;
WDTCR=0x0F;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
}

Fungsi diatas untuk inisialisasi register port maupun SFR. Silahkan baca sendiri ada keterangannya disamping atau diatas baris code.

// Main function
void main(void){
//--------------- Setting IO and peripheral at startup!
sett_regs();
_lcd_ready();
//--------------- Time for going CRAZY (looping forever)..
for(;;){ //mainloop looping forever until ERROR/POWER SHUTDOWN/RST/WDT ACTIVE
    #asm("wdr") //kick your DOG before timeout! hwahwa... :D
    if (temporary != read_adc(0)){
        tegangan = (read_adc(0)*4.8828125)/1000;
        lcd_gotoxy(0,0);
        lcd_putsf("WWW.NUBIELAB.COM");//Don't forget to visit :)
        lcd_gotoxy(0,1);
        sprintf(buffer,"TEGANGAN: %0.2fV",tegangan);
        lcd_puts(buffer);
        temporary = read_adc(0);
        delay_ms(100);
        }
    #asm("nop")
    };
}

Fungsi yang paling penting dalam C yaitu main() dalam fungsi ini terdapat kode yang berfungsi untuk pengolahan data ADC sampai dengan formatting character untuk ditampilkan di LCD. Pengambilan dan penulisan data tegangan tidak dilakukan secara terus menerus.. tapi menunggu perubahan nilai dulu. Kasihan kalo LCDnya dipenetrasi terus – menerus haha.. OK, berikut adalah listing program komplitnya:

/*__ ___        __  __ ___  ___ ___  ___ _  _
|_ _|     ___ |  /  |_ _|/ __| _ / _  | | - eMBEDDED Design &amp;
 | || |) ||___|| |/| || |  (__|   / (_)| .` | - System Development
|___|___/      |_|  |_|___|___|_|_\___/_|_|______________________+
 
;Homepage   : http://www.nubielab.com
;Email      : herlambang@nubielab.com
;Code by    : Herlambang Aribowo.
------------
input tegangan dihubungkan ke PINA.0 atau ADC 0
dalam aplikasi real, mungkin diperlukan buffer dan bisa dibuat dari
opamp single supply misal LM358. Jangan lupa kalo mo dibuat beneran, PIN AVCC
dan VREF ADC dihubungkan ke tegangan 5V yg stabil.
Atmega16 X-tall 4Mhz
;*/
#include
#include
#include
 
// Alphanumeric LCD Module functions
#asm
   .equ __lcd_port=0x18 ;PORTB
#endasm
#include
 
//#define ADC_VREF_TYPE 0xC0 //Internal
//#define ADC_VREF_TYPE 0x00 //AREF
#define ADC_VREF_TYPE 0x40 //AVCC
 
unsigned char buffer[16]; //Untuk buffer sprintf
float tegangan; //Untuk data perhitungan tegangan (float)
unsigned int temporary; //Untuk temporary data ADC (komparasi)
 
void sett_regs(void); //Fungsi untuk setting register di awal proses
unsigned int read_adc(unsigned char adc_input);//Fungsi baca ADC
 
// Main function
void main(void){
//--------------- Setting IO and peripheral at startup!
sett_regs();
_lcd_ready();
//--------------- Time for going CRAZY (looping forever)..
for(;;){ //mainloop looping forever until ERROR/POWER SHUTDOWN/RST/WDT ACTIVE
    #asm("wdr") //kick your DOG before timeout! hwahwa... :D
    if (temporary != read_adc(0)){
        tegangan = (read_adc(0)*4.8828125)/1000;
        lcd_gotoxy(0,0);
        lcd_putsf("WWW.NUBIELAB.COM");//Don't forget to visit :)
        lcd_gotoxy(0,1);
        sprintf(buffer,"TEGANGAN: %0.2fV",tegangan);
        lcd_puts(buffer);
        temporary = read_adc(0);
        delay_ms(100);
        }
    #asm("nop")
    };
}
 
// Function for setting register
void sett_regs(void){
// Port a initialization
PORTA=0x00;DDRA=0x00;
// Port b initialization
PORTB=0x00;DDRB=0x00;
// Port c initialization
PORTC=0x00;DDRC=0x00;
// Port D initialization
PORTD=0x00;DDRD=0x00;
// ADC initialization
// ADC Clock frequency: 1000.000 kHz
// ADC Voltage Reference: AVCC pin
// ADC Auto Trigger Source: Free Running
ADMUX=ADC_VREF_TYPE &amp; 0xff;
ADCSRA=0xA2;
SFIOR&amp;=0x1F;
 
// LCD module initialization
lcd_init(16);
 
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x00;
ACSR=0x80;
SFIOR=0x00;
 
// Watchdog Timer initialization
// Watchdog Timer Prescaler: OSC/2048k
#pragma optsize-
WDTCR=0x1F;
WDTCR=0x0F;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
}
 
// Routine baca ADC
unsigned int read_adc(unsigned char adc_input){
ADMUX=adc_input | (ADC_VREF_TYPE &amp; 0xff);
// Delay needed for the stabilization of the ADC input voltage
delay_us(10);
// Start the AD conversion
ADCSRA|=0x40;
// Wait for the AD conversion to complete
while ((ADCSRA &amp; 0x10)==0);
ADCSRA|=0x10;
return ADCW;
}

Oke let’s check it outnya sudah selesai.. haha kalo bingung ato mungkin ada pertanyaan silahkan posting di kolom komentar.. tengkiyu.
Ditunggu komengnya, awas kalo gk komeng :(
Download program komplit pake telor sama simulasi proteusnya disini

Sudah ane update bro.. silahkan didownload :D. O iya, schematics dalam simulasi proteus tidak mewakili konfigurasi schematics asli bila ingin dibuat secara real. Proteus ane gunakan sebagai sarana simulasi aja.. santai, tinggal modif dikit ja :D

Herlambang Aribowo