Skip to content

Latest commit

 

History

History
733 lines (631 loc) · 29.7 KB

README.md

File metadata and controls

733 lines (631 loc) · 29.7 KB

ESPHome компонент для подключения счетчиков электроэнергии Энергомера CE102M CE207 CE208 CE301 CE303 CE307 CE308 по RS-485 (ГОСТ МЭК/IEC 61107-2011)

1. Назначение

Компонент для считывания данных с электросчетчиков, поддерживающих протокол МЭК/IEC 61107, таких как Энергомера СЕ102М, СЕ301, СЕ303. Потенциально, может работать и сдругими счетчиками поддерживающими данный ГОСТ. Кроме того, работает и с некоторыми счетчиками Энергомера, заявленными как СПОДЭС (SPds в названии - например CE207-R7.849.2.OA SPds). Проверено на нескольких CE207, СЕ208, СЕ307, СЕ308.

2. Отказ от ответственности

Пользуясь данным ПО пользователь полностью берет на себя всю ответственность за любые последствия.

3. Функции

  • подключение как безадресное (широковещательный запрос), так и по адресу (9 последних цифр заводского номера),
  • работа с несколькими счетчиками на одной шине RS485,
  • работа с несколькими шинами RS485,
  • индивидуальна настройка сенсоров под конкретные запросы,
  • работа с массивом возвращаемых значений,
  • два вида сенсоров: числовой и текстовый,
  • работа только на скорости 9600 бод,
  • возможна, но не гарантируется, работа через оптопорт, если он поддерживает начальную скорость 9600 бод

4. Пример отображения в home-assistant

Пример отображения в home-asistant

5. Подключение

Устройства:

  • микроконтроллер Esp (работа провена на модулях на базе esp32, esp32s, esp32s2, esp8266)
    • если испольуется UART0, то в модуле логгера нужно отключать вывод в порт (baud_rate:0)
  • модуль трансивера RS485,
    • должен быть расчитан на 3.3 вольта (связка Esp + модуль на max485 расчитаный на 5 вольт может работать некорректно)
    • запитываем либо от esp модуля, либо отдельно, земля общая
  • счетчик электрической энергии (работа проверена со счетчиками Энергомера СЕ102М, СЕ301 версии CE301v11.8s4, СЕ303 версии CE303v11.8s4)
    • A+ и B- соединяем с модулем
      • желательно подключение витой парой (А и В переплетены между собой)
      • земли счетчика и модуля 485 не соединяем, а если кабель с экраном/оплеткой - можно соеденить с землей только со стороны модуля для уменьшения наводок
      • если расстояние до счетчика большое, то может понадобиться терминирующий резистор 120 Ом между A и B
    • CE301/CE303 в корпусах R32/R33 - необходимо отдельно подавать питание 9-12 вольт на клеммы V+, V-.
    • пользуемся документацией на счетчик для уточнения схем подключений

5.1 Рекомендуемый вариант подключения с RS-485 модулем с автоматическим выбором направления передачи

На данный момент в продаже много модулей RS-485 с расширеным набором функций - с логикой автоматического выбора направления передачи, защитными диодами и предохранителями. Эти модули рекомендуются к использованию, т.к. более надежны.
Например, модуль XY-017 Модуль XY-017

┌───────┐           3.3В     ┌─────────────┐                 ┌────────────────┐
│       │            └── VCC ┤             │                 │                │
│  MCU  ├ RX ──────────── RX ┤ RS485<->TTL ├ A ───┐─┐─┐─── A ┤ Электросчетчик │
│ ESPxx ├ TX ──────────── TX ┤   module    ├ B ───└─└─└─── B ┤                │
│       │                    │             │                 │                │
│       │                    │             │          ┌─── + ┤                │
│       ├ GND ────────── GND ┤             │      9-12В ── - ┤                │
└───────┘                    └─────────────┘                 └────────────────┘

