improve debounce

This commit is contained in:
Siwat Sirichai 2024-06-21 23:11:08 +07:00
parent 4ea2122f6e
commit 8aeb6ab30a
3 changed files with 119 additions and 58 deletions

View File

@ -57,11 +57,13 @@ bool DigitalInputCard::begin()
{ {
this->inputBankA = PCF8574(this->address_a); this->inputBankA = PCF8574(this->address_a);
this->inputBankB = PCF8574(this->address_b); this->inputBankB = PCF8574(this->address_b);
if (!this->inputBankA.begin()) { if (!this->inputBankA.begin())
{
ESP_LOGE("DigitalInputCard", "Input Card ERROR: Failed to install input bank A"); ESP_LOGE("DigitalInputCard", "Input Card ERROR: Failed to install input bank A");
return false; return false;
} }
if (!this->inputBankB.begin()) { if (!this->inputBankB.begin())
{
ESP_LOGE("DigitalInputCard", "Input Card ERROR: Failed to install input bank B"); ESP_LOGE("DigitalInputCard", "Input Card ERROR: Failed to install input bank B");
return false; return false;
} }
@ -134,39 +136,84 @@ void DigitalInputCard::handlePinChange(int pin, uint8_t &currentBuffer, uint8_t
{ {
// Get the index of the pin in the pin map // Get the index of the pin in the pin map
uint8_t virtualPin = virtualPinMap[pin]; uint8_t virtualPin = virtualPinMap[pin];
// Handle Bank A if (pin < 8)
if (((previousBuffer >> (7 - pin)) & 1) != ((currentBuffer >> (7 - pin)) & 1))
{ {
if (!pinChanged[pin]) { // Handle Bank A
lastDebounceTime[pin] = millis(); if (((previousBuffer >> (7 - pin)) & 1) != ((currentBuffer >> (7 - pin)) & 1))
pinChanged[pin] = true; {
} else { // When the pin first change, store the time
if (millis() - lastDebounceTime[pin] > debounceTime[pin]) if (!pinChanged[virtualPin])
{ {
previousBuffer ^= (-((currentBuffer >> (7 - pin)) & 1) ^ previousBuffer) & (1UL << (7 - pin)); ESP_LOGD("DigitalInputCard", "Pin %d changed", virtualPin);
for (const auto& callback : callbacks) pinChanged[virtualPin] = true;
callback.second(virtualPin, ((currentBuffer >> (7 - pin)) & 1)); lastDebounceTime[virtualPin] = millis();
pinChanged[pin] = false; }
else
{
ESP_LOGD("DigitalInputCard", "Pin %d (%d>%d) debounce time: %d", virtualPin, ((previousBuffer >> (7 - pin)) & 1), ((currentBuffer >> (7 - pin)) & 1), millis() - lastDebounceTime[virtualPin]);
// If the pin was already changed, check if the debounce time has passed
if ((millis() - lastDebounceTime[virtualPin]) > debounceTime[virtualPin])
{
ESP_LOGD("DigitalInputCard", "Pin %d triggered", virtualPin);
// Call the callback function
for (auto const &callback : callbacks)
{
callback.second(virtualPin, ((currentBuffer >> (7 - pin)) & 1));
}
// Store the previous buffer at the specified pin (bitwise operation)
// new value : (currentBuffer >> (7 - pin)) & 1)
previousBuffer = (previousBuffer & ~(1 << (7 - pin))) | (((currentBuffer >> (7 - pin)) & 1) << (7 - pin));
// Reset the pin changed flag
pinChanged[virtualPin] = false;
}
} }
} }
} else
// Handle Bank B {
if (((previousBuffer >> (15 - pin)) & 1) != ((currentBuffer >> (15 - pin)) & 1)) // Pin bounce back to previous state, reset the debounce time
{ lastDebounceTime[virtualPin] = millis();
if (!pinChanged[pin]) { pinChanged[virtualPin] = false;
lastDebounceTime[pin] = millis(); }
pinChanged[pin] = true; }
} else { else
if (millis() - lastDebounceTime[pin] > debounceTime[pin]) {
{ // Handle Bank B
previousBuffer ^= (-((currentBuffer >> (15 - pin)) & 1) ^ previousBuffer) & (1UL << (15 - pin)); if (((previousBuffer >> (15 - pin)) & 1) != ((currentBuffer >> (15 - pin)) & 1))
for (const auto& callback : callbacks) {
callback.second(virtualPin, ((currentBuffer >> (15 - pin)) & 1)); // When the pin first change, store the time
pinChanged[pin] = false; if (!pinChanged[virtualPin])
} {
ESP_LOGD("DigitalInputCard", "Pin %d changed", virtualPin);
pinChanged[virtualPin] = true;
lastDebounceTime[virtualPin] = millis();
}
else
{
ESP_LOGD("DigitalInputCard", "Pin %d (%d>%d) debounce time: %d", virtualPin, ((previousBuffer >> (15 - pin)) & 1), ((currentBuffer >> (15 - pin)) & 1), millis() - lastDebounceTime[virtualPin]);
// If the pin was already changed, check if the debounce time has passed
if ((millis() - lastDebounceTime[virtualPin]) > debounceTime[virtualPin])
{
ESP_LOGD("DigitalInputCard", "Pin %d triggered", virtualPin);
// Call the callback function
for (auto const &callback : callbacks)
{
callback.second(virtualPin, ((currentBuffer >> (15 - pin)) & 1));
}
// Store the previous buffer at the specified pin (bitwise operation)
// new value : (currentBuffer >> (15 - pin)) & 1)
previousBuffer = (previousBuffer & ~(1 << (15 - pin))) | (((currentBuffer >> (15 - pin)) & 1) << (15 - pin));
// Reset the pin changed flag
pinChanged[virtualPin] = false;
}
}
}
else
{
// Pin bounce back to previous state, reset the debounce time
lastDebounceTime[virtualPin] = millis();
pinChanged[virtualPin] = false;
} }
} }
} }
/** /**
@ -317,7 +364,8 @@ uint8_t DigitalInputCard::getType()
* *
* @note This function is useful if you want to preload the input buffers with a run-time value * @note This function is useful if you want to preload the input buffers with a run-time value
*/ */
void DigitalInputCard::preloadInputBuffer() { void DigitalInputCard::preloadInputBuffer()
{
refreshInputBankA(); refreshInputBankA();
refreshInputBankB(); refreshInputBankB();
previousInputBufferA = inputBufferA; previousInputBufferA = inputBufferA;

View File

@ -1,3 +1,3 @@
#pragma once #pragma once
#define SDK_VESRION "2.9.2" #define SDK_VESRION "2.9.3"

View File

@ -12,15 +12,17 @@
#include <AnalogCard.hpp> #include <AnalogCard.hpp>
#include <SmartVariable.hpp> #include <SmartVariable.hpp>
#define INPUT_DEBOUNCE_TIME_MS 1000
// #define FRAM_DEBUG // #define FRAM_DEBUG
// #define MQTT_DEBUG // #define MQTT_DEBUG
// #define RTC_DEBUG // #define RTC_DEBUG
#define WRITE_DEFAULT_NETCONF //#define WRITE_DEFAULT_NETCONF
#define CLIMATE_CARD_ENABLE //#define CLIMATE_CARD_ENABLE
#define MQTT_CARD_REGISTER //#define MQTT_CARD_REGISTER
// #define DISPLAY_ENABLE // #define DISPLAY_ENABLE
#define WEB_SERVER_ENABLE //#define WEB_SERVER_ENABLE
#define LCD_OTA_ENABLE //#define LCD_OTA_ENABLE
// #define REMOTE_VARIABLE_ENABLE // #define REMOTE_VARIABLE_ENABLE
// #define CT_ENABLE // #define CT_ENABLE
// #define SMART_VARIABLE_ENABLE // #define SMART_VARIABLE_ENABLE
@ -116,6 +118,7 @@ void input_change_callback(uint8_t pin, uint8_t value)
Serial.print(pin); Serial.print(pin);
Serial.print(" "); Serial.print(" ");
Serial.println(value); Serial.println(value);
espmega.outputs.toggleState(pin);
} }
void mqtt_callback(char *topic, char *payload) void mqtt_callback(char *topic, char *payload)
@ -187,6 +190,16 @@ void setup()
ESP_LOGI("Initializer", "Connecting to MQTT"); ESP_LOGI("Initializer", "Connecting to MQTT");
espmega.iot->connectToMqtt(); espmega.iot->connectToMqtt();
espmega.iot->registerMqttCallback(mqtt_callback); espmega.iot->registerMqttCallback(mqtt_callback);
// Set debounce time
for (uint8_t i = 0; i < 16; i++)
{
espmega.inputs.setDebounceTime(i, INPUT_DEBOUNCE_TIME_MS);
}
// Set all pin values to 4095
for (uint8_t i = 0; i < 16; i++)
{
espmega.outputs.setValue(i, 4095);
}
#ifdef MQTT_CARD_REGISTER #ifdef MQTT_CARD_REGISTER
ESP_LOGI("Initializer", "Registering cards 0"); ESP_LOGI("Initializer", "Registering cards 0");
espmega.iot->registerCard(0); espmega.iot->registerCard(0);