Problems with Microcontroller Projects? You may face many Problems, but do not worry we are ready to solve your Problems. All you need to do is just leave your Comments. We will assure you that you will find a solution to your project along with future tips. On Request we will Mail you the Codes for Registered Members of this site only, at free service...Follow Me.

0-20V Digital Voltmeter (DVM) using PIC12F683

After finishing the serial LCD project, it is time to do some cool projects using PIC12F683. Now we can have a nice LCD display with PIC12F683. This project shows how to make a digital voltmeter of range 0-20V using PIC12F683. Enjoy!



Background
You cannot feed 20V  directly to a PIC I/O pin, you need a resistor divider network that converts 0-20V range into 0-5V. The figure below shows how it will be achieved.
At any instant, the voltage Va will be 1/4th of the input voltage, Vin. So, for maximum input voltage of 20V, the Va will be 5V. A 5.1V Zener diode in the figure is to prevent Va to rise above 5.1V if the input voltage goes much above 20V. This will protect the microcontroller port. The analog voltage Va is read through AN0 port and is converted to 10-bit digital number (0-1023) by PIC12F683.


ADC Math
     0-5V Analog I/P ---> 0-1023 Digital Count
=> Resolution = (5-0)/(1023-0) = 0.00489 V/Count
=> I/P voltage = 4*Va = 4* Digital Count * 0.00489 = 0.01956 * Digital Count

To avoid floating point, use I/P voltage = 196*Digital Count. This number is a long integer.
Example, suppose
Vin = 13.6V. Then,
Va = 0.25*Vin = 3.4V
=> Digital Count = 3.4/0.00489 = 695
=> Calculated I/P Voltage = 196*695 = 136220 = 13.6V  (First 3 digits of 6 digit product)

Sources of error
The above math looks pretty easy but when you implement it, you will not errors in output measurements  because the above calculations are based on following ideal conditions:

  • Vcc supply voltage to PIC12F683 is exactly 5V,
  • R1 and R2 are exact 1.3K and 3.9K respectively

So, let's revise the math above with real figures. I measured the supply voltage to PIC and it is 5.02V. R1 and R2 are measured to be 1267 and 3890 Ohms. So this gives,

     0 - 5.02 V Analog I/P ---> 0-1023 Digital Count
=> Resolution = (5.02-0)/(1023-0) = 0.004907 V/Count
Va = 1267*Vin/(1267+3890) = 0.2457*Vin
=> I/P voltage = 4.07*Va = 4.07* Digital Count * 0.004907 
                       = 0.01997 * Digital Count 
                       = 0.02*Digital Count (Approx.)

To avoid floating point, use I/P voltage = 2*Digital Count. No need for Long integer.
Example, suppose 
Vin = 4.6V. Then, 
Va = 0.2457*Vin = 1.13V
=> Digital Count = 1.13/0.004907 = 230
=> Calculated I/P Voltage = 2*230 = 0460 = 04.6V  (First 3 digits of 4 digit product)

Circuit Setup
Connect the Va terminal in the above resistor network to AN0 (GP0) input of PIC12F683. Also connect the serial LCD the same way as we did in our 3-wire serial LCD project. Just maintain the same setup for display as shown below.


Software

 /* Digital Voltmeter and
 3-wire Serial LCD using 74HC595
 Rajendra Bhatt, Oct 3, 2010
*/

sbit Data_Pin at GP5_bit;
sbit Clk_Pin at GP1_bit;
sbit Enable_Pin at GP2_bit;

// Always mention this definition statement
unsigned short Low_Nibble, High_Nibble, p, q,  Mask, N,t, RS, Flag, temp;

void Delay_50ms(){
 Delay_ms(50);
}

void Write_LCD_Nibble(unsigned short N){
 Enable_Pin = 0;
 // ****** Write RS *********
 Clk_Pin = 0;
 Data_Pin = RS;
 Clk_Pin = 1;
 Clk_Pin = 0;
 // ****** End RS Write

 // Shift in 4 bits
 Mask = 8;
  for (t=0; t<4; t++){
   Flag = N & Mask;
   if(Flag==0) Data_Pin = 0;
   else Data_Pin = 1;
   Clk_Pin = 1;
   Clk_Pin = 0;
   Mask = Mask >> 1;
  }
  // One more clock because SC and ST clks are tied
  Clk_Pin = 1;
  Clk_Pin = 0;
  Data_Pin = 0;
  Enable_Pin = 1;
  Enable_Pin = 0;
}
// ******* Write Nibble Ends

 void Write_LCD_Data(unsigned short D){
 RS = 1; // It is Data, not command
 Low_Nibble = D & 15;
 High_Nibble = D/16;
 Write_LCD_Nibble(High_Nibble);
 Write_LCD_Nibble(Low_Nibble);
 }

void Write_LCD_Cmd(unsigned short C){
 RS = 0; // It is command, not data
 Low_Nibble = C & 15;
 High_Nibble = C/16;
 Write_LCD_Nibble(High_Nibble);
 Write_LCD_Nibble(Low_Nibble);
}

void Initialize_LCD(){
 Delay_50ms();
 Write_LCD_Cmd(0x20); // Wake-Up Sequence
 Delay_50ms();
 Write_LCD_Cmd(0x20);
 Delay_50ms();
 Write_LCD_Cmd(0x20);
 Delay_50ms();
 Write_LCD_Cmd(0x28); // 4-bits, 2 lines, 5x7 font
 Delay_50ms();
 Write_LCD_Cmd(0x0C); // Display ON, No cursors
 Delay_50ms();
 Write_LCD_Cmd(0x06); // Entry mode- Auto-increment, No Display shifting
 Delay_50ms();
 Write_LCD_Cmd(0x01);
 Delay_50ms();
}

void Position_LCD(unsigned short x, unsigned short y){
 temp = 127 + y;
 if (x == 2) temp = temp + 64;
 Write_LCD_Cmd(temp);
}

void Write_LCD_Text(char *StrData){
 q = strlen(StrData);
 for (p = 0; p < q; p++){
  temp = StrData[p];
  Write_LCD_Data(temp);
 }

}

char Message1[] = "DVM Project";
unsigned int ADC_Value, DisplayVolt;
char *volt = "00.00";

void main() {
CMCON0 = 7;  // Disable Comparators
TRISIO = 0b00001001;  // All Outputs, except GP0 and GP3
ANSEL = 0x01; // GP0 analog i/p

Initialize_LCD();
Position_LCD(1,3);
Write_LCD_Text(Message1);
Position_LCD(2,10);
Write_LCD_Data('V');

do {

 ADC_Value = ADC_Read(0);
 DisplayVolt = ADC_Value * 2;

 volt[0] = DisplayVolt/1000 + 48;
 volt[1] = (DisplayVolt/100)%10 + 48;
 volt[3] = (DisplayVolt/10)%10 + 48;
 volt[4] = DisplayVolt%10 + 48;
 Position_LCD(2,4);
 Write_LCD_Text(volt);
 delay_ms(100);
} while(1);

}


Testing
I tested my DVM with my variable power supply and also verified with another digital multimeter.




I hope you liked this project.

I have another version of this project that uses PIC16F688 and no serial LCD driver. If you are interested, find here.

No comments:

Post a Comment

Related Posts Plugin for WordPress, Blogger...

Recent Comments

Popular Projects

Give Support

Give Support
Encourage Me through Comments

Microcontroller Projects

Total Pageviews