Русский
Русский
English
Статистика
Реклама

Блог компании спецпромдизайн

Эмулятор ИБП с протоколами Megatec и Voltronic

11.05.2021 08:07:02 | Автор: admin

Ряд наших устройств имеет встроенный порт RS-232 для считывания данных с источников бесперебойного питания (ИБП) по двум наиболее распространённым протоколам обмена Megatec и Voltronic. Для облегчения тестирования устройств мы разработали небольшую программу-эмулятор. Именно о ней дальше и пойдёт речь.

Протоколы Megatec и Voltronic текстовые и довольно простые. Обмен данными ведётся на низкой скорости 2400 бит/сек, 8 бит данных, без контроля чётности по принципу запрос-ответ. Запросы представляют собой текстовые строки длиной от одного до трёх символов, оканчивающихся байтом перевода строки (код 0x0D). Ответы приходят также в текстовом виде с завершающим символом 0x0D. Значения в ответах разделяются пробелами. Числа могут передаваться либо с незначащими нулями в начале, либо с дополнительными пробелами.

В зависимости от конкретного ИБП таких команд может быть разное количество, но основную информацию можно получить при помощи четырёх из них. Рассмотрим их подробнее.

Q1 запрос текущего состояния
Ответ ИБП:
(MMM.M NNN.N PPP.P QQQ RR.R S.SS TT.T b7b6b5b4b3b2b1b0
( начальный символ.
MMM.M входное напряжение, В.
NNN.N напряжение, при котором последний раз был осуществлён переход на работу от батареи, В.
PPP.P выходное напряжение, В.
QQQ потребляемая мощность, %.
RR.R частота сети, Гц.
SS.S напряжение на батарее, В. Оно может передаваться в двух форматах: SS.S для линейно-интерактивных ИБП или S.SS для онлайн-ИБП (указывается напряжение на одном элементе).
TT.T температура ИБП, C.
b7...b0 статусные биты, которые могут принимать значение 0 или 1.
b7 1 : работа от АКБ, 0 : работа от сети.
b6 1 : низкий уровень заряда АКБ, 0 : АКБ в норме.
b5 1 : байпас включён, 0 : байпас выключен (только для онлайн-ИБП).
b4 1 : авария ИБП, 0 : ИБП в норме.
b3 1 : линейно-интерактивный ИБП, 0 : онлайн-ИБП.
b2 1 : запущен тест ИБП.
b1 1 : ИБП выключен, 0 : ИБП включён.
b0 1 : звуковой сигнал включён, 0 : выключен.

I запрос информации об ИБП
Ответ ИБП:
#CompanyName Model Version
# начальный символ.
CompanyName производитель ИБП.
Model название модели.
Version версия ИБП.

F запрос информации о номинальных параметрах ИБП
Ответ ИБП:
#MMM.M QQQ SS.SS RR.R
# начальный символ.
MMM.M номинальное выходное напряжение, В.
QQQ номинальный выходной ток, А.
SS.SS номинальное напряжение АКБ, В (может быть в форматах SS.SS или SSS.S).
RR.R номинальная частота выходного напряжения, Гц.

QBV запрос информации об АКБ
Ответ ИБП:
(RRR.R NN MM CCC TTT
( начальный символ.
RRR.R номинальное напряжение АКБ, В.
NN количество батарей в АКБ, шт.
MM количество параллельных групп батарей, шт.
CCC ёмкость АКБ, %.
TTT оставшееся время работы от АКБ, мин.

Помимо команд, которые считывают какие-либо параметры ИБП, есть ещё управляющие команды. Часто используются такие:
T запуск теста АКБ на 10 сек.
TL запуск теста АКБ до полного разряда.
T<n> запуск теста АКБ на заданное количество минут.
CT остановка теста АКБ.
Q включение/отключение звукового сигнала ИБП.

На первый взгляд вышеописанные команды очень простые, но дьявол, как обычно, кроется в мелочах. Например, некоторые ИБП вообще не выдают ответы на команды I и QBV. Примером может служить ряд моделей от Ippon.

Также замечено, что различные ИБП выполняют команду Q (управление звуковым сигналом) за совершенно разное время. То есть от момента выдачи команды Q и до момента смены бита b0 в ответе на команду Q1 может пройти до 30 сек!!! А так как включение и выключение осуществляется одной командой, то при автоматизированном управлении может начаться колебательный процесс. Например, контроллеру через Web-интерфейс задаётся выключенное состояние звукового сигнала. Он анализирует текущее состояние ИБП (по флагу b0), и если оно отличается от нужного, то подаёт команду Q. При следующем запросе Q1 контроллер опять проверяет флаг b0 и видит, что он не поменялся. В результате он опять подаёт команду Q. Но ИБП всё это время на самом деле что-то там у себя внутри обдумывал, поэтому не сразу среагировал на первую Q, а тут уже пришла и вторая. В результате звуковой сигнал может остаться включённым. И, более того, в некоторых ИБП при смене статуса звукового сигнала осуществляется короткий бип. А из-за такого колебательного процесса эти бипы могут издаваться много раз, пока наконец контроллер и ИБП не синхронизируются.

Мы решили эту проблему просто смену состояния звукового сигнала проводим только раз в минуту. За это время у ИБП внутри уже всё устаканится.

Ещё один интересный момент заключается в расчёте оставшейся ёмкости АКБ. Считается она по упрощённой формуле:

BatCap = \frac{U - U_{min}}{U_{max} - U_{min}}\times100\%

Здесь:
U текущее напряжение АКБ.
Umin минимально допустимое напряжение на АКБ (обычно около 10В).
Umax напряжение заряженной АКБ (обычно 13,8...14,2В).

Этого обычно достаточно для оценки оставшегося заряда.

Протокол Voltronic на множестве указанных выше команд отличается только одной из них вместо кода Q1 используется QS. При этом форматы ответов совпадают. В наших устройствах реализовано автоматическое определение протокола обмена как раз на основе данного отличия. Контроллер при включении пробует посылать по очереди команды Q1 и QS. На какую приходит ответ, тот протокол дальше и используется. Если в течение определённого тайм-аута на команду перестают приходить ответы (был подключён другой ИБП на горячую), то определение протокола автоматически запускается заново.

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

Она представляет из себя экран с настройками и выбором COM-порта, через который будет осуществляться обмен. Поддерживаются все указанные выше команды, в том числе и для запуска тестов:

Работа с программой нее вызовет затруднений. Менять любые параметры можно прямо в процессе работы, и тут же видеть результат:

Для оценки работы программы в динамике я записал небольшое видео:

Саму программу эмулятора можно скачать здесь.

Подробнее..

Бинарный поиск в микроконтроллере

10.02.2021 08:12:41 | Автор: admin

Алгоритм бинарного поиска или поиска делением пополам известен давно. В данной статье будет рассмотрен пример его железячной реализации на 8-битном микроконтроллере и особенностях, которые возникают при этом.

Одно время мы выпускали несложный контроллер облачной СКУД на 100 пользователей. В его основе лежал микроконтроллер PIC18F46K22. В качестве памяти для хранения кодов ключей пользователей использовалась FLASH-память с интерфейсом I2C ёмкостью 64 кБ. Сама флешка довольно быстрая, но на шине I2C находилась ещё микросхема часов DS1307, которая работает на скорости не выше 100 кбит/сек. Высокой скорости работы нам не требовалось, поэтому в итоге вся шина была запущена на частоте 100 кГц.

Однако со временем мы начали разрабатывать новую версию контроллера, поддерживающего уже 3000 пользователей. Не хотелось сильно менять архитектуру, поэтому основные узлы были сохранены, но при этом был увеличен объём FLASH-памяти до 256 кБ.

И вот тут возник один интересный момент. В первой версии поиск ключа в памяти осуществлялся простым перебором всех 100 ключей. Этот процесс занимал долю секунды и поэтому каких-либо оптимизаций кода не производилось. Но при количестве в 3000 записей это время увеличилось в 30 раз, что оказалось недопустимым, так как у пользователя появлялась неприятная задержка между считыванием карты и открытием замка.

Решить данную проблему можно двумя способами. Первый аппаратный вариант, предполагающий использование более быстрого интерфейса с флешкой, например, SPI. Скорости чтения здесь на два порядка выше, чем при использовании I2C. Это, так сказать, решение в лоб. Неудобство лишь состоит в том, что приходится закладывать в устройство новый компонент, переделывать код и печатную плату. Плюс потребуются дополнительные линии микроконтроллера для подключения такой микросхемы памяти.

Но есть и другой способ программный. Заключается он в переделке самой процедуры поиска. Изначально она выглядела так:

typedef struct{    uint32_t COD;    uint8_t nSchedule;} TSKUD_User;bool skudFindUserByCode(uint32_t pCOD){  TSKUD_User user;  for (uint8_t i = 0; i < SKUD_USERS_COUNT; i++)  {    skudReadUser(i, &user);    if (user.COD == pCOD)      return 1;  }  return 0;}

Функция skudReadUser считывала блок данных из I2C памяти, далее осуществлялась проверка на совпадение кода.

При ста пользователях в худшей случае (когда код находился в самом конце массива данных) время поиска занимало порядка 0,1 сек. При переходе же к 3000 пользователей время выросло 3 сек!

Поэтому для ускорения функция была переписана следующим образом:

bool skudFindUserByCode(uint32_t pCOD){  TSKUD_User user;  int16_t m, beg, end;  beg = 0;  end = SKUD_USERS_COUNT - 1;  while (beg <= end)  {    m = (beg + end) / 2;    skudReadUser(m, &user);    if (pCOD == user.COD)      return true;    if ((pCOD < user.COD) || (user.COD == 0))      end = m - 1;    else      beg = m + 1;  }  return false;}

Это классический вариант реализации алгоритма, работающий на отсортированном по возрастанию массиве данных. В нашем случае это не составляет проблемы, так как данные грузятся с сервера, который и осуществляет их сортировку перед отправкой в контроллер.

О различных частных случаях при реализации бинарного поиска можно почитать в статье:Я не могу написать бинарный поиск (http://personeltest.ru/aways/habr.com/ru/post/146228).

Итак, рассмотрим работу алгоритма. Переменные beg и end задают начальный и конечный индекс массива данных. На каждой итерации мы вычисляем индекс m, который находится посередине между beg и end, и сравниваем требуемое значения ключа с тем, что находится по этому индексу. В этом случае возможны три варианта:

  1. Если значения совпадают, то мы нашли нужный ключ и можно открывать замок.

  2. Если номер искомой карты меньше, то следует его искать в левой части массива. Тут мы отбрасываем сразу половину заведомо не подходящих вариантов. Индекс end теперь будет равен m 1.

  3. Если номер искомой карты меньше, то следует его искать в правой части массива. Так же отбрасываем сразу половину заведомо не подходящих вариантов, но меняем индекс beg (он будет равен m + 1).

Если в массиве данных вообще нет искомого значения ключа, то нам нужно выйти из цикла. Условием выхода является beg > end.

Очень важным является дополнительное условие user.COD == 0 в строке:

    if ((pCOD < user.COD) || (user.COD == 0))

Дело в том, что неиспользуемые элементы массива данных мы просто заполняем нулями. Реально это происходит так. Из базы данных получается отсортированная по значению кода карты выборка пользователей. Эта информация записывается в массив данных, начиная с нулевого индекса. Остальные значения дописываются нулями:

Индекс

Значение

0

1307131

1

1308780

2

1318001

3

2174082

4

2290467

5

2291521

...

0

2996

0

2997

0

2998

0

2999

0

Можно было бы записывать туда значения 0xFFFFFFFF, но его мы используем в качестве сервисного для служебных нужд системы. Поэтому дополнительное условие user.COD== 0 всегда заставляет алгоритм искать код в левой половине массива данных.

Кто-то может справедливо заметить, что нет смысла тогда вообще обрабатывать эти нулевые значения. Но дело в том, что мы не передаём в контроллер реальное количество карт доступа. Изначально для 100 карт это не имело смысла (поиск и так работал очень быстро), а потом мы просто не стали менять структуру данных. Но, по большому счёту, это и не нужно, так как бинарный поиск очень сильно ускоряет работу.

Рассмотрим следующий пример. Пусть у нас имеется полный массив из 3000 записей. Пользователь подносит ключ и мы должны проверить, есть такая карта или нет. При линейном поиске нам понадобится в худшем случае просмотреть все записи. Итого нужно будет сделать 3000 сравнений.

А вот при бинарном поиске количество сравнений будет составлять log23000 11 шт!

Интересно, что если записей будет аж 4 миллиарда, то количество сравнений при использовании бинарного поиска увеличится всего лишь до 32!

Попробуем пошагово проверить алгоритм бинарного поиска на вышеприведённой табличке. Допустим, нам требуется найти значение ключа 2174082.

Итерация

beg

end

m

Код искомой карты

Код карты в массиве по индексу m

1

0

2999

1499

2174082

0

2

0

1498

749

2174082

0

3

0

748

374

2174082

0

4

0

373

186

2174082

0

5

0

185

92

2174082

0

6

0

91

45

2174082

0

7

0

44

22

2174082

0

8

0

21

10

2174082

0

9

0

9

4

2174082

2290467

10

0

3

2

2174082

1318001

11

3

3

3

2174082

2174082

В итоге мы за 11 итераций нашли искомое значение. Важно понимать, что 11 итераций это максимальное время поиска. В вышеприведённом примере в случае, если бы мы искали значение 2290467, то количество итераций было бы равно 9.

Так в чём преимущество такого решения? В начале статьи я указывал, что алгоритм реализовывался на микроконтроллере. Использование крайне дешёвой памяти с интерфейсом I2C снижает общую себестоимость изделия, а новый алгоритм поиска сильно уменьшает время реакции контроллера.

Всегда интересно посмотреть как реализации алгоритмов работают вживую. Для этого я снял два небольших видео, где показана работа контроллера в двух вариантах: с линейным поиском и бинарным. Нужное значение карты памяти я специально внёс в самый конец списка (индекс 2999), чтобы можно было оценить работы обоих алгоритмов в худшем случае.

Вот работа линейного поиска:

А вот бинарного:

Результат, как говориться, на лицо!

Подробнее..

Как мы контроллер управления элементами наружной рекламы делали (часть 1)

05.11.2020 10:06:30 | Автор: admin


Однажды нам поступил интересный заказ на разработку и производство партии контроллеров для управления элементами наружной рекламы (ЭНР).

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

Помимо этого заказчик хотел, чтобы устройство измеряло напряжение в сети и ток потребления нагрузкой. В случае выхода этих параметров за заданные пределы все нагрузки должны были обесточиваться, а ему на телефон приходить SMS-сообщение.

О том как начиналась разработка будет рассказано в первой части статьи.

Итак, мы начали разработку с составления полных технических требований к устройству на основе хотелок заказчика. Для начала был проведён анализ текущего решения, которое уже эксплуатировалось в некоторых аптеках. Оказалось, что там было сделано всё довольно просто. Использовался вот такой электронный таймер:

И всё! Ни ток, ни напряжение не измерялись, никакого информирования, соответственно, тоже не было.

В ходе общения с заказчиком выяснился ещё один любопытный момент. Оказывается, его не устраивало то, что отсутствовала какая-либо возможность перепрограммировать устройство удалённо. А персонал аптек, естественно, с такой задачей не очень справлялся. Ещё заказчик жаловался, что в таймерах иногда сбоила сама программа и уходило время на встроенных часах. Собственно, под перепрограммированием он и имел в виду больше подстройку времени и простую смену интервалов работы.

Таким образом, в результате эксплуатации этих таймеров заказчик и пришёл к понимаю какой именно функционал он хотел бы получить от нового устройства. Укрупнённо вышло четыре пункта, которые нам следовало реализовать:

  1. Включать/выключать вывеску по расписанию, чтобы не получить штраф за работу в ночное время, если вывеска расположена, например, напротив жилого дома. Персонал аптеки часто забывал обесточивать её перед уходом, а также включать с утра.
    А вывеска в городе для аптеки очень важна, потому что её неисправность приводит к потере потенциальных клиентов, которые могут не заметить аптеку на первых этажах зданий.
  2. Контролировать напряжение и ток. Превышение напряжения всегда сказывается не лучшим образом на любой электронике. Поэтому, чтобы избежать выхода из строя ЭНР, было решено их просто обесточивать в такой ситуации. Большое превышение по току свидетельствует о том, что блок питания ЭНР скоро может выйти из строя, либо произошло замыкание в каких либо отдельных элементах, а низкое потребление что вышли из строя светящиеся элементы или сами источники питания ЭНР.
  3. Организовать оперативное уведомление о возникших неисправностях посредством отправки SMS-сообщений. Уж не знаю чем не устроило заказчика уведомление через боты различных мессенджеров (Telegram, TamTam, ICQ и пр.), но в ТЗ прописали именно отправку SMS.
  4. Хранить данные мониторинга (напряжение, токи, состояние реле, флаги срабатывания защиты и т.п.) в базе данных на нашем сервере с доступом к информации через Web-интерфейс.

В результате у нас уже вырисовывалось не простое электронное устройство, а целая система, состоящая из железа и информационного ресурса.
После проработки общей архитектуры мы приступили к разработке электрической принципиальной схемы устройства. Для этого её вначале тоже расписали в виде набора функциональных блоков:

  • Центральный контроллер со стеком протоколов TCP/IP для доступа к удалённому серверу.
  • Узел питания.
  • Узел измерения тока.
  • Узел измерения напряжения.
  • Узел управления нагрузками.

Основным элементом схемы стал микроконтроллер серии PIC18 и внешний Ethernet-контроллер ENC28J60 фирмы Microchip. К микроконтроллеру мы подключили классическую микросхему часов DS1307 с кварцевым резонатором и литиевой батарейкой.

Так как предполагалась постоянная связь с сервером, то с одной стороны можно было бы ограничиться программными часами и использованием внешнего NTP-сервера, но с другой стороны хотелось заложить большую автономность в устройство. В итоге это решение оказалось верным, так в процессе эксплуатации мы столкнулись с тем, что на ряде объектов не было постоянного доступа в Интернет, и устройства после первоначальных настроек работали полностью автономно иногда неделями.

Для узла питания мы использовали AC-DC преобразователь с диапазоном входного напряжения питания 85305В.

Узел измерения тока выполнили на базе токового трансформатора:



Он использовался один, хотя каналов управления нагрузкой было три. Сделано это с целью экономии на самих измерительных трансформаторах, а также для упрощения монтажа по просьбе заказчика. Мы ему поставляли только сами контроллеры, а работы по окончательной установке их в электрические щитки проводились его электриками.

Надо отметить, что у нас не стояло задачи по точному измерению тока. Это была больше защитная функция (хотя по итогу мы получили точность порядка 0,1А). Поэтому был реализован следующий алгоритм. Превышение тока мы контролируем постоянно, а вот снижение его для нижнего порога только при всех включённых нагрузках. Это не совсем универсально, но в нашем случае в течение дня всегда есть диапазон времени, когда работают все ЭНР.

Узел измерения напряжения решено было сделать на базе маленького трансформатора:



Это недорогое решение, обеспечивающее при этом гальваническую развязку с сетью. На выходе трансформатора стоит образцовый резистор, на котором мы измеряем падение напряжения. Так как не бывает двух одинаковых трансформаторов, то такое решение требует индивидуальной калибровки каждого прибора. Мы её автоматизировали при помощи специального стенда и совместили с общей наладкой устройства во время производства. Подробнее об этом я расскажу в следующих частях статьи.

В общем, все основные узлы выполнены без каких-либо хитрых решений. При этом самым интересным оказался узел управления нагрузками!

На первый взгляд достаточно взять электромагнитное реле нужной мощности и всё готово. Но это не совсем так. Всегда необходимо учитывать характер нагрузки, который определяется таким параметром как cos(). Изначально у заказчика присутствовала ещё одна проблема, которую иногда списывали на неисправность таймера, но в процессе проведения нашей разработки она стала более понятна.

Заключалась данная проблема в периодическом выходе из строя встроенного реле таймера. К сожалению, разобрать такой таймер и посмотреть тип реле у нас не получилось в силу его отсутствия, но и без этого причина была понятна. Стоит взглянуть на корпус самого устройства:



Параметры коммутируемой нагрузки приводятся только для значения cos() = 1. А это, по сути, резистивная нагрузка обычный ТЭН.

Самое интересное, что в документации на таймер этот параметр в явном виде не указан.

Мы провели небольшое экспериментальное исследование и получили следующую табличку со значениями cos() для различных нагрузок:
Тип нагрузки cos()
AC-DC MeanWell RS-35-12 (35 Вт, 12В) с нагрузкой 35 Вт 0,55
AC-DC MeanWell RS-35-12 (35 Вт, 12В) без нагрузки 0,07
AC-DC MeanWell SE-450-12 (450 Вт, 12В) с нагрузкой 35 Вт 0,5
AC-DC MeanWell SE-450-12 (450 Вт, 12В) без нагрузки 0,2
AC-DC MeanWell SE-1000-12 (1000 Вт, 12В) с нагрузкой 340 Вт 0,6
AC-DC MeanWell SE-1000-12 (1000 Вт, 12В) без нагрузки 0,2
Компьютерный системный блок с БП 450 Вт 0,5
Вытяжка (200 Вт) 0,86
Кондиционер 24000 BTU (3 кВт) 0,97
Печь-гриль (1,8 кВт) 1

Измерения проводились специальным прибором APPA 138:



Как известно, в случае превышения тока для заданного типа нагрузки ресурс контактов реле значительно уменьшается и увеличивается вероятность их залипания.

Мы использовали реле серии RT314 для которых максимальный ток указан в 16А. Но с учётом cos() нужно использовать следующие значения:
cos() Максимальный ток нагрузки, А
>0,95 16
0,6 10
0,4 0,5

Также надо отметить, что при максимальном токе количество переключений сильно снижается. Оно составляет всего 50 тыс. циклов.

В нашем случае, однако, максимальный ток не превышал 5А и переключения обычно осуществлялись два раза в сутки. Поэтому запас по мощности реле был довольно ощутимый.

Но всё же, не имея возможности, измерять величину cos() на каждом объекте, мы рекомендовали заказчику все нагрузки мощностью более 100Вт подключать через развязывающие контакторы:

На этом первая часть статьи окончена. Дальше я расскажу какое в итоге получилось устройство и как мы организовывали обмен данными с нашим сервером.
Подробнее..

Как мы контроллер управления элементами наружной рекламы делали (часть 2)

15.11.2020 02:05:31 | Автор: admin

В предыдущей части статьи мы рассмотрели этап начала проектирования системы. Сейчас я хочу рассказать какое устройство получилось в итоге.



Часть 1
Часть 2

В обсуждение первой части был затронут вопрос измерения напряжения и тока. Поэтому я решил осветить его более подробно. Как я уже писал ранее, датчиками напряжения и тока у нас в схеме являются трансформаторы. Для измерения напряжения используется миниатюрный трансик BV 201 0145, а для датчика тока AC-1020:



С них снимаются напряжения, которые оцифровываются встроенным в микроконтроллер АЦП. Аналоговая часть показана ниже:



Датчик тока нагружается на резистор R3. Стабилитрон VD3 защищает от резких всплесков напряжения, вызванных короткими бросками тока. Резисторы R2, R4 задают нулевую точку в районе 1,8В. Аналогично сделано для трансформатора напряжения. Только там делитель на резисторах R8 и R10, т.к. трансформатор в нашем случае выдаёт номинальное напряжение 12 В.

Оцифровку мы осуществляем с частотой 1000 Гц в течение 200 мс. На основе полученных значений рассчитываем RMS. Быстрый расчёт квадратов значений мы производим прямо в прерывании. После накопления 200 выборок уже в основном цикле программы осуществляется окончательный расчёт с использованием чисел с плавающей точкой.

Для чего нужно измерение RMS и как его лучше сделать хорошо описано вот в этой статье.

Я уже не раз писал, что при разработке наших устройств мы всегда стараемся максимально использовать самые обычные электронные компоненты, чтобы с одной стороны снизить себестоимость, а с другой стороны не иметь проблем с их поставкой при производстве серии. В данной разработке все используемые резисторы имеют 5% допуск. Естественно, из-за такой погрешности изделия после производства имели большую ошибку при измерении напряжения и тока. Данная ошибка устранялась на автоматизированном калибровочном стенде. Стенд, конечно, звучит немного громко, но свою функцию он исполняет как надо. Состоит стенд из следующих компонентов:

  • Набор из трёх галогеновых ламп мощностью по 500 Вт
  • Датчик тока, описанный выше
  • Электросчётчик Энергомера СЕ102М
  • Преобразователь USB-RS-485
  • Автоматический выключатель

Счётчик мы используем в качестве образцового измерителя напряжения в сети и тока нагрузок. Модель СЕ102М очень удобна тем, что, во-первых, подключается всего двумя проводами к преобразователю USB-RS-485 (внутри счётчика имеется собственный преобразователь питания), а, во-вторых, не требует для считывания данных ввода серийного номера. Вроде мелочи, но удобства в пользовании счётчиком они прибавляют.

Протокол обмена хорошо описан в руководстве от производителя. Так что сложностей с программной реализацией не возникало.

Кстати, по счётчикам можно отдельную небольшую статью написать. В своё время я с ними плотно работал, в итоге в некоторых наших устройствах реализована поддержка четырёх популярных моделей: Инкотекс-СК Меркурий 206, Энергомера СЕ102, Энергомера СЕ102М и IEK STAR 104/1.

Общий вид стенда получился такой:



Для автоматизации была разработана несложная программа, которая считывает данные со счётчика, управляем встроенными реле контроллера и автоматически подбирает коэффициенты для измерителя тока и напряжения:

Обычно мы используем штрих-коды для серийных номеров наших устройств. Их очень удобно вводить при помощи сканера штрих-кодов:



Но в данном случае девайс был заказным, и заказчик попросил выполнить серийник просто в виде крупных цифр на лицевой панели.

Программа по итогу калибровки сохраняет все данные в нашей внутренней системе. Там записывается кто, когда что проверял и соответствующий список параметров. Самые важные это серийный номер и MAC-адрес.

Кстати, по поводу MAC-адресов. Мы покупаем их в виде микросхем 24AA025E48-I/SN производства Microchip. При оптовой закупке они обходятся недорого, при этом очень удобны в использовании. MAC-адрес считывается по интерфейсу I2C.

Теперь что касается связи с сервером. На начало разработки основной функционал у нас уже имелся. Это несложный Web-сервис, написанный на ASP.net и отдельная серверная программа для обмена данными с железом. Каждый контроллер раз в минуту передаёт информационный пакет по протоколу UDP. Серверное ПО разбирает его, сохраняет данные в базе (с прореживанием до раза в час) и дополнительно запоминает внешний IP-адрес и порт, с которого пришёл пакет. Это нужно для управления контроллером с сервера.

Так как фактически 100% устройств расположены за NAT, то требуется учитывать некоторые особенности. Основная из них заключается в том, что некоторые NATы имеет малый тайм-аут для выделения внешнего порта клиенту (менее минуты). Процент таких по нашей статистике не очень большой, но это в любом случае приводит к необходимости уменьшения интервала отправки данных мониторинга от контроллера на сервер для поддержания выделенного порта.

Сразу напишу почему мы используем именно UDP-, а не TCP-соединение, хотя наше устройство, естественно, имеет реализацию обоих протоколов. Выбор UDP обосновывается всего лишь простотой использования и малыми вычислительными затратами как со стороны контроллера, так и со стороны сервера. Да, он не гарантирует доставку пакетов данных, но нужно понимать, что это легко реализуется протоколом более высокого уровня, который работает поверх UDP. Кроме того, при передаче данных мониторинга потеря нескольких пакетов в сутки абсолютна несущественна, особенно учитывая, что при сохранении в базу мы их всё равно прореживаем и сохраняем данные только раз в час. А вот при удалённом управлении контроллером, например, при включении/выключении реле в ручном режиме, работает система запрос-ответ и осуществляется несколько попыток отправки команды.

Помимо этого через сервер у нас реализовано удалённое обновление прошивок контроллеров. Оно так же работает по UDP. Правда обновление работает в полуавтоматическом режиме. Всё таки нехорошо запускать его в автомате в произвольный момент, так как это может привести к проблема в работе у конечных пользователей. Представьте как они удивятся, если средь бела дня Ethernet-реле отключить у них какую-то нагрузку и перезапуститься :-)

В заключение хочу сказать, за последние два года мы произвели почти тысячу таких устройств. Все она находятся в онлайне. Ещё около двух тысяч других контроллеров также постоянно общаются с нашим сервером. В целом всё работает достаточно устойчиво. Хотя функционал мы, конечно, постоянно расширяем. Например, недавно мы выпустили моб. приложение для удалённого управления нашими устройствами через Интернет. Но о нём напиши как-нибудь в следующий раз
Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru