NTC ADC problem

Go To Last Post
19 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Dear all,

I would like to measure NTC with Atmega 8 and show the result in celsius on the LCD.
If I run it with AD conversion the result is 000.0 in the LCD screen
If I add value to the variable =>
analog_result = 534 ;
Then on the LCD I got the right temperature.
Why the AD conversion doesn't run good?
Thanks in advance for your great support.

volatile uint16_t analog_result;
// all other variable definied

void main(void)
{

    ioconf(); //IO init
    lcd_init_4(); // LCD init
    adc_init(); // ADC init
	

	while (1)
	{
	

    adc_read(0);  //read AD ch0 
    gotoxy(0,1); //1 line 0. char on the LCD	
    ntc_conv();// calc temp from ADC value 
    _delay_ms(1000); //delay



	}	
}


void adc_init(void)   //normal AD init
{
ADMUX |= (1<<REFS0) | (1<<ADLAR) ;    //align left 
ADCSRA |= (1<<ADEN)    ;  // ADC enable 
}

void adc_read(unsigned char adchan) // start
{
ADMUX=(ADMUX&0xF0)|adchan | (1<<ADLAR) ; //chose chanel + align to left
ADCSRA |=  (1<<ADSC) | (1<<ADEN)  ;  // AD Enable + Start convversion

while(ADCSRA & (1<<ADSC)) ;  // wait conv. end 
analog_result = ADC ;  // reed ADC result 
//analog_result = 0x214; 
ADCSRA &= ~ (1<<ADEN) ; //AD disable
}



//***************
//NTC conversion
//***************
void ntc_conv(void)
    
{
	
    Vin_mv = analog_result*(Vref_mv/1024.0);  
	
    r=R1/((AVCC_mv/Vin_mv)-1.0);  
	
	    
    t=1.0/(log(r/10000.0)/3380.0+(1.0/(25.0+273.0))) - 273;
    
    /*
      display xxx.x degree in lcd.
     */
    t_temp=t*10.0;

    gotoxy(0,1); //lcd position 
    send_dr(t_temp/1000+'0'); //char to LCD
    send_dr((t_temp%1000)/100+'0');
    
    send_dr((t_temp%100)/10+'0');
    send_dr('.');
    send_dr(t_temp%10+'0');
	
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

1) Use the Code tags to preserve formatting, as described in many posts [added above now]

2) OK, we can assume GCC. What version/flavout
You mentioned Mega8. Clock speed? Supply voltage?

3) Describe connections to the AVR, in particular Vcc, AVcc, Gnd AGnd, AREF levels, and the level measured for the thermistor RIGHT AT THE AVR PIN.

4) Before the temperature, first concentrate on the ADC counts. "analog_results"? Put that to the LCD. What did you expect? What did you get?

5) There are zillions of thermistors, of various values. How is it connected to the AVR? What is the nominal value? Are you using a bias resistor?

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sounds like your confusing degrees Kelvin and degrees Centigrade

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Dear all,

thanks the reactions, and sorry for the missing informations. I didn't tought that the hardware circuit soo important.
1, I use AVR GCC 4.3.3 .
Clock speed 8 Mhz Int RC oscilaltor.
Supply voltage 5V.
2, VCC connect to +5V Gnd and AGnd to ground
3, Aref with 10K ohm resistor to the + 5V.
I measure the NTC voltage on the following way:
10K ohm resistor connected to +5V, above serially the NTC to the ground. So tipicall connection.
The NTC 10K ohm at 25 Celsius.
I simulate the whole circuit only in Proteus, so all the results I got from there.
At 25 Celsius simulated NTC on the ADC input pin I have around 2.5 V DC
4, analog_result variable used to get the ADC conversion result in 16 bit, because we have 10 bit ADC. That's 16 bit analog_result must be converted with the NTC routin into celsius, and should be written on the 2x16 LCD, which had been drive in 4 pin mode.
5, 10 K ohm at 25 Celsius, Beta : 3380

To sum up I thought that it might be tricky mistake, because if I remove the comment // from this line:
//analog_result = 0x214;
And give direct value 0x214 which is 532 decto analog_result, I got correct result calculated and displayed on the LCD in Celsius .
That's why I thought that some stupid error I had taken.

Thanks for your help.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

for a starter you by default do not have the ability to use foats or doubles. I see you using them, so did you set the compiler accordingly?

also in ntc_conf the vin_mv variable seems not to be declared, I wonder if the compiler is not complaining about that.

Also you use adlar to shift the conversion result. Why ?
if you want jst 8biot you need to read ADCH and not ADC. ADc now is always a very large number, zo it micht well be overflowing somewhere along te conversion way.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have to check if the compiler set accordingly.
Good point.

All the variable definied before, but I didn't posted, because I tought that it has no influence for the case.
I try to read separatly the ADCL and ADCH and After shift into the adc_result also. The result was the same. 000.0 Celsius on the display.
What do you mean the ADC always large number.
It's not 16 bit int the result?
I think that three posibble problam can cause it:

1, ADC conversion doesn't start / result wrong , not given to analog_result.
2, Wrong definition of on of the variable
3, Wrong Compiler settings

The calculation from analog_result into Celsius correct, as I mentioned before If I gave value for analog_result it calculated correct.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Dear meslomp,
Could you please tell me, where can I find the compiler settings for Float handling ?
Thanks in advance.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
for a starter you by default do not have the ability to use foats or doubles.
Where did you get that idea? Certainly if you don't specify the correct lib then you will get rather inefficient floating point, but it will still work.
Quote:
After shift into the adc_result also.
But why are you shifting at all? You are in effect multiplying your result by 64.
Quote:
Could you please tell me, where can I find the compiler settings for Float handling ?
That depends on how you are compiling your code. If you are using AVR Studio, it is in the project settings. If you are using a makefile then you need to specify the proper library there. In all cases the library is libm.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

