AVR ADC sample time

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

hello,

HW: Atmega32 clock 16mhz, ADC clock 125khz, ref 5V clean and steady, print conversions on GLCD

SW: interrupt driven adc , a ~100uS long 1000mV pulse is fed in to adc pin after each adc conversion is finished, witch means the pulse is present for the ~100uS time it takes the adc to make the conversion.

Problem: the conversion is ~600mV,  the pulse seams to have about ~8 uS rise time, then it stabilize with an average of about 980mV.

I think that 8uS rise time coincides with the 1,5 clock cycle ( 12uS ) that avr takes for sample hold, and that gives the error in conversion.

I attached a snapshot of the scope with the pulse and measurements, the pulse is measured at the avr adc pin.

(GLDC  prints conversions right, because i have other conversions printed witch are ok )

Any ideas might be helpful, on why or how to fix.

Attachment(s): 

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

Delay the start of the adc!

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

well it is a bit difficult because see code 

ISR(ADC_vect)
{
	

	switch (adcmux) // ADC input channel selector
		{
			case 0: //ch0 mux
				theLowADC = ADCL;
				// oldVal = theTenBitResultsADC[0];
				theTenBitResultsADC[0] = ADCH<<8 | theLowADC; //10 bit ADC result
				// if (theTenBitResultsADC[0] != oldVal)
				//     longBitFlag |= 1 << 0
				//else
				//     longBitFlag |= 0 << 0  
				ADMUX = 0x41;
				adcmux = 1; 
				break;

			case 1: //ch1 mux
				theLowADC = ADCL;
				theTenBitResultsADC[1] = ADCH<<8 | theLowADC; //10 bit ADC result
				ADMUX = 0x42;
				adcmux = 2;
				break;

			case 2: //ch2 mux
				theLowADC = ADCL;
				theTenBitResultsADC[2] = ADCH<<8 | theLowADC; //10 bit ADC result
				ADMUX = 0x43;
				adcmux = 3;
				break;

			case 3: //ch3 mux
				theLowADC = ADCL;
				theTenBitResultsADC[3] = ADCH<<8 | theLowADC; //10 bit ADC result
				ADMUX = 0x44;
				adcmux = 4;
				break;

			case 4: //ch4 mux
				theLowADC = ADCL;
				theTenBitResultsADC[4] = ADCH<<8 | theLowADC; //10 bit ADC result
				ADMUX = 0x45;
				adcmux = 5;
				break;

			case 5: //ch5 mux
				theLowADC = ADCL;
				theTenBitResultsADC[5] = ADCH<<8 | theLowADC; //10 bit ADC result
				ADMUX = 0x46;
				adcmux = 6;
				break;

			case 6: //ch6 mux
				theLowADC = ADCL;
				theTenBitResultsADC[6] = ADCH<<8 | theLowADC; //10 bit ADC result
				ADMUX = 0x47;
				adcmux = 7;
				break;

			case 7: //ch7 mux


				PORT_OutPinC &= ~(1 << S0); // S0
				PORT_OutPinC &= ~(1 << S1); // S1
				PORT_OutPinC &= ~(1 << S2); // S2
				PORT_OutPinC &= ~(1 << S3); // S3
				PORT_OutPinC &= ~(1 << E0); // E0 on
				PORT_OutPinC |= 1 << E1; // E1 off

				theLowADC = ADCL;
				theTenBitResultsADC[7] = ADCH<<8 | theLowADC; //10 bit ADC result
				
				adcmux = 8;
				break;

			case 8: //ch0 ext mux1 , ch7 int mux
				

				PORT_OutPinC |= 1 << S0; // S0
				PORT_OutPinC &= ~(1 << S1); // S1
				PORT_OutPinC &= ~(1 << S2); // S2
				PORT_OutPinC &= ~(1 << S3); // S3
				PORT_OutPinC &= ~(1 << E0); // E0 on
				PORT_OutPinC |= 1 << E1; // E1 off

				theLowADC = ADCL;
				theTenBitResultsADC[8] = ADCH<<8 | theLowADC; //10 bit ADC result Cell 1 voltage

				adcmux = 9;
				break;

			case 9: //ch1 ext mux1 , ch7 int mux
				

				PORT_OutPinC &= ~(1 << S0); // S0
				PORT_OutPinC |= 1 << S1; // S1
				PORT_OutPinC &= ~(1 << S2); // S2
				PORT_OutPinC &= ~(1 << S3); // S3
				PORT_OutPinC &= ~(1 << E0); // E0 on
				PORT_OutPinC |= 1 << E1; // E1 off

				theLowADC = ADCL;
				theTenBitResultsADC[9] = ADCH<<8 | theLowADC; //10 bit ADC result // Cell 2 voltage

				adcmux = 10;
				break;

			case 10: //ch2 ext mux1 , ch7 int mux
				

				PORT_OutPinC |= 1 << S0; // S0
				PORT_OutPinC |= 1 << S1; // S1
				PORT_OutPinC &= ~(1 << S2); // S2
				PORT_OutPinC &= ~(1 << S3); // S3
				PORT_OutPinC &= ~(1 << E0); // E0 on
				PORT_OutPinC |= 1 << E1; // E1 off

				theLowADC = ADCL;
				theTenBitResultsADC[10] = ADCH<<8 | theLowADC; //10 bit ADC result // Cell 3 voltage

				adcmux = 11;
				break;

			case 11: //ch3 ext mux1 , ch7 int mux
				

				PORT_OutPinC &= ~(1 << S0); // S0
				PORT_OutPinC &= ~(1 << S1); // S1
				PORT_OutPinC |= 1 << S2; // S2
				PORT_OutPinC &= ~(1 << S3); // S3
				PORT_OutPinC &= ~(1 << E0); // E0 on
				PORT_OutPinC |= 1 << E1; // E1 off

				theLowADC = ADCL;
				theTenBitResultsADC[11] = ADCH<<8 | theLowADC; //10 bit ADC result // Cell 4 voltage

				adcmux = 12;
				break;

			case 12: //ch4 ext mux1 , ch7 int mux
				

				PORT_OutPinC |= 1 << S0; // S0
				PORT_OutPinC &= ~(1 << S1); // S1
				PORT_OutPinC |= 1 << S2; // S2
				PORT_OutPinC &= ~(1 << S3); // S3
				PORT_OutPinC &= ~(1 << E0); // E0 on
				PORT_OutPinC |= 1 << E1; // E1 off

				theLowADC = ADCL;
				theTenBitResultsADC[12] = ADCH<<8 | theLowADC; //10 bit ADC result // Cell 5 voltage

				adcmux = 13;
				break;

			case 13: //ch5 ext mux1 , ch7 int mux
				

				PORT_OutPinC &= ~(1 << S0); // S0
				PORT_OutPinC |= 1 << S1; // S1
				PORT_OutPinC |= 1 << S2; // S2
				PORT_OutPinC &= ~(1 << S3); // S3
				PORT_OutPinC &= ~(1 << E0); // E0 on
				PORT_OutPinC |= 1 << E1; // E1 off

				theLowADC = ADCL;
				theTenBitResultsADC[13] = ADCH<<8 | theLowADC; //10 bit ADC result // Cell 6 voltage

				adcmux = 14;
				break;

			case 14: //ch6 ext mux1 , ch7 int mux
				

				PORT_OutPinC |= 1 << S0; // S0
				PORT_OutPinC |= 1 << S1; // S1
				PORT_OutPinC |= 1 << S2; // S2
				PORT_OutPinC &= ~(1 << S3); // S3
				PORT_OutPinC &= ~(1 << E0); // E0 on
				PORT_OutPinC |= 1 << E1; // E1 off

				theLowADC = ADCL;
				theTenBitResultsADC[14] = ADCH<<8 | theLowADC; //10 bit ADC result // Cell 7 voltage

				adcmux = 15;
				break;

			case 15: //ch7 ext mux1 , ch7 int mux
				

				PORT_OutPinC &= ~(1 << S0); // S0
				PORT_OutPinC &= ~(1 << S1); // S1
				PORT_OutPinC &= ~(1 << S2); // S2
				PORT_OutPinC |= 1 << S3; // S3
				PORT_OutPinC &= ~(1 << E0); // E0 on
				PORT_OutPinC |= 1 << E1; // E1 off

				theLowADC = ADCL;
				theTenBitResultsADC[15] = ADCH<<8 | theLowADC; //10 bit ADC result // Cell 8 voltage

				adcmux = 16;
				break;

			case 16: //ch8 ext mux1 , ch7 int mux
				

				PORT_OutPinC |= 1 << S0; // S0
				PORT_OutPinC &= ~(1 << S1); // S1
				PORT_OutPinC &= ~(1 << S2); // S2
				PORT_OutPinC |= 1 << S3; // S3
				PORT_OutPinC &= ~(1 << E0); // E0 on
				PORT_OutPinC |= 1 << E1; // E1 off

				theLowADC = ADCL;
				theTenBitResultsADC[16] = ADCH<<8 | theLowADC; //10 bit ADC result // Cell 9 voltage

				adcmux = 17;
				break;

			case 17: //ch9 ext mux1 , ch7 int mux
				

				PORT_OutPinC &= ~(1 << S0); // S0
				PORT_OutPinC |= 1 << S1; // S1
				PORT_OutPinC &= ~(1 << S2); // S2
				PORT_OutPinC |= 1 << S3; // S3
				PORT_OutPinC &= ~(1 << E0); // E0 on
				PORT_OutPinC |= 1 << E1; // E1 off

				theLowADC = ADCL;
				theTenBitResultsADC[17] = ADCH<<8 | theLowADC; //10 bit ADC result // Cell 10 voltage

				adcmux = 18;
				break;

			case 18: //ch10 ext mux1 , ch7 int mux
				

				PORT_OutPinC |= 1 << S0; // S0
				PORT_OutPinC |= 1 << S1; // S1
				PORT_OutPinC &= ~(1 << S2); // S2
				PORT_OutPinC |= 1 << S3; // S3
				PORT_OutPinC &= ~(1 << E0); // E0 on
				PORT_OutPinC |= 1 << E1; // E1 off

				theLowADC = ADCL;
				theTenBitResultsADC[18] = ADCH<<8 | theLowADC; //10 bit ADC result // Cell 11 voltage

				adcmux = 19;
				break;

			case 19: //ch11 ext mux1 , ch7 int mux
				

				PORT_OutPinC &= ~(1 << S0); // S0
				PORT_OutPinC &= ~(1 << S1); // S1
				PORT_OutPinC |= 1 << S2; // S2
				PORT_OutPinC |= 1 << S3; // S3
				PORT_OutPinC &= ~(1 << E0); // E0 on
				PORT_OutPinC |= 1 << E1; // E1 off

				theLowADC = ADCL;
				theTenBitResultsADC[19] = ADCH<<8 | theLowADC; //10 bit ADC result // Cell 12 voltage

				adcmux = 20;
				break;

			case 20: //ch12 ext mux1 , ch7 int mux
				

				PORT_OutPinC |= 1 << S0; // S0
				PORT_OutPinC &= ~(1 << S1); // S1
				PORT_OutPinC |= 1 << S2; // S2
				PORT_OutPinC |= 1 << S3; // S3
				PORT_OutPinC &= ~(1 << E0); // E0 on
				PORT_OutPinC |= 1 << E1; // E1 off

				theLowADC = ADCL;
				theTenBitResultsADC[20] = ADCH<<8 | theLowADC; //10 bit ADC result // Cell 13 voltage

				adcmux = 21;
				break;

			case 21: //ch13 ext mux1 , ch7 int mux
				

				PORT_OutPinC &= ~(1 << S0); // S0
				PORT_OutPinC |= 1 << S1; // S1
				PORT_OutPinC |= 1 << S2; // S2
				PORT_OutPinC |= 1 << S3; // S3
				PORT_OutPinC &= ~(1 << E0); // E0 on
				PORT_OutPinC |= 1 << E1; // E1 off

				theLowADC = ADCL;
				theTenBitResultsADC[21] = ADCH<<8 | theLowADC; //10 bit ADC result // Cell 14 voltage

				adcmux = 22;
				break;

			case 22: //ch14 ext mux1 , ch7 int mux
				

				PORT_OutPinC |= 1 << S0; // S0
				PORT_OutPinC |= 1 << S1; // S1
				PORT_OutPinC |= 1 << S2; // S2
				PORT_OutPinC |= 1 << S3; // S3
				PORT_OutPinC &= ~(1 << E0); // E0 on
				PORT_OutPinC |= 1 << E1; // E1 off

				theLowADC = ADCL;
				theTenBitResultsADC[22] = ADCH<<8 | theLowADC; //10 bit ADC result // Cell 15 voltage

				adcmux = 23;
				break;

			case 23: //ch15 ext mux1 , ch7 int mux
				

				PORT_OutPinC &= ~(1 << S0); // S0
				PORT_OutPinC &= ~(1 << S1); // S1
				PORT_OutPinC &= ~(1 << S2); // S2
				PORT_OutPinC &= ~(1 << S3); // S3
				PORT_OutPinC |= 1 << E0; // E0 off
				PORT_OutPinC &= ~(1 << E1); // E1 on

				theLowADC = ADCL;
				theTenBitResultsADC[23] = ADCH<<8 | theLowADC; //10 bit ADC result // Cell 16 voltage

				adcmux = 24;
				break;

			case 24: //ch0 ext mux2 , ch7 int mux
				

				PORT_OutPinC |= 1 << S0; // S0
				PORT_OutPinC &= ~(1 << S1); // S1
				PORT_OutPinC &= ~(1 << S2); // S2
				PORT_OutPinC &= ~(1 << S3); // S3
				PORT_OutPinC |= 1 << E0; // E0 off
				PORT_OutPinC &= ~(1 << E1); // E1 on

				theLowADC = ADCL;
				theTenBitResultsADC[24] = ADCH<<8 | theLowADC; //10 bit ADC result // Cell 17 voltage

				adcmux = 25;
				break;

			case 25: //ch1 ext mux2 , ch7 int mux
				

				PORT_OutPinC &= ~(1 << S0); // S0
				PORT_OutPinC |= 1 << S1; // S1
				PORT_OutPinC &= ~(1 << S2); // S2
				PORT_OutPinC &= ~(1 << S3); // S3
				PORT_OutPinC |= 1 << E0; // E0 off
				PORT_OutPinC &= ~(1 << E1); // E1 on

				theLowADC = ADCL;
				theTenBitResultsADC[25] = ADCH<<8 | theLowADC; //10 bit ADC result // Cell 18 voltage

				adcmux = 26;
				break;

			case 26: //ch2 ext mux2 , ch7 int mux
				

				PORT_OutPinC |= 1 << S0; // S0
				PORT_OutPinC |= 1 << S1; // S1
				PORT_OutPinC &= ~(1 << S2); // S2
				PORT_OutPinC &= ~(1 << S3); // S3
				PORT_OutPinC |= 1 << E0; // E0 off
				PORT_OutPinC &= ~(1 << E1); // E1 on

				theLowADC = ADCL;
				theTenBitResultsADC[26] = ADCH<<8 | theLowADC; //10 bit ADC result // Cell 19 voltage

				adcmux = 27;
				break;

			case 27: //ch3 ext mux2 , ch7 int mux

				PORT_OutPinC |= 1 << E0; // E0 off
				PORT_OutPinC |= 1 << E1; // E1 off

				theLowADC = ADCL;
				theTenBitResultsADC[27] = ADCH<<8 | theLowADC; //10 bit ADC result // Cell 20 voltage

				ADMUX = 0x40;

				

				adcmux = 0;
				break;

			default: //Default code
		
			break;
		} 		

	OCR1A = duty_cycle; // the duty cycle for PWM

	ADCSRA|=(1<<ADSC); //Restart Single conversion
}

 

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

