xoseperez / espurna

Home automation firmware for ESP8266-based devices
http://tinkerman.cat
GNU General Public License v3.0
3k stars 638 forks source link

Inverting digital sensor or its MQTT output. #2475

Open davebuk opened 3 years ago

davebuk commented 3 years ago

EDIT - HIGH and LOW WRT PIR switch state. Hi all.

I was using the EVENT sensor on a D1 mini with some PIR sensors to trigger MQTT outputs. The PIR sensors have external pull-ups and are LOW normally and go HIGH when triggered.

As EVENT doesn't seem to send MQTT messages anymore unless the SENSOR REPORT cycle is sending an update, I've gone back to looking at DIGITAL instead. The device is seeing the physical changes but starts at 1 going to 0 when triggered.

Can I set the DIGITAL_PIN to be inverted so it shows 0 even though the input is actually LOW and then shows 1 when HIGH?

I did also look at the comment here: https://github.com/xoseperez/espurna/issues/2368#issuecomment-700373781 but the code set digitalMaxDelta0 1 doesn't work as the digital output is going from 1 to 0. Can I change the Delta so that MQTT is sent straight away when the trigger goes from LOW to HIGH?

davebuk commented 3 years ago

Maybe I'm best to use BUTTONS and send all MQTT on button state change. Or I could pair each input to an inverted dummy relay and take the MQTT message from the relay?

mcspr commented 3 years ago

Can I set the DIGITAL_PIN to be inverted so it shows 0 even though the input is actually LOW and then shows 1 when HIGH?

I did also look at the comment here: #2368 (comment) but the code set digitalMaxDelta0 1 doesn't work as the digital output is going from 1 to 0. Can I change the Delta so that MQTT is sent straight away when the trigger goes from LOW to HIGH?

Should work? I having tried with -DNODEMCU_LOLIN -DDIGITAL_SUPPORT=1 -DDIGITAL1_PIN=5 -DDIGITAL1_DEFAULT_STATE=0 and touching D1 with GND:

[198677] [MQTT] Sending test/digital => 0 (PID 1)
[201695] [MQTT] Sending test/digital => 1 (PID 1)
[205720] [MQTT] Sending test/digital => 0 (PID 1)
[206723] [MQTT] Sending test/digital => 1 (PID 1)

Check is an absolute number, 0 -1 and 1 - 0 are always 1. Notice that report happens on reading, so snsRead interval should be lower. (above, it is 1)

davebuk commented 3 years ago

Check is an absolute number, 0 -1 and 1 - 0 are always 1. Notice that report happens on reading, so snsRead interval should be lower. (above, it is 1)

The problem with this is I'll get MQTT updates every 1 second even though there is nothing to process by OpenHAB as there could be no change of sensor state. There is also a small chance that the sensor may have cycled HIGH/LOW during the read time and miss the change.

I've tried a new build using:

    // PIR SWITCHES
    #define BUTTON_MQTT_SEND_ALL_EVENTS     1   
    #define BUTTON2_PIN          3
    #define BUTTON2_CONFIG       BUTTON_SWITCH | BUTTON_SET_PULLUP | BUTTON_DEFAULT_BOOT    
    #define BUTTON3_PIN          4
    #define BUTTON3_CONFIG       BUTTON_SWITCH | BUTTON_SET_PULLUP | BUTTON_DEFAULT_BOOT
    #define BUTTON4_PIN          12
    #define BUTTON4_CONFIG       BUTTON_SWITCH | BUTTON_SET_PULLUP | BUTTON_DEFAULT_BOOT
    #define BUTTON5_PIN          13
    #define BUTTON5_CONFIG       BUTTON_SWITCH | BUTTON_SET_PULLUP | BUTTON_DEFAULT_BOOT
    #define BUTTON6_PIN          14
    #define BUTTON6_CONFIG       BUTTON_SWITCH | BUTTON_SET_PULLUP | BUTTON_DEFAULT_BOOT

This works fine, sending pressed/released for each sensor trigger. I just need to update OpenHAB for the different MQTT strings.

mcspr commented 3 years ago

Could have another sensor modeling the button one. Previous EventSensor used digitalRead right from ISR function: https://github.com/xoseperez/espurna/blob/62ad7da332f3f904ad8241a2b738be9820b196e4/code/espurna/sensors/EventSensor.h#L159-L162

But, if the button model works, might re-do that with that one instead (i.e. instead of interrupt, digitalRead() every loop() call and compare with the previous to trigger value change)

davebuk commented 3 years ago

So to have an INVERT option for buttons?

mcspr commented 3 years ago

INVERT option for buttons would be setting a fixed LOW or HIGH default mode? Config above sets BOOT. And there is DIGITAL#_DEFAULT_STATE (config says 1, but it is really means HIGH) that does the same - 1 is reported when the state differs from default one. I meant to either tweak or add another sensor type to force more than 1-per-second pin status checks

davebuk commented 3 years ago

I don't think an additional sensor is needed. BUTTON with #define BUTTON_MQTT_SEND_ALL_EVENTS 1 works well.

So would setting the DEFAULT_STATE LOW mean that an input that was at 3V would actually represent OFF and taking the input to 0V would then represent ON? (If I've got my logic correct).

mcspr commented 3 years ago

So would setting the DEFAULT_STATE LOW mean that an input that was at 3V would actually represent OFF and taking the input to 0V would then represent ON? (If I've got my logic correct).

Other way around. DigitalSensor resulting value is comparing with the default value every 'snsRead'. It will show '0' when it's the same and '1' when it is different. The exact comparison happens here: https://github.com/xoseperez/espurna/blob/62d83c6194630076fa198ddbf0a899ae7fb79672/code/espurna/sensors/DigitalSensor.h#L89

(false == 0 and true == 1, ref. what cppinsights shows)

What I meant by button-like, is to report 'change' in the value during the time sensor idles, since as you've said it loses the values. Either as another sensor, or a 'mode' for the digitalsensor, or another value slot that only reports changes (i.e. DigitalSensor would create 'digital' and 'change' topics)

davebuk commented 3 years ago

Sounds good. A new sensor BI_STABLE_INPUT or mode for the digital sensor would work. It can output it's current status on every sensor report update as defined by the sensor update schedule as well as report status changes as soon as a difference is seen.

This would work well for any PIR or magnetic reed switch type input like the ones used in security systems.