ADC reading problems

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

Hello all!

I was using a routine to read the ADC, it worked for several hours/days without any problem.

I decided to add a Watchdog vector interrupt to read the ADC with an interval of 250ms (the timers doesn't have so long delay interval). After installing the routine I start seeing it was running 2, 3 or five minutes and stops at the ADC reading routine.

The code I have is the following:

ADC setup:


// ADC Enable
			ADCSRA |=(1<<ADEN);
			ADCSRA |=(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
			ADMUX  |=(1<<REFS0);
			DIDR0 =0b00011111;

The ADC reading routine I had is the following:

uint16_t Read_ADC(uint8_t adc_adr)
{

		uint16_t adc_value =0;
	
		ADMUX = (adc_adr);

		ADCSRA |=(1<<ADSC);

		while (!(ADCSRA & (1<<ADIF))) {}
			
				adc_value=ADCL;
				adc_value+=(ADCH<<8);
				ADCSRA|=(1<<ADIF);
		
				return adc_value;
				 
}		

The watchdog timer setup is the following:

void WDT_on(void)  
{
   //_watchdog_reset();
	MCUSR &= ~(1<<WDRF);

   	WDTCSR |=(1<<WDCE) | (1<<WDE);

 	// set prescaller to 0.250ms
 	WDTCSR= (0<<WDE)|(1<<WDIE) | (1<<WDP2);  

}

The watchdog ISR routine is the following:

/****************************************************************
* This is a timer Watchdog interrupt routine with 0.25 ms interrupt interval
* The ADC4 is readed to measure 4 times the currente and the total added.*/ 

ISR(WDT_vect)

{
  	sbi(PORTD, 6);// to test the time to measure the current

  if (I_status<=3)
  		{
		current_avg += Read_ADC(4+64); // +64 is the  REFS= bit, AVCC with external capacitor at AREF pin 
		I_status++;
		cbi(PORTD, 6);// to test the time to measure the current
		}
	else
		{
			GPS_data[43]=(uint8_t)(current_avg>>8);
		
		   	GPS_data[44]=(uint8_t)(current_avg);
			current_avg=0;
			I_status=0;
		}
}

The above was the first setup. After looking in the forum a tutorial I saw a different approach to read the ADC, that is the following:

/****************************************************************
* This routine is to read the ADC. The ADC is going to read the 
* motor battery voltage, receiver battery voltage, temperature and
* air speed.
*/
 uint16_t Read_ADC(uint8_t adc_adr)
{
		uint16_t adc_value =0;
	
		ADMUX = (adc_adr);

		ADCSRA |=(1<<ADSC);

		while(ADCSRA & (1<<ADSC)); {} // this was modified						
				adc_value=ADCL;
				adc_value+=(ADCH<<8);
				ADCSRA|=(1<<ADIF);
		
				return adc_value;
			 
}		

Instead of looking for the "ADIF: ADC Interrupt Flag" was changed to "Bit 6 "“ ADSC: ADC Start Conversion".

This doesn't make sense to me according to the device manual Atmega644P.

The fact is: i changed it and it has been running without problems.

Can some one explain me what is wrong in the first version?

Thanks.
Manuel

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

Just a minor difference. You can read the a/d converter by using an interrupt to signal when done (thats the ADIF), or you poll the ADSC (Start Conversion) bit to wait for conversion complete (takes about 100usecs). You start the conversion the same way for both cases... set the Start Conversion bit. Since it turns off when conversion is complete. you dont need the 1 instruction to reset it. You can also read both bytes of the result with one instruction.... result=ADCW, which is imperceptably faster.

Imagecraft compiler user

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

Bobgardner,

Thanks for your inputs. I changed the code and its working.

Regards,
Manuel

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

Quote:
I decided to add a Watchdog vector interrupt to read the ADC with an interval of 250ms (the timers doesn't have so long delay interval)
An 8 bit timer with /1024 could give 250 mS ISR, for a 1 MHz freq. Your problem's solved, but this is why it's good to always give which MCU used, and its freq. as part of an OP.

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1

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

Indianajones11,

Thanks for your inputs. I am running the MCU clock at 18.432MHz. I use this frequency to have a exact baudrate.

regards,
Manuel