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

Проведём небольшой обзор существующих решений.

В первую очередь следует обратится к материалам изготовителей микроконтроллеров. Именно они определяют тренды в индустрии и там рождается основная компонентная база и идеи по её применению. Нам интересен сегмент малых встраиваемых систем.

Недавно фирма ST, известный разработчик микроконтроллеров, опубликовала референсный дизайн высоконадёжного индустриального модуля ввода-вывода STEVAL-FSM01M1

на который устанавливается процессорная плата NUCLEO-F401RE

Хотя тут всего два входа и два выхода, но решение интересно в качестве демонстрации мер обеспечения надёжности работы ввода-вывода. Отсюда мы узнаем что существует градация дискретных входов согласно стандарту IEC 61131-2. И там декларируются достаточно большие токи для логических уровней сигналов. Это заставит нас осторожнее относится к индустриальным контроллерам, поскольку экономия электроэнергии явно не их сильная сторона.

Существует ещё архитектура под названием Tower System от NXP

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

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

BSP таких модулей обычно создаётся на основе того самого сырого BSP от NXP и других производителей микроконтроллеров. И надо быть готовым к долгой интеграции и сложной отладке. Сертификаты выданные модулю ничем не помогут получить такие же на весь ПЛК в котором они будут установлены.

Конечно существует масса устоявшихся экосистем для автоматизации домов и помещений. Например экосистема KNX.

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

Но обычные индустриальные модульные ПЛК выполняются по принципу монтажа в линию на DIN рейку.

Главный контроллер и модули соединяются вплотную друг к другу и на боковых стенках у них присутствуют скользящие контакты, через которые передаются данные и питание. Количество входов-выходов можно наращивать до многих сотен. благодаря высокопроизводительной шине данных построенной на ASIC. Документация на ASIC недоступна. Любой модуль ввода-вывода можно извлечь из линейки и заменить на другой. Часто у модулей верхняя крышка с контактами отсоединяется от корпуса модуля, это позволяет заменять модули не отсоединяя массу контактов.

Такой монтаж даёт максимальную плотность расположения клемм ввода-вывода.

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

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

Попадаются случаи, когда на специализированную плату ставят ПЛК общего назначения. Как видно на фотографии ниже, ПЛК общего назначения и даже очень мощный не может решить все задачи в системе. Для управления моторами разработчики устанавливают на ту же плату еще массу модулей собственного изготовления с отдельными микроконтроллерами для управления сервоприводами и покупные контроллеры моторов.

В этом случае монтаж ПЛК очень простой, но специализированная плата при этом дорожает, компактность и экономичность не достигается.

Ниже показан дизайн который привлек внимание. Очень удобное расположение и конструкция разъемов. Компактность на высоком уровне. Но пользовательский интерфейс реализован на DIP-переключателях. Причем переключателей столько, что по цене они могут превзойти стоимость дисплея занимающего такую же площадь. Нам не раз попадались случаи когда DIP переключатели работали ненадёжно.

Идея нашего ПЛК

ПЛК - это прежде всего работа в жёстком реальном времени. Реальное время должно быть гарантировано не только наличием операционной системы реального времени (RTOS) но и самой аппаратной архитектурой c высоким уровнем электромагнитной совместимости, препятствующим появлению сбоев. Кроме того в домашних условиях очень важна компактность и удобство инсталляции, обслуживания и ремонта. Удобство обслуживания напрямую связано с развитостью и доступностью средств локальной и удалённой диагностики. Очень желательна минимизация энергопотребления, наличие резервного питания и подключение зелёных источников энергии. Соблюдение стандартов IEC 61131-2 не так важно. В домашнем хозяйстве расстояния не велики. Требуемая масштабируемость в пределах сотни входов-выходов. Главный цикл центрального контроллера в 10...20 мс, такого хватает для типичных задач.

Одна из возможных схем автоматизации. Здесь представлена система управление механизмом домашнего подъёмника

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

Упрощённая архитектура ПЛК
Шаблон накладной платы для профиля с внутренней шириной 72 мм

