EmpVue getting I2C error 3, after update through ESPHome Builder

For many months I was getting and error when trying to update my Emporia Vue 2 from the Home Assistant Settins screen. I just kept skipping because it was still working fine.
Yesterday I had some time to dig and found out the reason for the updating issue was a breaking change which required “platform: esphome” to be added to the YAML under OTA.
After that I hit install assuming that would bring the device up to date, which I think it did.
Today I noticed that the power readings were “unavailable”. Checking the logs of the EmporiaVue, there are a lot of “Failed to read from sensor due to I2C error 3” entries.
Looking online a bunch of people have had the same problem. Most solved it with adjusting the frequency and adding a timeout.

I tried that but I’m still getting the same issue.
Has anyone else run into this? Any other solutions?

Just following up on this issue. It’s still spitting out loads of I2C errors.
I did notice in the logs the “Frequency: 200000 Hz” even though in my YAML I have it set to 400kHz.
Is that a recovery thing to lower it, or are my yaml changes not being saved/uploaded?

Latest logs. I removed 90% of the I2C error 3 entries for clarity.

I’m newly seeing “I2C error 3” errors too. My vue2 returns nan/Unknown for every circuit power sensor that previously worked. I haven’t run updates on my Gen 2 Vue since setting it up (2 years ago?), but the symptoms appeared when I accidentally flashed a different device build onto the vue by using the wrong IP address and subsequently re-flashed the correct build with the esphome CLI (version 2025.5.2).

The logs do show the correct frequency being set from yaml, but nothing I’ve tried works (it was set to 200 kHz, I’ve attempted 400 per the 50, 100, 200). I also tried adding a timeout (was not previously set) of 1ms and 11ms.

Searching for solutions I’ve found the issue that cropped up with the 2024.10 release[1], and that it could also be hardware failure[2]. Because the issue is directly correlated with my first attempt to re-flash the config since well before 2024.10, I didn’t think hardware failure was likely. But it’s not looking good - I reverted my esphome to 2024.9 and re-flashed the config with frequency: 200kHz and i2c still fails. So maybe the re-flash triggered hardware failure?!

[1] 2024.10.0 breaks i2c on Emporia Vue2 devices · Issue #6335 · esphome/issues · GitHub
[2] Anyone else getting i2c error 3 after updating esphome version? · emporia-vue-local/esphome · Discussion #108 · GitHub

Interesting. I saw those older threads about hardware failure as well. At the bottom of that thread the post says they fixed it by using the web flasher.
I originally flashed my Vue that way, and only flashed it via the ESPHome Builder a few times before I started getting the error from the missing ota “platform: esphome” entry. Didn’t bother correcting it for over a year. But now this.

I’m going to try removing the Vue from inside my panel, and manually reflash with https://web.esphome.io/.

I have a newly flashed and installed getting this issue as well. I’ve played with the i2c settings a bit but mostly blind checks with no success. Following

Funny enough, I just re-flashed mine and now it’s working fine.
The only error showing in the logs now is
[16:57:22][W][emporia_vue:066]: Detected 1 missing reading(s), data may not be accurate!

Interestingly the frequency is now showing at 400000 Hz, which wasn’t being saved before.

Just to make sure not a remote flash but hooked it back up and flashed via web?

I am interested in the solution here too. My vue stopped reporting around the same date after I reflashed it.

Unfortunately re-pinning it and web flashing did not resolve for me

IDK if this helps but I had the same issue today. Did try a reinstall from ESPHome within HA just to see if it made a difference and it didn’t. I just power cycled the device and now it is reporting again.

I was also having the i2c error after flashing, but it cleared after removing power from the Vue and then powering it back up.

For anyone looking for a config that still works, here’s mine:

substitutions:
  # Adjust as needed here
  c01_name: "01 Smoke Detectors"
  c02_name: "02 c02"
  c03_name: "03 Kitchen"
  c04_name: "04 Living Room A/C 1"
  c05_name: "05 c05"
  c06_name: "06 Living Room A/C 2"
  c07_name: "07 c07"
  c08_name: "08 c08"
  c09_name: "09 c09"
  c10_name: "10 Lights/Living Room/Microwave"
  c11_name: "11 c11"
  c12_name: "12 Bedrooms and Bathroom"
  c13_name: "13 c13"
  c14_name: "14 c14"
  c15_name: "15 c15"
  c16_name: "16 c16"

  # 0.022 is used as the default as starting point but may need adjusted to ensure accuracy
  # To calculate new calibration value use the formula <in-use calibration value> * <accurate voltage> / <reporting voltage>
  ##
  # NOTE: your values will be different / calculate your own!
  calibration_factor_a: "0.019246"
  calibration_factor_b: "0.019246"
  # This is a scalar offset to apply to the frequency sensor.
  # My Vue3 reports 60.6Hz when the mains frequency is 60Hz so I need to subtract 0.6Hz
  # NOTE: your values will be different / calculate your own!
  frequency_cal: "-.339"

