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.

Interrupt Level ADC - Problems!

Status
Not open for further replies.
Hey there,

Nice to be back! Ok, so I'm making my homebrew room thermometer, which is actually made from some transistors, a LM335Z temp. sensor (10mV per Kelvin), a 2 7-seg display and a PIC18F1320.

The thing is the multiplexing works pretty well, but not for the A/D conversion. The numbers on the display is very freaky, and not displaying anything that made sense. (It ended up displaying 09 instead of a room temperature, which is approx. 26 degrees celcius!)

Both of the A/D and Multiplexing are in interrupts by the way.

Here's the code. By the way, I have included a hefty conversion from Kelvin to Celcius. I have made it right-justified, and placed all the interrupt vectors properly. What could I have been missing? :confused:

Code:
#pragma config OSC = HS
#pragma config PWRT = OFF, BOR = OFF
#pragma config WDT = OFF
#pragma config DEBUG = OFF, LVP = OFF, STVR = OFF, MCLRE = OFF
#include <P18F1320.h>

void T0_ISR(void);
void AD_ISR(void);

#pragma interrupt chk_isr
void chk_isr(void)
{
    if (INTCONbits.TMR0IF == 1)
    T0_ISR();
    if (PIR1bits.ADIF == 1)
    AD_ISR();

}

#pragma code HiPrioInt = 0x0008
void HiPrioInt(void)
{
    _asm
    GOTO chk_isr
    _endasm
}
#pragma code

char d0, d1, flag, L_byte, H_byte;
char temp;
unsigned int num;


char lookup[] = {    0x7e, 0x30, 0x6d, 0x79, 0x33,
                    0x5b, 0x5f, 0x70, 0x7f, 0x73 
                  };

void main(void)
{    

    TRISAbits.TRISA0 = 0; // First Digit (Most Significant)
    TRISAbits.TRISA1 = 0; // Last Digit (Least Significant)
    TRISAbits.TRISA2 = 0;

    TRISB = 0x0;
    PORTB = 0x00;

    PORTAbits.RA0 = 0;
    PORTAbits.RA1 = 0;

    TMR0H = 0xCF;
    TMR0L = 0x2C;
    
    T0CON = 0x08;    

    INTCONbits.TMR0IF = 0;
    INTCONbits.TMR0IE = 1;

    T0CONbits.TMR0ON = 1;

    ADCON0 = 0b00001001;
    ADCON1 = 0b01110011;
    ADCON2 = 0b10101101;

    PIR1bits.ADIF = 0;
    PIE1bits.ADIE = 1;

    INTCONbits.PEIE = 1;
    INTCONbits.GIE = 1;
    
    flag = 0;
    temp = 0;
//    d0 = 1;
//    d1 = 6;
    while(1)
    {
        ADCON0bits.GO = 1;
        num = 0.4762 * temp + 6.8042;
        d0 = num / 10;
        d1 = num % 10;
    }    
}

void T0_ISR(void)
{
    flag = ~flag;
    if (flag == 0)
    {
        PORTAbits.RA1 = 0;
        PORTB = lookup[d0];
        PORTAbits.RA0 = 1;
    }
    else
    {
        PORTAbits.RA0 = 0;
        PORTB = lookup[d1];
        PORTAbits.RA1 = 1;
    }

    TMR0H = 0xCF; // reload values into the TMR0H and TMR0L
    TMR0L = 0x2C;
    INTCONbits.TMR0IF=0;
}

void AD_ISR(void)
{
    L_byte = ADRESL;
    H_byte = ADRESH;
    L_byte >> 2;
    L_byte &= 0b00111111;
    H_byte <<= 6;
    H_byte &= 0b11000000;
    temp = L_byte | H_byte;
    PIR1bits.ADIF = 0;
}

Also, when I tested this LM335Z on a voltmeter, it's showing values around 2.80-2.88V when it is supposed to be warmer than that! I guess I should calibrate the sensor! :)
 

Nigel Goodwin

Super Moderator
Most Helpful Member
Why are you using interrupts for the ADC?, it's totally pointless (and can only mess things up), just read the ADC in your main loop, and leave the interrupts for the multiplexing.
 
Why are you using interrupts for the ADC?, it's totally pointless (and can only mess things up), just read the ADC in your main loop, and leave the interrupts for the multiplexing.

Oh, I see. I thought it could be convenient to reserve the main loop for other things like debouncing and stuff. :)

Apart from the multiplexing, is it also safe to use the USART functions in interrupt as well? :rolleyes:
 

Mr RB

Well-Known Member
Is this your kelvin to celcius conversion??? :eek:
Code:
        num = 0.4762 * temp + 6.8042;

