ESPHome with Existing Arduino Programs


#1

This may be a dumb question but I am I am becoming interested in the ESPHome component because it would allow me to make updates over wifi without having to connect the board via USB each time I want to change something. Currently I have 4 nodeMCU boards around the house (3 for LED strips and 1 for controlling the doorbell) Each of the boards already has an .ino file which I uploaded to the board via the arduino software. All of these boards talk to home assistant via MQTT so I have already figured out how to get them to talk to home assistant and things are running on them fairly smooth.I would however like to transition over to using ESPHome for simplicity purposes as it is kind of a pain to update any of my codes currently. My LED boards are basically @bruhautomation code using the fastled with some of my own added ones in as well. The doorbell code was more customized to what I created (so that I can mute the doorbell or know when the button was pushed to take a picture with and outdoor camera). Is there a guide or easy way to convert this code over to using ESPHome. I wasn’t sure what it would look like or what to use to convert it over to use ESPHome. If it helps I can post my codes on here for someone to review to help guide me.


#2

Just wondering about this because i have .h files that i have included in my arduino program and when i try to compile i get errors. These were files that i have in a libraries folder in my arduino folder when i compile my programs.


#3

You can include standard C programming in the ESPhome code as per this tutorial, but by the sounds of things you would likely be able to write new code for your nodes in a matter of minutes using ESPhome anyway, so why not just start fresh?


#4

I am not sure I could redo my code in minutes. I struggled for days to get it to work on the nodemcu the way it is.


#5

ESPHome makes it much easier, for example, heres the code for one of my WS2812 strips running on a wemos D1 mini

https://hastebin.com/okasivokob.makefile


#6

The LED strips can be replaced with code like @CountParadox posted, which is pretty much the same as my LED strip code :smile:

What do you currently have for the doorbell?


#7

I quickly took a look at @CountParadox code and it seemed to make sense from the quick glance I took.

As far as my doorbell here is what I have in my code… It may not be the best code and I am sure there is a better way of doing it but it works for me.

#include <PubSubClient.h>
#include <ESP8266WiFi.h>
#include <Bounce2.h>

// Use these lines to setup MQTT Server and WiFi
#define MQTT_SERVER "XXX.XXX.XXX.XXX"
const char* ssid = "XXXXXXXX";
const char* password = "XXXXXXXXXXXXX";

// Define GPIO on ESP8266
const int buttonPin = 2;
const int relayPin = 4 ; 

// Topics to Publish or Subscribe to
char* doorbellbuttonTopic = "home/button";
char* doorbellsoundTopic = "home/sound";

// Create an instance of the bounce class
Bounce doorbellbutton = Bounce();

// Define when relay is on or off
#define RELAY_ON 1
#define RELAY_OFF 0

// Define variables
unsigned int doorbellDelay = 5000; // Interval (milliseconds) at which to keep doorbell sensor triggered to prevent multiple ringings
unsigned int ringTime = 700; // How long the relay is on (milliseconds)
boolean doorbellSound = 1; // Used to keep track if the doorbell should sound or be silent.  Value recieved from doorbell on/off switch (0=off, 1=on)
int buttonPush = 0;
int buttonState = 0;

struct bs_v {
  boolean b = 0;  // Value for button push
  boolean s = 1;  // Value for sound
};

struct bs_v bsvalues;

WiFiClient wifiClient;
PubSubClient client(MQTT_SERVER, 1883, callback, wifiClient);

void setup() {
	// Initialize the button pin with a internal pull-up
	pinMode(buttonPin, INPUT_PULLUP);
	doorbellbutton.attach(buttonPin);
	doorbellbutton.interval(5);
	
	// Initialize the relay pin
	pinMode(relayPin, OUTPUT);
	digitalWrite(relayPin, RELAY_OFF);
	
	// Start the serial line for debugging
	Serial.begin(115200);   // com to computer
	
	delay(100);
	
	// Start wifi subsystem
	WiFi.begin(ssid, password);
	
	// Attempt to connect to the WIFI network and then connect to the MQTT server
	reconnect();
	client.publish(doorbellsoundTopic, "1");
 
	// Wait for a bit before starting main loop
	delay(2000);
}

