MQTT Button Board for Automations

I am trying to create a button board that I can put on my desk to trigger the most used automations I have. I am using ezbutton (https://arduinogetstarted.com/library/button/example/arduino-multiple-button-all) library and my buttons are grounded (same set up as image in the link), no pullup to save space.

I am receiving messages when I listen to the topic, but when I press the button I get “Message 32698 received on homeassistant/switch/button1/state” That is a lot of messages in a few seconds. How do I stop it going from so wild?

I have put in a loop (if (now - lastMsg > 2000) ) to slow it down, but I dont know if this is correct.

I am also trying to get the state from HA in the event I want to move the button board it doesnt reset or change that state of the entities in HA.

My ESP8266 code is as follows:

#include <PubSubClient.h>
#include <ESP8266WiFi.h>
#include <Arduino_JSON.h>
#include <ezButton.h>
// constants won't change. They're used here to set pin numbers:
const int LED_PIN =  16;   // the number of the LED pin
ezButton button1(12);  // create ezButton object that attach to pin 6;
ezButton button2(13);  // create ezButton object that attach to pin 7;
int SwitchedPin = 12;
ezButton button3(14);  // create ezButton object that attach to pin 8;
// variables will change:
String strTopic;
String strPayload;


// Update these with values suitable for your network.
const char* ssid = "";//put your wifi ssid here
const char* password = "";//put your wifi password here.
const char* mqtt_server = "";
//const char* mqtt_server = "iot.eclipse.org";
const char *mqtt_user = "";
const char *mqtt_pass = "";

WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];

void setup_wifi() {
   delay(100);
  // We start by connecting to a WiFi network
    Serial.print("Connecting to ");
    Serial.println(ssid);
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) 
    {
      delay(500);
      Serial.print(".");
    }
  randomSeed(micros());
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void callback(char* topic, byte* payload, unsigned int length) {
  char dataBuf[length+1];               // define a char buffer to add 0 termination
  memcpy(dataBuf, payload, length);     // copy byte buffer to char buffer
  dataBuf[sizeof(dataBuf)-1] = 0;       // add 0 termination
  String str_payload= String(dataBuf);  // copy to string variable
  Serial.println(topic);
  if(strTopic == "homeassistant/switch1/mqttTest/cmd") {
    Serial.println(str_payload);
    if (str_payload == "ON") {
        Serial.println("ON");
        digitalWrite(SwitchedPin, HIGH);
        client.publish("homeassistant/switch1/mqttTest/state", "ON");
    } else {
        Serial.println("OFF");
        digitalWrite(SwitchedPin, LOW);
        client.publish("homeassistant/switch1/mqttTest/state", "OFF");
    }
  }
}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) 
  {
    Serial.print("Attempting MQTT connection..."); 
    // Attempt to connect
    if (client.connect("homeassistant-MQTTButtons","mqtt_user","mqtt_pass"))
    {
      Serial.println("connected");
     //once connected to MQTT broker, subscribe command if any
      client.subscribe("homeassistant");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
} //end reconnect()

void setup() {
  Serial.begin(115200);
  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
 // pinMode(BUTTON_PIN,INPUT);
  button1.setDebounceTime(50); // set debounce time to 50 milliseconds
  button2.setDebounceTime(50); // set debounce time to 50 milliseconds
  button3.setDebounceTime(50); // set debounce time to 50 milliseconds
}

void loop() {
  if (!client.connected()) {
    reconnect();
  }
  client.loop();
  long now = millis();
  int status;
  button1.loop(); // MUST call the loop() function first
  button2.loop(); // MUST call the loop() function first
  button3.loop(); // MUST call the loop() function first
  //send message every 2 second
  if (now - lastMsg > 2000) {
     lastMsg = now;
  if(button1.isPressed())
    Serial.println("The button 1 is pressed");    
      client.publish("homeassistant/switch/button1/state", "triggered");
  if(button1.isReleased())
    Serial.println("The button 1 is released");    
  if(button2.isPressed())
    Serial.println("The button 2 is pressed");    
      client.publish("homeassistant/switch/button2/state", "triggered");    
  if(button2.isReleased())
    Serial.println("The button 2 is released");    
  if(button3.isPressed())
    Serial.println("The button 3 is pressed");    
      client.publish("homeassistant/switch/button3/state", "triggered");   
  if(button3.isReleased())
    Serial.println("The button 3 is released");     
       }

     
}

My configuration.yaml code :

switch:
    - name: "MQTT Switch Test"
      command_topic: "homeassistant/switch1/MqttTest/cmd"
      state_topic: "homeassistant/switch1/MqttTest/state"
      unique_id: "switch.mqtttest"
      payload_off: "OFF"
      payload_on: "ON"
      optimistic: false
      retain: true # or false if you want to wait for changes

Any pointers would be great.

Thanks

You are probably seeing “button bounce” - the physical contacts rebound from each other for pico seconds, but enough to trigger the uP many, many times.

Look for software switch debounce, as adding a RC network to debounce in hardware would take space your omission of pullups suggests you don’t have.

Personally, I’d use ESPhome or Tasmota as debounce is baked-in, and both support auto-discovery via MQTT making HASS config a lot easier (although you could publish the extra topics yourself manually from Arduino code).

This ESP GPIO reference may also be of use:

Hello,

Thank you for the reply. I was tempted to use ESPhome and Tasmota(I have a few blind and curtains already running it), but they felt overkill for 4 buttons to send states. I am using the Wemo D1 Mini, it does look like those pins (12,14 and 14) dont have conflicting uses to High/Low for a switch.