So where is the problem? Just put a delay before starting the adc.
BTW you can just read ADC and get the full result - no need to stitch together two 8bit reads.

Last Edited: Wed. Dec 20, 2017 - 11:14 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think 8uS delay in the ISR is not a good practice issen't it? But for demo purpose might work. So reading ADC gets all 10bit with no need to read ADCH and ADCL i'l try it.

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

The isr overhead will probably be a few microseconds, so 8 microseconds delay is debateable if it is good/bad. You can always load a timer and have it trigger the adc.

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

well, 12uS did the trick, it probably works with 8uS i'l have to try it, and i think i'l do the timer triggered ADC in order not to waste 12uS every ~100uS.

Thank you for the suggestion.

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

well just in case this might be useful to others, i made the delay by activating the external mux 2 conversions before the atcual conversion, this way the signal has 100us (a conversion time) time to settle and then do the conversion.

 

example:

 

	        case 5: //ch5 mux
				theLowADC = ADCL;
				theTenBitResultsADC[5] = ADCH<<8 | theLowADC; //10 bit ADC result
				ADMUX = 0x46;
				adc_state = 6;
				break;

			case 6: //ch6 mux

				theLowADC = ADCL;
				theTenBitResultsADC[6] = ADCH<<8 | theLowADC; //10 bit ADC result

				PORT_OutPinC &= ~(1 << S0); // S0
				PORT_OutPinC &= ~(1 << S1); // S1
				PORT_OutPinC &= ~(1 << S2); // S2
				PORT_OutPinC &= ~(1 << S3); // S3
				PORT_OutPinC &= ~(1 << E0); // E0 on
				PORT_OutPinC |= 1 << E1; // E1 off

				ADMUX = 0x40;
				adc_state = 7;
				break;

			case 7: //ch0 mux
				theLowADC = ADCL;
				theTenBitResultsADC[0] = ADCH<<8 | theLowADC; //10 bit ADC result
				ADMUX = 0x47;
				adc_state = 8;
				break;

			case 8: //ch0 ext mux1 , ch7 int mux

				theLowADC = ADCL;
				theTenBitResultsADC[8] = ADCH<<8 | theLowADC; //10 bit ADC result Cell 1 voltage				

				PORT_OutPinC |= 1 << E0; // E0 off
				PORT_OutPinC |= 1 << S0; // S0
				PORT_OutPinC &= ~(1 << S1); // S1
				PORT_OutPinC &= ~(1 << S2); // S2
				PORT_OutPinC &= ~(1 << S3); // S3
				PORT_OutPinC &= ~(1 << E0); // E0 on
				PORT_OutPinC |= 1 << E1; // E1 off

				ADMUX = 0x41;
				adc_state = 9;
				break;

			case 9: //ch1 mux
				theLowADC = ADCL;
				theTenBitResultsADC[1] = ADCH<<8 | theLowADC; //10 bit ADC result
				ADMUX = 0x47;
				adc_state = 10;
				break;

			case 10: //ch1 ext mux1 , ch7 int mux

				theLowADC = ADCL;
				theTenBitResultsADC[9] = ADCH<<8 | theLowADC; //10 bit ADC result // Cell 2 voltage

				PORT_OutPinC |= 1 << E0; // E0 off
				PORT_OutPinC &= ~(1 << S0); // S0
				PORT_OutPinC |= 1 << S1; // S1
				PORT_OutPinC &= ~(1 << S2); // S2
				PORT_OutPinC &= ~(1 << S3); // S3
				PORT_OutPinC &= ~(1 << E0); // E0 on
				PORT_OutPinC |= 1 << E1; // E1 off

				ADMUX = 0x42;
				adc_state = 11;
				break;

 

Last Edited: Sat. Dec 30, 2017 - 10:02 PM