• AVR Freaks

Hot!ADC Vref - Purpose?

Author
Hydrogen1
New Member
  • Total Posts : 3
  • Reward points : 0
  • Joined: 2008/02/26 16:09:14
  • Location: Washington, DC
  • Status: offline
2008/02/26 17:09:17 (permalink)
0

ADC Vref - Purpose?

Greetings... I'm trying to setup a LM35 temp sensor on a PIC16F819 using the built-in ADC. I plan to use a 2.048V reference voltage on the Vref+ PIC pin, as the ADC is 10bit.
 
The LM35 outputs 10mV/degC, which at my setup yields 2mV/step or 5steps/degC.  This should give me a resolution of 1/5 of one degree.  This output voltage is accurate straight off the LM35 output pin starting with 0deg = 0mV.  As I plan to use it for an ambient air temp sensor, I would like to get full range output (-55 to +150 deg C) to be able to read below freezing temps.  National Semiconductor recommends a setup for this which has a Vout+ and Vout-.  I'm not sure how to interface this to my PIC. 
 
My initial though it to run Vout+ to my AN0/analog in pin, and the Vout- to the Vref- pin.  I would still supply 2.048V to Vref+.
 
I don't fully understand the concept of why there is a minus Vref-, as well as how this LM35 Vout+/- setup gives a full range.  The LM35 setup uses two diodes in series on the ground after the Vout-, and an 18kOhm resistor to ground on the output after Vout+ is pulled off. LM35 datasheet  I'm guessing its some sort of offset that allows Vout+ to dip below Vout- to signify negative numbers.  This is Figure 7 on page 7 of the LM35 datasheet: http://www.national.com/ds/LM/LM35.pdf
 
1. Can someone please explain how to setup an ADC using this Vref + & -?
2. Can someone please explain how this LM35 setup yields a full -55 to +150 degC? 
 
 
This is my first post on my first PIC project, so please let me know if I should modify my posting style.
Thanks!
 

Attached Image(s)

#1