Иногда RX/TX на модуле перепутаны - ничего страшного, просто меняем.

5.2 Вариант подключения с классическим RS-485 модулем с 4 входами

Классический модуль с RO/DI/DE/RE входами + общая земля. MAX485 расчитан на 5В, а MAX3485 на 3.3В, хотя первый в 90% случаев прекрасно работает и от 3.3В тоже.

  • RO - прием,
  • DI - передача,
  • DE + R̅E̅ - контроль линии для передачи данных (flow_control_pin в yaml)

Модуль без автоматического выбора направления


┌───────┐           3.3В     ┌─────────────┐                 ┌────────────────┐
│       │            └───VCC ┤             │                 │                │
│  MCU  ├ RX ──────────── RO ┤ RS485<->TTL ├ A ───┐─┐─┐─── A ┤ Электросчетчик │
│ ESPxx ├ TX ──────────── DI ┤   module    ├ B ───└─└─└─── B ┤                │
│       ├ FLOW ──────┬─── RE ┤             │                 │                │
│       │            └─── DE ┤             │          ┌─── + ┤                │
│       ├ GND ────────── GND ┤             │      9-12В ── - ┤                │
└───────┘                    └─────────────┘                 └────────────────┘

5.3 Подключение нескольких счетчиков

Подключение нескольких счетчиков возможно двумя способами:

  • Подключение к одной шине RS485 - самый простой вариант, просто необходимо параллельно подключить счетчики к одной шине: соединить А c А, B с B
     ┌─────┐    ┌─────┐         ┌─────┐
     │ # 1 │    │ # 2 │  ...    │ # N │
     │ A B │    │ A B │  ...    │ A B │
     └─┬─┬─┘    └─┬─┬─┘         └─┬─┬─┘
       │ │        │ │             │ │
  ─ A ─┴──────────┴───── ... ─────┘ │
  ─ B ───┴──────────┴─── ... ───────┘

  • Подключение к разным шинам RS485 - нужно подключать два модуля RS485.

6. Настройка основного компонента

Подлючаем внешний компонент из репозитория

external_components:
  - source: github://latonita/esphome-energomera-iec
    refresh: 30s
    components: [energomera_iec]

Конфигурируем UART 9600 7E1:

uart:
  rx_pin: GPIO16
  tx_pin: GPIO17
  baud_rate: 9600
  data_bits: 7
  parity: EVEN
  stop_bits: 1

Основной модуль (hub)

energomera_iec:
  id: ce102m
  update_interval: 30s
#  address: 123456789             # обязательно, если несколько устройств на одной шине
#  receive_timeout: 500ms         # время ожидания ответа от счетчика
#  delay_between_requests: 100ms  # задержка между запросами к счетчику
#  flow_control_pin: GPIO32
#  uart_id: bus_01
  • address - по-умолчанию пустой, если счетчик один - то адрес не требуется. Если несколько счетчиков - то там указываем его адрес - это последние 9 цифр его заводского номера.
  • receive_timeout - по-умолчанию 500мс, если ответы длинные - то можем не успеть дождаться ответа - увеличиваем.
  • delay_between_requests - по-умолчанию 100мс, иногда счетчик может тупить после больших запросов и не успевает принять новый - увеличиваем. важно - больше 1.5с не рекомендую, в счетчиках есть таймаут от 1.5с до 3с - если их не дергают, они считают, что общение закончено и закрывают сессию.
  • flow_control_pin - указываем, если 485 модуль требует сигнал направления передачи RE/DE
  • uart_id - если использьзуете несколько портов UART, указать его id

7. Настройка сенсоров для опроса счетчика

Реализованы два типа сенсоров:

  • sensor - числовые данные, float
  • text_sensor - текстовые данные в формате "как пришли от счетчика"
