[recovery mode] DIY PLC для IoT, часть 3

image
Продолжение,
Начало:
Часть 1
Часть 2
Ну что-ж, пока не заминусовали в усмерть, буду продолжать публикации на тему: сделай сам контроллер и PowerLine модем. Если все же такое произойдет, то дальнейшие публикации и все уже опубликованное можно будет найти на моем сайте. Кому интересно — добро пожаловать под кат, если просто размять пальцы клавиатурой в комментариях — большая просьба дальше не читать. Да и картинок в данной статье мало.
И так, для начала, мы собрали два модуля: модуль датчиков и модуль CAN-Gate. Попробуем из них построить систему. Вообще, модулей в системе ( допустим «Умный дом» ), может быть достаточно много, требуется их объединить в единую сеть. Уже упоминалось, что «на борту» платы процессорной модулей имеется физическая реализация поддержки CAN. Эта шина (протокол) крайне гибка и пригодна для многих применений. Её используют в тяжёлых и ответственных применениях: автомобили, суда, самолёты, тепловозы, ядерные реакторы, ускорители частиц, управление телескопами и лифтами, банковские терминалы, медицинские приборы… На основе CAN, Rockwell Automation, Inc (Allen-Bradley) разработали свой протокол и шину — DeviceNet.

После анализа и сравнения различных шин/протоколов был выбран именно CAN. Вернее, как стартовое решение были выбраны CAN и PowerLine (домашней «выпечки»).
Причины и критерии выбора перечислять не буду, если интересно, можете это сделать самостоятельно. Но пожалуй один из критериев все же приведу: специализированные микросхемы обеспечивающие поддержку CAN-шины соизмеримы по стоимости с аналогичными для RS-485.
И так, начнем с CAN:

Протокол


CAN (англ. Controller Area Network — сеть контроллеров) — стандарт промышленной сети, ориентированный прежде всего на объединение в единую сеть различных исполнительных устройств и датчиков. Режим передачи — последовательный, широковещательный, пакетный.

CAN разработан компанией Robert Bosch GmbH в середине 1980-х и в настоящее время широко распространён в промышленной автоматизации, технологиях «умного дома», автомобильной промышленности и многих других областях.

CAN является синхронной шиной с типом доступа Collision Resolving (CR, разрешение коллизии), который, в отличие от Collision Detect (CD, обнаружение коллизии) сетей (Ethernet), приоритетно обеспечивает доступ на передачу сообщения, что особо ценно для промышленных сетей управления (fieldbus). Передача ведётся кадрами. В шину будет передан пакет с наибольшим приоритетом. Приоритет кадра определяется состояниям бит идентификатора кадра ( доминирующие, рецессивные )

Все узлы в сети должны работать с одной скоростью. Стандарт CAN не определяет скоростей работы, но большинство как отдельных, так и встроенных в микроконтроллеры адаптеров позволяют плавно менять скорость в диапазоне, по крайней мере, от 10 килобит в секунду до 1 мегабита в секунду.

В то же время консорциум CANopen рекомендует следующие скорости передачи:
10 кбит/с; 20 кбит/с; 50 кбит/с; 100 кбит/с; 125 кбит/с; 250 кбит/с; 500 кбит/с; 1 Мбит/с. Рекомендуемое количество точек выборки = 3. Ну что же, будем придерживаться данных рекомендаций.

Соотношение между скоростью передачи и максимальной длиной кабеля приведено в таблице:
image

Стандарт CAN предлагает два варианта форматов кадра: базовый формат кадра и расширенный формат кадра. Основное отличие — длина идентификатора. В первом случае — 11 бит, во втором — 29. Первый вариант — уж сильно «куцо», посему его рассматривать не будем, остановимся на варианте 2.

Расширенный формат кадра данных
image

Физическая реализация


