Hi there, I'm trying to have both interrupts on my Arduino respond to the rising edge of 5V buttons (one button per interrupt). Currently Interrupt1 responds as expected, however, Interrupt2 only activates when it's pulled to ground. Is there a way to have Interrupt2 behave in the same manner as Interrupt1? Should I be doing some manual work with the AVR interrupt library? It appears that the digital pin 2 idles at logic low and digital pin 3 idles at logic high.
Thanks for the help!
Brandon
#define INTERRUPT1 2
#define INTERRUPT2 3
int interrupt1 = 0;
int interrupt2 = 0;
unsigned long interrupt1_time = 0;
unsigned long interrupt1_last_time = 0;
unsigned long interrupt2_time = 0;
unsigned long interrupt2_last_time = 0;
void setup() {
// put your setup code here, to run once:
pinMode(INTERRUPT1, INPUT_PULLUP);
pinMode(INTERRUPT2, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(INTERRUPT1), int1, RISING);
attachInterrupt(digitalPinToInterrupt(INTERRUPT2), int2, RISING);
Serial.begin(115200);
}
void loop() {
// put your main code here, to run repeatedly:
Serial.print("Interrupt 1: ");Serial.println(interrupt1);
Serial.print("Interrupt 2: ");Serial.println(interrupt2);
delay(1000);
}
void int1(){
interrupt1_time = millis();
//check to see if increment() was called in the last 1000 milliseconds
if (interrupt1_time - interrupt1_last_time > 1000)
{
interrupt1++;
interrupt1_last_time = interrupt1_time;
}
}
void int2(){
interrupt2_time = millis();
//check to see if increment() was called in the last 1000 milliseconds
if (interrupt2_time - interrupt2_last_time > 1000)
{
interrupt2++;
interrupt2_last_time = interrupt2_time;
}
}
'm trying to have both interrupts on my Arduino respond to the rising edge of 5V buttons (one button per interrupt). Currently Interrupt1 responds as expected, however, Interrupt2 only activates when it's pulled to ground. Is there a way to have Interrupt2 behave in the same manner as Interrupt1? Should I be doing some manual work with the AVR interrupt library? It appears that the digital pin 2 idles at logic low and digital pin 3 idles at logic high.
Your buttons are not wired the same if they are not behaving the same.
Take a step back, and run a simple sketch with digitalRead() to get the buttons wired to respond as you wish. With INPUT_PULLUP and a RISING interrupt, the interrupt should activate on button release if the button is pulling the input to ground.
Human fingers are slow and arduino's are fast, sohere is no reason to use interrupts to read the state of a button? Why are you trying to use them?
Cattledog - this quick program is just testing for a larger state machine that requires interrupts during low-power modes where the interrupts are still being monitored by the ATMEGA328. The buttons are simply wired from +5 to the respective pins and are shorted when the button is depressed. I'll do a quick sketch with the digitalRead() as you suggested.
I understand why you are wanting to use interrupts, and I do that myself. That's perfectly fine
As far as the code, you always should put variables that are being changed by the ISR's (the functions int1 and int2) as type "volatile".Here's something you can try:
/* This code toggles the ATtiny84 in and out of sleep mode using the button1 pin momentarily
* connected to GND. The ATtiny can also be woken up by connecting another pin to GND using
* another PCINT.
*
* For Arduino (ATmega328), you can use attachInterrupt(digitalPinToInterrupt(pin), ISR, mode)
* and detachInterrupt(digitalPinToInterrupt(pin));
* instead of the PinChangeInterrupt library
*
* Written by: Timothy Woo
* Last Modified: 8/21/2017
*/
#include <PinChangeInterrupt.h>
#define LED 13
#define button1 1
#define button2 2
// Declare variables as volatile if changed in an ISR
volatile unsigned long interrupt1_time = 0;
volatile unsigned long interrupt1_last_time = 0;
volatile unsigned long interrupt2_time = 0;
volatile unsigned long interrupt2_last_time = 0;
volatile unsigned int interrupt1 = 0;
volatile unsigned int interrupt2 = 0;
void setup() {
Serial.begin(115200);
pinMode(LED, OUTPUT);
pinMode(button1, INPUT_PULLUP); // Wire each button to connect the pins to GND
pinMode(button2, INPUT_PULLUP);
attachPCINT(digitalPinToPCINT(button1), ISR1, CHANGE);
attachPCINT(digitalPinToPCINT(button2), ISR2, CHANGE);
}
void loop() {
// Flash LED during normal operation (or do nothing at all)
digitalWrite(LED, HIGH);
delay(250);
digitalWrite(LED, LOW);
delay(250);
}
void ISR1() {
interrupt1_time = millis();
if (millis() - interrupt1_last_time > 100) {
interrupt1++;
interrupt1_last_time = interrupt1_time;
}
}
void ISR2() {
interrupt2_time = millis();
if (millis() - interrupt2_last_time > 100) {
interrupt2++;
interrupt2_last_time = interrupt2_time;
}
}
Also, I said the wrong thing earlier. For ATmega328P it should work with the standard attachInterrupt without PCINT.
The buttons are simply wired from +5 to the respective pins and are shorted when the button is depressed.
With INPUT_PULLUP, you just need to wire across the button to ground. If its one of the common square tactile push buttons, wire diagonally across the button to pick up the switched legs. The interrupt should be set to FALLING to pick up when the button is pushed.
Thanks guys, I managed to get the system working with my original code. Since the button in its "OFF" state was floating the interrupt couldn't get a solid rising edge... So I was switching between "High" and "Unknown" instead of "Hight" and "Low". Once I made the "off" state ground it could tell the difference between the two.
Not sure why it was still working with Interrupt 1, but now it's definitely more reliable. I'll blame it on a case of the Mondays.