sensor/text_sensor:
  - platform: energomera_iec
    # energomera_iec_id: ce102m   # обязательно, если несколько счетчиков
    name: Название сенсора
    request: ЗАПРОС()
    index: индекс ответа, по-умолчанию 1
    sub_index: суб-индекс внутри ответа, по-умолчанию 0 = весь ответ из скобок
    ... остальные стандартные параметры для сенсора ...

Названия функций для запроса берем из документации на счетчик. Если запрос возвращает несколько значений, то, по-умолчанию, берется первое, но можно выбрать указав номер ответа (индекс, начинается с 1). Если в скобках указано несколько значений через запятую, то можно указать какое именно брать (суб-индекс, начинается с 1). Примеры запросов и ответов от счетчика:

Счетчик Запрос Ответ счетчика Индекс Суб-индекс Результат
CE102M VOLTA() VOLTA(228.93) не указан не указан 228.93
CE301/303 VOLTA() VOLTA(228.93)VOLTA(230.02)VOLTA(235.12) не указан не указан 228.93
CE301/303 VOLTA() VOLTA(228.93)VOLTA(230.02)VOLTA(235.12) 1 не указан 228.93
CE301/303 VOLTA() VOLTA(228.93)VOLTA(230.02)VOLTA(235.12) 2 не указан 230.02
*, кроме СПОДЭС ET0PE() ET0PE(34261.8262567)(25179.1846554)(9082.6416013)(0.0)(0.0)(0.0) 2 не указан 25179.1846554
CE307/308 EMD01(0.0,1) EMD01(20.08.24,0.45991)(0.41342) 1 2 0.45991
CE307/308 EMD01(0.0,1) EMD01(20.08.24,0.45991)(0.41342) 2 не указан 0.41342

Запросы берем из руководств на счетчики. Например, Руководство по эксплуатации CE102M , или Руководство пользователя CE301 и CE303.

Кроме того, оказалось, что некоторые СПОДЭС счетчики Энергомера (например, 307 и 308, и, возможно, также 207 и 208) тоже уверенно отвечают на запросы по стандарту МЭК, но с некоторыми особенностями. Например, там не работает команда ET0PE для получения накопленной энергии. Вместо этого можно использовать команды работы с архивом EMDzz/ENDzz и аналогичные. Документация по командам CE208 и CE308, взятая с форума поддержки Энергомеры.

7.1 Пример. Запрос потребления электроэнергии в кВт*ч

sensor:
  - platform: energomera_iec
    request: ET0PE()
    index: 2
    name: Энергия Тариф 1
    unit_of_measurement: kWh
    accuracy_decimals: 3
    device_class: energy
    state_class: total_increasing

  - platform: energomera_iec
    request: ET0PE()
    index: 3
    name: Энергия Тариф 2
    unit_of_measurement: kWh
    accuracy_decimals: 3
    device_class: energy
    state_class: total_increasing

7.2 Пример. Запрос даты

Дату счетчик возвращает в формате нн.дд.мм.гг, где - день недели 00 - воскресенье, 01 понедельник. Пример: 03.13.07.24. Превратить это в нормальную дату можно, например,так:

text_sensor:
  - platform: energomera_iec
    name: Date
    request: DATE_()
    filters:
      - lambda: |-
          std::string str{x};
          str.erase(0,3);
          str.insert(6,"20");
          return str;

Некоторые счетчики (например, СЕ207) дату возвращают в формате н.дд.мм.гг, например 3.11.09.24. Поэтому в lambda выражении надо поправить удаление лишних символов: str.erase(0,2);:

text_sensor:
  - platform: energomera_iec
    name: Date
    request: DATE_()
    filters:
      - lambda: |-
          std::string str{x};
          str.erase(0,2); 
          str.insert(6,"20");
          return str;

7.3 Пример. Несколько счетчиков на одной шине

Можно опрашивать несколько устройств на одной шине, необходимо обязательно указывать адрес счетчика. В противном случае счетчики начнут отвечать одновременно и процесс считывания данных будет нарушен.

