Github Boards Devices Community Docs Blog

Evaluate 2 reed contacts

Hello,

First of all, thank you for such a great project!

I have several “AZDelivery ESP32 NodeMCU” on which I want to run:

  • 433 MHz RF → Sockets
  • BLE → presense,
  • BH170 → Light
  • BME280 → Temperature, air pressure, humidity
  • DS18B20 → Temperature (freezer, refrigerator)
  • IR → TV remote control
  • RCWL-0516 (als HC-SR501) → motion detector
  • Reed-Kontakte → Door / window sensors

433 MHz, BLE and BME280 are already running, with: OMG V0.9.5

And now to the question:

I want 2 reed contacts like this one:
https://community.openmqttgateway.com/t/project-with-lora-sensors/1030/30
evaluate, but find no information on this for OMG.

If I understood it right:
with “GPIOInput” I can query 1 contact,
with “GPIOKeyCode” I can query 3 contacts if: “GPIOKeyCode_LATCH_GPIO” is true?

With the default settings of “GPIOKeyCode” I have GPIO conflicts

  • GPIO 12 → HFY-FST
  • GPIO 14 → IR_Emitter
  • GPIO 5 → HC SR-501
  • GPIO 13 → FASTLED + GPIOInput

and:

   # define GPIOKeyCode_D3_GPIO XX // ??
  # endif
 #else
  // must define !!!

into “config_GPIOKeyCode.h” I do not understand.

  • for “D3_GPIO XX” I suspect I can enter a GPIO myself, but it is not evaluated in “ZsensorGPIOKeyCode.ino” !?
  • “// must define !!!” ": What must / should I define there?

Because of the wiring, it is enough:
GPIO — o / o — GND
or:
3.3 V — o / o — GPIO

or do I have to use pullup or pulldown?
3.3 V ----- | R 100 k | — GPIO — o / o — GND
3.3 V — o / o ----- GPIO — | R 100 k | — GND

Is “R 100 k” okay? I find circuits from 5k to 470k. Unfortunately, I am not an electronics technician and I do not want to destroy the ESP32.

Many thanks in advance for your help!

LutzG

No answer is also an answer. :pensive:

I’m not a programmer, but I borrowed a few lines from “GPIOInputt” and “PWM actuator” and modified “config_GPIOInput.h” and “ZsensorGPIOInput.ino”.It works, but it would be nice if someone could have a look who is familiar with it.

The wiring, is:
GPIO — o / o — GND

My config_GPIOInput.h:

#ifndef config_GPIOInput_h

#define config_GPIOInput_h

extern void setupGPIOInput();

extern void GPIOInputtoMQTT();

/*----------------------------USER PARAMETERS-----------------------------*/

/*-------------DEFINE YOUR MQTT PARAMETERS BELOW----------------*/

#define subjectGPIOInputtoMQTT "/GPIOInputtoMQTT"

#define GPIOInputDebounceDelay 60 //debounce time, increase if there are issues

/*-------------------PIN DEFINITIONS----------------------*/

#if defined(ESP8266) || defined(ESP32)

#  ifndef INPUT_GPIO_PINS

#    define INPUT_GPIO_NAMES { "gpio0", "gpio2", "gpio4", "gpio15" }

#    define INPUT_GPIO_PINS { 0, 2, 4, 15 }

#  else

#    // must define, i only have one ESP32 !!!

#    define INPUT_GPIO_NAMES { “gpio1”, “gpio2”, “gpio3” }

#    define INPUT_GPIO_PINS { 1, 2, 3 }

#  endif

#endif

#endif

My ZsensorGPIOInput.ino:

#include "User_config.h"

#ifdef ZsensorGPIOInput

unsigned long lastDebounceTime = 0;

static const char* GPIO_NAMES[] = INPUT_GPIO_NAMES;

static const int INPUT_GPIO[] = INPUT_GPIO_PINS;

static const int kNumChannels = sizeof(INPUT_GPIO) / sizeof(int);

int InputState[kNumChannels]; // Set to 3 so that it reads on startup

int lastInputState[kNumChannels];

void setupGPIOInput() {

  for (int i = 0; i < kNumChannels; ++i) {

    // Configure the pin for pullup.

    Log.notice(F("Reading GPIO at pin: %d" CR), INPUT_GPIO[i]);

    pinMode((INPUT_GPIO[i]), INPUT_PULLUP); // declare GPIOInput pin as input_pullup to prevent floating. Pin will be high when not connected to ground

    InputState[i] = 3; 

    lastInputState[i] = 3;

  }

  Log.notice(F("ZsensorGPIOInput setup done " CR));

}

