Pfannex / OmniESP

Omni ESP - Universelles Framework für ESP-Devices mit MQTT-Anbindung
http://s6z.de
GNU General Public License v3.0
9 stars 4 forks source link

Button Interrupt questions #17

Open caco3 opened 5 years ago

caco3 commented 5 years ago

I would like to have an external interrupt (eg. button) to trigger an IRQ handler.

The implemented irqHandle() in GPIO.cpp seems not to support a custom handle for this. I therefore created a standard interrupt handler and configuration:

volatile uint32_t count = 0;

void ICACHE_RAM_ATTR myPinIrq() {
  count++;
  Serial.println(count);
}

void customDevice::start() {
  // [..]
  pinMode(D3, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(D3), myPinIrq, FALLING);
  // [..]
}

This seems to work, how ever only if I pull this pin low for 1+ second! What could be the reason for this suppression? Is it possible that the OmniESP core interferes which the interrupt handler?

Pfannex commented 5 years ago

Hi caco3,

The implemented irqHandle() in GPIO.cpp seems not to support a custom handle for this.

The GPIO-module supports everything you need:

For more information take a look in our example device simpleSwitch: https://github.com/Pfannex/OmniESP/tree/master/_customDevices/simpleSwitch

and our Wiki: https://github.com/Pfannex/OmniESP/wiki/devices#simpleswitch

caco3 commented 5 years ago

Thanks for the reply! I had a look on this before. If I understand it directly, those interrupts will send a MQTT message. I how ever need to be able to call a local function.

See the following scenario: For my weatherstation I want to use a rain gauge, eg. https://www.aliexpress.com/item/32793367115.html If a lot of rain comes, I might get a lot of interrupts, how ever I do not want to send each one of them separately. The idea is to have a counter and only sent a MQTT message every one minute or so (if the counter is > 0). This is mainly to reduce the dBLog of my FHEM.

Pfannex commented 5 years ago

Hi caco3,

OK, I understand..... So, you have to write your own module based on the gpio-class. There are more than one possible solutions:

I prefear solution #3

e.g.

//===============================================================================
//  GPIOinput
//===============================================================================
GPIOinput::GPIOinput(string name, LOGGING &logging, TopicQueue &topicQueue,
          int GPIOinputPin, int count = 0)
          : Module(name, logging, topicQueue), pin(GPIOinputPin)
          {
}
//...............................................................................
// start
//...............................................................................
void GPIOinput::start() {
  Module::start();
  logging.info("setting GPIO pin " + String(pin) + " for input");
  pinMode(pin, INPUT_PULLUP);
  irqSetMode(FALLING);

  (!count) ? (countActive = false) : (countActive = true);

}
void GPIOinput::irqHandle() {
  unsigned long now = millis();
  String eventPrefix= "~/event/device/" + String(name) + "/";

// main handling

...
...
...
      }else{
        //just a simple click
        if (!counterActive){
          lastEvent = click;
          logging.debug("GPIO " + String(pin) + " CLICK");
          topicQueue.put(eventPrefix + "click short");
        }else{
        //do the counter events
           inCount++;
           if (inCount > count){
           lastEvent = click;
            logging.debug("GPIO " + String(pin) + " counterEvent");
            topicQueue.put(eventPrefix + "counterEvent");
            }      
        }
      }
      //handling complete, prepare to start again
      tstart = 0;
      irqSetMode(FALLING);
    }
  }

...
...
...

}