esphome / issues

Issue Tracker for ESPHome
https://esphome.io/
290 stars 35 forks source link

ATM90E32 Power Sensor - voltage measurement accuracy flip flops between accurate and high each restart #3741

Closed alexruffell closed 1 year ago

alexruffell commented 1 year ago

The problem

I have a CircuitSetup 6 channel energy monitor and an addon board so a total of 12 channels. I am in the process of calibrating the boards so I have a load of approximately 100W with all the clamps on the same load. For the purposes of the calibration both L1 and L2 voltage references are the same (but they come from 2 different transformers, one small as it only provides a voltage reference and another larger as it powers the electronics).

I have a Siglent SDM 3055 5 1/2 digit benchtop DMM measuring the line voltage at the transformer inputs, and I am calibrating to that as it is most likely way more accurate and stable that the chips on this energy monitor.

The issue I am seeing is that I never seem to manage to get the 4 voltage measurements to jive. I expect that to some extent but what appears to be a software bug is the fact that the voltage measurement on the 1st board and 1st chip swaps places with the 2nd board and 1st chip in terms of accuracy.

The measurements are being taken every 3s. If I take them faster the system chokes, if slower the delta goes wild likely due to relatively large time delays between when the measurements are taken (line voltage fluctuates constantly quite a bit due to loads changing).

image

The arrows point to where I restarted the ESP32. 3 references always seem to match while one is high by about 0.5V. Each time you press restart, it trades place with the other one... so this must be some software issue.

