ATM90E26 Power Sensor
=====================

.. seo::
    :description: Instructions for setting up ATM90E26 energy metering sensors
    :image: atm90e26.jpg
    :keywords: ATM90E26, Single-Phase High-Performance Wide-SpanEnergy Metering IC, Single Phase Energy Meter

The ``atm90e26`` sensor platform allows you to use your ATM90E26 voltage/current and power sensors
(`datasheet <https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-46002-SE-M90E26-Datasheet.pdf>`__) with
ESPHome. This sensor is found in the `DitroniX GTEM ESP32 <https://ditronix.net/wiki/gtem-esp32-atm90e26-sdk-v1-specification/>`__ energy meter and other devices.

Communication with the device is done via an :ref:`SPI bus <spi>`, so you need to have an ``spi:`` entry in your configuration
with both ``mosi_pin`` and ``miso_pin`` set.

The ATM90E26 IC measures a single phase's voltage (using a transformer) and current (using a shunt or CT clamp)
and additionally provides active, reactive, and apparent power, frequency, power factor and phase angle measurements.

Configuration variables:
------------------------

- **cs_pin** (**Required**, :ref:`Pin Schema <config-pin_schema>`): The pin CS is connected to. For the 6 channel meter main board, this will always be 5 and 4. For the add-on boards a jumper can be selected for each CS pin, but default to 0 and 16.
- **line_frequency** (**Required**, string): The AC line frequency of the supply voltage. One of ``50Hz``, ``60Hz``.
- **meter_constant** (**Required**, float): The number of pulses per kWh. The ATM90E26 internally works based on pulses and 
  this value converts a pulse into Wh, which are emitted as ``forward_active_energy`` etc. Matching it against an existing 
  meter is useful in that it allows visual confirmation for some devices that blink an LED for each pulse. Common values are
  1000 pulses/kWh, 1666.66 pulses/kWh, or 3200 pulses/kWh. See also **gain_metering** which determines after how much energy
  a pulse is emitted.
- **voltage** (*Optional*): Use the voltage value of this phase in V (RMS).
  All options from :ref:`Sensor <config-sensor>`.
- **current** (*Optional*): Use the current value of this phase in amperes. All options from
  :ref:`Sensor <config-sensor>`.
- **power** (*Optional*): Use the power value on this phase in watts. All options from
  :ref:`Sensor <config-sensor>`.
- **reactive_power** (*Optional*): Use the reactive power value on this phase. All options from
  :ref:`Sensor <config-sensor>`.
- **power_factor** (*Optional*): Use the power factor value on this phase. All options from
  :ref:`Sensor <config-sensor>`.
- **forward_active_energy** (*Optional*): Use the forward active energy value on this phase in watt-hours.
  All options from :ref:`Sensor <config-sensor>`.
- **reverse_active_energy** (*Optional*): Use the reverse active energy value on this phase in watt-hours.
  All options from :ref:`Sensor <config-sensor>`.
- **frequency** (*Optional*): Use the frequency value calculated by the meter. All options from
  :ref:`Sensor <config-sensor>`.
- **pl_const** (*Optional*, int): A constant derived from the physical characteristics of your measurement setup. See the Calibration section.
  Defaults to ``1429876``.
- **gain_metering** (*Optional*, int): This value determines how quickly internal energy registers accumulate and hence defines the value of a "pulse". Matching it against an existing meter is useful in that it allows visual confirmation for some devices that blink an LED for each pulse. See also the **meter_constant**.
  Defaults to ``7481``.
- **gain_voltage** (*Optional*, int): Voltage gain to scale the low voltage AC power back to household mains feed.
  Defaults to ``26400``.
- **gain_ct** (*Optional*, int): CT clamp calibration value.
  Defaults to ``31251``.
- **gain_pga** (*Optional*, string): The gain for the CT clamp. Valid values are ``1X``, ``4X``, ``8X``, ``16X``, and ``24X``.
  Defaults to ``1X``.
- **update_interval** (*Optional*, :ref:`config-time`): The interval to check the sensor. Defaults to ``60s``.
- **spi_id** (*Optional*, :ref:`config-id`): Manually specify the ID of the :ref:`SPI Component <spi>` if you want
  to use multiple SPI buses.

Calibration
-----------

This sensor needs calibration to show correct values. In order to calibrate your AC-AC transformer and CT clamp
it is easiest to start with the default values and then adjust them as necessary while measuring a known current.
For a more accurate calibration you can use a Kill-A-Watt or similar meter.

**Voltage** is adjusted linearly to bring the observed value in agreement with a reference measurement. If your
Kill-A-Watt shows 241 Volts and the ATM90E26 shows 234 Volts using the default `gain_voltage` of 26400, it would
need to be adjusted to `241 / 234 * 26400 = 27190`.

