Go Down

Topic: Interrupt Question (Read 1 time) previous topic - next topic

mash4t

I'm pretty new to arduino,so bear with me please if I am doing something stupid...

I am making a speedometer/odometer/in-car metrics thing for a friend. It's got a little LCD screen (The LiquidCrystal library is awesome), and I am using attachInterrupt to listen for button presses to switch between modes.

However, the button doesn't seem to work, it just seems to make the screen flicker. The code I am using is below...

Code: [Select]

int Setting=0;

//Setup
void setup(){
  //Setup LCD
  lcd.begin(16,2);
  Startup();
  //Load last mode selection//
  Load();
  pinSetup();
  //attachInterrupt(0,Pulse,CHANGE);
  attachInterrupt(1,button1Press,FALLING);
  //attachInterrupt(2,button2Press,LOW);
}
//Loop
void loop(){
  double currSpeed = Speed();
  Distance();
 
  switch (Setting) {
    case 0:
      printOdo(currSpeed);
      break;
    case 1:
      printRPM(currSpeed);
      break;
  }
}

void button1Press(){
  Setting++;
  Setting = (Setting % NumberofSettings);
}

//printOdo - Prints the Odometer readout to the screen.
void printOdo(double currSpeed){
  lcd.setCursor(0,0);
  lcd.print("Speed  ");
  lcd.print(currSpeed);
  lcd.print("mph");
  lcd.setCursor(0,1);
  lcd.print("Distance ");
  lcd.print(Mileage);
  lcd.print("m");
}
//printRPM - Prints the RPM readout to the screen.
void printRPM(double currSpeed){
  int revs = RPM();
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Speed  ");
  lcd.print(currSpeed);
  lcd.print("mph");
  lcd.setCursor(0,1);
  lcd.print(revs);
  lcd.print("RPM");
}

I've taken out the bits that aren't important, to make it shorter.

Anyway, I have no idea what I am doing wrong.
Thanks in advance.

Coding Badly

Quote
I am using attachInterrupt to listen for button presses to switch between modes


Why are you using an interrupt?

AWOL

Code: [Select]
int Setting=0;
sp.
Code: [Select]
volatile int Setting=0;

But otherwise, what CodingBadly said
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

mash4t

I was under the impression that it was needed because the button may only be pressed for a short amount of time, so the interrupt makes sure that the button press is registered. Like I said, I am new to this, so I could be very wrong.

AWOL

Quote
the button may only be pressed for a short amount of time

Your idea of a "short amount of time" and that of a processor running at 16MHz are quite different.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

PaulS

Even with interrupts (or maybe especially with), debouncing is required. You should also record when the interrupt occurred, and ignore the interrupt if it happens too soon after the last interrupt.

mash4t

Other than me not being able to make it work, are there any downsides to using the interrupt?

PaulS

Quote
Other than me not being able to make it work, are there any downsides to using the interrupt?

That's not a big enough downside?

Interrupts often lead to complex code, primarily due to the need to respond at any time to the interrupt. Your situation is properly using an interrupt handler - to do nothing more than set a value that gets used later, so there are no real downsides.

Coding Badly

At least two...

1. The added complexity.  Getting the details correct can be extremely difficult.  Even for seasoned professionals.

2. Overhead.  Entering and exiting an interrupt service handler can be an expensive journey (in CPU time and, to a lesser extent, SRAM used).

Interrupts are like a stick of dynamite.  The average person will go their entire lifetime without needing one.  But, if you do need one1, you can't live without it.

1 For example, to shift an especially well anchored very large tree stump.

AWOL

I'm now going to have to go into the garden and find a large, well-anchored tree stump.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Coding Badly


XD

Well-anchored granite boulders are my bane.  When it's taken all day to install three fence posts, a few sticks of dynamite would be a very welcome addition to the tool chest.

InvalidApple

#11
Aug 23, 2011, 03:55 am Last Edit: Aug 23, 2011, 03:58 am by InvalidApple Reason: 1
Interrupts can be tricky.  However; I don't think that you should avoid them all together, because they can be useful in multitasking.

Try declaring "setting" as:

volatile int setting = 0;

[edit] Sorry, I didn't see that AWOL already suggested that in post #2 [/edit]

Nick Gammon

Personally I don't mind interrupts if used properly. As you say, they are useful for catching short button presses, maybe which might happen while updating the LCD.


  • Make sure you have the button on the right pin (D3 for interrupt 1).

  • Make sure you have correct pull-up or pull-down resistors as appropriate.

  • Some debounce code is essential (eg. check millis () and make sure something like 100 have elapsed)

  • Use "volatile" on the interrupt flag or the compiler might optimize away your check of it.



Apart from that you seem to be on the right track. :)
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

retrolefty

My introduction to using interrupts on the Arduino was using the MStimer2 library. That library make interrupts very understandable and it's a great tool to have in one's tool box.

http://www.arduino.cc/playground/Main/MsTimer2


retrolefty

Quote
Some debounce code is essential (eg. check millis () and make sure something like 100 have elapsed)


Do you have an example of using software debouncing with a interrupt driven button? I have not quite figured out how to do it inside a ISR where millis() is frozen.

Lefty


Go Up