В качестве примера сборка может выглядеть так:

Пример сборки для профиля с внутренней шириной 100,5 мм

В качестве базового процессорного модуля возьмём S7V30. Проект открытый и его описание здесь.

Плата процессорного модуля S7V30 не новичок в деле.

Предыдущие версии модуля и программная архитектура также описывались в статьях.
Да, модули не создаются на пустом месте, в их основе всегда лежит хороший бэкграунд из прошлого опыта. От программной архитектуры на основе Azure RTOS (бывшей ThreadX) решено было не отказываться, а продолжать наращивать.

Разъёмный комплекс

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

Сделать кастомные разъёмы как у Wago мы не можем. Но можем подобрать из того что есть достаточно удобные варианты. От клеммных колодок отказываемся сразу.

Ассортимент клеммных колодок

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

Маленькие разъёмы неудобны для извлечения, а иногда не удовлетворяют сечению проводников подключаемых к ним.

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

Останавливаем свой выбор на разъёмах класса MCV 1,5/ xx-G-3,5 согласно принятому именованию у фирмы Phoenix Contact.

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

Базовая плата

Базовая плата несёт основные компоненты связанные с ПЛК. На системный разъем платы выведено 69 свободно перепрограммируемых на ввод или вывод сигналов с напряжением 3.3 В. Из этих сигналов 16 могут также работать как входы 12-разрядного АЦП. Кроме этого выведена внешняя последовательная шина для модулей расширения и аналоговые аудио сигналы.

Лист схемы с разъёмами для подключения процессорного модуля (разъёмы с префиксом S7_)
Лист схемы с внешними интерфейсам, подключением дисплея и ручного энкодера для управления пользователем
Лист схемы с раcширителями ввода-вывода по SPI. У аналоговых входов IN1...IN16 по умолчанию не паяются резисторы подтяжки к 3.3 В. Разъёмы X6 и X7 предназначены для передачи сигналов на верхнюю плату.
Лист схемы с источниками питания, ключами управления внешними нагрузками и управлением подсветкой

Двунаправленный универсальный зарядник

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

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

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

В последнее время двунаправленные зарядники стали реализовываться в одном корпусе микросхемы. Первым был Renesas c чипом ISL81601FRZ, но за ним быстро поспел TI с микросхемами BQ25756. Поскольку BQ25756 появился совсем недавно, то им воспользоваться не успели. Однако ISL81601FRZ хоть и менее интегрирована, но под управлением микроконтроллера и недорогой обвязки может выполнять те же и больше функций.

Схема зарядника выглядит так:

Схема универсального двунаправленного зарядника

Схема позволяет регулировать зарядное напряжение от 0.1 до 32 В и зарядный ток от 0.01 до 10 А. Оба параметра регулируются в 12-и битном диапазоне микросхемой U28 MCP47CVD12T по интерфейсу I2C. Предполагается что радиатор заряднику будет не нужен. Поскольку КПД достигает 99%.

Если напряжение от внешнего блока питания превышает 24.3 В, то схема работает как зарядник, если напряжение падает ниже, то схема начинает потреблять ток от аккумулятора и передавать его в систему. Аккумулятор подключается на схеме слева к клеvме P2. Питание в/из системы поступает с шины +24V. Блок питания должен быть способным стартовать при наличии напряжения на своих выходных клеммах. Схема содержит измерители тока U25, U26 на микросхемах INA310A и шунтах R115 и R114. Микросхемы измеряют ток в одном направлении и поэтому система может точно измерять ток заряда аккумулятора и ток от зарядника в систему в режиме разряда. К микросхеме зарядника U29 подключены две внешние дополнительные петли регулировки зарядного напряжения (на U30) и тока (на U32). Процесс зарядки ведётся под управление процессорного модуля. В микросхему ISL81601 встроены защиты от перегрузки по току в обоих направлениях. Также есть защита от переразряда аккумулятора. Даже если микроконтроллер перестанет следить за разрядом схема отключит аккумулятор от системы при падении напряжения на нем до 15 В (устанавливается резистивным делителем R122 R124). Микросхема U33 измеряет температуру в районе силовых элементов зарядника и не даст ему перегреться.