**Current** is best measured with an ideal load (e.g. a space heater). The process is the same as for voltage, but
you modify the `gain_ct` value instead. For a SCT-013-000 clamp a value of 28621 worked well for me but you should
calibrate your specific clamp. Note that the ATM90E26 can output a **maximum current of 65A**. If you expect to
measure higher current, simply "mis-calibrate" the CT clamp by a factor of e.g. 2 so that the ATM90E26 thinks it is
measuring a lower current (e.g. 10A when 20A are flowing) and multiply the sensor's output by 2.

**PL Constant** is computed using the physical characteristics of the device we use. We compute the constant
as `as 838860800 * gain_pga * <mV at 1A current> * <mV at ref voltage> / (<pulse constant> * <ref voltage>)`.
See Section 3.2.2 in the
`application note <https://ww1.microchip.com/downloads/en/Appnotes/Atmel-46102-SE-M90E26-ApplicationNote.pdf>`__
for additional details. Say we use a SCT-013-000 CT clamp, which has an output of 50mA for 100A input current. Our
burden has a value of 12 Ohm. We therefore expect to measure 6mV per amp of input current. Say our AC-AC
transformer outputs 19.3V at 230V and we use a 100:1 voltage divider in front of the ATM90E26. We would therefore
expect to measure 193 mV at a line voltage of 230V. The resulting PL Constant is, assuming a meter constant of
3200 pulses/kWh (see below): `838860800 * 1 * 6 * 193 / (3200 * 230) = 1319838`.

**Meter Calibration** is completed by matching the ATM90E26's CF1 (active energy) pulse to those of your electricity
meter by adjusting the `gain_metering` value until the pulses match. Next, set the `meter_constant`, which defines
how many pulses make up one kWh of energy. If you are matching an existing meter, typical values may be 3200 pulses/kWh,
1000 pulses/kWh, or for some rotating meters 1666.66 pulses per kWh. If you're not matching against a meter you may
want to calibrate this value to emit 1000 pulses per kWh, or whatever other value is useful for your project.

If your current clamp or voltage transformer aren't well matched to the specific A90E26-based device you're using
it **may be necessary to multiply values**, to stay within the value ranges specified in the
`datasheet <https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-46002-SE-M90E26-Datasheet.pdf>`__ and
`application note <https://ww1.microchip.com/downloads/en/Appnotes/Atmel-46102-SE-M90E26-ApplicationNote.pdf>`__.
This component will enforce the stated maxima. In the example below, the AC-AC transformer used read 230V line voltage
as 86.6V with default settings. This would imply a `gain_voltage` value of `230 / 86.6 * 26400 = 70115`.
However, the chip's application note says this value must be below 32768. If we divide the `gain_voltage` by 4, we
stay within the specified range, but must then multiply the voltage output as well as the power reading, which are
off by a factor of 4. This is due to the width of registers in the chip and **is not necessary if your components
can be calibrated within the specified range.**

Keeping the calibration values at the top of your yaml might make editing easier.

.. code-block:: yaml

    substitutions:
      plconst_cal: '1429876' # default: 1429876, compute as 838860800 * (gain_pga * <sampled voltage (mV) at 1Amp current> * <sampled voltage (mV) at reference voltage> / (<pulse constant (e.g. 3200 pulses/kWh)> * <reference voltage, e.g. 230V>))
      current_cal: '32801'   # default: 31251
      voltage_cal: '17528'   # default: 26400 - Application note says this should be < 32768, maybe for some internal computation?
      metering_cal: '7481'   # default: 7481 - Calibrate this to match your meter based on the CF1 (CFx) pulse.

    spi:
      clk_pin: 18
      miso_pin: 19
      mosi_pin: 23

    sensor:
        - platform: atm90e26
            cs_pin: 5
            voltage:
                name: House Voltage
                accuracy_decimals: 1
                filters:
                    - multiply: 4
            current:
                name: House Amps
      # 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: 2
            power:
                name: House Watts
                accuracy_decimals: 1
                filters:
                    - multiply: 4
            reactive_power:
                name: House Reactive Power
            power_factor:
                name: House Power Factor
                accuracy_decimals: 2
            forward_active_energy:
                name: House Forward Active Energy
            reverse_active_energy:
                name: House Reverse Active Energy
            frequency:
                name: House Freq
            line_frequency: 50Hz
            pl_const: ${plconst_cal}
            meter_constant: '3200.0'  # My old rotating-disc meter has a meter constant of 1666.66
            gain_metering: ${metering_cal}
            gain_voltage: ${voltage_cal}
            gain_ct: ${current_cal}
            gain_pga: 1X
            update_interval: '10s'

See Also
--------

- :ref:`sensor-filters`
- :apiref:`atm90e26/atm90e26.h`
- :ghedit:`Edit`