Среда передачи — гальванически развязанная неэкранированная витая диф.пара, часто её объединяют в одном кабеле с шиной питания. Стандартами оговорена также возможность применения оптики, но я не знаком с реальными примерами его использования.
Для обеспечения работы шины требуется как минимум два провода: CAN_L и CAN_H ( High и Low ). CAN неприхотлив, можно использовать даже «телефонную лапшу», и всё равно как то, но будет работать. Однако конечно, для достижения высоких скоростей и надежного обмена данными лучше использовать более качественные кабели — например, Ethernet cat5/5e, который и использую в своих проектах (по нему же можно и питание поставлять). Ещё хорош кабель USB — там два толстых провода питания и экранированная витая пара. Вообще подойдет любая витая пара с волновым сопротивлением 100–120 Ом.
Не желательны длинные отводы. Если вы соединяете несколько устройств — то лучше сделать максимально короткий отвод (до 10 см), а еще лучше — сделать у устройства два порта CAN, соединить их вместе, и включать устройство в разрыв цепи, либо как в реализации наших контроллеров помещать два скрученных провода в одно отверстие клеммника.
Конечно, нужно терминировать концы линии резистором в 100–120 Ом, в нашем случае для этого предусмотрены «джамперы». Чип интерфейса CAN на плате процессора в состоянии физически поддерживать до 100 устройств на шине.

Витая пара cat 5/5e


Каких то «жестких» требований по использованию провода cat 5e для шины CAN нет, будем использовать следующие провода/маркировку:
image
Это обыкновенная медная витая пара. По одному проводу сечением 0.2 мм2 можно подать до 1.5А. Падение напряжение в отношении к расстоянию считается исходя из того, что среднее сопротивление медного провода данного сечения составит примерно 18–20 Ом на 100 м. Минимальное напряжение для питания модулей должно быть не менее 7‑8V. Самое простое — измерить напряжение на крайнем подключенном модуле, если недостаточно, то придется установить дополнительный источник питания.

Протокол логический


Как уже упоминалось, мастер непрерывно, с заданным временным интервалом, шлет запросы известным (имеющим уникальный номер в сети) модулям. Рассылкой запросов занимается отдельный программный поток. Ответы от модулей приходят асинхронно. Пакеты принимает другой поток, отвечающий за прием пакетов. Исходим из того, что примерно 50% общего времени канала должно остаться для ответа модуля, т. е. Процент «заполнения» запросами тоже — 50%. При скорости CAN 250 кбит/сек это составит примерно 1 кГц. Эту частоту делим на количество модулей в сети — получаем частоту опроса каждого модуля.
Логический протокол CAN никак не специфицирован, т. е. Формат идентификатора может быть любым.
Почитал, что предлагает консорциум CANopen… Возник вопрос, а зачем столь сложный протокол, когда мне всего то требуется пара функций? Решено протокол использовать свой. Что должно быть:

  • команда установить значения
  • команда дать значения
  • номер модуля на шине CAN


Так как битовое представления команд — идентично для всех модулей, то в начало идентификатора поместим номер модуля. В случае синхронного ответа модулей или какой то из модулей решил отправить сообщение самостоятельно, без команды опроса (напр. аварийная ситуация требующая немедленной отправки сообщения), высший приоритет будет иметь кадр с большим номером на шине CAN. Если какой-то модуль не ответил в течении максимального времени ответа — то с этим модулем явно какие то проблемы.

Протокол представляет из себя:
image

Будем «работать» полубайтами (4 бита). Первые 3 бита — не используются (длина идентификатора — 29 бит).
Далее:

  • 9 бит адрес на CAN (какому конкретно модулю пакет адресован)
  • 12 бит — код функции часть №1 (1-установить значения; 2-читать значения)
  • 8 бит — код функции часть №2, или расширение основной функции