After writing this, I restarted and this time it opted to match all the others (which is what it should do since the circuit (line voltage) feeding both transformers is the same:

image

I waited a little and restarted the ESP32 and now it is L1 AO V that is high, while before the brief interval where they all matched, it was L1V that was high.

image

In conclusion, the calibration makes all 4 voltage measurements close enough, however every time the system starts up something happens that introduces something like 0.5V error in one of the 1st chip of the board (there are 2 of these chips per board). The issue appears to only affect chip 01.

This issue may be related:

https://github.com/CircuitSetup/Expandable-6-Channel-ESP32-Energy-Meter/issues/88

Part of the issue discussed there is the fact that L1 on board 1 also powers the ESP32 so when it transmits the voltage dips (transformers output a higher voltage than rated as the rating refers to the voltage under specific load, since there is very little load the transformers' voltage is high and dips as soon as the ESP32 draws some current, but line voltage does not actually change in the same way so the hardware modification solution provided in the last few posts fixes that but has nothing to do with what I am reporting here). I am guessing there is some bootup setup for the chips that happens and something goes wrong.

Edit:

In this snapshot both L1s were high, so I restarted and one went to normal the other remained high. So the alternating between boards was random having started in opposing states

image

...another restart and now we are back to having both L1s high...

image

Which version of ESPHome has the issue?

2022.10.1

What type of installation are you using?

Home Assistant Add-on

Which version of Home Assistant has the issue?

2022.10

What platform are you using?

ESP32

Board

ESP-WROOM-32

Component causing the issue

atm90e32

Example YAML snippet

# Example config for when jp8-jp11 are all bridged - this connects all the voltage channels and allows for power to be calculated by the meter directly.
# Boards >= v1.4 jp8-jp11 are removed and have all voltage channels connected

# Oven 40A, Dryer 30A, HVAC 25A, HVAC 40A, SubPanel 80A

substitutions:
  devicename: home-energy-meter
  devicename_no_dashes: home_energy_meter
  friendly_devicename: "Home Energy Meter"
  device_description: "Home Energy Meter"
  appliance1: "Dryer"
  appliance2: "Oven"
#  appliance3: "TBD"
  hvac1: "Downstairs HVAC"
  hvac2: "Upstairs HVAC"
# Current Transformers:
# 20A/25mA SCT-006: 11143
# 30A/1V SCT-013-030: 8650
# 50A/1V SCT-013-050: 15420
# 80A/26.6mA SCT-010: 41660
# 100A/50ma SCT-013-000: 27518
# 120A/40mA: SCT-016: 41787
# 200A/100mA SCT-024: 27518
  current_cal_ct1:  '45800' #L1 Main
  current_cal_ct2:  '42170' #L1 Dryer
  current_cal_ct3:  '42070' #L1 Oven
  current_cal_ct4:  '42075' #L2 Oven
  current_cal_ct5:  '42500' #L2 Dryer
  current_cal_ct6:  '46000' #L2 Main
  current_cal_ct7:  '41660' #L1 CT7
  current_cal_ct8:  '41955' #L1 HVAC DS
  current_cal_ct9:  '41880' #L1 HVAC US
  current_cal_ct10: '41880' #L2 HVAC US
  current_cal_ct11: '41945' #L2 HVAC DS
  current_cal_ct12: '41660' #L2 CT12
# voltage calibrations done by feeding 60Hz sine on seconday input
# and painfully on primary but they match as close as I can get it
  v1_cal: '5022' #5022 1L1
  v2_cal: '5378' #5355 1L2 V2 and V4 match when stabe 60Hz sine is fed to them. Do not change independently
  v3_cal: '5004' #5006 2L1
  v4_cal: '5352' #5329 2L2 V2 and V4 match when stabe 60Hz sine is fed to them. Do not change independently
  # Interval of how often the wifi info is updated
  update_interval_wifi: "120s"
  # Interval of how often the power is updated
  update_interval_s:   "3s"
  update_interval_s_totals:   "60s"
  v_accuracy: "3"
  a_accuracy: "3"
  w_accuracy: "3"
  kwh_accuracy: "1"

esphome:
  name: ${devicename}
  comment: ${device_description}
  platform: ESP32
  board: nodemcu-32s

wifi:
  ssid: !secret iot_wifi_ssid
  password: !secret iot_wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "${devicename} Hotspot"
    password: !secret iot_wifi_password

#Faster than DHCP. Also use if can't reach because of name change
#  manual_ip:
#    static_ip: 192.168.3.196
#    gateway: 192.168.3.1
#    subnet: 255.255.255.0
#    dns1: 192.168.1.25
#    dns2: 192.168.1.26

#Manually override what address to use to connect to the ESP.
#Defaults to auto-generated value. Example, if you have changed your
#static IP and want to flash OTA to the previously configured IP address.
  use_address: 192.168.3.198

# Enable logging
logger:

# Enable Home Assistant API
api: 
  password: !secret api_pwd

ota:
  password: !secret ota_pwd

web_server:
  port: 80

spi:
  clk_pin: 18
  miso_pin: 19
  mosi_pin: 23

text_sensor:
  - platform: wifi_info
    ip_address:
      name: "${friendly_devicename}: IP"
      icon: "mdi:ip-outline"
      update_interval: ${update_interval_wifi}
    ssid:
      name: "${friendly_devicename}: SSID"
      icon: "mdi:wifi-settings"
      update_interval: ${update_interval_wifi}
    bssid:
      name: "${friendly_devicename}: BSSID"
      icon: "mdi:wifi-settings"
      update_interval: ${update_interval_wifi}
    mac_address:
      name: "${friendly_devicename}: MAC"
      icon: "mdi:network-outline"
    scan_results:
      name: "${friendly_devicename}: Wifi Scan"
      icon: "mdi:wifi-refresh"
      disabled_by_default: true

sensor:
  - platform: wifi_signal
    name: "${friendly_devicename}: WiFi Signal"
    update_interval: ${update_interval_wifi}
    device_class: signal_strength

#IC1
  - platform: atm90e32
    cs_pin: 5
    phase_a:
      voltage:
        name: "${friendly_devicename}: L1 V"
        id: ic1Volts
        accuracy_decimals: ${v_accuracy}
      current:
        name: "${friendly_devicename}: L1 A"
        id: ct1Amps
        accuracy_decimals: ${a_accuracy}
        # The max value for current that the meter can output is 65.535. If you expect to measure current over 65A, 
        # divide the gain_ct by 2 (120A CT) or 4 (200A CT) and multiply the current and power values by 2 or 4 by uncommenting the filter below
        filters:
          - multiply: 4
      power:
        name: "${friendly_devicename}: L1 W"
        id: ct1Watts
        accuracy_decimals: ${w_accuracy}
        filters:
          - multiply: 4
      gain_voltage: ${v1_cal}
      gain_ct: ${current_cal_ct1}
    phase_b:
      current:
        name: "${friendly_devicename}: ${appliance1} L1 A" #Dryer
        id: ct2Amps
        accuracy_decimals: ${a_accuracy}
      power:
        name: "${friendly_devicename}: ${appliance1} L1 W" #Dryer
        id: ct2Watts
        accuracy_decimals: ${w_accuracy}
      gain_voltage: ${v1_cal}
      gain_ct: ${current_cal_ct2}
    phase_c:
      current:
        name: "${friendly_devicename}: ${appliance2} L1 A" #Oven
        id: ct3Amps
        accuracy_decimals: ${a_accuracy}
      power:
        name: "${friendly_devicename}: ${appliance2} L1 W" #Oven
        id: ct3Watts
        accuracy_decimals: ${w_accuracy}
      gain_voltage: ${v1_cal}
      gain_ct: ${current_cal_ct3}
    frequency:
      name: "${friendly_devicename}: L1 Hz"
      device_class: frequency
    chip_temperature:
      name: "${friendly_devicename}: L1 Chip Temperature"
      id: l1_chip_temperature
      device_class: temperature
    line_frequency: 60Hz
    gain_pga: 1X
    update_interval: ${update_interval_s}
#IC2
  - platform: atm90e32
    cs_pin: 4
    phase_a:
      current:
        name: "${friendly_devicename}: ${appliance2} L2 A" #Oven
        id: ct4Amps
        accuracy_decimals: ${a_accuracy}
      power:
        name: "${friendly_devicename}: ${appliance2} L2 W" #Oven
        id: ct4Watts
        accuracy_decimals: ${w_accuracy}
      gain_voltage: ${v2_cal}
      gain_ct: ${current_cal_ct4}
    phase_b:
      current:
        name: "${friendly_devicename}: ${appliance1} L2 A" #Dryer
        id: ct5Amps
        accuracy_decimals: ${a_accuracy}
      power:
        name: "${friendly_devicename}: ${appliance1} L2 W" #Dryer
        id: ct5Watts
        accuracy_decimals: ${w_accuracy}
      gain_voltage: ${v2_cal}
      gain_ct: ${current_cal_ct5}
    phase_c:
      #this voltage is only needed if monitoring 2 voltages
      voltage:
        name: "${friendly_devicename}: L2 V"
        id: ic2Volts
        accuracy_decimals: ${v_accuracy}
      current:
        name: "${friendly_devicename}:  L2 A"
        id: ct6Amps
        accuracy_decimals: ${a_accuracy}
        # The max value for current that the meter can output is 65.535. If you expect to measure current over 65A, 
        # divide the gain_ct by 2 (120A CT) or 4 (200A CT) and multiply the current and power values by 2 or 4 by uncommenting the filter below
        filters:
          - multiply: 4
      power:
        name: "${friendly_devicename}: L2 W"
        id: ct6Watts
        accuracy_decimals: ${w_accuracy}
        filters:
          - multiply: 4
      gain_voltage: ${v2_cal}
      gain_ct: ${current_cal_ct6}
    frequency:
      name: "${friendly_devicename}: L2 Hz"
      device_class: frequency
    chip_temperature:
      name: "${friendly_devicename}: L2 Chip Temperature"
      id: l2_chip_temperature
      device_class: temperature
    line_frequency: 60Hz
    gain_pga: 1X
    update_interval: ${update_interval_s}

#IC1 AddOn
  - platform: atm90e32
    cs_pin: 0
    phase_a:
      voltage:
        name: "${friendly_devicename}: L1 AO V"
        id: ic3Volts
        accuracy_decimals: ${v_accuracy}
      current:
        name: "${friendly_devicename}: CT7 Amps"
        id: ct7Amps
        accuracy_decimals: ${a_accuracy}
      power:
        name: "${friendly_devicename}: CT7 Watts"
        id: ct7Watts
        accuracy_decimals: ${w_accuracy}
      gain_voltage: ${v3_cal}
      gain_ct: ${current_cal_ct7}
    phase_b:
      current:
        name: "${friendly_devicename}: ${hvac1} L1 A" #Downstairs
        id: ct8Amps
        accuracy_decimals: ${a_accuracy}
      power:
        name: "${friendly_devicename}: ${hvac1} L1 W" #Downstairs
        id: ct8Watts
        accuracy_decimals: ${w_accuracy}
      gain_voltage: ${v3_cal}
      gain_ct: ${current_cal_ct8}
    phase_c:
      current:
        name: "${friendly_devicename}: ${hvac2} L1 A" #Upstairs
        id: ct9Amps
        accuracy_decimals: ${a_accuracy}
      power:
        name: "${friendly_devicename}: ${hvac2} L1 W" #Upstairs
        id: ct9Watts
        accuracy_decimals: ${w_accuracy}
      gain_voltage: ${v3_cal}
      gain_ct: ${current_cal_ct9}
    line_frequency: 60Hz
    gain_pga: 1X
    update_interval: ${update_interval_s}
#IC2 AddOn
  - platform: atm90e32
    cs_pin: 16
    phase_a:
      current:
        name: "${friendly_devicename}: ${hvac2} L2 A" #Upstairs
        id: ct10Amps
        accuracy_decimals: ${a_accuracy}
      power:
        name: "${friendly_devicename}: ${hvac2} L2 W" #Upstairs
        id: ct10Watts
        accuracy_decimals: ${w_accuracy}
      gain_voltage: ${v4_cal}
      gain_ct: ${current_cal_ct10}
    phase_b:
      current:
        name: "${friendly_devicename}: ${hvac1} L2 A" #Downstairs
        id: ct11Amps
        accuracy_decimals: ${a_accuracy}
      power:
        name: "${friendly_devicename}: ${hvac1} L2 W" #Downstairs
        id: ct11Watts
        accuracy_decimals: ${w_accuracy}
      gain_voltage: ${v4_cal}
      gain_ct: ${current_cal_ct11}
    phase_c:
      voltage:
        name: "${friendly_devicename}: L2 AO V"
        id: ic4Volts
        accuracy_decimals: ${v_accuracy}
      current:
        name: "${friendly_devicename}: CT12 Amps"
        id: ct12Amps
        accuracy_decimals: ${a_accuracy}
      power:
        name: "${friendly_devicename}: CT12 Watts"
        id: ct12Watts
        accuracy_decimals: ${w_accuracy}
      gain_voltage: ${v4_cal}
      gain_ct: ${current_cal_ct12}
    line_frequency: 60Hz
    gain_pga: 1X
    update_interval: ${update_interval_s}

#Appliance1 Watts (Dryer)
  - platform: template
    name: "${friendly_devicename}: ${appliance1} W" #Dryer
    id: appliance1TotalWatts
    accuracy_decimals: ${w_accuracy}
    lambda: return id(ct2Watts).state + id(ct5Watts).state ;
    unit_of_measurement: "W"
    device_class: energy
    update_interval: ${update_interval_s_totals}

#Appliance1 Amps (Dryer)   
  - platform: template
    name: "${friendly_devicename}: ${appliance1} A" #Dryer
    id: appliance1TotalAmps
    accuracy_decimals: ${a_accuracy}
    lambda: return id(ct2Amps).state + id(ct5Amps).state ;
    unit_of_measurement: "A"
    device_class: current
    update_interval: ${update_interval_s_totals} 

#Appliance1 kWh - (Dryer)
  - platform: total_daily_energy
    name: "${friendly_devicename}: ${appliance1} kWh" #Dryer
    power_id: appliance1TotalWatts
    accuracy_decimals: ${w_accuracy}
    filters:
      - multiply: 0.001
    unit_of_measurement: "kWh"
    device_class: energy
    state_class: total_increasing

#Appliance2 Total Watts (Oven)
  - platform: template
    name: "${friendly_devicename}: ${appliance2} W" #Oven
    id: appliance2TotalWatts
    accuracy_decimals: ${w_accuracy}
    lambda: return id(ct3Watts).state + id(ct4Watts).state ;
    unit_of_measurement: "W"
    device_class: energy
    update_interval: ${update_interval_s_totals}

#Appliance2 Total Amps (Oven)
  - platform: template
    name: "${friendly_devicename}: ${appliance2} A" #Oven
    id: appliance2TotalAmps
    accuracy_decimals: ${a_accuracy}
    lambda: return id(ct3Amps).state + id(ct4Amps).state ;
    unit_of_measurement: "A"
    device_class: current
    update_interval: ${update_interval_s_totals}

#Appliance2 kWh - (Oven)
  - platform: total_daily_energy
    name: "${friendly_devicename}: ${appliance2} kWh" #Oven
    power_id: appliance2TotalWatts
    accuracy_decimals: ${kwh_accuracy}
    filters:
      - multiply: 0.001
    unit_of_measurement: "kWh"
    device_class: energy
    state_class: total_increasing

#HVAC1 Watts (Downstairs)
  - platform: template
    name: "${friendly_devicename}: ${hvac1} W" #Downstairs
    id: hvac1TotalWatts
    accuracy_decimals: ${w_accuracy}
    lambda: return id(ct8Watts).state + id(ct11Watts).state ;
    unit_of_measurement: "W"
    device_class: energy
    update_interval: ${update_interval_s_totals}

#HVAC1 Amps (Downstairs)  
  - platform: template
    name: "${friendly_devicename}: ${hvac1} A" #Downstairs
    id: hvac1TotalAmps
    accuracy_decimals: ${a_accuracy}
    lambda: return id(ct8Amps).state + id(ct11Amps).state ;
    unit_of_measurement: "A"
    device_class: current
    update_interval: ${update_interval_s_totals} 

#HVAC1 kWh (Downstairs)
  - platform: total_daily_energy
    name: "${friendly_devicename}: ${hvac1} kWh" #Downstairs
    power_id: hvac1TotalWatts
    accuracy_decimals: ${w_accuracy}
    filters:
      - multiply: 0.001
    unit_of_measurement: "kWh"
    device_class: energy
    state_class: total_increasing

#HVAC2 Watts (Upstairs)
  - platform: template
    name: "${friendly_devicename}: ${hvac2} W" #Upstairs
    id: hvac2TotalWatts
    accuracy_decimals: ${w_accuracy}
    lambda: return id(ct9Watts).state + id(ct10Watts).state ;
    unit_of_measurement: "W"
    device_class: energy
    update_interval: ${update_interval_s_totals}

#HVAC2 Amps (Upstairs)  
  - platform: template
    name: "${friendly_devicename}: ${hvac2} A" #Upstairs
    id: hvac2TotalAmps
    accuracy_decimals: ${a_accuracy}
    lambda: return id(ct9Amps).state + id(ct10Amps).state ;
    unit_of_measurement: "A"
    device_class: current
    update_interval: ${update_interval_s_totals} 

#HVAC2 kWh (Upstairs)
  - platform: total_daily_energy
    name: "${friendly_devicename}: ${hvac2} kWh" #Upstairs
    power_id: hvac2TotalWatts
    accuracy_decimals: ${kwh_accuracy}
    filters:
      - multiply: 0.001
    unit_of_measurement: "kWh"
    device_class: energy
    state_class: total_increasing

#Watts - L1 & L2
  - platform: template
    name: "${friendly_devicename}: L1 & L2 W"
    id: l1l2Watts
    accuracy_decimals: ${w_accuracy}
    lambda: return id(ct1Watts).state + id(ct6Watts).state ;
    unit_of_measurement: "W"
    device_class: energy
    update_interval: ${update_interval_s_totals}

#Amps - L1 & L2
  - platform: template
    name: "${friendly_devicename}: L1 & L2 A"
    id: l1l2Amps
    accuracy_decimals: ${a_accuracy}
    lambda: return id(ct1Amps).state + id(ct6Amps).state ;
    unit_of_measurement: "A"
    device_class: current
    update_interval: ${update_interval_s_totals}  

#Volts - L1 & L2 - Average
  - platform: template
    name: "${friendly_devicename}: L1 & L2 V (Avg)"
    id: l1l2Volts
    accuracy_decimals: ${v_accuracy}
    lambda: return (id(ic1Volts).state + id(ic2Volts).state)/2;
    unit_of_measurement: "V"
    device_class: voltage
    update_interval: ${update_interval_s_totals}  

#kWh - L1
  - platform: total_daily_energy
    name: "${friendly_devicename}: L1 kWh"
    power_id: ct1Watts
    accuracy_decimals: ${kwh_accuracy}
    filters:
      - multiply: 0.001
    unit_of_measurement: "kWh"
    device_class: energy
    state_class: total_increasing

#kWh - L2
  - platform: total_daily_energy
    name: "${friendly_devicename}: L2 kWh"
    power_id: ct6Watts
    accuracy_decimals: ${kwh_accuracy}
    filters:
      - multiply: 0.001
    unit_of_measurement: "kWh"
    device_class: energy
    state_class: total_increasing

#kWh - Whole House (L1 + L2)
  - platform: total_daily_energy
    name: "${friendly_devicename}: L1 & L2 kWh"
    power_id: l1l2Watts
    accuracy_decimals: ${kwh_accuracy}
    filters:
      - multiply: 0.001
    unit_of_measurement: "kWh"
    device_class: energy
    state_class: total_increasing

switch:
  - platform: restart
    name: "${friendly_devicename}: Restart"

button:
  - platform: safe_mode
    name: "${friendly_devicename}: Restart (Safe Mode)"

time:
  - platform: sntp
    id: sntp_time   


### Anything in the logs that might be useful for us?

_No response_

### Additional information

_No response_
github-actions[bot] commented 1 year ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

alexruffell commented 1 year ago

This issue is still present. Can anyone please look into it?