ADC creating delay in Timer2, How to avoid it?

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

ATMega8 with 8Mhz internal oscillator, calibrated, used in my project.

Also using 32.768 Khz external crystal for timer 2 as async CTC mode with an interrupt.

Inaddidion using ADC with left adjusted result, 64 presclar.

ADC value checking is in an end less loop.

I am counting mili seconds, for this, incrementing a global varialble in Timer 2 CTC Interrupt and checking if it exceeds the set value to be counted.

If i use Timer alone (Remove ADC code) then, timer 2 gives me perfect result as expected.

But if ADC + Timer is used then Timer becomes FAST. i.e. when i set 9000 ms to count and give me a signal, then it signals me at 5670 ms.

Why timer 2 goes fast with ADC?

YB

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

I know of no hardware reason these two should interact, so it's presumably
an interaction in your software. Please post your code.

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

I've used a similar setup before (using ATMega8535), but used an external crystal (for system clock). I didn't have any interaction between the ADC and Timer2. I have never used the internal oscillator, maybe that could have an effect?

The only thing more dangerous than a hardware guy with a code patch is a programmer with a soldering iron.

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

Partial code here:

ISR (TIMER2_COMP_vect, ISR_BLOCK) 
{ 
	//will be called every 1ms	
	glb_ms_counter ++;	
	error_corrector++;
	glb_trip_time_updater++;
	
	if(error_corrector==125)
	{
		error_corrector=0;
		glb_ms_counter=glb_ms_counter+3;
	}
	
		//sbi(DDRD,5);
		//cbi(PORTD,5);
	if(glb_ms_counter==glb_max_ms) 
	{
		sbi(DDRC,5);
		cbi(PORTC,5);
		while(1){}
	}		
}



int
main(void)
{
	DDRC|=0x30;
	PORTC|=0x30;
	
	OSCCAL_Calibrate(); 
	
	lcdInit();
	Init_ADC();
	ReadEEPROM(0,1,2);
	ISet=eep_ISET;
	Kfact=eep_KFACT;
	formula_type=eep_FORMULA;
	PrintUserSettings();
	
	menu_status=0;
	menu_level=0;
	
	ADCSRA |= _BV(ADSC); //freaks start conversion		
		while (ADCSRA & (1 << ADSC));
		
	start_timer_flag=0;
	glb_ms_counter=0;
	error_corrector=0;
		
	while(1)
	{		
		if(menu_status==0)
		{
			Read_and_Print_Current();		//temp
			CheckCurrentLimit();			//temp
		}
		MotitorKeys();		//temp
		_delay_us(500);		
	}	
return 0;
}

Quote:
Let me know which part of code you want more to understand the problem

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
   if(glb_ms_counter==glb_max_ms)
   {
      sbi(DDRC,5);
      cbi(PORTC,5);
      while(1){}
   }

Loops inside an ISR are a TERRIBLE idea in general, but since you are using an eternal loop (to kill the program) I don't see any major problems - unless you change the ISR type to a ISR_NOBLOCK later on. Best practise is to set a flag in the ISR (so the ISR can complete as fast as possible) and then act upon it in the main code body.

Also, where are you setting up the timer? If it's still being driven via an external crystal like in your last post, I can't see how the ADC would affect it.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

I only see one reference to the ADC, a one-shot that seems unlikely to interfere with
anything. Are you using the ADC elsewhere? What does Init_ADC() do?

When do you enable interrupts (sei())? Are you disabling interrupts anywhere?

Quote:
when i set 9000 ms to count and give me a signal, then it signals me at 5670 ms

Where do these numbers come from? What I mean is: Are they (a) from an external
reference (oscilloscope, wristwatch, "thousand-one..", e.g.) or (b) based on the values
in your counters when the program stops?

Unsolicited:

   if(glb_ms_counter==glb_max_ms)

This is a bit worrisome -- if glb_max_ms isn't a multiple of 128 the ISR can overshoot
and you'll miss your event. ">=" might be preferable here.

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

I have modified buttload's calibration routine, hence i have to use the ISR in this way.

ISR (TIMER2_COMP_vect, ISR_BLOCK) 
{

}

with ISR_BLOCK.

I dont know the use and importance of ISR_BLOCK. Should I continue using it.

Quote:
Also, where are you setting up the timer? If it's still being driven via an external crystal like in your last post, I can't see how the ADC would affect it.

Yes, its as you told me, on external 32.768 Khz crystal

Quote:

only see one reference to the ADC, a one-shot that seems unlikely to interfere with
anything. Are you using the ADC elsewhere? What does Init_ADC() do?

When do you enable interrupts (sei())? Are you disabling interrupts anywhere?

Read_and_Print_Current();
CheckCurrentLimit();
These 2 functions also have ADC reading code in it.
I am not disabeling any interrupt any where.

Quote:

Where do these numbers come from? What I mean is: Are they (a) from an external
reference (oscilloscope, wristwatch, "thousand-one..", e.g.) or (b) based on the values
in your counters when the program stops?


These numbers come from a calculation formula based upon ADC reading.

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

Quote:
Reason

I found the fault. Timer malfunction is due to "SOME" LCD routines.
Let me checkup and post the exact cause of it.

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

yellowboy_75 wrote:
I have modified buttload's calibration routine, hence i have to use the ISR in this way.
ISR (TIMER2_COMP_vect, ISR_BLOCK) 
{

}

with ISR_BLOCK.

I dont know the use and importance of ISR_BLOCK. Should I continue using it.

If you don't like my alternative ISR macro, you can just remove ISRMacro.h and delete the ", ISR_BLOCK" section from all the ISRs.

The normal ISR macro creates ISRs which are ISR_BLOCK by default - that is when they execute they block other ISRs from running (by keeping the global interrupt enable flag set while they execute). If you want to make a non-blocking ISR (ISR_NOBLOCK) in your code, you need to create your own macro to do so. My header file make it easier to create ISRs of different types and improves code readability.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

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

I found a surprising reason about the malfunction. Read my thoughts here:

Quote:
Problem is in between External Crystal of 32.768Khz AND the LCD.
And this problem is NOT of software, but of hardware. If i change distance of Crystal to controller, result changes. If I make ctystal's body ground, result changes.
If I connect crystal from TOP of PCB and DOWN side of PCB, result varies.
All varied results remain CONSTANTS in their environment.

Any one experienced this before?

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

Can anyone validate my thoughts?