How to share hardwired signals between two ESPHome modules?

I’m working on a project to control and automate the watering system for the greenhouse and some parts of the garden.

The plan is to split the system in two independent parts, each one with its own ESPHome.
One ESPHome will sit at the “pump station” and control the water valves, measure the level in the rain water barrel, stop the pump at low level and so on.
The other ESPHome will sit inside the greenhouse and measure the climate in the greenhouse and the plants.

When the plants need water I would like the “greenhouse ESPHome” to be able to communicate to the “water tank ESPHome” to turn on the water valve.

As I want this to be as robust as possible I will not use any wireless communication for functional signals, only for monitoring and settings.
That means the signals between the two ESPHome nodes must be hardwired.

The simplest way is of course to just tie a few I/Os between them, but then I know myself and will later think “it would be cool to have that signal and nice to pass that value between”…

With that in mind we now at last are coming to my actual question:
What is the best and easiest way to pass let’s say 5-10 signals and values hardwired between two ESPHome, and maybe also with some error correction in mind? The distans between the ESP will be about 5-10 meters and there is no speed requirements.

  • Shift register?
  • UART Serial?
  • I2C?
  • SPI?
  • ?
    Any wise and clever ideas are appreciated.

I would target UART. I’m pretty sure there is no way to create “server” components in ESPHome for the likes of I2C or SPI.

You will have to device your own “protocol”, though. See Lambda Magic — ESPHome for pointers using uart.

Thanks for the link to the Lambda Magic. I’m aware of Lambda, but I had not seen that site. I’m quite new to create my own ESPHome code.

Yes, UART was my first thought too, but I wanted to ask an open question in case there is some clever function I don’t know about. ESPome have all kind of weird & wonderful things already built in! :slightly_smiling_face:

But with UART it’s easy to add a RS232 level shifter circuit like MAX232 on each side to add some more robustness to the signal and avoid exposing the ESP32 I/O directly to the environment.
For “error correction” it will probably be enough here to go at low speed and just send the data maybe three times and only accept it if all three are the same.

A simple “protocol” maybe can be something like:

  1. Send all data three times in one stream
  2. Wait for the other node to respond with the same data to confirm
  3. If the responded data is wrong, resend the correct data again
  4. Stop retrying and rise an alarm if the respond is wrong five times in a row

Anyone that has done something similar and is willing to share some code? :wink:

Did you look into just having one esp and say long wire runs to the greenhouse sensors from the pump one? Not sure how feasible that is and guessing you’ve thought about it but curious if/how that was knocked out.

Quick search…

To be honest, I’d put wireless and long-wires-in-a-wet-environment on the same level as far as expected reliability… To improve wireless reliability, I’d just put a cheapo dedicated router for that purpose.

Keep in mind that pure wired also implies hardwiring a way to upload firmware updates, no logging, … (unless you keep wireless for “non-essential” functions like this).

One ESP is of course the easiest way and something I have considered, but it will have some drawbacks in my opinion.

  1. As I will have sensors in both the greenhouse (temp, moister, light humidity…) and in the pump (water level, critical low level, leakage…) I’m facing similar problems with long sensor cables regardless where I place the ESP.
  2. One ESP will make it harder to add more sensors at the “wrong” place later on as more cables likely has to be installed.
  3. As the functions of the systems are very different (pump control vs evaluating environment sensors) I think it can be easier to develop, test, and maintenance if it is separate systems.

My experience is that a proper installed hardwired connection hardly never can beat wireless. Well ok, maybe hardwire isn’t the best chose for space flights then… :stuck_out_tongue_winking_eye:

However, as it looks like there is no easy “of the shelf” solution to handle hardwired signals between two ESPHome I’m starting to thinking on a plan B for wireless, at least to start with:

Problem 1: Flooding
The biggest fear is that the stop/shut off command not will be received and causing a flooded greenhouse.

Solution 1: Hart beat
This can probably be handled in a way where the “pump ESP” only open the water valve for a short time. That means the “greenhouse ESP” must resend that trigger as long it’s requesting for more water. This will acting like a hart beat / watchdog and stop the water if the signal for some reason is lost.