Check your datasheet.
The LM335 should give about 2.98v out for 25'C.
That's 25'C = (2.98v/5v * 1024) = 610 ADC counts
So 0'C = (2.73/5v *1024) = 559 ADC counts

So get your 0-1023 ADC reading and subtract 559 counts, then you have a temp figure that is referenced to 0'C. You also know that (610-559) ie 51 ADC counts = 25'C. So you can work out a calibration based on that.
 

Nigel Goodwin

Super Moderator
Most Helpful Member
Oh, I see. I thought it could be convenient to reserve the main loop for other things like debouncing and stuff. :)

Apart from the multiplexing, is it also safe to use the USART functions in interrupt as well? :rolleyes:

I would advise not to blindly try and use interrupts for everything - consider what they are doing, and what the main program is doing, before deciding the interrupt route or not.

If you're going to use interrupts for a USART input, then you most probably need to use it to feed a buffer, and check the buffer contents in your main loop. But again, it depends what's going on.
 
Is this your kelvin to celcius conversion??? :eek:
Code:
        num = 0.4762 * temp + 6.8042;

Check your datasheet.
The LM335 should give about 2.98v out for 25'C.
That's 25'C = (2.98v/5v * 1024) = 610 ADC counts
So 0'C = (2.73/5v *1024) = 559 ADC counts

So get your 0-1023 ADC reading and subtract 559 counts, then you have a temp figure that is referenced to 0'C. You also know that (610-559) ie 51 ADC counts = 25'C. So you can work out a calibration based on that.

Oh sorry I wrote that in a haste - no wonder the formula I had written looked weird. I had changed it already. However, another question - I tested the sensor on the voltmeter - but it's giving temperatures like 2.78V to 3.2V (it's in Kelvins, te r.t. is estimated around 2.99V) which is not tallying with the room temperature at all. Must I recalibrate the sensor, or the sensor is faulty?

I would advise not to blindly try and use interrupts for everything - consider what they are doing, and what the main program is doing, before deciding the interrupt route or not.

If you're going to use interrupts for a USART input, then you most probably need to use it to feed a buffer, and check the buffer contents in your main loop. But again, it depends what's going on.

Oh got it. I will use the interrupts if the system allows it. Right now I'll use interrupt for multiplexing only for my homemade electronic thermometer. :D
 
Last edited:

Mr RB

Well-Known Member
LM335 should put out about 2.98v DC when it is at 25'C. Check how you have it wired, that you used the right value resistor with it.

Also you might try putting a big cap (47uF) right at the PIC ADC input pin, between ADC pin and Gnd.
 
LM335 should put out about 2.98v DC when it is at 25'C. Check how you have it wired, that you used the right value resistor with it.

Also you might try putting a big cap (47uF) right at the PIC ADC input pin, between ADC pin and Gnd.

I see. So if I want to directly wire it, the ADJ pin must be grounded, and the positive terminal is connected with the 1K resistor and to the AD pin on the microcontroller, and also the negative pin to the ground?

But the strange thing is, when the ADJ pin is grounded, it gives at least 3.15V and when it's ungrounded it gives like 2.75V.

By the way, this thing should show up at least 2.99V in the voltmeter with just basic wiring, isn't it? :D
 
The datasheet is your friend. :)

I already read the datasheet. Need to see whether must I calibrate the ADC in the microcontroller or not, by means of software. :)

Also, I have already checked the allowable current range: between 450µA and 5mA.

However, when I placed a resistor on the +ve terminal, say like two 1K resistor in series, it still gives me 3.26V instead of anything within 2.99V.

Here's the small schematic (LM335Z):

V- ------------------------| GND
V+ ---(1)--/\/\/\/\-------------| +5V
2k resistor (2x 1k resistors in series)
ADJ ---- (floating)

(1) to voltmeter or AD pin in µC
 
Last edited:
Okay, got the sensors giving the real values finally. It's the voltmeter's faulty and give funny results.

However, another problem. From the voltmeter, the sensor gives around 3.01V at room temperature, and should be translated to 155 or 9Bh in ADC operation (fyi, Vref is Vdd, step size: 5V/1024 = 4.883mV and finally, 3.01/4.883mV = 616.42 -> 616. Then divide it to four, I get 154 or 9Ah).

I connected that sensor to the AD pin in the microcontroller. It just gives me 168 or A8h. The value just runs away.

I've double checked the datasheet and tuned the A/D oscillator configurations and stuff, but it's giving me the same thing.

Anything else I could have missed out?
 
Status
Not open for further replies.

Latest threads

EE World Online Articles

Loading
Top