ATmega324P - Ext. Interrupt Causing printf issues

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

I'm currently using an external interrupt on the ATmega324P. I have my code working so that it prints out an ADC value and converts it to a PWM and shows the percentage on the screen. It works fine and does what I want it to do when I start the program and if I manually power it down and up again. The issue I'm having is that when I press my button to toggle the ISR(INT0_vector) function it prints out most of the screen fine but leaves some garbage printf data at the end of my reset. I'm using VT100 (ANSI escape codes) to format my terminal output. So I can see that the garbage is from one of those commands; but I can't stop it. It happens on most of the resets but some are clean.

 

-- Basically my reset works and clears/reprints the screen but it leaves some printf statement garbled at the end. Expected output is that of PWM2... but i get the garbage and it overwrites my %.

-- I didn't want to post code as it's a lot; but if needed i can.

 

This topic has a solution.
Last Edited: Sun. Sep 24, 2017 - 11:59 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You really shouldn’t use an external interrupt for pushbuttons as it gives a slew of interrupts due to contact bounce. What does your isr do? Any printf()? Any shared variables? Atomic access?

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

I'm new to AVR's and programming them; our assignment requires using a button to perform the interrupt, clear the avg adc value and update everything to it's current values. I don't know what atomic access does, though i have seen it used. Printf() is called during the vt_reset and print_pwm to set up my new terminal screen.  PWM3 is the last pwm updated and if i change it to update something else last that is where the garbage is printed.

 

void interrupt_button()
{
    vt_reset_screen();          // clears screen, reprints titles and setup values
    adc_avg_reset();            // resets average calculation to 0 and updates based upon current ADC level
        
    update_pwm();              // updates current pwm value
    print_pwm();                  // prints pwm value
}


ISR(INT0_vect)
{
    // Reset ADC avg and clear screen
    interrupt_button();
}

 

 

 

Last Edited: Sun. Sep 24, 2017 - 11:29 PM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

You’re calling your screen update in an interrupt context. If the main line code is also printing stuff out then you have a problem as two tasks contend for the same device (usart).
Generally you do not do lengthy operations via the interrupt as this locks out other interrupt sources. You would normally have the isr set a flag and the main code responds to it.

Last Edited: Sun. Sep 24, 2017 - 10:53 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That makes sense; it worked when I made the ISR call a toggle. Thanks for the help.

Last Edited: Sun. Sep 24, 2017 - 11:59 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Google ganssle debounce
On the joys of mechanical switches and why you don’t tie them to an interrupt.

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

If using an interrupt for a button is conditio sine qua non, then try the folowing example to avoid multiple interrupts ( #2)

 

volatile unsigned char flag;       // variables used both in main() and ISR() must be "volatile"

ISR(INT0_vect)
{
   _delay_ms(50);                  // wait while button bouncing
   flag = 1;                       // set flag
   loop_until_bit_is_set(PIND,2);  // wait for button released (suppose button active LOW)
   _delay_ms(50);                  // wait while button bouncing
   EIFR |= (1<<INT0);              // clear interrupt flag
}

int main()
{
   if(flag == 1)                   // if button pressed
   {
      flag = 0;                    // clear flag
      vt_reset_screen();           // clears screen, reprints titles and setup values
      adc_avg_reset();             // resets average calculation to 0 and updates based upon current ADC level
      // and so on
}

 

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

@Visovian,

Hanging in an ISR while a button is active would only be valid in a VERY limited set of circumstances, NEVER in any projects I have come across...

David (aka frog_jr)

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

frog_jr wrote:
Hanging in an ISR ... would only be valid in a VERY limited set of circumstances

+99

because, as Kartman wrote:
Generally you do not do lengthy operations via the interrupt as this locks out other interrupt sources

Last Edited: Mon. Sep 25, 2017 - 01:36 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 2

Perkins1220 wrote:
our assignment requires using a button to perform the interrupt,
is there a potential for telling the person that set this assignment that they are an idiot and while this may work in their partiulcar ivory tower in the real world no one does button reading this way?

 

(feel free to direct them to this thread!)

 

The recognised way to do this is using a timer interrupt to poll the state of button inputs regularly and maintain a history of their state. Only when the history shows the same state for several samples is the button considered to be in a fixed state that can then be reported. There are two fairly "famous" implementations of this for AVR from Lee Theusch and Peter Danegger. One stores the history "across" the bits in a byte per input and one stores the history down the bits of bytes in successive samplings.

 

The only use of an external interrupt or pin change interrupt in the whole process of such button reading might be if the application is battery powered in which case the ext-int/pcint is used as a "wake up source" to get the AVR out of SLEEP once a button is used but as soon as its awake that interrupt source is disabled and then timed polling of button states (to mitigate bounce) takes over with the ext-int/pcint only being re-enabled just before the AVR next SLEEPs.

 

Your tutor / assignment setter should know this and be educating you appropriately.

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

clawson wrote:
Your tutor / assignment setter should know this and be educating you appropriately.

OR ... the signal must be known to be "clean", with external debouncing circuitry or similar.

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

clawson wrote:
 The only use of an external interrupt or pin change interrupt in the whole process of such button reading might be if the application is battery powered in which case the ext-int/pcint is used as a "wake up source" 

Another candidate - where bounce is not an issue: http://www.avrfreaks.net/comment... ?

 

clawson wrote:
feel free to direct them to this thread 

Note that you can direct them to a particular post:  the link is in the post number at the far right of the the title bar of each post; eg, #2

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

Perkins1220 wrote:
I'm new to AVR's and programming them

Note that the comments about switch bounce are not specific just to AVRs - they would apply equally to any microcontroller.

 

In fact, they aren't specific just to programming - anything that receives input from a mechanical switch has to cope with contact bounce

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

In case OP has not seen what switch bounce looks like, here are different scope traces of the same button being pushed multiple times.  Time scale is 100us / div.

 

 

And here is proof that a micro controller is plenty fast enough to see these bounces and respond to them as separate button pushes.  This is the micro output when reading the raw button input.

 

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

Perkins1220 wrote:
I'm new to AVR's and programming them; our assignment requires using a button to perform the interrupt
frog_jr wrote:

@Visovian,

Hanging in an ISR while a button is active would only be valid in a VERY limited set of circumstances, NEVER in any projects I have come across...

 

Why do you suppose that every beginner uses 100 functions and 20 interrupts in his code?

Besides, it seems like a homework, I think showing more variants cannot harm.

 

I remember when I was a beginner I made some simple projects like a watch, cook-timer, freq. counter, C-meter.

In all of them a button delay played no role.

(Which of course does not mean that I have something against better methods.)

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

Visovian wrote:
Why do you suppose that every beginner uses 100 functions and 20 interrupts in his code?

Nobody said that.

 

The point is that the OP needs to understand that, in general, this is not a good approach.

 

If the OP goes away thinking, "this is the way to do buttons" - we will not hve server him/her well.