preferences:
  # the default of 1min is far too short--flash chip is rated
  # for approx 100k writes.
  flash_write_interval: "48h"   

esp32:
  board: esp32dev
  framework:
    type: esp-idf
    version: recommended

external_components:
  - source: github://emporia-vue-local/esphome@vue3
    components:
      - emporia_vue

i2c:
  sda: 5
  scl: 18
  scan: false
  frequency: 400kHz
  timeout: 1ms
  id: i2c_a


# Cut down on repetition with common filter for each channel
.defaultfilters:
  - &moving_avg
    # we capture a new sample every 0.24 seconds, so the time can
    # be calculated from the number of samples as n * 0.24.
    sliding_window_moving_average:
      # we average over the past 2.88 seconds
      window_size: 24
      # we push a new value every 1.44 seconds
      send_every: 12
  # I wasn't super happy with how slow the above was. I would turn the microwave/range lights on and the draw would immediately be 70W but the
  #    average was taking several refresh cycles to catch up.
  - &ewa
    exponential_moving_average:
      alpha: 0.85
      # I believe the units here is "samples", same math as above
      send_every: 12
      send_first_at: 1

  # invert and filter out any values below 0. Seems to be needed for the Vue3 on ESPHome newer than 2024.03 ?
  # In any case, this was correct for me. I did not get accurate values until I moved from `pos` to `invert`.
  # See: https://github.com/emporia-vue-local/esphome/discussions/264#discussioncomment-9170097
  - &invert
    lambda: "return max(-x, 0.0f);"
  
  # For reasons that do not make sense to me, the primary / main sensors need `pos` and not `invert`. 
  - &pos # filter out any values below 0.
    lambda: "return max(x, 0.0f);"