uart:
    id: bus_1
    rx_pin: GPIO4
    tx_pin: GPIO5
    baud_rate: 9600
    data_bits: 7
    parity: EVEN
    stop_bits: 1

energomera_iec:
  - id: meter_01
    uart_id: bus_1
    address: 123456001
  - id: meter_02
    uart_id: bus_1
    address: 123456002

sensor:
  - platform: energomera_iec
    energomera_iec_id: meter_01
    request: ET0PE()
    index: 1
    name: Электроэнергия. Счетчик №1
    unit_of_measurement: kWh
    accuracy_decimals: 3
    device_class: energy
    state_class: total_increasing

  - platform: energomera_iec
    energomera_iec_id: meter_02
    request: ET0PE()
    index: 1
    name: Электроэнергия. Счетчик №2
    unit_of_measurement: kWh
    accuracy_decimals: 3
    device_class: energy
    state_class: total_increasing

8. Примеры готовых конфигураций

Важный момент - в примерах имена сенсоров указаны на русском языке для лучшего понимания. При компиляции Esphome заменяет все не-латинские символы на _. И если попадутся два сенсора с одинаковыми названиями с учетом замен - то Home Assistant будет смешивать их данные. Крайне рекомендую в yaml писать на английском/латинице, а уже в HASS переименовывать на русский.

Для однофазного счетчика CE102M
esphome:
  name: energomera-ce102m

esp32:
  board: esp32dev
  framework:
    type: arduino

logger:
  level: DEBUG

external_components:
  - source: github://latonita/esphome-energomera-iec
    refresh: 30s
    components: [energomera_iec]

uart:
  rx_pin: GPIO16
  tx_pin: GPIO17
  baud_rate: 9600
  data_bits: 7
  parity: EVEN
  stop_bits: 1

energomera_iec:
  id: ce102m
  update_interval: 30s
#  receive_timeout: 500ms
#  delay_between_requests: 150ms
#  flow_control_pin: GPIO32

sensor:
  - platform: energomera_iec
    request: ET0PE()
    index: 1
    name: Energy
    unit_of_measurement: kWh
    accuracy_decimals: 3
    device_class: energy
    state_class: total_increasing

  - platform: energomera_iec
    request: ET0PE()
    index: 2
    name: Energy T1
    unit_of_measurement: kWh
    accuracy_decimals: 3
    device_class: energy
    state_class: total_increasing

  - platform: energomera_iec
    request: ET0PE()
    index: 3
    name: Energy T2
    unit_of_measurement: kWh
    accuracy_decimals: 3
    device_class: energy
    state_class: total_increasing

  - platform: energomera_iec
    name: Current
    request: CURRE()
    unit_of_measurement: A
    accuracy_decimals: 2
    device_class: current
    state_class: measurement

  - platform: energomera_iec
    name: Voltage
    request: VOLTA()
    unit_of_measurement: V
    accuracy_decimals: 1
    device_class: voltage
    state_class: measurement

  - platform: energomera_iec
    name: Frequency
    request: FREQU()
    unit_of_measurement: Hz
    accuracy_decimals: 2
    device_class: frequency
    state_class: measurement

  - platform: energomera_iec
    name: Power Factor
    request: COS_f()
    unit_of_measurement: "%"
    accuracy_decimals: 2
    device_class: power_factor
    state_class: measurement

  - platform: energomera_iec
    name: Active Power
    request: POWEP()
    unit_of_measurement: kW
    accuracy_decimals: 3
    device_class: power
    state_class: measurement

text_sensor:
  - platform: energomera_iec
    name: Serial Number
    request: SNUMB()
    entity_category: diagnostic

  - platform: energomera_iec
    name: Time
    request: TIME_()
    entity_category: diagnostic

  - platform: energomera_iec
    name: Date
    request: DATE_()
    entity_category: diagnostic
    filters:
      - lambda: |-
          std::string str{x};
          str.erase(0,3);
          str.insert(6,"20");
          return str;

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  reboot_timeout: 5min
  power_save_mode: NONE