void adc_init(void) //normal AD init
{
ADMUX |= (1<<REFS0) | (1<<ADLAR) ; //align left
ADCSRA |= (1<<ADEN) ; // ADC enable
}

-- Reference selection: the datasheet says that combination means "use AVcc with cap on AREF". You then said that AREF was connected to Vcc with a resistor.
-- So, you enable the ADC at init. Then disable it every conversion. Interesting at best. I'd think perhaps problematic. But I'm not sure.

Quote:

ADCSRA |= (1<<ADSC) | (1<<ADEN) ; // AD Enable + Start convversion

So, you are running the ADC with an 8MHz clock rate? And for good results, it should be no more than 200kHz?

What is the purpose of left-justify ADLAR?

Work on your ADC read first, perhaps with a pot, until you get good conversion results displayed in ADC counts. Then do it on a real chip.

>>Then<< perhaps work on conversion to temperature. I cannot comment on your formula approach, since I either use bias resistor to pull the area of interest to linear, or use a table lookup and interpolations.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I found my stupid mistake.
I removed ADLAR Left alignmet from the AD initialization, because it was a mistake.
I didn't readed deeply the ADLAR setting result.
All the conversion unit expected right aligned AD result.
BTW thanks freaks the support.
Thanks again.

Last Edited: Mon. Mar 18, 2013 - 07:59 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

I read all the ADC function again, and realized that the huge mistake is the Left aligned ADC result.

And not the 8MHz ADC clock rate? And not the mis-connection on the AREF pin?

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

No. The ADC clock rate was 8 Mhz/2 originally, but it had no influence I try to change it to 8Mhz/16 also before I found the mistake. I connect the Aref pin to +5V with a 10K ohm resistor, as I mentioned before.

Now it calculate the temperature, and shows on the LCD. Somehow I have 2.1 celsius deviation between the NTC setted value in Proteus and the displayed temperature. I have to find it. But it's better than it was....

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hunber wrote:
Somehow I have 2.1 celsius deviation between the NTC setted value in Proteus and the displayed temperature. I have to find it. But it's better than it was....

Be aware, that standard NTC's are not precision components, they are far from linear and may change value over time. They are not made for this purpose. A deviation of 2.1C is better than I would expect.

A PTC like KTY82 is a precision alternative with long term stability. I use them myself. PTC's increase resistance with temperature.

Another inexpensive option is LM35 with a precision of +/- 0.5C. Or SE95D with I2C interface, +/- 1.0C. SE95D have a builtin ADC.

Peter

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

The ADC clock rate was 8 Mhz/2 originally,

What kind of result do you expect to get in the >>real world<< with overclocking the ADC?

Quote:

I connect the Aref pin to +5V with a 10K ohm resistor, as I mentioned before.

What kind of result do you expect to get in the >>real world<< with an improper AREF connection?

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

All the result what I got only in Simulator with Proteus.
I set the NTC in Proteus to the value, what I would like to measure it.
Do you think that in simulator normall the 2.1 celsius deviation? Or I have to find in my code mistake again ?
Why you sad, that I overlocked the ADC ? what is the suggested AD conversion frequency for NTC measurement ? I know less is more than enough, but isaw that this has no influence for the result in simulator.

What is the sugested proper connection for AREF L +C filter, what Atmel suggest ? Or you suggest something else?
Thanks in advance.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

What is the sugested proper connection for AREF L +C filter, what Atmel suggest ?

No, Atmel does NOT suggest that L+C filter for AREF connection. Perhaps for AVCC. What does the datasheet say about it, when you select AVcc as Vref?

I have no idea where your two degrees go. Tell what voltage is on the AVR pin. Tell what reference voltage is being used. Tell what the resulting ADC counts are.

What you do after that is up to you. As I mentioned, I've never used the equation(s) to calculate thermistor temperature. I've always used a lookup table and interpolation, or used a bias resistor with a value that gave linear results over the span of interest.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hunber wrote:
What is the sugested proper connection for AREF L +C filter, what Atmel suggest ? Or you suggest something else?
Thanks in advance.

It is perfectly possible to leave AREF open, unconnected. Set up the AVR to use VCC as analog reference, and forget the AREF pin.

Your formula for NTC calculation is an approximation. Real world NTC's will vary considerably. If a 2.1 degree is a problem, then NTC's are not suited for your purpose, even if you calibrate. NTC's will drift over time and ruin any calibration.

Precision components exist, PT1000, precision PTC, LM35 and many more. Unless your NTC is a special precision component, forget it!

Peter

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hunber wrote:
Why you sad, that I overlocked the ADC ? what is the suggested AD conversion frequency for NTC measurement ? I know less is more than enough, but isaw that this has no influence for the result in simulator.

As a rule of thumb, most AVR's give 10 bit precision at max. 150kHz conversion speed. Perhaps up to 200kHz. An ADC conversion takes 13 ADC clocks (prescaled from CPU). For higher precision, choose a lower conversion frequency, and average over a number of samples.

Proteus simulator don't care for conversion speed or other real world limitations, but a real AVR does. Use simulation with care.

Peter

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks, this rule is new for me.
Very helpful, I will keep in my mind, and modify the code accordingly.