GreyGnome / EnableInterrupt

New Arduino interrupt library, designed for Arduino Uno/Mega 2560/Leonardo/Due
329 stars 73 forks source link

Any chance of integrating esp8266? #40

Closed linuxlurak closed 5 years ago

linuxlurak commented 7 years ago

Is there any chance of integrating esp8266 chips?

GreyGnome commented 7 years ago

Not by me, sorry. I don't have the time to delve into this chip. Since I don't use it, I don't have a personal interest in it. I should mention that the chip is quite different from the ATmega series.

I will leave this open until May 2018 in case someone decides that they want to tackle it.

SamuelM333 commented 6 years ago

+1

MulajEgzon commented 6 years ago

@linuxlurak Do you need this library to work on esp8266 ? Maybe I can try to do something during this year! attachInterrupt(digitalPinToInterrupt(interruptPin), handleInterruptFunc, InterruptStateFR); I think that "attachInterrupt" works on esp8266, you should try it !

zoomx commented 6 years ago

From ESP8266 core reference Pin interrupts are supported through attachInterrupt, detachInterrupt functions. Interrupts may be attached to any GPIO pin, except GPIO16. Standard Arduino interrupt types are supported: CHANGE, RISING, FALLING. http://esp8266.github.io/Arduino/versions/2.1.0-rc2/doc/reference.html

SamuelM333 commented 6 years ago

@zoomx Yes but we don't get a way to Determine the Pin That Was Interrupted. I needed that for a project and I had to fallback to a conventional port check every N ms.

stickbreaker commented 6 years ago

@SamuelM333 Just create a interrupt handler for each pin that pass it's pin to your general interrupt handler.


void interruptHandler( uint8_t pin){
// do something base on pin
switch(pin){
  case 1: //something important
    break;
  case 2: // something important for pin 2
   break;
  default :;
  }
}

void pin1(void){
interruptHandler(1);
}

void pin2(void){
interruptHandler(2);
}

attachInterrupt(digitalPinToInterrupt(1),pin1,change);
attachInterrupt(digitalPinToInterrupt(2),pin2,change);

Chuck.

SamuelM333 commented 6 years ago

@stickbreaker I need to add the handlers in a dynamic way. I get some IoT task from a DB with the ports that I want to operate, so that's not an option for me. Thanks, either way.

zoomx commented 6 years ago

@SamuelM333 EnableInterrupt is useful on Arduino Atmega328 boards because you have only 2 pin you can attach interrupt. All the others give you a signal but you have to determine which one. ESP8266 seems different so you can use attachInterrupt to any pin (except 16) in the same way that you use in Arduino for the two dedicated pin. It means that the pin that have interrupted is determined and you don't need this library.

SamuelM333 commented 6 years ago

@zoomx Ok could you give me an example of that please?

MulajEgzon commented 6 years ago

@SamuelM333 Exactly, I tested this a year ago by using attachInterrupt function in every gpio of esp8266 huzzah feather of adafruit ! esp8266 @zoomx For further examples and discusses you can find them on this issue https://github.com/esp8266/Arduino/issues/715

SamuelM333 commented 6 years ago

I just want to be able to get the pin that got interrupted inside the callback assigned by attachInterrupt. In all the examples that I've seen, the pins are defined as constants. But I can't do that because I set up the interrupt pins dynamically by a JSON payload. That's why I was interested in Determine the Pin That Was Interrupted.

zoomx commented 6 years ago

I don't understand If you don't use attachInterrupt to a pin you don't get any interrupt on that pin. You have to use attachInterrupt on any pin you want to use. You have to use a different interruptHandler for every pin. If in your project you espect an interrupt on 5 pins (for example) you must use attachInterrupt on all 5 pins (five attachInterrupt) and use 5 interruptHandler (interruptHandler is just the name of function called in attachInterrupt.

something like this void HandlerPin1(void){ //something important on pin1 }

void HandlerPin2(void){ //something important on pin2 }

void HandlerPin3(void){ //something important on pin3 }

attachInterrupt(GPIO_1,HandlerPin1,RISING); attachInterrupt(GPIO_2,HandlerPin2,RISING); attachInterrupt(GPIO_3,HandlerPin3,RISING);

There are a tutorial also here https://techtutorialsx.com/2016/12/11/esp8266-external-interrupts/ You don't need to use function digitalPinToInterrupt, you can use directly pin name.

SamuelM333 commented 6 years ago

@zoomx Let me show you a piece of my code. Here is a function that receives a JSON object using the ArduinoJSON lib. It setups a port as output and several others as input.

void setup_new_task(JsonObject &task) {
    // Set output port pinMode
    const char *task_id = task["_id"];
    uint8_t output_port_number = task["output_port"]["number"];
    pinMode(output_port_number, OUTPUT);

    // Set input port pinMode for conditions
    JsonArray &conditions = task["conditions"];

    for (JsonArray::iterator conditions_iterator = conditions.begin();
      conditions_iterator != conditions.end(); ++conditions_iterator) {

        if (conditions_iterator->as<JsonObject &>()["input_port"].success()) {
            uint8_t input_port_number = conditions_iterator->as<JsonObject &>()["input_port"]["number"];
        pinMode(input_port_number, INPUT_PULLUP);
            attachInterrupt(input_port_number, general_handler, CHANGE); // This is the functionality that I need
    }
    }
}

// Somewhere else in my project
void general_handler() {
    switch(pin) { // Get pin number somehow
        case 1:
            //something for pin 1
            break;
        case 2:
            // something for pin 2
            break;
        // case ...    
        default :;
    }
}

Hope that with this now you understand why I can't have a defined set of handlers. The user can set any valid port as output or input via an API, so I need this dynamic.

This is the project that I'm working on Serverchip/ESP8266. It is a WIP so it's not documented.

zoomx commented 6 years ago

You have to add an interruptHandler for every possible pin then you will use only those contained in the json definition file. In every interrupt handle you call general_handler and pass pin number, like in stickbreaker example above. But I believe that is better to break general_handler code and put every case in the interruptHandler for that pin, it's more simple. Remember that if there is not an attachInterrupt for a interruptHandler his code will never be executed.

If you have to change pins you must use detachInterrupt on the previous pins used.

SamuelM333 commented 6 years ago

@zoomx I ended up defining a handler for every possible pin like you said. But like @stickbreaker suggested, I defined short functions with a call to a main handler and hardcoding the pin number in each function. I also defined a map to make the things easier. It works and I don't have to check for port changes in each loop(). I still don't like this approach but it's far better than checking all ports every 100ms.


std::map<int, void (*)(void)> input_port_interrupt_handlers;

void pin_state_change(uint8_t pin) {
    // Actual hard work for the handler
}

void handler_pin0(void) { pin_state_change(0); }
void handler_pin2(void) { pin_state_change(2); }
void handler_pin3(void) { pin_state_change(3); }
//And so on

input_port_interrupt_handlers[0] = handler_pin0;
input_port_interrupt_handlers[2] = handler_pin2;
input_port_interrupt_handlers[3] = handler_pin3;
// And so on

// Inside setup_new_task(JsonObject &task)
pinMode(input_port_number, INPUT_PULLUP);
detachInterrupt(input_port_number);
attachInterrupt(input_port_number, input_port_interrupt_handlers[input_port_number], CHANGE);
GreyGnome commented 5 years ago

Thanks for all the input and feedback! I'll close this as not an issue.