Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ESP32 INTERRUPT ON BOTH FALLING AND RISING EDGE #1111

Open
usmanshahid001 opened this Issue Feb 14, 2018 · 19 comments

Comments

Projects
None yet
6 participants
@usmanshahid001
Copy link

usmanshahid001 commented Feb 14, 2018

Hiii i am using proximity sensor with esp32 and it is calling ISR routine on both Falling and Rising Edge
i have verified it using nodemcu which is working properly i have tried all things like Falling Rising Change HIGH but its showing the same behaviour kindly help me in this regard...

@dazjd02

This comment has been minimized.

Copy link

dazjd02 commented Feb 16, 2018

I am using an interrupt on io34 and having the same issue; I have a 10K resistor pulling it high to try to stabilized it. It seems to show the same behavior whether FALLING or RISING is used. Sometimes interrupt occurs on the falling edge and other times it occurs on the rising edge and switches back every few seconds.

@usmanshahid001

This comment has been minimized.

Copy link
Author

usmanshahid001 commented Feb 16, 2018

actually its working on change no matter which mode is selected...

@usmanshahid001

This comment has been minimized.

Copy link
Author

usmanshahid001 commented Apr 26, 2018

i am having interrupts both on falling and rising edge .........how to resolve that problem related to gpio

@yashfaith

This comment has been minimized.

Copy link

yashfaith commented Apr 29, 2018

i also have the same problem. I am using an interrupt on pin 27, i tried using FALLING and RISING but it seems that the ISR got trigger on CHANGE. are there any solution to this problem?

@usmanshahid001

This comment has been minimized.

Copy link
Author

usmanshahid001 commented Jun 4, 2018

i have check using esp-idf gpio code that is working fine for positive edge trigger....but not working in arduino............

@usmanshahid001

This comment has been minimized.

Copy link
Author

usmanshahid001 commented Jun 6, 2018

#include "driver/gpio.h"

#define GPIO_OUTPUT_IO_0 18
#define GPIO_OUTPUT_IO_1 19
#define GPIO_OUTPUT_PIN_SEL ((1ULL<<GPIO_OUTPUT_IO_0) | (1ULL<<GPIO_OUTPUT_IO_1))
#define GPIO_INPUT_IO_0 4
#define GPIO_INPUT_IO_1 5
#define GPIO_INPUT_PIN_SEL ((1ULL<<GPIO_INPUT_IO_0) | (1ULL<<GPIO_INPUT_IO_1))
#define ESP_INTR_FLAG_DEFAULT 0
extern "C" {
#include "soc/gpio_struct.h"
}

static xQueueHandle gpio_evt_queue = NULL;

static void IRAM_ATTR gpio_isr_handler(void* arg)
{
Serial.println("yes");

}

void setup()
{

Serial.begin(115200);
gpio_config_t pGPIOConfig
{
GPIO_INPUT_PIN_SEL,
GPIO_MODE_INPUT,
GPIO_PULLUP_ENABLE,
GPIO_PULLDOWN_DISABLE,
GPIO_INTR_POSEDGE,
};
pGPIOConfig.intr_type=GPIO_INTR_POSEDGE;
gpio_config(&pGPIOConfig);
gpio_set_intr_type(GPIO_NUM_5, GPIO_INTR_POSEDGE);
gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));

gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
//hook isr handler for specific gpio pin
gpio_isr_handler_add(GPIO_NUM_4, gpio_isr_handler, (void*) GPIO_INPUT_IO_0);
//hook isr handler for specific gpio pin
gpio_isr_handler_add(GPIO_NUM_5, gpio_isr_handler, (void*) GPIO_INPUT_IO_1);
 gpio_isr_handler_remove(GPIO_NUM_4);
//hook isr handler for specific gpio pin again
gpio_isr_handler_add(GPIO_NUM_4, gpio_isr_handler, (void*) GPIO_INPUT_IO_0);

int cnt = 0;

}
void loop()
{

}

@usmanshahid001

This comment has been minimized.

Copy link
Author

usmanshahid001 commented Jun 6, 2018

working in this way

@musskopf

This comment has been minimized.

Copy link

musskopf commented Jul 5, 2018

I can confirm the issue is happening to me as well. My test code looks like:

// User Buttons
#define USER_BT1      25

/*
 * Interrupt Definitions
 */
volatile uint8_t bt1Pressed = 0;

void bt1IntHandler()
{
  bt1Pressed++;
}


void setup() {
  Serial.begin(115200);
  Serial.println("Starting Up");
  
  Serial.println(" - User Buttons");
  pinMode(USER_BT1, INPUT_PULLUP);

  // Some Delay for things to calm down
  delay(30);

  // Add Interrupts
  attachInterrupt(digitalPinToInterrupt(USER_BT1), bt1IntHandler, FALLING);
}