api:
  password: !secret api_password

ota:
  password: !secret ota_password
Для трехфазных счетчиков CE301, CE303
esphome:
  name: energomera-ce303

esp8266:
  board: nodemcuv2

logger:
  level: DEBUG

external_components:
  - source: github://latonita/esphome-energomera-iec
    refresh: 10s
    components: [energomera_iec]

uart:
  rx_pin: D5
  tx_pin: D6
  baud_rate: 9600
  data_bits: 7
  parity: EVEN
  stop_bits: 1
  rx_buffer_size: 512

energomera_iec:
  id: ce303
  address: 123456789
  update_interval: 10s
#  delay_between_requests: 50ms
#  receive_timeout: 500ms

sensor:
  - platform: energomera_iec
    request: ET0PE()
    index: 1
    name: Energy
    unit_of_measurement: kWh
    accuracy_decimals: 3
    device_class: energy
    state_class: total_increasing

  - platform: energomera_iec
    request: ET0PE()
    index: 2
    name: Energy T1
    unit_of_measurement: kWh
    accuracy_decimals: 3
    device_class: energy
    state_class: total_increasing

  - platform: energomera_iec
    request: ET0PE()
    index: 3
    name: Energy T2
    unit_of_measurement: kWh
    accuracy_decimals: 3
    device_class: energy
    state_class: total_increasing

  - platform: energomera_iec
    name: Current Phase A
    request: CURRE()
    index: 1
    unit_of_measurement: A
    accuracy_decimals: 3
    device_class: current
    state_class: measurement

  - platform: energomera_iec
    name: Current Phase B
    request: CURRE()
    index: 2
    unit_of_measurement: A
    accuracy_decimals: 3
    device_class: current
    state_class: measurement

  - platform: energomera_iec
    name: Current Phase C
    request: CURRE()
    index: 3
    unit_of_measurement: A
    accuracy_decimals: 3
    device_class: current
    state_class: measurement

  - platform: energomera_iec
    name: Voltage Phase A
    request: VOLTA()
    index: 1
    unit_of_measurement: V
    accuracy_decimals: 3
    device_class: voltage
    state_class: measurement

  - platform: energomera_iec
    name: Voltage Phase B
    request: VOLTA()
    index: 2
    unit_of_measurement: V
    accuracy_decimals: 3
    device_class: voltage
    state_class: measurement

  - platform: energomera_iec
    name: Voltage Phase C
    request: VOLTA()
    index: 3
    unit_of_measurement: V
    accuracy_decimals: 3
    device_class: voltage
    state_class: measurement

  - platform: energomera_iec
    name: Active Power
    request: POWEP()
    index: 1
    unit_of_measurement: kW
    accuracy_decimals: 3
    device_class: power
    state_class: measurement

  - platform: energomera_iec
    name: Active Power Phase A
    request: POWPP()
    unit_of_measurement: kW
    accuracy_decimals: 3
    index: 1
    device_class: power
    state_class: measurement

  - platform: energomera_iec
    name: Active Power Phase B
    request: POWPP()
    unit_of_measurement: kW
    accuracy_decimals: 3
    index: 2
    device_class: power
    state_class: measurement

  - platform: energomera_iec
    name: Active Power Phase C
    request: POWPP()
    unit_of_measurement: kW
    accuracy_decimals: 3
    index: 3
    device_class: power
    state_class: measurement

text_sensor:
  - platform: energomera_iec
    name: Serial Number
    request: SNUMB()
    entity_category: diagnostic

  - platform: energomera_iec
    name: Time
    request: TIME_()
    entity_category: diagnostic

  - platform: energomera_iec
    name: Date
    request: DATE_()
    entity_category: diagnostic
    filters:
      - lambda: |-
          std::string str{x};
          str.erase(0,3);
          str.insert(6,"20");
          return str;

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