void loop() {
	// Reconnect if connection is lost
	if (!client.connected() && WiFi.status() == 3) {	reconnect();}
	
	// Maintain MQTT connection
	client.loop();
	
	// Monitor the button
	checkButton();
	
	// Handle doorbellbutton
	if(bsvalues.b == 1 && bsvalues.s == 1){
		digitalWrite(relayPin, RELAY_ON);
		delay(ringTime);
    bsvalues.b = 0;
		digitalWrite(relayPin, RELAY_OFF);
    delay(doorbellDelay);

    doorbellbutton.update();
    buttonState = doorbellbutton.read();
    //Serial.println("Will ring");
	}
	else if(bsvalues.b == 0){
		digitalWrite(relayPin, RELAY_OFF);
	}
	else{
		digitalWrite(relayPin, RELAY_OFF);
	}
	
	// Delay to allow ESP8266 WIFI functions to run
	delay(10);
}

// MQTT callback function -(Use only if topics are being subscribed to)
 void callback(char* topic, byte* payload, unsigned int length){
  
	// Convert topic to string to make it easier to work with
	String topicStr = topic;
	//char byteToSend = 0;
	
	// Handle doorbellbuttonTopic
	if(topicStr.equals(doorbellbuttonTopic)){
		if(payload[0] == '1'){
		  buttonPush = 1;
      (bsvalues) = passButtonPush(bsvalues, buttonPush);
      Serial.println(bsvalues.b);
		}
		else if (payload[0] == '0'){
			buttonPush = 0;
      (bsvalues) = passButtonPush(bsvalues, buttonPush);
      Serial.println(bsvalues.b);
		}
	}
	
	// Handle doorbellsoundTopic
	else if(topicStr.equals(doorbellsoundTopic)){
		if(payload[0] == '1'){
			doorbellSound = 1;
      (bsvalues) = passDoorbellSound(bsvalues, doorbellSound);
      Serial.println(bsvalues.s);
		}
		else if (payload[0] == '0'){
			doorbellSound = 0;
      (bsvalues) = passDoorbellSound(bsvalues, doorbellSound);
      Serial.println(bsvalues.s);
		}
	}
}

struct bs_v passButtonPush(struct bs_v, int buttonPush){
  //struct bs_v bsvalues;
  bsvalues.b = buttonPush;
  return bsvalues;  
}

struct bs_v passDoorbellSound(struct bs_v, int doorbellSound){
  //struct bs_v bsvalues;
  bsvalues.s = doorbellSound;
  return bsvalues;
}

void checkButton(){
	
	//buttonState = digitalRead(buttonPin);
  doorbellbutton.update();
	buttonState = doorbellbutton.read();

  if(doorbellbutton.fell() == 1){
    client.publish(doorbellbuttonTopic, "1");
  }
  else if(doorbellbutton.rose() == 1){
    client.publish(doorbellbuttonTopic, "0");
  }
  else{
    //client.publish(doorbellbuttonTopic, "0");
    //buttonPush = 1;
  }
}

void failMQTTcheckButton(){
	
	buttonState = digitalRead(buttonPin);
	//buttonState = doorbellbutton.read();
	doorbellSound = 1;
	
	
	if(buttonState == HIGH){
		buttonPush = 1;
	}
	
	// Else if relay is on and button is pushed publish Off state to doorbellbuttonTopic
	else if(buttonState == LOW){
		buttonPush = 0;
	}
	
}