void loop() {
  // Print the number of interrupts every 3 second
  Serial.print("Number of Interrupts: ");
  Serial.println(bt1Pressed);
  delay(3000);
}

I also capture the button press on my scope, no noise in the signal.
ds1104z_ds1za180300224_2018-07-05_15 23 06

The output on the Serial Print always increment by "2" every time I press the button. If I press and hold, it increments 1, but it'll increment 1 again once I release it.

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:956
load:0x40078000,len:0
load:0x40078000,len:13256
entry 0x40078a90
Starting Up
 - User Buttons
Number of Interrupts: 0
Number of Interrupts: 2 <- Quick Press and Release
Number of Interrupts: 4 <- Another Press and Release
Number of Interrupts: 5 <- Press and Hold
Number of Interrupts: 5 <- Still holding
Number of Interrupts: 6 <- Released
Number of Interrupts: 6
@usmanshahid001

This comment has been minimized.

Copy link
Author

usmanshahid001 commented Jul 5, 2018

@usmanshahid001

This comment has been minimized.

Copy link
Author

usmanshahid001 commented Jul 5, 2018

try this code

#include "driver/gpio.h"

#define GPIO_OUTPUT_IO_0 18
#define GPIO_OUTPUT_IO_1 19
#define GPIO_OUTPUT_PIN_SEL ((1ULL<<GPIO_OUTPUT_IO_0) | (1ULL<<GPIO_OUTPUT_IO_1))
#define GPIO_INPUT_IO_0 4
#define GPIO_INPUT_IO_1 5
#define GPIO_INPUT_PIN_SEL ((1ULL<<GPIO_INPUT_IO_0) | (1ULL<<GPIO_INPUT_IO_1))
#define ESP_INTR_FLAG_DEFAULT 0
extern "C" {
#include "soc/gpio_struct.h"
}

static xQueueHandle gpio_evt_queue = NULL;

static void IRAM_ATTR gpio_isr_handler(void* arg)
{
Serial.println("yes");

}

void setup()
{

Serial.begin(115200);
gpio_config_t pGPIOConfig
{
GPIO_INPUT_PIN_SEL,
GPIO_MODE_INPUT,
GPIO_PULLUP_ENABLE,
GPIO_PULLDOWN_DISABLE,
GPIO_INTR_POSEDGE,
};
pGPIOConfig.intr_type=GPIO_INTR_POSEDGE;
gpio_config(&pGPIOConfig);
gpio_set_intr_type(GPIO_NUM_5, GPIO_INTR_POSEDGE);
gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));

gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
//hook isr handler for specific gpio pin
gpio_isr_handler_add(GPIO_NUM_4, gpio_isr_handler, (void*) GPIO_INPUT_IO_0);
//hook isr handler for specific gpio pin
gpio_isr_handler_add(GPIO_NUM_5, gpio_isr_handler, (void*) GPIO_INPUT_IO_1);
gpio_isr_handler_remove(GPIO_NUM_4);
//hook isr handler for specific gpio pin again
gpio_isr_handler_add(GPIO_NUM_4, gpio_isr_handler, (void*) GPIO_INPUT_IO_0);

int cnt = 0;
}
void loop()
{

}

@usmanshahid001

This comment has been minimized.

Copy link
Author

usmanshahid001 commented Jul 5, 2018

attach interrupt function is not working as expected

@musskopf

This comment has been minimized.

Copy link

musskopf commented Jul 5, 2018

Yes, I saw it, many thanks!

In any case, I was highlighting that this still a problem with the Arduino "attachInterrupt" function.

@dazjd02

This comment has been minimized.

Copy link

dazjd02 commented Jul 5, 2018

@william-ferguson-au

This comment has been minimized.

Copy link

william-ferguson-au commented Jul 8, 2018

Just to be clear this happens with the ESPIF libraries too. Not just the Arduino attachInterrupt() function.

Using the same board that @musskopf provided images for above and the following:

volatile uint8_t triggerPressed = 0;

static void IRAM_ATTR triggerIntHandler(void *args) {
    triggerPressed = 1;
}

void setup_hardware() {
    log("Initialising Pins");

    // input pins
    gpio_config_t gpioInputConfig;
    gpioInputConfig.pin_bit_mask = 1ULL << TRIGGER_BT;
    gpioInputConfig.mode = GPIO_MODE_INPUT;
    gpioInputConfig.pull_up_en = GPIO_PULLUP_ENABLE;
    gpioInputConfig.pull_down_en = GPIO_PULLDOWN_DISABLE;
    gpioInputConfig.intr_type = GPIO_INTR_POSEDGE;
    ESP_ERROR_CHECK(gpio_config(&gpioInputConfig));

    ESP_ERROR_CHECK(gpio_install_isr_service(ESP_INTR_FLAG_IRAM));
    gpio_isr_handler_add(TRIGGER_BT, triggerIntHandler, NULL);
}