К вопросу о гальвано-изоляции

Может возникнуть вопрос почему в нашем ПЛК нигде нет гальвано-изоляции, хотя в промышленных ПЛК она буквально повсюду. Ответ в том, что наш ПЛК с одной стороны предназначен для довольно локальных объектов, с другой стороны в инвертерах и другом силовом оборудовании и без того есть своя гальвано-изоляция и делать дополнительную нет смысла. Локальность объектов означает отсутствие большой разницы в земляных потенциалах, и отсутствие риска больших блуждающих импульсных токов по шинам земли. А именно эти импульсные наносекундные токи являются основной угрозой для сбоев микроконтроллеров, как показывает практика. Дополнительно наша базовая плата снабжена сплошным слоем земли что ещё больше снижает риск сбоев от проходных токов.

Пример накладной платы ввода-вывода

Как писалось выше, накладная плата ПЛК создаётся индивидуально под каждое конкретное применение. Поэтому здесь приводится лишь пример реализации платы. Плата двухслойная, и не содержит сложных компонентов. Все сводится к адаптации уровней сигналов к сигналам базовой платы. Это резистивные делители и буферы с верхними ключами на микросхемах TBD62783. Тут же можно реализовать измеритель сетевого напряжения и тока потребления от сети на микросхеме ACS37800KMACTR-030B3-I2C.

Интересная проблема возникает с индикацией состояний входов и выходов. В ПЛК принято отображать их светодиодами. Но дискретные светодиоды у каждого входа и выхода создают большое количество дорожек. Трассировка двусторонней платы с требованиями на достаточно большие зазоры становится очень трудной. Здесь мы применили адресные светодиоды B3DK3BRG-05C000113U1930.

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

Возможности Altium Designer по созданию сборок из нескольких плат

Идея делать ПЛК из нескольких плат со стековой структурой сама по себе тривиальна. Но до последнего времени могла не вызывать энтузиазма. Поскольку традиционные EDA ориентированы на создание одной платы. Системами плат занимались уже в конструкторско-электротехнических программах типа SolidWorks Electrical. Нельзя было в одной среде совместить несколько плат и одновременно работать над всеми без длительных рутинных операция экспорта-импорта. Но недавно в Altium Designer появилась возможность работы над проектами включающими несколько плат. Проекты каждой платы по прежнему создаются отдельно, но потом ещё до окончательной трассировки они складываются в один общий проект. В общем проекте на верхнем уровне иерархии создаётся схема межплатных соединений с указанием какой разъём на одной плате соединяется с разъёмом на другой.

Cхема соединений между печатными платами в Altium Designer

Далее все платы переносятся в одну общую 3D сборку и привязываются друг к другу, как это обычно делается в механических CAD-ах.

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

На 3D сборке можно просмотреть все механические конфликты между деталями и разъёмами

Красным цветом обозначены конфликты. Здесь серьёзных конфликтов нет. Контакты моделей разъёмов взятые у производителей как правило немного конфликтуют, поскольку там предусмотрена упругая деформация.

Если обнаруживаются конфликты совмещения, то тут же на модели детали можно подвигать для лучшего совмещения. Изменения расположения деталей сразу переносятся в проекты плат. Общий проект позволяет создавать общий BOM.

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

Вопрос о программировании ПЛК. Как и чем?

Обычно для ПЛК производители создают свои особые инструменты разработки ПО. Главной целью этих инструментов является максимальное упрощение процесса программирования. Но как мы знаем программирование сильно упростить никому ещё не удалось. Поэтому такие инструменты сильно ограничивают предметную область программирования и часто прибегают к графической нотации. Графическая нотация в принципе достаточно мощный инструмент, но те нотации, что стандартизируются документом IEC 61131-3 надо сказать плохо годятся для ПО развитого многофункционального контроллера.

