A good setting of a reference voltage can be considered a must where precision is an important matter. 90% of projects are based assuming the VDD (microcontroller 5V power supply) as voltage reference but when the voltages to be compared are very small or the precision is a critical factor, very probably, it is better to reduce the value of this reference.
Synthesizing, we can reduce the different possibilities to obtain a reference supply voltage to the following:
- using the 5V regulated power supply voltage, normally obtained by the use of a positive voltage regulator (7805 precision 4%, according to datasheets)
- using dedicated components as micropower voltage reference diodes, as the LM385 for instance (a 1.235V or 2.5V zener diode, 1% precision).
The first solution is quite common where absolute precision is not a critical factor, the second regards components not easy to find and sometimes a little difficult to manage because of the calculation of the conversion procedure (normally an 8 bit microcontroller divides the reference voltage in 1024 steps because of the 10bit adc).
A really economical and easy solution can be found using a normal multiturns trimmer. In this example we'll show the value in degrees of the temperature using an LM35, a precision centigrade temperature sensor (LM34 for farheneit temperatures) according to the following schematic using a 16F877 (reading the datasheet of the microcontroller, we'll discover that the minimum level of Vref+ is around 2.5V).
As we know, according to the datasheet of the component, the LM35 provides a voltage of 10mV every centigrade of temperature; this means only 1V at 100°c therefore the value of the vdd voltage, as reference, can be considered too high for our needs.
|
Here, on the left, a quick schematic regarding a traditional configuration for an ADC conversion. We have a LM35 sensor connected to RA2 and a multiturns trimmer connected to RA3. We have to turn the trimmer until to read, using a good tester, the value of 2,5V on the pin RA3, the pin we are going to use as voltage reference pin. According to previous articles we should already know how to set correctly the registers but we'll pay again a look to theyr settings. |
![]() |
ADCON0 will be set as:
ADCON0 = 0b01010000 =0x90 |
|
ADCON1 will be set as:
ADCON1 = 0b10000001 = 0x81 At this point we can start to write our program (we are using C but the code, with small modifications, can be used with any other language) |
Ff the Vref+ has been set to 2.5V mV the conversion is: ADC_read_value = 2500/1024 = 2,441 (mV/step).
The LM35 provides 10mv/degree therefore the conversion will be very simply: ADC_read value * (2,441*1000 to avoid float point math) /1000*10(mV/degree).
Let's start. To check the validity of the results it is suggested to replace, initially, the LM35 temperature sensor with a trimmer connected to the 5V power supply simulating a temperature value.
/-------------------------------- LCD connections, could be different
sbit LCD_RS at RB4_bit;
sbit LCD_EN at RB5_bit;
sbit LCD_D4 at RB3_bit;
sbit LCD_D5 at RB2_bit;
sbit LCD_D6 at RB1_bit;
sbit LCD_D7 at RB0_bit;
sbit LCD_RS_Direction at TRISB4_bit;
sbit LCD_EN_Direction at TRISB5_bit;
sbit LCD_D4_Direction at TRISB3_bit;
sbit LCD_D5_Direction at TRISB2_bit;
sbit LCD_D6_Direction at TRISB1_bit;
sbit LCD_D7_Direction at TRISB0_bit;
unsigned int adc_value;
long temp;
char value [15];
char *degs = "00.00";
void main()
{
ADCON0 = 0b01010000; // Fosc/32, RA2 input
ADCON1 = 0b10000001; // Ra3 = Vref, all analog = 2.5V
TRISB = 0x00; // PORTB All Outputs
TRISA = 0xFF; // PORTA All Inputs
Lcd_Init();
Lcd_Cmd(_LCD_CLEAR);
Lcd_Cmd(_LCD_CURSOR_OFF);
do
{
adc_value = ADC_Read(2); // channel2 (RA2)
temp = ((long)adc_value*2441)/100; // 2.5V/1023 = (adc* 2,443 * 1000)/100 (10mV *°C)
LongToStr(temp,value); // display value 'brutely'
lcd_out(1,1,"Temp.:");
lcd_out(2,5,value);
degs[0] = temp/1000 + 48; // display formatted value in degrees
degs[1] = (temp/100)%10 + 48;
degs[3] = (temp/10)%10 + 48;
degs[4] = (temp)%10 + 48;
Lcd_Out (3,12,degs);
delay_ms(300);
} while (1);
}