Venmar (Vanee/Broan) ERV / HVAC controller output

Just ordered a ESP32-S3 6-Channel Relay Module. I’ll start playing around with my Constructo 1.0 and deco-touch.

As I understand it, I just flash it with the esphome code on @nspitko github, uncomment the debug code, wire it in between the HRV and controller and then I can send commands with the controller and examine the resulting communications?

Nevermind. My unit is controlled based on a resistor value between G and B wires.

Thank you for your work on this!

I finally had some time to try this out on my HRV. Mine is a VENMAR AVS N Series (A160H65RS Venmar AVS® N Series HRV 159 CFM 68% SRE with Virtuo Air Technology™ Side ports). Venmar is now part of Broan and the HRVs are basically the same even before they dropped the Venmar name.

It seems to work so far - fan mode selection works, including INT. The reported power draw is a little low compared to the draw I’m seeing from the panel, but within reason. I am seeing the same multiple sensor issue reported in the repo in #2 - my HRV is reporting a valid temperature from 01 E0, and an invalid one from 03 E0 (always -100: 03 E0 04 00 00 C8 C2).

I currently have the Dehumidistat control (41402 Venmar Dehumidistat Control - unhooked right now of course), and I’m happy to try to grab some dumps of the humidity control mode in action. What do you recommend for hardware/software for sniffing the control panel communication?

I’m happy to contribute however I can!

Matt

Just noticed something interesting. When I use one of the secondary controls (20-40-60 override in the bathrooms and kitchen), the HRV responds as it did before, but during the override, the “fan mode” is reported as “off”. Once the override ends, it goes back to the previous setting (“int” in this case).

We’re probably missing the enum value for that specific case.

This should be easy to track down, open the esphome logs, and trigger the override. You should see something like this in the logs

[16:42:20.857][D][broan:384]: 0020 is now Byte  01

I just need to know the value of 0020 in the override case. It may take up to a minute to pop up after you start the override.

the dual temp thing is on my radar, I’ve just been busy with some other projects.

I believe we have all of the machinery to reproduce the behavior of the humidistat in HA, I just haven’t wired any of it up yet since there hasn’t been any demand for it. Feel free to open that issue as well if it’s a feature you’d actually care about. it will require a bit of work though as we need to feed in data from HA to the ERV for it to work, and I don’t know how complicated that will be vs just setting up as automation in HA to control it there.

I will crank up some logging and write up a couple of issues about it, and see what I can do about some pull requests. I’m fine with C++ or Python, but I haven’t explored esphome modules yet. I’ll dig into the docs this weekend and see if I can put something together.

1 Like

Loving this so much on my Broan B160E75RS!

The thing I really miss from the controller is the Recirculation function. Turning the whole unit off when my sensors detect my neighbor’s chimney smoke works, but then there’s no airflow anymore.

Do we know where that code is yet?

Yeah, reacting to smoke was my main use case too (of the wildfire kind out here)

My unit doesn’t have recirc though, so I have to use the circ mode on my hvac instead. Most likely it’s just another “mode” we need an enum for, but I don’t have any way of triggering it locally.

If you’re tech savvy, read the blog post on how to read the protocol, it’s not too hard to figure out what is being sent from the dumps. You can even use the esp32 as a packet capture device by just turning serial debugging on and turning off the component. If you’re not sure how to read the dumps, the component has a define you can enable where it just dumps value changes, which can highlight what’s going on.

Or, plan C, just try untested values in the mode enum. there are gaps which probably do things on certain machines.

I have been playing with an RS485 adapter for the last week or so with my ERV. Have learned a couple things;

  • I found the CFM registers, 0x1005 for source CFM (into the house) and 0x1006 for exhaust CFM; there are also what appear to be RPM registers which can show how hard the unit is working (my unit only seems to go to 3000 RPM)
  • Some RS485 adapters have two pins that need to be pulled high/low based on whether we are transmitting or receiving, which took a lot of debugging to figure out
  • I wrote some logic to scan all the registers, and got these example responses for my unit

Not sure what is different about my unit, but was having a hard time with the component. I wrote a new version here, which has a couple features like listen-only mode and a poll_registers to add arbitrary registers to the polling for inspecting the protocol. My config looks like this:

external_components:
  - source:
      type: git
      url: https://github.com/krconv/esphome-broan-erv
      ref: main
    components: [ broan_erv ]
    refresh: 1s

uart:
  - id: uart_1
    tx_pin: GPIO4
    rx_pin: GPIO36
    baud_rate: 38400
    stop_bits: 1
    parity: NONE
    rx_buffer_size: 2048

broan_erv:
  uart_id: uart_1
  re_de_pin: GPIO14
  src_address: 0x11
  dst_address: 0x10

  power:
   id: broan_erv_power
   name: "Power"
  mode:
    name: "Mode"
  supply_fan_rpm:
    name: "Supply fan RPM"
  exhaust_fan_rpm:
    name: "Exhaust fan RPM"
  supply_fan_cfm:
    name: "Supply fan CFM"
  exhaust_fan_cfm:
    name: "Exhaust fan CFM"
  # listen_only: true

sensor:
  - platform: total_daily_energy
    name: "Daily Energy"
    power_id: broan_erv_power
    unit_of_measurement: "Wh"
    icon: "mdi:counter"
    accuracy_decimals: 2
    device_class: energy
    state_class: total_increasing