Как эффективно применять графическую нотацию Simulink Stateflow для программирования ПЛК и микроконтроллеров я попытался показать в этой статье про рольставни и в этой про зарядник.

В данном проекте предусмотрено создание ПО на C или С++ или создание загрузочных модулей в среде MATLAB Simulink. Для реализации загрузки и исполнения модулей в проекте Azure RTOS есть компонент Azure RTOS ThreadX Modules.
Сам процессорный модуль S7V30 уже содержит в себе исполняющее ядро на основе Azure RTOS с коммуникационными стеками и драйверами, начальный загрузчик по USB, через FTP, через MQTT брокеров и просто с SD карты. Коммуникационные возможности модуля предыдущей версии описаны в этой статье про передачу телеметрии и в этой статье про защищённый WEB сервер.

Техника организации в Renesas Synergy аппаратного отражения сигналов на память с помощью DTC

Стандартный подход в логических контроллерах для работы с системой ввода вывода - это доступ через общую память. Т.е. системы ввода-вывода ПЛК получает по последовательным каналам оцифрованные сигналы и кладёт их в память на каком-то интервале времени основного цикла, а прикладная программа на другом интервале читает эти значения и использует. Это немного не соответствует идеологии RTOS. RTOS создавались чтобы уйти от идеи основного цикла и по полной использовать асинхронность с целью экономии ресурсов процессорного времени. Беда асинхронности в отсутствии гарантии обслуживания всех сигналов в заданный интервал времени. Т.е. если мы, например, будем реагировать на изменение сигналов в прерываниях, то не сможем точно рассчитать сколько времени нам максимально понадобится для обслуживания их всех при их случайном возникновении. В дело вступает статистика, а не жёсткий детерминизм. Да, на какие-то сигналы сможем среагировать очень быстро, за микросекунды, но другие могут остаться надолго без внимания. Словом трудность планирования очевидна. Но главный цикл заставляет нас жертвовать процессорным временем, иногда на пустое сканирование. В микроконтроллерах проблема решается механизмом DMA. DMA освобождает процессор от программного обслуживания пересылок. Как то я писал про использование DMA для последовательного вывода. Там был микроконтроллер от ST, здесь же используется Renesas Synergy. В чипах Synergy кроме модуля DMA есть модуль DTC (Data Transfer Controller). Про DTC достаточно подробно написано в мануале. Здесь продемонстрируем работу с ним.

DTC не имеет конкурирующих каналов, как DMA. DTC может обслуживать только один запрос на пересылку, но пересылка эта может быть цепочечной и очень комплексной и обращаться за один проход к десяткам периферийных модулей. Это позволяет за один запрос пересылки DTC собрать информацию со всех внешних расширителей ввода-вывода и АЦП.

Семейство Synergy обеспечивается софтом под названием Synergy Software Package и в нем есть программный модуль для работы с DTC. В примере ниже используются этот модуль.

Главное при работе с DTC - это создать правильный массив управляющих блоков цепочечной пересылки.