Если в коде функции часть №2 8-й бит установлен, то пришел ответ от модуля. Данное решение предназначено потоку-приемнику пакетов. Т.к. поток приема пакетов «слушает» все подряд, то необходима фильтрация только ответов.
Если в коде функции часть №1 установлен старший бит, то пришел пакет идентифицирующий ошибку в модуле или сообщение об аварии.
В каждый модуль «зашивается» идентификатор устройства (тип) и уникальный серийный номер.
Модули всегда отвечают на пакеты им адресованные. Это одновременно является подтверждением получения пакета.
Адрес=0 — широковещательная рассылка.

Примеры (лог программы candump Linux):

can0 400200 [8] 00 00 00 00 00 00 00 00 — Запрос данных устройству с номером 4
can0 400280 [8] 07 00 00 00 00 00 00 00 — Ответ устройства номер 4

can0 400100 [8] 07 00 00 00 00 00 00 00 — Передача данных устройству с номером 4
can0 400180 [8] 07 00 00 00 00 00 00 00 — Ответ устройства номер 4 (текущее состояние)

can0 100200 [1] 00 — Запрос данных устройству с номером 1 (один байт)
can0 100280 [8] 00 00 00 00 00 00 00 00 — Ответ устройства номер 1

can0 100100 [1] FF — Передача данных устройству с номером 1 (один байт)
can0 100180 [8] FF 00 00 00 00 00 00 00 — Ответ устройства номер 1 (текущее состояние)

can0 100F00 [1] 00 — Передача данных устройству с номером 1
can0 108F80 [8] 00 00 00 00 00 00 00 00 — Ответ устройства номер 1 (ошибка, неверная команда)

Команды широковещательной рассылки (номер CAN=0;):
(Формат — «код функции часть №1»: «код функции часть №2»)
2: x — запрос данных
2:0 — дать серийный номер; устройство вернет в первых 4-х байтах Sn
в следующих 4-х байтах код (идентфикатор) устройства
2:1 — дать номер CAN; в первых 4-х байтах Sn, кому адресовано

1: x — установка значений
1:1 — не откликаться на широковещательный запрос серийного номера.
в первых 4-х байтах Sn, кому адресовано
1:2 — присвоить номер CAN.
в первых 4-х байтах Sn, кому адресовано
5-й байт номер CAN

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

Поле данных — устройство возвращает 8 байт. В зависимости от типа устройства и кода функции эти значения могут трактоваться как массивы/значение:
int/uint8_t[8]
int/uint16_t[4]
int/uint32_t[2]
int/uint64_t

Пример для «C»:

uint8_t          buf_8[8]; // Тут записаны данные полученные из CAN, этот же буфер используется для передачи данных.
uint16_t        *buf_16;
uint32_t        *buf_32;
uint64_t        *buf_64;

buf_16 = &buf_8;
buf_32 = &buf_8;
buf_64 = &buf_8;


Далее используем нужный массив/значение в зависимости от типа устройства/модуля. Контроль за границами массива — на разработчике ПО.

Конфигурированиемодулей


Для начала, необходимо выполнить «конфигурацию» модулей. Делается при помощи USB-UART переходника. Запустить программу типа terraterm, putty, …, подключиться к СОМ-порту. Скорость — 115200, один стоповый, без паритета.
Нажать «Enter», будет выведена подсказка, специфичная для каждого типа модулей.
Далее печатаем: cfg«Enter», устанавливаем номер модуля на CAN и скорость CAN. Номер в принципе может быть установлен/изменен через широковещательные команды, скорость — обязательна, и должна быть одинаковой на всех модулях сети.
Выход из режима конфигурации: q«Enter».

Пример экрана конфигурации для модуля входа 0–20 мА:
image

Модуль CAN-Gate так же требует конфигурации. При нормальной работе (не режим конфигурации) отправка-получение информации подобна работе утилитам Linux candump, cansend (в одном флаконе).
Данный логический протокол, как унифицированный для системы в целом, использован в PowerLine, радиомодулях упомянутых ранее, но об этом в следующих «сериях»…

© Geektimes