5 Replies Related Threads

    iabel
    Starting Member
    • Total Posts : 90
    • Reward points : 0
    • Joined: 2008/02/20 13:37:46
    • Location: Hungary
    • Status: offline
    RE: ADC Vref - Purpose? 2008/02/26 20:15:32 (permalink)
    0
    LM35 has a tipical otutput voltage of 1.5 V at 150 C and -0.55 V at -55C
    because -0.55V can't be sensed simply, there is the 2 rectifier, which will rise the sensor GND point with aprox. 2x0.6 V depending
    on rectifier type and temperature :-)
    Because the rectifiers are temperature dependant, the actual full range output can only be calculated as the voltage diference of
    the sensor output ( + ) and sensor GND (-) ( which is above MCU GND with approximately 1.2 V now ).

    So you will have to connect 2 AD input lines of the MCU to the two sensor lines, do AD on plus and do AD on minus sensor line, and subtract (-) from (+).

    Another issue is the Vref+ and Vref- of the MCU.
    These lines can be selected to be the lower and upper limit of the full AD range of the MCU.
    Depending on the rectifier selection, You may set Vref- to around ( 1.2 V - 0.55 V ), and Vref+ to (1.2V + 1.5 V ).
    You have to check rectifier voltage over the full temperature range before setting this Vref values.

    If you connect sensor GND (-) to the MCU Vref (-) then you may spare a subtract, but because of the temperature dependant behaviour of the rectifiers and the fixed value of Vref+ your AD result's resolution will change with temperature, and I guess it is not what you want.
    post edited by iabel - 2008/02/26 20:25:04
    #2
    Hydrogen1
    New Member
    • Total Posts : 3
    • Reward points : 0
    • Joined: 2008/02/26 16:09:14
    • Location: Washington, DC
    • Status: offline
    RE: ADC Vref - Purpose? 2008/02/27 17:27:29 (permalink)
    0
    Thank you, iabel.  Essentially I am shifting my voltages up with the rectifiers/diodes to eliminate the negative voltage sensing issue, right?
     
    Do you think I could get away with using only one diode?  As I am only going to be sensing ~-20 degC to +50 degC (-0.2V to 0.5V), adding one diode should allow for all positive readings (-0.2 + 0.6 = 0.4V margin) while still keeping my upper voltage (0.5 + 0.6 = 1.1V) below my Vref+ target of 2.048V.  I would then set Vref- to MCU GND to keep things nice and simple.
     
    Thanks again!
     
    NOTE: On the suggested diode 1N914 the max fwd voltage is 1.0V.  No min or typical is listed, but at +65C / 0.01mA the fwd voltage is listed at 0.325mV, still giving me a positive Vout- (-0.2 + 0.325 = 0.125V). 
     
     
     
    #3
    iabel
    Starting Member
    • Total Posts : 90
    • Reward points : 0
    • Joined: 2008/02/20 13:37:46
    • Location: Hungary
    • Status: offline
    RE: ADC Vref - Purpose? 2008/02/28 17:27:15 (permalink)
    0
    Essentially I am shifting my voltages up with the diodes to eliminate the negative voltage sensing issue, right?

    right :-)
    Do you think I could get away with using only one diode ?
    As I am only going to be sensing ~-20 degC to +50 degC (-0.2V to 0.5V), adding one diode should allow for all positive readings (-0.2 + 0.6 = 0.4V margin) while still keeping my upper voltage (0.5 + 0.6 = 1.1V) below my Vref+ target of 2.048V.  I would then set Vref- to MCU GND to keep things nice and simple.


    I'm not shure about it. The output of the sensor is also pulled down with a resistor, maybe there is something inside,
    what needs this room.

    To find the forvard voltage: You may want to buy such a diode, and measure the forward voltage at the sensor's supply
    current. I think diode selection is not critical, any silicon PN junction diode will do, but use that what You measure.
    The 0.6 V was a common approximation for common silicium diodes around 1 mA current around room temperature.

    If You like simulation, You may want to simulate just the diode with Spice or Pspice or similar.
    If You like calculation: the diode If curent and Uf forward voltage for a given diode is approx:
    If=I0*(exp(Uf/Ut) - 1). If you know a given If - Uf pair, then You may calculate Uf for another point.
    The Ut is approx. 26 mV for room temperature ( 25C ) and is 1:1 related to absolute temperature ( in Kelvin ): Ut2=Ut1*(T2/T1)
    The philips 1N914 datasheet has graphs about Uf/If at 25C.

    I think the simplest and best way is to measure :-)

    the max fwd voltage is 1.0V

    O.K. but in this case you don't need this parameter.

    If I wouldn't need 150C sensing just 50C then my choice would be leaving the 2 diodes in the cicruit, and the 100C drop in sensor output voltage would bring down the upper limit below Your 2.048 V, and leaving 2 x diode forward voltage room to the sensor
    in the case it needs it ( I don't know what's inside ).
    post edited by iabel - 2008/02/28 17:33:29
    #4
    tunelabguy
    Super Member
    • Total Posts : 1713
    • Reward points : 0
    • Joined: 2005/04/03 08:30:19
    • Location: Hopkins, MN USA
    • Status: offline
    RE: ADC Vref - Purpose? 2008/03/03 09:21:44 (permalink)
    0
    The output of the LM35 will never go lower than the voltage that is pulling it down through the load resistor on Vout, no matter how low the temperature goes. The two diodes shown in the circuit diagram provide the equivalent of a negative power supply, as seen from the perspective of the return pin on the LM35. This allows the output of the LM35 to go lower than the return pin.

    It was never intended that the exact forward drop of the two 1N914 diodes should figure in the precise calculation of temperature. They are just providing an effective negative power supply to the LM35. The reason that the diagram shows both Vout (+) and (-) is that you are supposed to measure the differential voltage between Vout (+) and (-). Do not assume that Vout (-) is exactly two diode drops above ground. Account for the variability of the diode drops by measuring the differential voltage rather than just Vout (+).

    The A/D converter in the PIC does not have a differential input mode as some other A/Ds do. But you can accomplish the same thing by reading both Vout(+) and Vout(-) on two separate A/D channels and subtracting the two readings in software. That will be much more accurate than trying to temperature-compensate the forward drop of the 1N914 diodes. Connect Vref+ to +2.048 and Vref- to ground, and use two A/D pins to measure Vout(+) and Vout(-). Vref(+) and Vref(-) just establish the voltages where the the A/D will read 0x3ff and 0x000.

    Maybe you should use only one diode. The reason is that you want to read 150 degrees C. That corresponds to Vout(+) being 1.5v. higher than Vout(-). But Vout(-) is already offset from ground. If you add two diode drops onto the 1.5 volt output, that will make Vout(+) equal to 2.7 volts with respect to ground. But if your Vref = 2.048, then 2.7v will be outside the range of what the A/D can read. If you used just one diode, then 150 degrees C would correspond to 2.1v, which is only a little above 2.048. You still couldn't read 150 degrees C, but you could come closer. Another solution is to get a higher reference, like 2.900 volts for Vref. I don't know what standard values are available, but you would want a reference that is higher than 2.7 and still low enough to give you the needed resolution.

    Here is an approach that allows you to keep your 2.048 reference and still read the entire temperature range. Connect the return pin on the LM35 (the top of the two diodes) to an I/O pin on your PIC. Normally you configure this I/O pin as an input so that it has no effect. But when you read Vout(+) and find it near the to of the range (above, say, 1000 out of 1023 counts), then you could re-configure that I/O pin as an output driven to logic low. That would short out the diodes and bring both Vout(+) and Vout(-) down by about 1.2 volts, putting them both in the range of your A/D. Conversely, if you read Vout(+) and find it dangerously close to 0, then re-configure the I/O pin as an input and allow the two diodes back into action. Then read again. The temperature changes slowly enough that you can afford these retries.

    Robert Scott
    Real-Time Specialties
    post edited by tunelabguy - 2008/03/03 09:33:09
    #5
    chernandezg
    New Member
    • Total Posts : 1
    • Reward points : 0
    • Joined: 2019/07/10 08:21:31
    • Location: 0
    • Status: offline
    Re: RE: ADC Vref - Purpose? 2019/07/10 12:48:42 (permalink)
    0
    Greetings ... I am trying to set up an LM35 temperature sensor on a PIC16F819 using the built-in ADC. I plan to use a reference voltage of 2048 V on the Vref + PIC pin, since the ADC is 10 bits. I am trying that when it is in -1 ° C to -55 ° C turn on a led in the portB.0, when 0 ° C to 2 ° C turn on another led in the portB.1 and turn off the LED of the PORTB.0 and that when it is between 25 ° C to 45 ° C light an LED on the PORTB.2 and turn off the PORTB.0 and the PORTB.1. I provide what I have from the code if someone can help me to make it work. regards.
     
    #pragma config FOSC = INTOSCIO // Oscillator Selection bits (INTRC oscillator; port I/O function on both RA6/OSC2/CLKO pin and RA7/OSC1/CLKI pin)
    #pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
    #pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
    #pragma config MCLRE = ON // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is MCLR)
    #pragma config BOREN = OFF // Brown-out Reset Enable bit (BOR disabled)
    #pragma config LVP = ON // Low-Voltage Programming Enable bit (RB3/PGM pin has PGM function, Low-Voltage Programming enabled)
    #pragma config CPD = OFF // Data EE Memory Code Protection bit (Code protection off)
    #pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off)
    #pragma config CCPMX = RB2 // CCP1 Pin Selection bit (CCP1 function on RB2)
    #pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
    //******************************************************************************
    // Includes.
    //******************************************************************************
    #include <xc.h>
    //******************************************************************************
    // Variables
    //******************************************************************************
    unsigned int adcRead (void);
    void adcInit(void);
    char bufEntero[5]; // Almacena la parte enterala temperatura.

    //******************************************************************************
    // Main code
    //******************************************************************************
    void main (void)
    {
    unsigned int Radc = 0;
    char tempEntero = 0;
    char tempdecimal = 0;
    float temperatura;

    char bufDecimal[3]; // Almacena la parte decimal de temperatura.
    TRISAbits.TRISA0 = 1; // Configura AN0 como entrada.
    TRISAbits.TRISA1 = 1; // Configura AN1 comoo entrada.
    ADCON0bits.CHS = 0b000; // Utilizar AN0 como fuente Anáalogica.
    ADCON0bits.CHS = 0b001; // Utilizar AN0 como fuente Análogica.
    TRISB = 0x00; // Configurar el puerto B como salidas.
    ADRESH = ADRESL = 0; // Registros que resibiran el valor de la conversión.

    //**************************************************************************
    //Pic Starts here
    //**************************************************************************

    OSCCONbits.IRCF = 0b000; // Correr a 31.25 KHz.

    //**************************************************************************
    //Configurar el ADC
    //**************************************************************************

    ADCON0bits.ADCS = 0b11; // Usar el oscilador interno rc de ADC.
    ADCON0bits.ADON = 1, // Enciende el modulo.
    ADCON1bits.PCFG = 0b1100; // Use AN0 y AN1 como entrada, VDD y VSS como ref.
    ADCON1bits.ADFM = 1; // Derecho justificado para resultado de 10 bits.
    ADCON1bits.ADCS2 = 0; // División de reloj normal.

    //**************************************************************************
    // Nuestro bucle principal
    //**************************************************************************

    while(1)
    {
    Radc = adcRead();
    temperatura = Radc * .244; // Resultado de 2.5V * Radc/10.23.
    tempEntero = (int) temperatura; // Obteniendo la parte entera.
    temperatura = temperatura - (float) tempEntero; // Obteniendo la parte decimal con dos digitos.
    temperatura *= 100;
    tempdecimal (int) temperatura;
    _delay_ms(500);
    }
    return;
    }
    void adcInit(void)
    {
    ADCON1bits.PCFG = 0b1100;
    }
    unsigned int adcRead(void)
    {
    int temp1 = 0;
    int temp2 = 0;
    int valorADC = 0;
    ADCON1bits.PCFG = 0b1100;

    _delay_us(30);

    ADCON0bits.GO = 1; // Hacer una lectura ADC
    while(ADCON0bits.GO == 1); // Esperar hasta que el ADC haya terminado.
    temp1 = (ADRESH << 8) + ADRESL;

    ADCON1bits.PCFG = 0b1100;
    _delay_us(30);

    ADCON0bits.GO = 1;
    while (ADCON0bits.GO);
    temp2 = (ADRESH << 8) + ADRESL;

    if (temp1 > temp2)
    {
    valorADC = temp1 - temp2;
    bufEntero[0] = '+';

    }
    else
    {
    valorADC = temp2 - temp1;
    bufEntero[0] = '-';
    }
    return valorADC;

    if(temperatura = -1 && temperatura <= -55)
    {
    PORTBbits.RB0 = 1;
    PORTBbits.RB1 = 0;
    PORTBbits.RB2 = 0;
    _delay_ms(500);
    }

    if (temperatura >= 0 && temperatura <=5)
    {
    PORTBbits.RB0 = 0;
    PORTBbits.RB1 = 1;
    PORTBbits.RB2 = 0;
    _delay_ms(500);
    }

    if (temperatura >= 20 && temperatura <=35)
    {
    PORTBbits.RB0 = 0;
    PORTBbits.RB1 = 0;
    PORTBbits.RB2 = 1;
    }
    }
    #6
    Jump to:
    © 2019 APG vNext Commercial Version 4.5