// =========================================================================================================================================================================================================================================
// Структура повторяющая управляющую структуру DTC
transfer_info_t SCI8_RX_dtc[] =
{
  // DM[1:0]         | DTS             | DISEL            | CHNS & CHNE     | SM[1:0]         | SZ[1:0]       |  MD[1:0]      | SAR                   | DAR                          | CRB              | CRA
  // Destination     | DTC Transfer    | DTC Interrupt    | DTC Chain       | Source          | DTC Data      |  DTC Transfer | DTC Transfer          | DTC Transfer                 | DTC Transfer     | DTC Transfer
  // Addressing Mode | Mode Select     | Select           | Transfer Select | Addressing Mode | Transfer Size |  Mode Select  | Source Register       | Destination Register         | Count Register B | Count Register A

  // Устанавливаем сигнал CS в начале
  {ADDR_FIXED,        SRC_REPEATED,    DISEL_1_SETIRQ,    CHAIN_NO_LOOPING,   ADDR__INCR,      UNIT_4_BYTE,      MODE_REPEAT,   &S_CS_ARRAY[0],        (void*)&R_IOPORT11->PCNTR3,     0 ,        (SCI8_DTC_CN << 8)| SCI8_DTC_CN },

  // Записываем в 4-ую строку адрес назначения - регистр данных SPI.
  // На последнем цикле адрес назначения будет указавать в пустую облать RAM
  // Таким образом бедет исключено инициирование приема лишнего байта в последнем цикле DTC
  {ADDR_FIXED,        SRC_REPEATED,    DISEL_1_SETIRQ,    CHAIN_NO_LOOPING,   ADDR__INCR,      UNIT_4_BYTE,      MODE_REPEAT,   &DEST_REG_ARRAY[0],    (void*)&SCI8_RX_dtc[3].p_dest,  0 ,        (SCI8_DTC_CN << 8)| SCI8_DTC_CN },

  // Читаем байт из SPI
  {ADDR__INCR,        DST_REPEATED,    DISEL_1_SETIRQ,    CHAIN_NO_LOOPING,   ADDR_FIXED,      UNIT_1_BYTE,      MODE_REPEAT,   (void*)&R_SCI8->RDR ,  &EXT_ADC_RESULTS[0],            0 ,        (SCI8_DTC_CN << 8)| SCI8_DTC_CN },

  // Записываем нулевой байт в SPI чтобы продолжить чтение
  {ADDR_FIXED,        DST_REPEATED,    DISEL_1_SETIRQ,    CHAIN_NO_LOOPING,   ADDR_FIXED,      UNIT_1_BYTE,      MODE_REPEAT,   &zero_byte,            (void*)&R_SCI8->TDR,            0 ,        (SCI8_DTC_CN << 8)| SCI8_DTC_CN },

  // При обработке этой строки движок DTC посылает маску в регистр ELSEGR1 и на последней пересылке маска содержит бит вызова прерывания по событию ELC_EVENT_ELC_SOFTWARE_EVENT_1
  // В обработчике прерывания взводится флаг окончания циклов переслыки DTC
  // Наличие DISEL=0 в этой записи критично. В ином случае не происходит циклического повторения пересылок
  {ADDR_FIXED,        SRC_REPEATED,    DISEL_0_IR_RES,    CHAIN___DISABLED,   ADDR__INCR,      UNIT_1_BYTE,      MODE_NORMAL,   &INT_PEND_ARRAY[0],    (void*)&R_ELC->ELSEGRnRC0[1],   0 ,        SCI8_DTC_CN                     },

};
// =========================================================================================================================================================================================================================================

Эта цепочка вызывается по кругу и в течении обработки модифицирует саму себя, через некоторое количество циклов она приводит к тому что в один из регистров вызова программного прерывания (void*)&R_ELC->ELSEGRnRC0[1] записывается флаг прерывания.

Во время циклического повторения цепочки инкрементируются или декрементируются адреса приёма и записи данных. В данном случае первая запись в массиве записей цепочки выставляет сигнал CS на нужной микросхеме SPI расширителя ввода-вывода на плате процессорного модуля S7V30.

SPI расширителе ввода-вывода с встроенными АЦП

Затем в микросхему расширителя записывается адрес регистра чтения, затем из регистра микросхемы читаются данные. Потом выдаётся команда микросхеме о продолжении операции чтения на следующем цикле. Спустя несколько циклов начинается аналогичное чтение из следующей микросхемы с переключением соответствующих CS. Сигнал прерывания на процессор придёт, когда будут прочитаны все необходимые данные из всех микросхем расширителей ввода-вывода. Таким образом без программного вмешательства можно прочитать и записать на максимальной скорости данные со всех внешних микросхем расширителей ввода-вывода и АЦП. По прерыванию процессор выставит флаг для основного цикла о том что данные готовы к обработке. Пересечения моментов чтения данных и их использования главным циклом не произойдёт.

Итог

Здесь мы показали общие принципы разработки архитектуры и конструкции ПЛК для малых встраиваемых систем и основные идеи по реализации ПО. Но это только верхушка айсберга. Работа продолжается.