void loop() {
    while (1) {
        if (triggerPressed) {
            triggerPressed = 0;
            Serial.println("Responding to trigger pressed");
        }

        ...
    }
}

The trigger fires when it is depressed and then once again when it is released.
But it should fire only for GPIO_INTR_POSEDGE.

As you can see from the screenshots from @musskopf the signal is clean.
So what needs to be done to get it to fire on a single edge instead of both edges?

@stickbreaker

This comment has been minimized.

Copy link
Contributor

stickbreaker commented Jul 8, 2018

@william-ferguson-au If the interrupt is allocated to a shared interrupt it only act as a level interrupt. This design choice is required because because of the interrupt latency of sharing an interrupt. The ISR has to do the filtering. Currently pin interrupt routine assumes the hardware will filter base on selection (FALLING, RISING, LOW, HIGH, CHANGE).

I assume(ass u me) that the code has been tested in a single interrupt(non Shared) environment. On a non shared interrupt it will correctly respond.

I ran into the same problem when I was building the I2C ISR.
I cheated, I allocated the interrupt on edge and specified the interrupt status register for my peripheral, and a mask. This allows FreeRTOS to only call my ISR when an Edge happens and the Interrupt status bit is high in the StatusRegister.

    if(!i2c->intr_handle) { // create ISR for either peripheral
        // log_i("create ISR %d",i2c->num);
        uint32_t ret = 0;
        uint32_t flags = ESP_INTR_FLAG_EDGE |  //< Edge-triggered interrupt
          ESP_INTR_FLAG_IRAM |  //< ISR can be called if cache is disabled
          ESP_INTR_FLAG_LOWMED;   //< Low and medium prio interrupts. These can be handled in C.

        if(i2c->num) {
            ret = esp_intr_alloc_intrstatus(ETS_I2C_EXT1_INTR_SOURCE, flags, (uint32_t)&i2c->dev->int_status.val, 0x1FFF, &i2c_isr_handler_default,i2c, &i2c->intr_handle);
        } else {
            ret = esp_intr_alloc_intrstatus(ETS_I2C_EXT0_INTR_SOURCE, flags, (uint32_t)&i2c->dev->int_status.val, 0x1FFF, &i2c_isr_handler_default,i2c, &i2c->intr_handle);
        }

i2c->dev=>int_status.val is the status register, 0x1fff is the mask to apply.

I think the Pin interrupt ISR need to be rewritten. I have not needed it yet.

Chuck.

@william-ferguson-au

This comment has been minimized.

Copy link

william-ferguson-au commented Jul 8, 2018

Note also, that it also fires twice if I use GPIO_INT_NEGEDGE

@william-ferguson-au

This comment has been minimized.

Copy link

william-ferguson-au commented Jul 8, 2018

@stickbreaker when you say "shared" interrupt, what do you mean?

I do want to have interrupts for several pins, but I am getting this behaviour when I have only configured an interrupt for a single pin.

@william-ferguson-au

This comment has been minimized.

Copy link

william-ferguson-au commented Jul 8, 2018

@stickbreaker I read http://esp-idf.readthedocs.io/en/latest/api-reference/system/intr_alloc.html and am now confused.

By using:

gpio_install_isr_service(ESP_INTR_FLAG_IRAM);
gpio_isr_handler_add(BUTTON_1, myHandler, NULL);

am I somehow using a shared interrupt?
For source ETS_GPIO_INTR_SOURCE?

If so, how do I define interrupts for 3 buttons that only fire only the falling edge?

@stickbreaker

This comment has been minimized.

Copy link
Contributor

stickbreaker commented Jul 8, 2018

@william-ferguson-au I'm not able to answer you questions. I have not studied interrupts exhaustively. I just learned enough to solve my problems.
If you read that link you can see that the results you are seeing are mirroring a Shared Level interrupt.

To solve your problem you are going to have to delve deeper into the hardware and the ESP interrupt allocation code. I believe that issues revolve around interrupt source assignment and shared interrupt filtering. Through a quick(non authoritarian review) I surmise that all pin interrupt sources use one interrupt(shared) and either the pin source configuration is wrong, or my understanding is bogus.

This link describes the hardware GPIO interface:
gpio_struct.h

This is the part of the GPIO structure that I think relates to interrupt configuration.
pin interrupt configuration

I think the current GPIO interrupt functions are not correct, but I have not had the need to fix them. Have a Go.

Chuck.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.