sensor:
  - platform: emporia_vue
    i2c_id: i2c_a
    phases:
      - id: phase_a
        input: BLACK
        calibration: ${calibration_factor_a}
        voltage:
          name: "Phase L Voltage"
          # Voltage shouldn't change as often so we can use the moving average filter
          filters: [*pos, *moving_avg]
        #Frequency is not supported for the red and blue wires, only for the black wire.
        frequency:
          name: "L1 Frequency"
          filters:
            - offset: ${frequency_cal}
            - *moving_avg
      - id: phase_b
        input: RED
        calibration: ${calibration_factor_b}
        voltage:
          name: "Phase R Voltage"
          # Voltage shouldn't change as often so we can use the moving average filter
          filters: [*pos, *moving_avg]

        phase_angle:
          name: "Phase L Phase Angle"
          # Phase Angle shouldn't change... ever so don't allocate ram for the average
          filters: [*pos]

    # NOTE: Verify the CT going to this device input also matches the phase/leg and that the phases match with the input/colors above
    ct_clamps:
      - input: "A"
        phase_id: phase_a
        power:
          name: "Phase L Power"
          id: phase_a_power
          device_class: power
          filters: [*invert]

      - input: "B"
        phase_id: phase_b
        # Verify the CT going to this device input also matches the phase/leg
        power:
          name: "Phase R Power"
          id: phase_b_power
          device_class: power
          filters: [*pos]

      # Pay close attention to set the phase_id for each breaker by matching it to the phase/leg it connects to in the panel
      - input: "1"
        phase_id: phase_a
        # Note: you do not need the `platform: copy` sensors. Everything under `power` is just like any other Sensor in ESPHome
        # It's worth noting that the class/config/icon ... etc are already set to reasonable defaults but if you don't like the lightning bolt icon,
        #    and you have a single appliance on a circuit, just change the icon to `mdi:fridge` or `mdi:oven` or whatever is appropriate.
        power:
          id: cir01
          name: "${c01_name} Power"
          # Note, this icon will show up for the power AND daily energy sensors unless you change it on the daily energy sensor as well.
          icon: "mdi:fridge"
          filters: [*invert, *ewa]

      - input: "2"
        phase_id: phase_a
        power:
          id: cir02
          name: "${c02_name} Power"
          filters: [*invert, *ewa]

      - input: "3"
        phase_id: phase_a
        power:
          id: cir03
          name: "${c03_name} Power"
          filters: [*invert, *ewa]

      - input: "4"
        phase_id: phase_a
        power:
          id: cir04
          name: "${c04_name} Power"
          filters: [*invert, *ewa]

      - input: "5"
        phase_id: phase_a
        power:
          id: cir05
          name: "${c05_name} Power"
          filters: [*invert, *ewa]

      - input: "6"
        phase_id: phase_a
        power:
          id: cir06
          name: "${c06_name} Power"
          filters: [*invert, *ewa]

      - input: "7"
        phase_id: phase_a
        power:
          id: cir07
          name: "${c07_name} Power"
          filters: [*invert, *ewa]

      - input: "8"
        phase_id: phase_a
        power:
          id: cir08
          name: "${c08_name} Power"
          filters: [*invert, *ewa]

      - input: "9"
        phase_id: phase_a
        power:
          id: cir09
          name: "${c09_name} Power"
          filters: [*invert, *ewa]

      - input: "10"
        phase_id: phase_a
        power:
          id: cir10
          name: "${c10_name} Power"
          filters: [*invert, *ewa]

      - input: "11"
        phase_id: phase_a
        power:
          id: cir11
          name: "${c11_name} Power"
          filters: [*invert, *ewa]

      - input: "12"
        phase_id: phase_a
        power:
          id: cir12
          name: "${c12_name} Power"
          filters: [*invert, *ewa]

      - input: "13"
        phase_id: phase_a
        power:
          id: cir13
          name: "${c13_name} Power"
          filters: [*invert, *ewa]

      - input: "14"
        phase_id: phase_a
        power:
          id: cir14
          name: "${c14_name} Power"
          filters: [*invert, *ewa]

      - input: "15"
        phase_id: phase_a
        power:
          id: cir15
          name: "${c15_name} Power"
          filters: [*invert, *ewa]

      - input: "16"
        phase_id: phase_a
        power:
          id: cir16
          name: "${c16_name} Power"
          filters: [*invert, *ewa]

  ##
  # SENSORS
  ##
  # Instantaneous consumption
  - name: "Total Power"
    platform: template
    id: total_power
    lambda: return id(phase_a_power).state + id(phase_b_power).state;
    update_interval: 10s
    unit_of_measurement: "W"
    device_class: power
    state_class: measurement

  # The day's consumption
  - name: "Total Daily Energy"
    platform: total_daily_energy
    power_id: total_power
    accuracy_decimals: 0
    unit_of_measurement: "Wh"

  ##
  # Per circuit Energy
  ##
  - name: "${c01_name} Daily Energy"
    power_id: cir01
    platform: total_daily_energy
    accuracy_decimals: 0

  - name: "${c02_name} Daily Energy"
    power_id: cir02
    platform: total_daily_energy
    accuracy_decimals: 0

  - name: "${c03_name} Daily Energy"
    power_id: cir03
    platform: total_daily_energy
    accuracy_decimals: 0

  - name: "${c04_name} Daily Energy"
    power_id: cir04
    platform: total_daily_energy
    accuracy_decimals: 0

  - name: "${c05_name} Daily Energy"
    power_id: cir05
    platform: total_daily_energy
    accuracy_decimals: 0

  - name: "${c06_name} Daily Energy"
    power_id: cir06
    platform: total_daily_energy
    accuracy_decimals: 0

  - name: "${c07_name} Daily Energy"
    power_id: cir07
    platform: total_daily_energy
    accuracy_decimals: 0

  - name: "${c08_name} Daily Energy"
    power_id: cir08
    platform: total_daily_energy
    accuracy_decimals: 0

  - name: "${c09_name} Daily Energy"
    power_id: cir09
    platform: total_daily_energy
    accuracy_decimals: 0

  - name: "${c10_name} Daily Energy"
    power_id: cir10
    platform: total_daily_energy
    accuracy_decimals: 0

  - name: "${c11_name} Daily Energy"
    power_id: cir11
    platform: total_daily_energy
    accuracy_decimals: 0

  - name: "${c12_name} Daily Energy"
    power_id: cir12
    platform: total_daily_energy
    accuracy_decimals: 0

  - name: "${c13_name} Daily Energy"
    power_id: cir13
    platform: total_daily_energy
    accuracy_decimals: 0

  - name: "${c14_name} Daily Energy"
    power_id: cir14
    platform: total_daily_energy
    accuracy_decimals: 0

  - name: "${c15_name} Daily Energy"
    power_id: cir15
    platform: total_daily_energy
    accuracy_decimals: 0

  - name: "${c16_name} Daily Energy"
    power_id: cir16
    platform: total_daily_energy
    accuracy_decimals: 0