# A question on PIC based Volt Meter

Status
Not open for further replies.

#### swapan

##### Full Member level 4
Friends,

Surfing net I got a project on PIC based Volt Meter. The code is given as under. Going through the code I stopped at a point and seek your help please. What I got from the code is that, Input voltage is first scaled down to a factor. Then the scaled down voltage is digitized using ADC module. Then the ADC value is multiplied by 2. The resultant value is converted to ASCII and finally displayed using 2x16 LCD module.

I got the entire project except the multiplication by 2 factor. It is not clear why the ADC value is multiplied by 2. Though the matter has been detailed as "To avoid floating point, use I/P voltage = 2*Digital Count", still I could not get the idea.

Help in this regard is solicited please.

regards,

swapan

Code:
// LCD module connections

sbit LCD_RS at RC4_bit;

sbit LCD_EN at RC5_bit;

sbit LCD_D4 at RC0_bit;

sbit LCD_D5 at RC1_bit;

sbit LCD_D6 at RC2_bit;

sbit LCD_D7 at RC3_bit;

sbit LCD_RS_Direction at TRISC4_bit;

sbit LCD_EN_Direction at TRISC5_bit;

sbit LCD_D4_Direction at TRISC0_bit;

sbit LCD_D5_Direction at TRISC1_bit;

sbit LCD_D6_Direction at TRISC2_bit;

sbit LCD_D7_Direction at TRISC3_bit;

// End LCD module connections
char Message1[] = “DVM Project”;

char *volt = "00.0";
void main() {

ADCON0 = 0b00001000; // Analog channel select @ AN2

ADCON1 = 0x00;   // Reference voltage is Vdd

CMCON0 = 0x07 ; // Disable comparators

TRISC = 0b00000000; // PORTC All Outputs

TRISA = 0b00001100; // PORTA All Outputs, Except RA3 and RA2

Lcd_Init();        // Initialize LCD

Lcd_Cmd(_LCD_CLEAR);      // CLEAR display

Lcd_Cmd(_LCD_CURSOR_OFF); // Cursor off

Lcd_Out(1,1,Message1);

Lcd_Chr(2,10,'V');
do {

volt = DisplayVolt/1000 + 48;

volt = (DisplayVolt/100)%10 + 48;

volt = (DisplayVolt/10)%10 + 48;

Lcd_Out(2,5,volt);

delay_ms(500);   // Hold for 500 ms

} while(1);

This will be a factor of the electronics and what the PIC is using as a reference in this case if your supply is 5V then and input of 5V would generate a 10 bit digital value of 1023. Lets assume your input is a divider of 4 perhaps, then 10V input would be 2.5V to be converted by the A/D giving a digital value of 512, multiply by 2 to give 1024. Subsequent processing via the volt[] array will format the 1024 count to display 10.24. All very rough but with the right divider value this could be made to display 10.0 when the input is 10V.

I got the entire project except the multiplication by 2 factor. It is not clear why the ADC value is multiplied by 2. Though the matter has been detailed as "To avoid floating point, use I/P voltage = 2*Digital Count", still I could not get the idea.
The calculation in the project you are refering is simple. Since you understand all the calculation except the multiplication of 2. I will try to explain it. The input voltage is equal to
I/P voltage = 4.07*Va = 4.07* Digital Count * 0.004907
which is equal to 0.01997 * Digital Count
OR
I/P voltage = 0.02 * Digital Count. (0.01997 ~ 0.02)
Hope you understand to this point as you mentioned.

Now in coding we can either multiply 0.02 (a float value) with Digital Count (ADC value) and get the result in a float. and then display it. But this method of coding consume more processing time. OR we can use a more efficient method i.e. multiply the ADC value with 2 and place a decimel point after two digits. This method will bypass (avoid) the floating calculations.

The calculation in the project you are refering is simple. Since you understand all the calculation except the multiplication of 2. I will try to explain it. The input voltage is equal to
I/P voltage = 4.07*Va = 4.07* Digital Count * 0.004907
which is equal to 0.01997 * Digital Count
OR
I/P voltage = 0.02 * Digital Count. (0.01997 ~ 0.02)
Hope you understand to this point as you mentioned.

Now in coding we can either multiply 0.02 (a float value) with Digital Count (ADC value) and get the result in a float. and then display it. But this method of coding consume more processing time. OR we can use a more efficient method i.e. multiply the ADC value with 2 and place a decimel point after two digits. This method will bypass (avoid) the floating calculations.

Where did this 4.07 come from? Do you have a circuit diagram to refer to?

I think I must have missed a posting somewhere as your web reference hasn't appeared in this thread until now.

- - - Updated - - -

Why are you using 4.07 and not 4.

The voltage divider is

Vo=Vin*1.3/(1.3+3.9) ie Vin*0.25

Why are you using 4.07 and not 4.
The voltage divider is Vo=Vin*1.3/(1.3+3.9) ie Vin*0.25

Idealy you are right, but if you check the author website, you will find that the measured resistors were 1267 and 3890 Ohms.

Part of the problem is resistor values but also the reference based on the power supply is causing a problem, adjusting the code for resistor values or even using a pot would solve the resistor issues but the supply being used as the reference is just plain trouble. The reference should be a true reference perhaps something simple like a LM4040 would improve reliability of the design.

Thanks iukhan for your explanation in a very simple way. Being a newbie I have no conception that float value multiplication consumes more time in execution. meanwhile, I decided to multiply the ADC value by .02 and display the result as follows.

volt = (DisplayVolt / 10) % 10 + 48;
volt = DisplayVolt % 10 + 48;
volt = (DisplayVolt * 10) % 10 + 48;

Would it yield the same result as that of multiplying ADC value by 2 ? However, as such float value multiplication takes long time, this method will be discarded.

regards,

swapan

Thanks iukhan for your explanation in a very simple way. Being a newbie I have no conception that float value multiplication consumes more time in execution. meanwhile, I decided to multiply the ADC value by .02 and display the result as follows.

volt = (DisplayVolt / 10) % 10 + 48;
volt = DisplayVolt % 10 + 48;
volt = (DisplayVolt * 10) % 10 + 48;

Would it yield the same result as that of multiplying ADC value by 2 ?
No, you will get zero after decimal point. The reason is that DisplayVolt is an integer variable, The result of DisplayVolt x 0.02 will be integer.

Yes iukhan, the result will be integer. In that case could it be overcome by declaring DisplayVolt as float?

Yes iukhan, the result will be integer. In that case could it be overcome by declaring DisplayVolt as float?

You can declare DisplayVolt as float and get the desired result BUT you will also need cast as

volt = (int8)(DisplayVolt / 10) % 10 + 48;
volt = (int8)DisplayVolt % 10 + 48;
volt = (int8)(DisplayVolt * 10) % 10 + 48;

Status
Not open for further replies.