api:
  password: !secret api_password

ota:
  platform: esphome
  password: !secret ota_password
Для однофазного счетчика CE207 СПОДЭС
esphome:
  name: energomera-ce207-esp32
  friendly_name: Energomera-ce207-esp32

esp32:
  board: esp32dev
  framework:
    type: arduino

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

api:
  password: !secret api_password

ota:
  platform: esphome
  password: !secret ota_password

external_components:
  - source: github://latonita/esphome-energomera-iec
    refresh: 30s
    components: [energomera_iec]

uart:
  rx_pin: GPIO16
  tx_pin: GPIO17
  baud_rate: 9600
  data_bits: 7
  parity: EVEN
  stop_bits: 1 

energomera_iec:
  id: ce207

sensor:
  - platform: energomera_iec
    request: EMD01(0.0,3)
    index: 1
    sub_index: 2
    name: Energy
    unit_of_measurement: kWh
    accuracy_decimals: 3
    device_class: energy
    state_class: total_increasing

  - platform: energomera_iec
    name: Current
    request: CURRE()
    unit_of_measurement: A
    accuracy_decimals: 2
    device_class: current
    state_class: measurement

  - platform: energomera_iec
    name: Voltage
    request: VOLTA()
    unit_of_measurement: V
    accuracy_decimals: 1
    device_class: voltage
    state_class: measurement

  - platform: energomera_iec
    name: Frequency
    request: FREQU()
    unit_of_measurement: Hz
    accuracy_decimals: 2
    device_class: frequency
    state_class: measurement

  - platform: energomera_iec
    name: Power Factor
    request: COS_f()
    unit_of_measurement: "%"
    accuracy_decimals: 2
    device_class: power_factor
    state_class: measurement

  - platform: energomera_iec
    name: Active Power
    request: POWEP()
    unit_of_measurement: kW
    accuracy_decimals: 3
    device_class: power
    state_class: measurement

text_sensor:
  - platform: energomera_iec
    name: Serial Number
    request: SNUMB()
    entity_category: diagnostic

  - platform: energomera_iec
    name: Time
    request: TIME_()
    entity_category: diagnostic

  - platform: energomera_iec
    name: Date
    request: DATE_()
    entity_category: diagnostic
    filters:
      - lambda: |-
          std::string str{x};
          str.erase(0,2);
          str.insert(6,"20");
          return str;

9. Проблемы, особенности, рекомендации

  • "да должно всё работать" :)
  • основная проблема - неверно выбранное питание/модуль для 485. еще достаточно часто модули встречаются нерабочие.
  • при слабом сигнале wifi, esp может терять точку доступа и часто заново подключаться. А если esp одноядерная (например, esp8266 или esp32s2), то это может влиять на сбор данных со счетчика и, в целом, может приводить к неожиданным перезагрузкам
  • по идее, hardware uart всегда надежнее, но, в целом, software uart и на esp8266 работает без сбоев, если не делать запросы, которые возвращают кучу данных
  • забавно, что у кого-то бывает работает только software uart, у кого-то - только hardware uart, у многих - и так и так
  • модуль 485 желательно брать с защитными диодами - наблюдали как умершую esp8266, так и модуль, у которого работала только отправка, а прием не работал
  • модули 485 с маркировкой пинов rx/tx - иногда rx/tx наоборот :)
  • внимательно смотрите на номера пинов на esp - ориентируйтесь на распиновку модулей (pinout diagram). Часто производители нумеруют пины на плате совсем не так, как они пронумерованы на чипе esp (например, nodemcu). Указывайте номера, как на чипе (GPIOxx)
  • при подключении нескольких счетчиков на одну шину - опрос происходит последовательно
  • при подключении нескольких счетчиков на разные шины - опрос может происходить параллельно и если используется SoftwareSerial, то могут появляться ошибки при считывании, рекомендуется использовать esp32 и только HardwareSerial