Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

c code for a2d

Status
Not open for further replies.

hitechbob

New Member
Hi everyone

I'm trying to write a c code to read a 0-20v input on a pic16F690 using MPLAB IDE
and display it on a LCD.

My code for the LCD works great, but when I read the analog input and display it I get the wrong result.

Can anyone give me the correct formula and the correct code.

Thanks
hitechbob
 
You're not reading 20v directly on the ADC input are you? 0 - Vcc on the pin (Vcc max is 5 volts). A simple voltage divider, A 10k resistor between the 20v and the ADC input then a 3.3k to ground will do the trick.. At 20v you'll have about 4.92v on the pin, digitally this should be around 1000 bits

Take two readings, add together and hey presto 2000 bits artificially stick in the decimal place and you have 20.00 volts

Cheers Ian
 
I'm only using 8-bit on the ADC. I read voltage, but my voltmeter does not red the same as my LCD. What formula should I ue to calculate the display voltage?
 
I'm only using 8-bit on the ADC. I read voltage, but my voltmeter does not red the same as my LCD. What formula should I ue to calculate the display voltage?

Neglecting the required voltage divider for a moment, the decimal value of the ADC reading will be integer(Vin*256/Vdd).

Suppose Vin = 3.000V and Vref=Vdd=5.100V, the ADC value returned will be integer((3.000*256/5.100) = int(150.588) = 150 = 0x96.

Suppose your ADC reading is 240 (0xF0). The input voltage corresponding to that would be (ADC*Vref)/256 = 240*5.100/256 = 4.78V

Note that you have to know what the ADC reference voltage is. If it changes, so will the ADC reading. Also note that in the 8 bit mode, the ADC can resolve a minimum change of Vref/256 ≈ 20mV.

The ADC input cannot go any higher than Vref (Vdd); that is why you must use a voltage divider.
 
Last edited:
Yes thanks I have my voltage devider in place.

Here is my code. If you can help me it would be great.

Thanks
hitechbob


#include <htc.h>
#include <stdio.h>
#include "lcd.h"
#include "pause.h"


void init(void){
// ADON=1; /* enable A2D converter */
ADIE=0; /* not interrupt driven */
ADCON1=0;
ADCON0=0x2B;
T1CON=0x31; // turn on timer 1
TMR1IE=1; // timer 1 is interrupt enabled
PEIE=1; // enable peripheral interrupts
GIE=1; // turn on interrupts
}

void interrupt isr(void){
if(TMR1IE && TMR1IF){
PORTB++;
TMR1IF=0;
}
}



void main(void){

unsigned char outString[20];
unsigned char String[20];
unsigned char advalue;

init();
lcd_init();

while(1){
GODONE=1;
while(GODONE)continue;
ADIF=0;
{
advalue = (ADRESH*5)/256;
lcd_goto(0);
sprintf(outString,"%d",ADRESH);
lcd_puts(outString);
lcd_goto(40);
sprintf(String,"Bat = %d.%d V",advalue);
lcd_puts(String);
pause(2);
}

}
}
 
Don't you need more resolution? with integer values you will have 1,2,3,4,5 (not very accurate ) Try these lines
Code:
advalue = (ADRESH*50)/64;
printf(String,"Bat = %d.%d V",advalue / 10 , advalue % 10);

Cheers Ian

This gives you 200 resolutions. 20.0 volts
 
Last edited:
You are (without knowing it) using fixed point arithmetic. Your advalue will contain 0 to 200 you are printing 20.0 therefore 200/10 = "20" and 200 modulus 10 yields the decimal place" .0".

Example advalue = 136 so: 136 / 10 = "13" and then the point "." and then the decimal 136 % 10 = "6"

Most people end up using fixed point arithmetic, as floating point does tend to use a lot of resources and processing power.
Cheers Ian
 
One more question.

How did you come up with the numbers in this formula?

(ADRESH*50)/64

Thanks
Bob
 
Last edited:
You need to display up to 20 volts right! ADRESH contains 0 to 255 so 20v on ADC input after the divider should be approx 5v or 255 bits Your original equation ((ADRESH * 5) / 256)
would yield just 5, you need 20 if you take ADRESH and multiply by 50 then / 255 this would yield 50 BUT as you need 200 and 50 is a 1/4 0f 200!!! 64 is a quarter of 255.. So I used 50 (to get 1 decimal place) and 64 (which is a quarter of 255) so the result would be (256 / 64) ie.. 4 x 50 = 200..

Is this too long winded?

Cheers Ian

Oh! and by the way I have a maths degree and sometimes go over board.
 
Last edited:
Status
Not open for further replies.

New Articles From Microcontroller Tips

Back
Top