It’s missing some of the features that the main component has; not sure if it’d be worth trying to merge the two, at some point I got too deep in debugging and veered way off the original implementation.

For what it’s worth, my implementation has both listen only and scan registers features, they’re not documented and not super user friendly but the defines are in broan.h

Interesting that you have data in the 0x10 range, my unit didn’t show anything in this range when I scanned. I’ll double check later, but we’ve been finding a lot of cases where some units report data others don’t (eg, my unit lacks the output temp sensor so we only discovered that from another person’s scans). it’s also possible i just missed these due bugs in the protocol when I was doing scans.

My implementation is certainly not the best and I don’t think there’s any value in having two parallel versions of this component. Happy to talk about merging in either direction and deprecating the other.

If you plan to keep working on this you should open an issue in GitHub - nspitko/broan_erv_uart: ESPHome component for reading/writing information to Broan ERVs via serial and we can figure out what the best path forward is.

1 Like

Thanks for the context. Good idea, when I get some time I’ll take a closer look and come up with some suggestions for what I could bring over to the main implementation, and spin up an issue for discussion. I’m just happy to have my ERV back up and running after being out of commission while I was debugging haha. Thanks again for your work on this!

I added CFM as an experiment and it works; I guess my crappy scanning code missed the whole 0x10 block! I wonder what else I missed.

I’ll add RPM next, just to keep things in step until we can do a proper merge. I suspect at a miminum, cleaning up the code and adding a cleaner scan and listen implementation like yours would be a good long term feature. A lot of my code is a complete mess since I was still figuring out the protocol.

Found another Waveshare Device ESP32-S3 that may work as well. will try and test in a few days. Amazon.com: Industrial 1-Ch ESP32-S3 WiFi Relay Module, Support RS485 and Bluetooth/WiFi Remote Control, Better for RS485 Modbus Industrial Modules or Sensors, Built-in Protection Circuits, Safe & Stable : Electronics

1 Like

You’d have to power it with an external power supply - it looks like that one will only accept 5V, while the original one will accept the 12V that the HRV supplies.

Not having any luck getting waveshare esp32-s3-relay-1ch communicating with my Broan ERV over rs485. Im not getting communication status light to go on. I tested with ground wire, flipping TX and rx wire and the jumper transistor. Nothing is working. Just the same repeating message:

[22:00:36.130][W][broan:269]: ERV has not yielded control in over 5000ms, communication has likely failed. Please restart the device.
[22:00:37.495][W][broan:302]: Dropping queued message: Stack is full. (Tried to queue 40)

I’m not sure if I got esphome setting correct. I used

esp32:
board: esp32-s3-devkitc-1
variant: ESP32S3
framework:
type: esp-idf
version: recommended

Any pointers?

For my work devices I use a usb to rs485 converter to listen in to the network traffic on my laptop first with a serial comms tool. If you can sniff the traffic successfully, then move on to trying to get your ESP to work. You are flying double bind right now.

You can uncomment the uart debugging in the yaml to get a bit more information. From your description it sounds like you’re not getting any data flow through the rs485 tranceiver, which is obviously going to preclude the component working.

I’d start by triple checking the uart config. That’s the easiest place to make a mistake here.

I’ve just been working through my new implementation of this. I solved my first issue with your errors by changing from telephone cabling to cat5e (or cat 6) and using the twisted pair for the signal and a different one for the ground. I was getting crazy interference initially without this.

Hey awesome work here! got it working in a pinch. I have a Venmar V160H75RT with recirculation and the basic wall control. I would very much like to figure out the recirc mode command but I’m a bit lost in the protocol.

At 1400 = 1497 I switch it off from the wall control:

[19:09:48.890][D][broan:472]: 1400 is now Int 1497
[19:09:49.150][W][broan:257]: Unhandled m_nType 40
[19:09:49.155][W][broan:175]: 40 00 20 01 01 
[19:09:57.107][W][broan:257]: Unhandled m_nType 40
[19:09:57.112][W][broan:175]: 40 07 50 04 FF FF FF FF 
[19:09:57.118][W][broan:232]: Got write response for unknown field 07 50
[19:09:58.922][W][broan:257]: Unhandled m_nType 40
[19:09:58.927][W][broan:175]: 40 00 50 00 
[19:09:58.951][D][broan:472]: 1400 is now Int 1507

At 1517, I switch to recirc:

[19:10:08.961][D][broan:472]: 1400 is now Int 1517
[19:10:13.772][W][broan:257]: Unhandled m_nType 40
[19:10:13.777][W][broan:175]: 40 03 20 00 
[19:10:13.782][W][broan:232]: Got write response for unknown field 03 20
[19:10:15.739][W][broan:257]: Unhandled m_nType 40
[19:10:15.742][W][broan:175]: 40 00 20 01 06 
[19:10:17.102][W][broan:257]: Unhandled m_nType 40
[19:10:17.107][W][broan:175]: 40 07 50 04 FF FF FF FF 
[19:10:17.112][W][broan:232]: Got write response for unknown field 07 50
[19:10:18.966][W][broan:257]: Unhandled m_nType 40
[19:10:18.971][W][broan:175]: 40 00 50 00 
[19:10:18.994][D][broan:472]: 1400 is now Int 1527

I must be missing something?

It’s not very user friendly but it’s doing what I need. Recirc appears to be 0x06.

I went ahead and pushed this to git, pull the latest version and see if that works for you.

1 Like