Interrupt issues

I believe this is the right spot to ask this… How might I be able to use an interrupter with multiple buttons? I have 3 buttons, each doing different things. However, I only have 2 interrupt options on this nano. I did something and it seems to be working fairly well, except… Well, there are a few issues. It does work, but not as well as I’d hoped. Any advice would be appreciated. (See picture included for my basic set up)

void setup()
{
  pinMode(13, OUTPUT);
  pinMode(2, INPUT_PULLUP);
  pinMode(8, INPUT_PULLUP);
  pinMode(9, INPUT_PULLUP);
  pinMode(10, INPUT_PULLUP);
  Serial.begin(9600);
  attachInterrupt(digitalPinToInterrupt(2),btn,FALLING);
}

void btn()
{
  Serial.print("Pins: ");
  Serial.print(digitalRead(9)==0);
  Serial.print(digitalRead(10)==0);
  Serial.println((digitalRead(8)==0));
//   more code for button 1 - 8
//   more code for button 2 - 9
//   more code for button 3 - 11
}

void loop()
{
  digitalWrite(13, HIGH);
  delay(1000); // Wait for 1000 millisecond(s)
  digitalWrite(13, HIGH);
  delay(1000); // Wait for 1000 millisecond(s)
}

So, currently, I’d press a button and there’s a random chance it will do the “more code” but sometimes it simply says there’s a, say “100” but doesn’t do the ‘more code.’ Additionally, sometimes it triggers, but it ends up printing “000” to the output and as such, don’t do anything more, agian not running the appropriate additional code.
After this wasn’t working, I tried setting a value in the interrupt and having it so the look checks if said value is 1 2 or 3, after which it does the code in the loop function and then sets the value to 0. Still the same issues though, but it does seem to be a little more stable…

Any help would be greatly appreciated! Thank you and have a nice day!

NOTE: This is for a project that I’m unsure how much help I can get. Due to this, I’ve only done a small slice of the program. This is an idea I had before this, so It’s more a “I’m writing an essay, but is it effect or affect?” not something limited to just this project.

It would be very unlikely that you need to use interrupts to detect buttons. Humans pressing buttons are very slow by Arduino standards and the buttons should be easily capable of being read by polling - i.e. reading the button states on each iteration of loop().

Have a look at how the code is organized in Several Things at a Time

Note how each function runs very briefly and returns to loop() so the next one can be called. None of the functions tries to complete a task in one call. And there may be dozens of calls to a function before it is actually time for it to do anything.

...R

As Robin says, interrupts are not the right tool for detecting button presses.

Below is some sample code for detecting button presses, offered ‘as is’. You might need to modify it to do what you need.

Note that one of the reasons people new to micro-controllers want to use interrupts for buttons is because they have written blocking code that cannot possibly poll inputs anything like often enough. The answer is to write non-blocking code and the link Robin has given you will help you with that. The code I have put below is to complement what Robin has shown you, not to offer an alternative to it.

/* Simple button debounce for 4 buttons. Increments a count and sends the updated count to the serial monitor once per button press */
/* Tested on an Uno */
/* Connect simple push to make buttons between 0V and pin 2, 0V and pin 3, 0V and pin 4 and between 0V and pin 5 */

#define noOfButtons 4     //Exactly what it says; must be the same as the number of elements in buttonPins
#define bounceDelay 20    //Minimum delay before regarding a button as being pressed and debounced
#define minButtonPress 3  //Number of times the button has to be detected as pressed before the press is considered to be valid

const int buttonPins[] = {2, 3, 4, 5};      // Input pins to use, connect buttons between these pins and 0V
uint32_t previousMillis[noOfButtons];       // Timers to time out bounce duration for each button
uint8_t pressCount[noOfButtons];            // Counts the number of times the button is detected as pressed, when this count reaches minButtonPress button is regared as debounced 
uint8_t testCount[noOfButtons];             //Test count, incremented once per button press

void setup() {
  uint8_t i;
  uint32_t baudrate = 115200;
  Serial.begin(baudrate);
  Serial.println("");
  Serial.print("Serial port connected: ");
  Serial.println(baudrate);
  for (i = 0; i < noOfButtons; ++i) {
    pinMode(buttonPins[i], INPUT_PULLUP);
    Serial.print("Testcount ");
    Serial.print(i);
    Serial.print(" = ");
    Serial.println(testCount[i]);
  }
}

void loop() {
  debounce();
  delay(10);     //Your other code goes here instead of this delay. DO NOT leave this delay here, it's ONLY for demonstration.
}

void debounce() {
  uint8_t i;
  uint32_t currentMillis = millis();
  for (i = 0; i < noOfButtons; ++i) {
    if (digitalRead(buttonPins[i])) {             //Input is high, button not pressed or in the middle of bouncing and happens to be high
        previousMillis[i] = currentMillis;        //Set previousMillis to millis to reset timeout
        pressCount[i] = 0;                        //Set the number of times the button has been detected as pressed to 0
      } else {
      if (currentMillis - previousMillis[i] > bounceDelay) {
        previousMillis[i] = currentMillis;        //Set previousMillis to millis to reset timeout
        ++pressCount[i];
        if (pressCount[i] == minButtonPress) {
          doStuff(i);                             //Button has been debounced. Call function to do whatever you want done.
        }
      }
    }
  }
}

// Function to do whatever you want done once the button has been debounced.
// In this example it increments a counter and send the count to the serial monitor.
// Put your own functions here to do whatever you like.
void doStuff(uint8_t buttonNumber) {
  ++testCount[buttonNumber];
  Serial.print("Button ");
  Serial.print(buttonNumber);
  Serial.print(" testcount = ");
  Serial.println (testCount[buttonNumber]);
}

That is not what interrupts are for!

As a beginner, it is incredibly unlikely that interrupts will be useful to you.

A common "newbie" misunderstanding is that an interrupt is a mechanism for altering the flow of a program - to execute an alternate function. Nothing could be further from the truth! :astonished:

An interrupt is a mechanism for performing an action which can be executed in "no time at all" with an urgency that it must be performed immediately or else data - information - will be lost or some harm will occur. It then returns to the main task without disturbing that task in any way though the main task may well check at the appropriate point for a "flag" set by the interrupt.

Now these criteria are in a microprocessor time scale - microseconds. This must not be confused with a human time scale of tens or hundreds of milliseconds or indeed, a couple of seconds. A switch operation is in this latter category and a mechanical operation perhaps several milliseconds; the period of a 6000 RPM shaft rotation is ten milliseconds.

Unless it is a very complex procedure, you would expect the loop() to cycle many times per millisecond. If it does not, there is most likely an error in code planning; while the delay() function is provided for testing purposes, its action goes strictly against effective programming methods. The loop() will be successively testing a number of contingencies as to whether each requires action, only one of which may be whether a particular timing criteria has expired. Unless an action must be executed in the order of microseconds, it will be handled in the loop().

So what sort of actions do require such immediate attention? Well, generally those which result from the computer hardware itself, such as high speed transfer of data in UARTs(, USARTs) or disk controllers.

An alternate use of interrupts, for context switching in RTOSs, is rarely relevant to this category of microprocessors as it is more efficient to write cooperative code as described above.

I would suggest getting the Arduino cookbook by Michael Margolis and read it. You will find on line many videos etc showing the Arduino and how to do use it some of it may be what you want. This additional information will go a long way in getting your problem solved and reference material for your essay. There are also many videos showing how to read a data sheet. Once you get past this you then need to select your sensors and actuators. At that point you start on the hardware design and write your software.