Ряд наших устройств имеет встроенный порт RS-485 для прямого подключения электросчётчиков, имеющих данный интерфейс. Для облегчения тестирования устройств мы разработали небольшую программу-эмулятор. Именно о ней дальше и пойдёт речь.
Данная статья появилась после написания предыдущей про эмулятор ИБП.
Идея эмулятора оказалась очень полезной. С его помощью были отловлены некоторые баги в «прошивках» микроконтроллеров.
В итоге возникла идея реализовать то же самое и с электросчётчиками. Ранее отладку мы вели очень просто, вот на таком вот стенде:
Подключая по очереди каждый из электросчётчиков, разработчик «прошивки» убеждался в корректности считывания данных.
Надо сказать, что современные электросчётчики достаточно навороченные, но мы снимаем с них не всю информацию, а только следующие параметры:
Серийный номер
Напряжение сети (В)
Частота сети (Гц)
Ток нагрузки (А)
Мощность нагрузки (Вт)
Текущее значение тарифов (кВт x ч)
Начинали мы с модели «Меркурий 206», но постепенно список стал расширяться. На текущий момент у нас поддерживаются четыре модели:
Инкотекс-СК «Меркурий 206»
Энергомера «СЕ102»
Энергомера «СЕ102М»
IEK «STAR 104/1»
В будущем наверняка добавим поддержку и других приборов учёта.
Каждый электросчётчик имеет свой протокол работы и свою скорость обмена данными по RS‑485 интерфейсу. Ниже я хочу кратко рассказать об особенностях каждого из них.
Инкотекс-СК «Меркурий 206»
Данный счётчик весьма популярен, по нему несложно найти примеры подключения и примеры кода для считывания информации.
Счётчик подключается к считывающему устройству четырьмя проводами: линии A, B интерфейса RS-485, питание и «земля».
Скорость обмена данными 9600 бит/сек без контроля чётности.
Напряжение питания может быть в диапазоне от 6 до 12В.
Имеются модификации со встроенным источником питания: Меркурий 206 PRSN и Меркурий 206 PRSNO.
С этим счётчиком была связана одна проблема. Изначально мы питали его от напряжения 12В, от которого запитывался и наш контроллер. Но в процессе эксплуатации несколько счётчиков вышло из строя. Точнее они работали, но обмен данными по RS-485 пропал. Мы вскрыли несколько из них и обнаружили что там вышел из строя сам драйвер. Он питался через стабилизатор, выполненный на резисторе и стабилитроне. Так вот стабилитрон просто вышел из строя и всё напряжение шло непосредственно на драйвер.
Для исключения подобных случаев мы сделали у себя в контроллере отдельный выход на напряжение 10В для запитывания электросчётчиков. После этого было выпущено более 10 тыс. таких изделий и проблем с ними в этой части больше не было.
Теперь надо немного остановиться на протоколе обмена данного электросчётчика.
Он довольно простой и в чём-то похож на Modbus RTU.
Описание протокола можно найти здесь.
Форматы запросов и ответов совпадают.
Название поля |
Условное обозначение |
Длина поля (байт) |
Примечание |
Сетевой адрес |
ADDR |
4 |
Серийный номер счётчика (передаётся старшим байтом вперёд) |
Команды |
CMD |
1 |
Двоичный код команды |
Данные |
- |
0…17 |
Может отсутствовать (в зависимости от типа и назначения пакета) |
Контрольная сумма |
CRC16 |
2 |
2-х байтовый̆ циклический̆ избыточный̆ код, вычисляемый̆ по всем предшествующим байтам данного пакета (передаётся младшим байтом вперёд) |
CRC16 рассчитывается при помощи полинома 0xA001 и стартового значения 0xFFFF, точно так же, как в протоколе Modbus RTU.
Приведу пример функций расчёта контрольной суммы, которые используются у нас в проектах:
typedef struct
{
uint16_t CRC;
uint16_t Polynom;
} TCRC16;
void InitCRC16(TCRC16 *pCRC, uint16_t pInitValue, uint16_t pPolynom)
{
pCRC->CRC = pInitValue;
pCRC->Polynom = pPolynom;
}
void UpdateCRC16(TCRC16 *pCRC, uint8_t pValue)
{
pCRC->CRC ^= pValue;
for (uint8_t i = 8; i > 0; i--)
if (pCRC->CRC & 1)
pCRC->CRC = (pCRC->CRC >> 1) ^ pCRC->Polynom;
else
pCRC->CRC >>= 1;
}
К сожалению, в данном протоколе обмена отсутствует какой-либо префикс начала пакета данных, поэтому определить его можно только по времени отсутствия обмена данными на линии, необходимого для передачи 5-6 байт.
Мы используем следующие команды для этого счётчика:
0x27 (чтение тарифов) – в ответ получаем пакет из 16 байт данных по 4 байта на каждый тариф. При этом данные передаются в двоично-десятичном формате с точностью до 10 Вт.
Запрос:00 00 04 D2 27 79 7B
00 00 04 D2 – адрес счётчика
27 – команда
79 7B – CRC16
Ответ:00 00 04 D2 27 00 02 27 50 00 02 27 50 00 02 27 50 00 02 27 50 A5 FB
00 00 04 D2 – адрес счётчика
27 – команда
00 02 27 50 – тариф №1 (227,5 кВт × ч)
00 02 27 50 – тариф №2 (227,5 кВт × ч)
00 02 27 50 – тариф №3 (227,5 кВт × ч)
00 02 27 50 – тариф №4 (227,5 кВт × ч)
A5 FB – CRC16
0x63 (чтение U, I, P) – получаем значения сетевого напряжения, тока и мощности потребления. Данные также передаются в двоично-десятичном формате.
Величина напряжения передаётся с коэффициентом 10, тока – 100, мощности – без коэффициента.
Запрос:00 00 04 D2 63 79 48
00 00 04 D2 – адрес счётчика
63 – команда
79 48 – CRC16
Ответ:00 00 04 D2 63 23 00 01 50 00 01 00 A5 FB
00 00 04 D2 – адрес счётчика
63 – команда
23 00 – напряжение (230,0 В)
01 50 – ток нагрузки (1,5 А)
00 01 00 – потребляемая мощность (100 Вт)
A5 FB – CRC16
0x81 (F, текущего тарифа и битовых флагов) – из ответа данной команды нас интересуют только первые два байта, представляющие частоту в двоично-десятичном формате. Частота передаётся с коэффициентом 100.
Запрос:00 00 04 D2 81 F9 01
00 00 04 D2 – адрес счётчика
81 – команда
09 01 – CRC16
Ответ:00 00 04 D2 81 50 50 3A 00 00 00 00 00 00 CC A4
00 00 04 D2 – адрес счётчика
81 – команда
50 50 – частота (50,5 Гц)
3A – битовые флаги (0 бит – неравенство токов, 1 бит – обратная энергия, остальные биты не используются).
00 00 00 00 00 00 – резерв
CC A4 – CRC16
Энергомера «СЕ102»
Этот электросчётчик недорогой, но имеет меньше возможностей. В частности, он не позволяет выдавать значения напряжения сети, частоты, тока и мощности потребления нагрузкой.
Поэтому с данного счётчика мы считываем только значения тарифов и полное значение серийного номера. Полное потому, что адресация счётчика осуществляется по пяти последним цифрам серийника, а сам он имеет длину до 16 десятичных цифр.
Счётчик подключается к считывающему устройству также четырьмя проводами: линии A, B интерфейса RS-485, питание и «земля».
Скорость обмена данными 9600 бит/сек без контроля чётности.
Напряжение питания, указанное в документации: 12В.
Внутри для питания драйвера RS-485 используется классический линейный стабилизатор 78L05, проблем с выходом из строя модуля связи на данных счётчиках зафиксировано не было. Реально питать его можно напряжением от 7 до 18В.
Теперь рассмотрим протокол обмена. Тут он более навороченный.
Описание его находится здесь.
Формат запроса и ответа следующий:
Условное обозначение |
Длина поля (байт) |
Примечание |
END |
1 |
Байт начала пакета |
OPT |
1 |
Тип адресации и контрольной суммы |
AddrD |
2 |
Адрес электросчётчика (последние 5 цифр серийного номера) |
AddrS |
2 |
Адрес устройства, отправившего запрос. В нашем случае адрес контроллера. |
PAL |
N |
Структура данных |
CRC8 |
1 |
Контрольная сумма |
END |
1 |
Байт окончания пакета |
END (0xС0) – флаг, обозначающий начало и конец пакета. Если в пакете встречается байт с кодом, идентичным END, то такой байт замещается на последовательность из 2 байтов: 0xDB и 0xDC. Специальный символ 0xDB называется ESC-символом. Если в пакете встречается байт с кодом ESC-символа, то он замещается двухбайтовой последовательностью 0xDB, 0xDD.
OPT (0x48): включена 16-битная адресация и 8-битный циклический код.
AddrD – адрес назначения (счётчика), передаётся младшим байтом вперёд.
AddrS (253) – адрес источника, передаётся младшим байтом вперёд.
CRC8 – контрольная сумма пакета, рассчитывается до применения ESC-символов для всех байтов, исключая первый и последний END. Вычисление производится с использованием полинома 0xB5 и стартового значения 0x00.
Внутренняя структура сообщения PAL при запросе следующая:
Условное обозначение |
Длина поля (байт) |
Примечание |
Passw |
4 |
Пароль доступа |
Serv |
1 |
Сервисное поле |
CmdH |
1 |
Старший байт кода команды |
CmdL |
1 |
Младший байт кода команды |
Data |
N |
Данные |
Passw (777777) – пароль доступа к информации.
Формат поля Serv:
Условное обозначение |
Бит |
Примечание |
Direct |
7 |
Тип обмена (1 – запрос, 0 – ответ) |
ClassAccess |
6…4 |
Класс доступа к счётчику (0x05) |
MessageLen |
3…0 |
Количество байт, которые помещены в данные |
CmdH, CmdL – старший и младший байты кода команды счётчику.
Data – данные.
Внутренняя структура сообщения PAL при ответе повторяет структуру запроса, но только адреса AddrD и AddrS меняются местами, а поле пароля отсутствует:
Условное обозначение |
Длина поля (байт) |
Примечание |
Serv |
1 |
Сервисное поле |
CmdH |
1 |
Старший байт кода команды |
CmdL |
1 |
Младший байт кода команды |
Data |
N |
Данные |
Расчёт контрольной суммы осуществляется следующими функциями:
uint8_t emCRC8;
uint8_t emPolynom8;
void emUpdateCRC8(uint8_t pValue)
{
emCRC8 ^= pValue;
for (uint8_t i = 8; i > 0; i--)
{
if ((emCRC8 & 128) > 0)
emCRC8 = (uint8_t) (emCRC8 << 1) ^ emPolynom8;
else
emCRC8 <<= 1;
}
}
Мы используем следующие команды для данного счётчика:
0x0130 (чтение тарифа). В запросе передаём два значения: индекс глубины опроса (0 – текущие значения) и номер тарифа (1…5).
Запрос:C0 48 D2 04 FD 00 31 DE 0B 00 D2 01 30 00 02 33 C0
C0 – END
48 – OPT
D2 04 – адрес счётчика 1234
FD 00 – адрес контроллера 253
31 DE 0B 00 – Passw 777777
D2 – запрос с двумя байтами в пакете
01 – AddrH
30 – AddrL
00 – текущие значения
02 – тариф №2
33 – CRC8
C0 – END
Ответ:C0 48 FD 00 D2 04 57 01 30 10 08 21 DE 58 00 00 94 C0
C0 – END
48 – OPT
FD 00 – адрес контроллера 253
D2 04 – адрес счётчика 1234
57 – ответ с семью байтами в пакете
01 – AddrH
30 – AddrL
10 08 21 – текущая дата в двоично-десятичном формате
DE 58 00 00 – значение тарифа №2 (227,5 кВт × ч)
94 – CRC8
C0 – END
0x011A (чтение серийного номера). Серийник считывается за два запроса с передачей одного байта, который указывает какую часть серийного номера считать, младшую – 0 или старшую – 1. Каждая часть состоит из восьми символов.
Запрос:C0 48 D2 04 FD 00 31 DE 0B 00 D1 01 1A 01 CB C0
C0 – END
48 – OPT
D2 04 – адрес счётчика 1234
FD 00 – адрес контроллера 253
31 DE 0B 00 – Passw 777777
D1 – запрос с одним байтом в пакете
01 – AddrH
1A – AddrL
01 – старшая часть
CB – CRC8
C0 – END
Ответ:C0 48 FD 00 D2 04 58 01 1A 30 30 30 30 30 30 30 00 E0 C0
C0 – END
48 – OPT
FD 00 – адрес контроллера 253
D2 04 – адрес счётчика 1234
58 – ответ с восемью байтами в пакете
01 – AddrH
1A – AddrL
30 30 30 30 30 30 30 00 – старшая часть серийного номера (0000000)
E0 – CRC8
C0 – END
Запрос:C0 48 D2 04 FD 00 31 DE 0B 00 D1 01 1A 00 7E C0
C0 – END
48 – OPT
D2 04 – адрес счётчика 1234
FD 00 – адрес контроллера 253
31 DE 0B 00 – Passw 777777
D1 – запрос с одним байтом в пакете
01 – AddrH
1A – AddrL
00 – младшая часть
7E – CRC8
C0 – END
Ответ:C0 48 FD 00 D2 04 58 01 1A 34 33 32 31 30 30 30 30 DB DD C0
C0 – END
48 – OPT
FD 00 – адрес контроллера 253
D2 04 – адрес счётчика 1234
58 – ответ с восемью байтами в пакете
01 – AddrH
1A – AddrL
30 30 30 30 30 30 30 00 – младшая часть серийного номера (0000000)
DB DD – CRC8 (0xDB с учётом ESC-последовательности)
C0 – END
Энергомера «СЕ102М»
Данный электросчётчик интересен двумя моментами.
Во-первых, он имеет встроенный источник питания для порта RS-485, вследствие чего, подключение к контроллеру осуществляется всего двумя проводами – A и B.
Скорость обмена данными 9600 бит/сек, 7 бит данных, контроль чётности.
Во-вторых, он может работать без адресации, поэтому не нужно указывать никаких цифр серийного номера, чтобы снимать с него данные.
Протокол обмена этого электросчётчика соответствует ГОСТ Р МЭК 61107-2001 «Обмен данными при считывании показаний счетчиков, тарификации и управлении нагрузкой». Он достаточно навороченный, но в стандарте описан весьма тщательно, поэтому полностью приводить здесь я его не буду, а сосредоточусь лишь на основных моментах и примерах запросов.
Описание команд применительно к данному счётчику приведено здесь.
В первую очередь надо отметить, что протоколом предусмотрены следующие управляющие символы:
ACK (0x06) – подтверждение
SOH (0x01) – начало заголовка
STX (0x02) – начало текста
ETX (0x03) – конец текста
Хотя протокол и основан на системе «запрос-ответ», но единого формата пакетов тут нет. Более того, одни запросы и ответы могут содержать контрольную сумму, а другие передаются без неё!
Контрольную сумму далее будем обозначать как BCC. Она рассчитывается как сумма всех байтов за исключением начального SOH или STX.
Чтобы что-то считать со счётчика в первую очередь нужно установить связь специальной командой, затем отправить нужные команды на считывание параметров, после чего другой командой завершить обмен.
Разберём эти команды подробнее. В примерах далее пробелы будут разделять символы команд для наглядности, реально они не передаются. Специальным символы будут указываться своими аббревиатурами, а различные числовые значения в 16-ричном формате с префиксом 0x:
Начало передачи данных без адреса. С это команды начинается обмен:
Запрос:/?! 0x0D 0x0A
Ответ:/EKT5CE102Mv01 0x0D 0x0A
Подтверждение начала обмена:
Запрос:ACK 051 0x0D 0x0A
0 – нормальная процедура протокола
5 – скорость 9600 бод
1 – режим программирования.
Ответ:SOH P0 STX (1234) ETX BCC
P – команда пароля
0 – без пароля
(1234) – серийный номер в скобках
Чтение величины напряжения:
Запрос:SOH R1 STX VOLTA() ETX BCC
R – команда чтения
1 – чтение в формате ASCII
VOLTA() – чтение напряжения
Ответ:STX VOLTA(230.1) 0x0D 0x0A ETX BCC
VOLTA(230.1) – величина напряжения в скобках
Чтение величины тока нагрузки, мощности и частоты сети
Данные команды аналогичный команде чтения напряжения за исключением текстового названия кода команды:
CURRE() – ток нагрузки
POWEP() – мощность нагрузки
FREQU() – частота электрической сети
Чтение значения тарифов:
Запрос:SOH R1 STX ET0PE(02) ETX BCC
ET0PE – команда нужного тарифа. Нумерация начинается с 02. Индекс 01 предназначен для считывания суммарного значения всех тарифов
Ответ:STX ET0PE(118.74) 0x0D 0x0A ETX BCC
ET0PE(118.74) – значение тарифа в скобках
Завершение обмена:
Запрос:SOH B0 ETX BCC
B – команда выхода
0 – признак завершения обмена
Ответа на данную команду нет.
IEK «STAR 104/1»
Данный электросчётчик имеет много схожего с вышеописанными моделями. Он подключается к считывающему устройству четырьмя проводами: линии A, B интерфейса RS-485, питание и «земля».
Скорость обмена данными 9600 бит/сек без контроля чётности.
Напряжение питания может быть в диапазоне от 10 до 24В.
Для считывания данных следует обязательно использовать адресацию по пяти последним цифрам серийного номера.
Протокол обмена этого электросчётчика собственный. К сожалению, в открытом доступе его описание мне найти не удалось, поэтому мы обратились к производителю. Всего через неделю после запроса нам на электронную почту прислали текстовый документ с подробным описанием протокола. Никаких NDA подписывать не потребовалось. Даже никто не уточнил зачем он нам нужен.
Итак, разберём необходимые нам команды.
Формат запроса и ответа следующий:
Условное обозначение |
Длина поля (байт) |
Значение |
Примечание |
|
Start1 |
1 |
0x73 |
||
Start2 |
1 |
0x55 |
||
Parameters + Len |
1 |
С V0 D L4 L3 L2 L1 L0 |
Для этих полей вычисляется CRC8 |
Это подлежит байтстаффингу |
Reserved |
1 |
0x00 |
||
Address Destination |
2 |
|||
Address Source |
2 |
|||
Command |
1 |
|||
Password / Status |
4 |
|||
Data |
0…31 |
|||
CRC8 |
1 |
|||
Stop |
1 |
0x55 |
Start1, Start2: начало пакета.
Stop: конец пакета.
Parameters:
бит C – кодирование данных (1 – данные закодированы, 0 – нет).
бит V0 – вид структуры пакета (0 – пакет для устройств с малыми вычислительными мощностями (счётчиков), 1 – пакет для устройств с достаточными вычислительными мощностями (УСПД).
бит D – направление движения пакета (1 – запрос к устройству, 0 – ответ устройства).
биты L4…L0 –длина поля Data.
Address Destination: адрес устройства.
Address Source: адрес программы опроса, всегда равен 0xFFFF.
Command: код команды.
Password / Status: пароль для пакета запроса / статус для пакета ответа. Пароль заполняется только для пакетов, которые адресованы устройству. Когда устройство отвечает на запрос, оно заполняет это поле статусными значениями, это могут быть флаги уведомления об авариях в устройстве и другие информационные идентификаторы, к примеру код ошибки выполнения команды.
Data: поле данных. Оно может быть пустым, если в нём нет необходимости. Многобайтные значения передаются младшим байтом вперёд. Все дробные значения представляются как целые, с жёстко фиксированным положением запятой, согласно описанию структуры данных.
Контрольная сумма CRC8 вычисляется с использованием полинома 0хA9 и стартового значения 0x00.
Пакет перед отправкой подлежит обработке механизмом байтстаффинга, а при приёме – обратного байтстаффинга.
Байтстаффингу подвергаются все байты пакета за исключением стартовых и стопового.
При байтстаффинге анализируется каждый байт, и:
0х55 заменяется на 0х73 0х11
0х73 заменяется на 0х73 0х22
При обратном байтстаффинге проводится противоположная замена.
ИТОГИ
Рассмотрев эти четыре модели электросчётчиков можно сделать вывод о большом разнообразии протоколов обмена. Мне больше всего понравились реализации от Инкотекс и IEK. Они простые, бинарные, без лишних заморочек.
Жаль только, что производители не пришли ещё к какой-то единой реализации.
А пока на данном эмуляторе мы тестируем все наши изделия во всём возможном диапазоне напряжений, токов, частоты и мощности.
Программа эмулятора представляет из себя экран с настройками и выбором COM‑порта, через который будет осуществляться обмен. Поддерживаются все указанные выше электросчётчики.
Менять любые параметры можно прямо в процессе работы, и тут же видеть результат:
Скачать эмулятор можно по ссылке.
Комментарии (9)
vlad1988_1
03.11.2021 19:49Основной заказчик любит счётчики ПСЧ (Фрунзе), там описание интерфейса талмуд на 100+ страниц, где описываются не менее 50 параметров вплоть до температуры воздуха и показаний встроенного аксилометра. А парсинг достоен маньяка-программиста.
FDA847 Автор
03.11.2021 19:52В этих электросчётчиках параметров тоже полно. Только не все они нужны. Главное основное вытащить - напряжение, ток, частоту и тарифы.
smart_pic
03.11.2021 21:04Главное основное вытащить - напряжение, ток, частоту и тарифы.
С Энергомерой поосторожнее - у них есть баг. Неправильно измеряют ток если подключить нагрузку , регулируемую ШИМ. Подключите к примеру строительный фен на 1-2кВт с регулировкой температуры. Для контроля тока подключите обычный аналоговый (тот что со стрелкой) амперметр и снимите показания тока со счетчика. Будите удивлены.
FDA847 Автор
03.11.2021 21:07Интересная мысль. Надо опыт будет провести. Напишу тогда отдельный пост.
Но сами-то мы не используем электросчётчики. Это заказчики сами их закупают, наше дело контроллеры только им поставить.
smart_pic
Спасибо за обзор используемых счетчиков.
Работал со всеми этими счетчиками. В статье https://habr.com/ru/post/576470/ есть перечень счетчиков СЕ102М, СЕ303, Меркурий204, Меркурий206, Меркурий236, Миртек-12-РУ-W3, Миртек-32-РУ-W3. Но продолжаем и дальше расширять перечень поддерживаемых счетчиков.
Счетчик IEK «STAR 104/1» . Похоже что IEK только производит эти счетчики , а разработчик у них другой . Вы обращались за описанием в IEK или непосредственно к разработчику? Действительно эти счетчики лучшие из представленного вами списка.
На второе место я бы поставил счетчики Энергомеры, особенно СЕ102М, и совсем не рекомендовал бы для использования в серьезных проектах счетчики Меркурий. Тех поддержка никакая , от слова совсем. И надежность у них намного ниже других представителей. На Меркурий 236, Меркурий 206 нет никакой поддержки и специалистов, просто продолжают выпускать по инерции, то что когдато было разработано. Для хобийных проектов Меркурий подойдет.
FDA847 Автор
Я обратился в сам IEK по электронной почте. Написал в четверг, в следующую среду мне прислали просто файл с описанием протокола. В теле письма ничего не было :-) Никто не спросил зачем он мне.
СЕ102М удобен тем, что подключается двумя проводами A и B и не требует указания адреса для считывания показаний. Мы даже у себя на производстве используем его на проверочных стендах.
smart_pic
Понятно.
Разработчик дает программное обеспечение MeterTools и Протокол программного обмена - отличная помощь в разработке ПО для контроллеров. Техподдержка разработчика хорошая. Всегда отвечали на непонятные моменты и давали все необходимую информацию. Я общался напрямую с разработчиками. Можно поговорить с инженером , который разрабатывал именно эту модель, если интересуют нюансы.
С этим протоколом еще несколько заводов выпускают счетчики под своей маркой.
FDA847 Автор
Да там вроде исчерпывающее описание протокола. Мы его ещё в 19 году добавили в свои устройства.
Он самый удобный с точки зрения программной реализации оказался :-)
smart_pic
Самый удобный , быстрый. Команды легко составлять и распарсивать ответ.
Хорошо что начал с Энергомеры и Меркурия . После них IEK - игрушка :-)