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
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’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.
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”.
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.