void MeasureGPIOInput() {

  for (int i = 0; i < kNumChannels; ++i) {

    int reading = digitalRead(INPUT_GPIO[i]);

    // check to see if you just pressed the button

    // (i.e. the input went from LOW to HIGH), and you've waited long enough

    // since the last press to ignore any noise:

    // If the switch changed, due to noise or pressing:

    if (reading != lastInputState[i]) {

      // reset the debouncing timer

      lastDebounceTime = millis();

    }

    if ((millis() - lastDebounceTime) > GPIOInputDebounceDelay) {

      // whatever the reading is at, it's been there for longer than the debounce

      // delay, so take it as the actual current state:

#    if defined(ESP8266) || defined(ESP32)

      yield();

#    endif

      // if the Input state has changed:

      if (reading != InputState[i]) {

        InputState[i] = reading;

        Log.trace(F("Creating GPIOInput buffer" CR));

        const int JSON_MSG_CALC_BUFFER = JSON_OBJECT_SIZE(1);

        StaticJsonBuffer<JSON_MSG_CALC_BUFFER> jsonBuffer;

        JsonObject& GPIOdata = jsonBuffer.createObject();

        if (InputState[i] == HIGH) {

          GPIOdata.set(GPIO_NAMES[i], "HIGH");

        }

        if (InputState[i] == LOW) {

          GPIOdata.set(GPIO_NAMES[i], "LOW");

        }

        if (GPIOdata.size() > 0)

          pub(subjectGPIOInputtoMQTT, GPIOdata);

      }

    }

    // save the reading. Next time through the loop, it'll be the lastInputState:

    lastInputState[i] = reading;

  }

}

#endif

LutzG

1 Like

That’s nice, if you want you can submit a PR, I will review it.

Sorry for not answering you earlier.

Sorry, i don’t know what you mean by:

“if you want you can submit a PR”

? :thinking: If it comes to inclusion in the project, I would be really excited about it!

My problem is, I don’t understand some commands and don’t know what they do / whether they are necessary. Example:

#    define INPUT_GPIO_NAMES { "gpio0", "gpio2", "gpio4", "gpio15" }
  • I have the name “gpio”, but I can’t pass the number of the pin with it Like: “gpio” + "15 " = “gpio15”

  • I don’t found the difference between Log.notice and Log.trace

  • I don’t know who is the variable “%d”?

    Log.notice(F("Reading GPIO at pin: %d" CR), INPUT_GPIO[i]);
    

And events are only fired when something changes. The status of the contacts should be transmitted from time to time, a door or window can be open or closed for months …

I haven’t continued there yet.

LutzG

Sorry, PR = Pull request, this means submitting your code to a github repository
https://github.com/1technophile/OpenMQTTGateway/pulls

I’m not sure we need the GPIO names, should the input number be enough INPUT_GPIO

This are two different level of log depending on the information criticity that we want to display in the serial monitor, notice correspond to the log level use to monitor the standard behaviour of the gateway.
Trace would be used for extended informations.

In this, %d is replaced by the value of INPUT_GPIO[i] it specifies the information to display, see below:
https://www.cplusplus.com/reference/cstdio/printf/

Sorry, I’m getting off at this point. I didn’t think that I would be the only one who wanted to use reed contacts (simple HIG / LOW queries).

I already have a very steep learning curve:

  • English (I’m from Germany, the translation is by Aunt Gogel)
  • Visual Studio Code,
  • PlatformIO,
  • MicroPython (a customized c ++?)
  • fhem,
  • OpenMQTTGateway.

I’ve read a lot about Git now, but still don’t understand it. I’m 58, so learning isn’t that easy anymore.

Incidentally, I only found out today that the programming language is not Python.

Thank you for your patience and the great project!

LutzG

Hello,

I have expanded “GPIO KeyCode” a little. If no contact is changed, the state is fired every minute. The time can be adjusted in “config_GPIOInput.h: TimeMinPulling”.

I had the problem in fhem that the reading was:

  "GPIOInputtoMQTT: {" gpio ":" HIGH "}"

But that could also have happened through my gimmick. The correct reading is:

OMG_Test: home / OMG_Test / GPIOInputtoMQTT:. * {Json2nameValue ($ EVENT)}

where “OMG_Test” is the name of my ESP32. Can be changed in the device with “Raw definition”. Maybe there will be someone who makes this version a “PR”. :wink:

My config_GPIOInput.h:

#ifndef config_GPIOInput_h
#define config_GPIOInput_h

extern void setupGPIOInput();
extern void GPIOInputtoMQTT();

/*----------------------------USER PARAMETERS-----------------------------*/
/*-------------DEFINE YOUR MQTT PARAMETERS BELOW----------------*/
#define subjectGPIOInputtoMQTT "/GPIOInputtoMQTT"
#define GPIOInputDebounceDelay 60 //debounce time, increase if there are issues
#define TimeMinPulling 60000      // maximum time without a pulling

/*-------------------PIN DEFINITIONS----------------------*/
#if defined(ESP8266) || defined(ESP32)

// The number of names and pins must be identical!
#  ifndef INPUT_GPIO_PINS
#    define INPUT_GPIO_NAMES { "Gpio 0", "SZ-left", "SZ-right", "Door" }
#    define INPUT_GPIO_PINS { 0, 2, 4, 15 }
#  else
#    // must define, i only have one ESP32 !!!
#    define INPUT_GPIO_NAMES { “gpio1”, “gpio2”, “gpio3” }
#    define INPUT_GPIO_PINS { 1, 2, 3 }
#  endif

#endif

#endif

My ZsensorGPIOInput.ino:

#include "User_config.h"

#ifdef ZsensorGPIOInput

static const char* GPIO_NAMES[] = INPUT_GPIO_NAMES;
static const int INPUT_GPIO[] = INPUT_GPIO_PINS;
static const int GPIOIndex = sizeof(INPUT_GPIO) / sizeof(int);

int InputState[GPIOIndex]; // Set to 3 so that it reads on startup
int lastInputState[GPIOIndex];
unsigned long lastPull[GPIOIndex];
unsigned long lastDebounceTime[GPIOIndex];
bool bNewPull = false;

void setupGPIOInput() {
  for (int i = 0; i < GPIOIndex; ++i) {
    // Configure the pin for pullup.
    Log.notice(F("Reading GPIO at pin: %d" CR), INPUT_GPIO[i]);
    pinMode((INPUT_GPIO[i]), INPUT_PULLUP); // declare GPIOInput...
    InputState[i] = 3; 
    lastInputState[i] = 3;
    lastPull[i] = 0;
  }
  Log.notice(F("ZsensorGPIOInput setup done " CR));
}

void MeasureGPIOInput() {
  for (int i = 0; i < GPIOIndex; ++i) {
    int reading = digitalRead(INPUT_GPIO[i]);

// check to see if you just pressed the button
// (i.e. the input went from LOW to HIGH), and you've waited long enough
// since the last press to ignore any noise:

// If the switch changed, due to noise or pressing:
if (reading != lastInputState[i]) {
  // reset the debouncing timer
  lastDebounceTime[i] = millis();
  bNewPull = true;
}

// overflow
if (millis() < lastPull[i]) {
  lastPull[i] = millis();
}

// Time last pulling
if ((millis() - lastPull[i]) > TimeMinPulling) {
  lastPull[i] = millis();
  bNewPull = true;
}

    if ((millis() - lastDebounceTime[i]) > GPIOInputDebounceDelay) {
      // whatever the reading is at, it's been there for longer than the debounce
      // delay, so take it as the actual current state:
#    if defined(ESP8266) || defined(ESP32)
      yield();
#    endif
      // if the Input state has changed:
      if (reading != InputState[i]) {
        InputState[i] = reading;
        bNewPull = true;
      }
      if (bNewPull) {
        Log.trace(F("Creating GPIOInput buffer" CR));
        const int JSON_MSG_CALC_BUFFER = JSON_OBJECT_SIZE(1);
        StaticJsonBuffer<JSON_MSG_CALC_BUFFER> jsonBuffer;
        JsonObject& GPIOdata = jsonBuffer.createObject();
        if (InputState[i] == HIGH) {
          GPIOdata.set(GPIO_NAMES[i], "HIGH");
        }
        if (InputState[i] == LOW) {
          GPIOdata.set(GPIO_NAMES[i], "LOW");
        }
        if (GPIOdata.size() > 0)
          pub(subjectGPIOInputtoMQTT, GPIOdata);
      }
    }

    // save the reading. Next time through the loop, it'll be the lastInputState:
    lastInputState[i] = reading;
    bNewPull = false;
  }
}
#endif

With “INPUT_GPIO_NAMES” I left, so everyone can call his contacts what he wants.

LutzG

1 Like