Problem 2: Drying / HA down
I will have the automations local in the ESP not being dependent of Home Assistant running.
Is it possible for two ESPHome nodes to communicate and trig the water “hart beat” if HA is down but wifi is up?

Never used it myself, but ESPHome has a “web server” component that does just that

together with “http request”, I guess

That web server solution looks interesting, but I’m afraid that may me a little over my head to master, at least for the moment.

Thinking this over a little more during some grass cutting the last hours I may have a solution that hopefully will be both quite easy and reliably enough for my needs:

  1. Two ESP as discussed above, one for the pump and one for the greenhouse.
  2. Connect the two ESP trough UART and MAX232 level shifters.
  3. Use the UART Switch and Lambda Magic Custom UART Switch to send and receive the “valve open hart beat signal” witch will open the water valve for a short time, and close it again if a new hart beat is not received.
  4. More signals should be possible add through UART the same way if needed, and the text sensor is probably reliable and fault tolerant enough for this purpose as the received string is a couple of bytes that must mach exactly to flip the switch.
  5. All other kind of “non critical / for fun” signals can be handeld wireless.

For now I think this will be the way I go, at least to start with.
Any obvious thought errors?

Honestly, if that’s over your head, UART will be worse :wink:

As both ESP will have the same logic, I don’t think you need the level shifter, but that’s a bit above my head :wink:

I’m not that deep into this new fancy web rubbish. I’ll stick to an good old trusted UART, like I used to in the -90s! :stuck_out_tongue_winking_eye:

Well to be honest, it feels like a web server is a little to much and komplex for my needs, but I can be wrong. Could be worth to have a look at.

However, I will start with the UART trace as that (hopefully) will give me a system with both robustness and some flexibility where the core functions are working regardless of wifi, HA or any other surrounding systems, as long as I have 230VAC power.

You are absolutely right about that the level shifters are not needed from a signal level aspect, but it is not wise, and not a common praxis, to expose the “naked” I/Os to the world. Especially if the wires are long, like they will be in my case, the risk is quite high that the sensitive, high impedance 3,3V inputs will pick up some noise that can interfere or block the signal, or worse be destroyed by some electro static discharge (ESD).

Those risks can be reduced by using the MAX232 level shifter as they will boost the signal several volts (to RS232 level) and bring some basic ESD protection to it as well.
Not needed in theory or on the bench, but probably nearly a “must have” in the real world. :blush:


Are you comfortable with reading uart in ESPHOME? It’s a bit more involved than writing it.

Nope, not at all. :grin:
But until I know better I believe that the Magic Lambda Custom UART Switch example will do pretty much what I want - I hope!
As long as the interrupt pick up the receiving message and i don’t overflow the input buffer, I think it will be pretty straight forward.
We’ll find out… :stuck_out_tongue_winking_eye:

Whats the hard part in your opinion?

If you’re comfortable with the custom sensor approach you should be fine. c++ scares me.

There’s this kind of thing too, which gives a good overview of the challenge and an alternative. I tend to use this approach to read uart.

That’s looks interesting. I may give that a try as well.

If you would make an effort to read the documentation, you’d quickly realize its not rubbish at all and it’s very simple to use.

Yes, now when I have a solution that I believe is right for my purpose, I will dig down deeper into the documentation and do some testing.

1 Like

Your plan re uart and max232’s will work just fine. I’ve done exactly this and it works fine over long runs that I’ve tested up to a few hundred feet.

1 Like

Yes, correct used RS232 is a fairly reliable and easy communication over reasonable distances.

How did you implement the readings?

@Pjoms it’s probably not be best/cleanest implementation but here’s a snippet of one of the switches on the receiver side:

- platform: template
  id: text_switch_z2
  name: "Text Switch 2"
  lambda: |-
    if (id(uart_readline).state == "1-Z2-ON") {
      return true;
    } else if(id(uart_readline).state == "1-Z2-OFF") {
      return false;
    } else {
      return {};