void reconnect() {
	//attempt to connect to the wifi if connection is lost
	if(WiFi.status() != WL_CONNECTED){
		//debug printing
		Serial.print("Connecting to ");
		Serial.println(ssid);
		
		//loop while we wait for connection
		while (WiFi.status() != WL_CONNECTED) {
			delay(500);
			Serial.print(".");
		}
		
		//print out some more debug once connected
		Serial.println("");
		Serial.println("WiFi connected");  
		Serial.println("IP address: ");
		Serial.println(WiFi.localIP());
	}
	
	//make sure we are connected to WIFI before attemping to reconnect to MQTT
	if(WiFi.status() == WL_CONNECTED){
		// Loop until we're reconnected to the MQTT server
		while (!client.connected()) {
			Serial.print("Attempting MQTT connection...");

			failMQTTcheckButton();

			// Generate client name based on MAC address and last 8 bits of microsecond counter
			String clientName;
			clientName += "esp8266-";
			uint8_t mac[6];
			WiFi.macAddress(mac);
			clientName += macToStr(mac);
			
			//if connected, subscribe to the topic(s) we want to be notified about
			if (client.connect("(char*) clientName.c_str()", "mgranger", "Magnum27")) {
				Serial.print("\tMQTT Connected");
				client.subscribe(doorbellbuttonTopic);
        client.subscribe(doorbellsoundTopic);
			}
			
			//otherwise print failed for debugging
			else{	Serial.println("\tFailed."); abort();}
		}
	}
}

// Generate unique name from MAC addr
String macToStr(const uint8_t* mac){
	
	String result;
	
	for (int i = 0; i < 6; ++i) {
		result += String(mac[i], 16);
		
		if (i < 5){
			result += ':';
		}
	}
	
	return result;
}

#8

Alternatively you could add OTA ability to your own code, but I get the feeling that esphome is just easier all round.


#9

I’ll put together some ESPhome code for you shortly. You will see how much simpler it is


#10

I was going to do that, but I am at work and it looks like you’ll beat me to it.


#11

Try this as a first rough shot at what you need…

doorbell.yaml

esphomeyaml:
  name: doorbell
  platform: ESP8266
  board: nodemcuv2

wifi:
  ssid: 'your_wifi_ssid'
  password: 'your_wifi_password'
  manual_ip:
    static_ip: 192.168.0.65   # CHANGE THESE TO SUIT YOUR NETWORK
    gateway: 192.168.0.1
    subnet: 255.255.255.0

api:

# Enable logging
logger:

ota:
  password: 'some_password'   # THIS IS NOT REQUIRED BUT ALLOWS YOU TO REQUIRE A PASSWORD TO CHANGE CODE OVER THE AIR

binary_sensor:
  - platform: gpio
    name: "Doorbell button"
    icon: mdi:bell-circle-outline
    pin:
      number: D2
      mode: INPUT_PULLUP
    filters:
      - delayed_on: 10ms   # THIS DOES THE DEBOUNCE
    on_press:
      then:
        - switch.turn_on: relay1
        - delay: 700ms
        - switch.turn_off: relay1

switch:
  - platform: gpio
    name: "Doorbell Relay"
    id: relay1
    icon: mdi:alarm-bell
    pin: 
      number: D4
      inverted: true

#12

Ok I tried this and I am not getting anything out of it. I have it connected to home assistant and when i turn the relay on/off i see the log update however when I go to the doorbell and push the button the relay does not seem to turn on and off. Also there is no log update when I push the button.


#13

Are you seeing the doorbell button in HA? Also, how is the button wired? I took a bit of a guess here with regards to the internal_pullup


#14

Dont know if this helps but here is what I have… The button is connect on the left with yellow wires


#15

You shouldn’t need that transistor in there… I don’t use one with my relay boards (but if thats how you previously had it working then leave it be, we are only changing code). The input (button) looks ok to me.

…but back to my question, are you seeing the ‘Doorbell button’ in the HA GUI? Does it change state when you press it? (try holding it to make sure the state change is nice and long for the sake of testing)


#16

Sorry I didn’t answer your question. I do see the button in HA GUI however when I push (and hold the button) nothing changes in the GUI.

Also I can turn the relay on in the GUI but it does not ring the bell from the GUI


#17

When you say you can turn the relay on in the GUI, the actual relay energises?


#18

No it does not energize. I just meant i could see it in the GUI and I could turn the switch on/off in the GUI but nothing happens on the actual relay.


#19

Ok, so we need to confirm that the pin assignments in my code are correct. I’m on my phone now so hard to see the details in your schematic


#20

Ok I switched the pins and now the relay is on all the timeand when I push the button it turns off for a half second and then buzzes.(I think I picked the worst pins for this because D2 is GPIO4 and D4 is GPIO2) I assume I have to set inverted o the relay to off to fix this.