Подключение RPi к Clunet

Хочу поделиться опытом в подключении Raspberry Pi 2/3 к сети Clunet
На входе имеем сеть на Clunet с каким-то количеством устройств, которыми надо управлять через, например, интернет или Телеграм.
Еще есть RPi который будет выполнять роль моста между IP и Clunet

Совсем коротко о Clunet

Что такое RPi (Raspberry Pi) знают многие. А что такое Clunet даже не многие инженеры знают. А зря.
https://habrahabr.ru/post/160469/

Clunet — это такой протокол для обмена данными по двум проводам.
И на мой взгляд, он очень хорош.
Странно даже, почему он еще не стал популярен и всемирно известен?
Долгое время сам думал сделать нечто подобное и завязать это все с netgraph. Были некоторые наработки на которые всегда не хватало времени.
Как оказалось, велосипед уже был изобретен и почти один в один как мне он представлялся.

За Clunet надо сказать спасибо двум людям:
Его разработчиу Алексею Авдюхину ( https://clusterrr.com/ ) ( https://github.com/ClusterM/clunet )
И человеку внёсшему огромный вклад в доработку Сергею Дудуанову ( https://github.com/dudanov/CLUNET-2.0 )

Немного о том, чем хорош этот протокол и его реализация для AVR микроконтроллеров:
Открытый исходный код, само собой.
Работает как одноранговая сеть. Нет, не master-slave, а как в привычной ЛВС.
По принципу устройства протокол близок к ethernet-кадрам.
Для работы нужно минимум электронной обвязки.
Есть bootloader
И еще есть много чего интересного. Лучше почитать о нем в оригинальной статье.

Условный минус такой: Этот протокол полностью программный, за исключением используемых прерываний. Сознает некотороую нагрузку на ЦП. Бывает сложно или даже невозможно совместить его с какими-то еще наворотами. Однако, выход всегда находился.

 

Дружим c Raspberry Pi 

Первая мысль была о том, что на RPi в принципе можно это реализовать напрямую с уже имеющимися портами.
Но, данная идея не прижилась так же как и использование USB-Clunet адаптера (здесь будет ссылка на отдельную статью про костыли что бы это сделать на V-USB).
А прижился переходник в виде маленькой мезонинной платы на RPi с интерфейсом UART

Выглядит это вот так:

Сам проект в каком-то виде лежит здесь:
https://github.com/SheshkoKonstantin/clunet-gw

Ставится на RPi и подключаются три провода от сети Clunet.
В моем случае это именно три провода:
1. Сама шина данных Clunet
2. GND
3. Питание 12V

Для проектирования печатных плат я использую не очень популярный KiCad поэтому схема и разводка на всякий случай лежат в PDF на GitHub

Схема в целом выглядит так:

Разводка платы в KiCad:

 

Некоторые моменты

  1. На плате используется стабилизатор напряжения на 5 вольт в SMD корпусе SOIC (уже почти год работает исправно) Хотя сперва было подозрение, что будет сильно греться и все полетит через некоторое время.
  2. Порт UART в RPi работает с напряжением 3.3 вольта. А наши устройства в сети Clunet с напряжением 5 вольт. И шина данных Clunet тоже с 5 вольтами. Если подключить UART RPi к 5В микроконтроллеру напрямую это будет работать. Подозреваю, что только некоторое время, пока порт или все устройство не выйдет из строя. Шифтеров под рукой не было, поэтому использовал вот такую схему подключения (Кстати, очень даже рабочая схем. В свое время подсмотрел в блоге у одного японца.):
  3. В этой схеме я использовал одну ногу микроконтроллера atmega8a. Но все же практика показала, что что с двумя ногами работает лучше. Если нет необходимости экономить ноги, лучше воспользоваться двумя отдельными ногами на микроконтроллере для отправки и получения данных.

Программная часть

В программной части пришлось изобрести свой велосипед. На выходе получилась утилита под Linux. Которая называется просто util. Собрать утилиту под Windows так руки и не дошли. В любом случае, исходный код лежит на GitHub.

Что может утилита:

  1. Запускаться в режиме сервера для выполнения роли шлюза между Clunet и Telnet
    Примерно так:
    ./util srv 8888 /dev/ttyAMA0
    8888 — порт, который будет слушаться
    /dev/ttyAMA0 — путь к устройству UART (через который подключена плата) в RPi или на любом другом устройстве
    После запуска можно подключаться по Telnet на порт 8888 и «слушать», что происходит в сети CLunet, а так же отправлять туда пакеты в формате: FAAPPССLLDD
    F — просто префикс, что бы служба понимала, что мы именно хотим отправить пакет в Clunet
    AA — адрес устройства в сети Clunet которому адресован пакет в шестнадцатиричном формате
    PP — приоритете согласно протоколу в шестнадцатиричном формате. Например, 03
    СС — команда согласно протоколу в шестнадцатиричном формате. Например FE (ping) или пользовательские команды
    LL — длина передаваемых данных в байтах в шестнадцатиричном формате (от 0 до 255)
    DD — сами данные в указанном количестве. Один байт кодируется в двух символах в шестнадцатиричном форматеРассмотрим пример. Пинганем устройство в сети. Для этого используем команду F6403FE00
    64 — адрес устройства
    03 — приоритет
    FE — код команды PING
    00 — не передаем никаких данных. 0 байт.Подключение к шлюзу Clunet через Telnet и отправка команды PIND
    В ответ поучаем PONG в виде P64FF00
    P — означает, что пакет пришел из сети Clunet
    64 — адрес отправителя
    FF — команда соответствующая PONG
    00 — 0 передача 0 байт.
    Это для простоты. А вообще можно передавать данные устройству и оно должно их вернуть. Например:

    Таким образом можем обмениваться данными в обе стороны.
  2. Утилита может прошивать устройства в сети через загрузчик непосредственно со шлюза ( RPi )
    Например. Работает у нас такой шлюз и передает туда-обратно данные (из локальной сети в Clunet и наоборот) А нам надо  обновить прошивку на каком-то устройстве.
    Пример команды:
    ./util main.hex AA /dev/ttyAMA0
    main.hex прошивка для микроконтроллер AVR в HEX формате
    AA — адрес устройства в сети Clunet которое надо перепрограммировать (в десятичной системе)
    /dev/ttyAMA0 — путь к устройству UART
  3. Может прошивать устройства в сети через загрузчик с рабочей станции через шлюз
    Например. Работает у нас такой шлюз и передает туда-обратно данные (из локальной сети в Clunet и наоборот) А нам надо  обновить прошивку на каком-то устройстве с рабочей станции.
    Собираем прошивку в HEX и отправляем ее.
    ./util main.hex AA IP:PORT
    main.hex прошивка для микроконтроллер AVR в HEX формате
    AA — адрес устройства в сети Clunet которое надо перепрограммировать (в десятичной системе)
    IP — IP адрес нашего шлюза
    PORT — порт на котором работает службаПример:
    ~/dev/clunet-gw/flash_util/util main.hex 100 192.168.88.136:8888У меня для каждого устройства есть своя директория с исходниками и на каждое свой Makefile
    В Makefile функция программирования через шлюз добавлена так:prog: hex
    $(CLUNET_FLASHER) $(PRG).hex $(CLUNET_DEVICE_ID) $(CLUNET_IP):$(CLUNET_PORT)
  4. Утилита может прошивать прошивку в самой плате переходнике при помощи UART загрузчика
    Иногда приходилось обновить прошивку в самом переходнике Clunet-RPI (Clunet-UART)
    Это легко сделать указав вместо адреса self
    Например:
    ./util main.hex self /dev/ttyAMA0

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