avatar_i

Универсальный протокол обмена между микроконтроллерными устройствами

Автор i, 04 Июнь 2011 в 13:34

« назад - далее »

0 Пользователи и 1 гость просматривают эту тему.

i

Цитата: zap от 03 Июнь 2011 в 20:09
Могу поделиться готовым универсальным легковесным протоколом для BMS, чтобы не городить пицот несовместимых протоколов. Обмен данными через UART. В протоколе предусмотрено считывание текущего тока, общее напряжение батареи, напряжение каждой отдельной ячейки, ампер*часы (всего и оставшихся), ватт*часы (всего и оставшихся), ну и прочее по мелочи (идентификация устройства, калибровку напряжений и токов (задание коэффициентов для линейной функции y = a*x+b) итп), плюс можно по необходимости расширять. В протоколе всего 4 команды (PING, READ, WRITE, RESET); размер кода - порядка 700 байт для AVR, код на C, хорошо документирован, легко переносим на другие платформы (зависимость кода от аппаратной части AVR минимальная).

Описание протокола обмена.

zap

Напишу несколько более развёрнуто.

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

Смысл единого стандарта в том, чтобы:
a) Иметь хорошо документированный базовый протокол, который используется для общения с разными устройствами (т.е. не будет дублирования кода). Возможна даже публикация библиотек для разных микроконтроллеров, реализующих данный протокол на базовом уровне.
б) Сделать возможным поддержку одним устройством целой линейки родственных устройств от разных производителей. Например, велокомпьютер может поддерживать множество "умных" BMS от разных производителей.
в) Сделать возможной написание программ для ПК, которые обслуживают целый класс устройств, используя единый базовый протокол.

Протокол может работать поверх любого аппаратного протокола обмена, который обеспечивает полудуплексный, посимвольный обмен 8-битными данными (типа UART, CAN), либо аппаратных протоколов с блочной передачей данных (типа i2c). В случае использования протокола UART предлагается использовать скорость 9600 бод, 8 бит данных без чётности, 1 стоповый бит, как наиболее универсальный.

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


  • Идентификатор производителя (0-255)
  • Идентификатор устройства (0-255)
  • Версия аппаратной части
  • Версия программной части

Версии аппаратной и программной части это 8 бит, разбитых на группы по 2, 3 и 3 бита (старший номер версии, младший номер версии и ревизия).

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

За одну операцию возможно чтение до 255 байт данных, либо запись до 30 байт данных. Чтение/запись может осуществляться как из одного параметра, так и из целого набора параметров, последовательно расположенных в памяти. Для этого при чтении задаётся номер начального параметра и длина считываемых данных, захватывающая сразу несколько параметров.

Более подробно о протоколе можно прочитать здесь.

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

P.S. Кстати, надо бы придумать какое-то названия для базовой части протокола. Какой-нибудь Единый Стандарт Обмена Данными Микроконтроллерных Устройств. Или Открытый Стандарт. ОСОД(МУ), гы :bj:.
С уважением,
Андрей

Поражаю масштабностью некопмпетентность (ц) из лички

DarthGray

Вот бы ещё протокол инфинеона в 164-ом режиме вычислить...(это 2-ой режим индикации)
Но там явно не асинхронный порт, может SMBUS
Может конечно там и вообще не порт организуется, но причём тогда CLK и DAT?
Различие между теорией и практикой на практике гораздо больше, чем в теории.

zap

С уважением,
Андрей

Поражаю масштабностью некопмпетентность (ц) из лички

DarthGray

Ну тогда по идее, еслиб он был мастером, то там должно что-то корячиться, а там глушняк
Хотя может конечно он в режиме Slave - Transmit, тогда надо будет как нибудь попробовать ему туда тактовую плюнуть
Может чего и ответит...
Различие между теорией и практикой на практике гораздо больше, чем в теории.

i

На счёт универсальности я пока сомневаюсь. Контрольная сумма понравилась, 4 команды то же, но мне пока не понятно как обращаться к конкретному устройству из кучи однотипных. Пока мне видится только возможность  разговора двух "собеседников", типа компа с устройством.
В ЭТС мы можем (в скором времени) иметь дело с кучей устройств, как одинаковых, так и различных. Может я не всё понял, но мне кажется, что каждое устройство должно иметь право высказаться, если у него что-то случилось. В описании CAN мне понравились идеи стандартных сообщений и автоматического арбитража на шине.  Один говорит, все остальные слушают. Если одновременно заговорят двое и более, то в процессе передачи от шины отвалятся те, чьи сообщения менее критичные (определяется количеством старших нулей в мажоре), не мешая передаче победившего. Сообщение правильно примут либо все, либо никто  (в том числе и передающий, тем самым он узнает, что передача не удалась).
Стоит подумать о стандартной системе сообщений и тогда нам не нужно будет знать какие устройства у нас есть в системе и сколько их, кто их произвел, какую версию залил и прочую инфу, напрямую не относящуюся к самому транспорту.

Например, мы шлём в шину ОДНО сообщение "правый поворот", и все правые поворотники (два, три или ноль) включаются и моргают, а если какой-то поворотник моргать не может (лампочка сгорела), то он шлёт сообщение "сгорела лампочка по правому борту", которое пишется в диагностику для последующего ремонта.


i

Извиняюсь. Спутал пресное с холодным.
Только сейчас понял, что описанный [b-b]zap[/b-b]-ом протокол предназначен именно для конфигурирования некоего устройства, то есть для разговора компа с девайсом, с целью выяснения, кто, чего, куда и сколько. Адресация тут действительно не нужна, а производитель и прочее могут пригодиться.
Предлагаю назвать его Конфуций.

zap

Не совсем так.

Протокол расчитан на всё, и на конфигурирование, и на общение устройств между собой, для устройства это абсолютно без разницы.
Адресация устройств производится в рамках выбранного протокола, например в i2c есть 7-битный номер устройства как часть формата i2c блока, а в UART такого нет. В протоколе CAN тоже есть свой метод адресации.
А вот UART это вообще протокол для общения точка-точка. Как оно может работать при подключении к шине более двух устройств я как-то слабо себе представляю. Если придумаете, можно рассмотреть какой-нибудь вариант введения адресации. Почему я выбрал для начала UART - этот протокол проще всего для конечного пользователя, ибо USB-UART переходники стоят копейки, а вот USB-i2c стоят немерянных денег.

Ваши мысли насчёт CAN мне понятны и близки. К сожалению, все микросхемы с CAN стоят больших денег, а широко используемые микроконтроллеры не имеют CAN. Поэтому можно подумать о чём-то CAN-образном поверх i2c, там вроде как аппаратный протокол вполне годится под эти нужды. Либо ещё лучше - если придумать, как можно реализовать нечто подобное поверх UART.
С уважением,
Андрей

Поражаю масштабностью некопмпетентность (ц) из лички

zap

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

Для реализации такого подхода в моём текущем низкоуровневом протоколе можно сделать дополнительную команду: выбор устройства. То есть, первым делом компьютер (по UART) спрашивает тип устройства (поле DEVICE FAMILY). Увидев в этом поле значение "BUS BRIDGE" (то бишь мост на нашу внутреннюю шину) он выполняет команду "SELECT DEVICE" (с идентификатором устройства), после чего все дальнейшие команды напрямую передаются к выбранному устройству. Для того, чтобы "отключиться" от выбранного устройства надо просто выполнить команду "SELECT DEVICE" с идентификатором 0.
С уважением,
Андрей

Поражаю масштабностью некопмпетентность (ц) из лички

i

Поверх UART у меня не получилось (да и вряд-ли у кого получится), а программно-аппаратно (с помощью таймера с двумя регистрами сравнения) мне удалось связать два контроллера по однопроводной шине. Болтали они вместе и при этом слышали друг друга. Причём один работал на тактовой 8МГц, а другой на 1МГц. Уложился в 490 байт.
Для иллюстрации идеи прикладываю картинки которые рисовал в процессе работы, чтобы разобраться что-куда. Они не слишком информативные (и не слишком верные), но пока нет времени расписывать всё досконально (до сих пор сезон не открыл  :()

i

У I2C кто-то должен дёргать clock, а тут данные сами тактируют шину. Короче, у меня пока проглядывает вариация на тему 1ware, с адаптивной скоростью и элементами CAN.

zap

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

Во-первых, при отсутствии сигнала CLK система становится крайне чувствительна к помехам. Если длительность начального бита нарушается помехой, дальше всё идёт вкривь и вкось.
Во-вторых, отсутствие аппаратного передатчика и приёмника очень сильно подкосит и без того небольшие ресурсы микроконтроллера. Плюс к тому, если устройство всё "лишнее" время проводит в состоянии спячки (для экономии энергии), то всё будет очень грустно. Пример: велокомп, всё время опрашивающий BMS. Микроконтроллеру BMS придётся вообще не спать (ведь велокомп может в любой момент обратиться за данными). При аппаратном же приёмнике (только I2C на AVR, к сожалению UART этим свойством не обладает), во время спячки контроллера он всё равно "слушает" линию и разбудит МК если что.

Что же до "кто-то должен дёргать CLK" то пусть его, Вам что, жалко лишний провод? Однопроводные интерфейсы крайне ненадёжны, по своему домофону сужу.
С уважением,
Андрей

Поражаю масштабностью некопмпетентность (ц) из лички

i

Тактирование идёт по каждому нулевому уровню, т.е. каждый бит может иметь свою длительность. Прерывания PCINT работают и в спячке. Регулярный опрос не планируется, так как сообщения в основном будут идти по событию. Помехи это да, могут всю малину..., мне не ножек жалко, мне не ясно как сделать дифференциальную шину с монтажным И.
Насчёт ресурсов: 490 байт кода включают в себя подсчет бита паритета, его проверку,формирование бита ответа-подтверждения, подгонку скорости, приемник и передатчик, контроль коллизий.
Если есть желание ковыряться в исходниках - выложу без проблем (как на форт-ассемблере, так и в листинге). Только без человеческого описания я и сам там запутаюсь...

zap

Если уж ориентироваться на дифференциальную шину, то надо сразу брать CAN и не париться. По любому, если её делать то придётся городить довольно большое количество внешних компонентов. Хотелось бы для велосипеда обойтись как-нибудь минимумом внешних компонент. Для борьбы с помехами по шине есть CRC и запрос на повтор передачи. Думаете, этого не хватит?
С уважением,
Андрей

Поражаю масштабностью некопмпетентность (ц) из лички

zap

Хмм.

Информация к размышлению.

Интерфейс RS485. Плюсы:


  • Позволяет подключение множества устройств к одной шине, всего по двум проводам если не нужен полный дуплекс: http://www.novosoft.by/Ency/rs-485.htm
  • Передача ведётся дифференциальными сигналами с разницей до 6В (как я понимаю, зависит от питания), нет геммороя с повышением напряжения до +-12В как на RS232
  • Для него есть очень дешёвые микросхемы MAX487, ADM485, да и вообще полно (можно найти по цене <30р), в корпусе SO8 и с микроскопическим потреблением
  • На ебэе продаются готовые недорогие USB-RS485 переходники
  • На крайняк можно прицепиться по UART напрямую к нужному девайсу, отцепив его от шины RS485 (надо только на плате предусмотреть вывод на штырьки между МК и MAX487)
  • Требует всего 2 провода (витая пара) для шины.

Минусы:


  • UART не работает в режиме спячки AVR. По сути это означает, что на время спячки ноги UART придётся перевести в высокоимпендансный режим и включить прерывания на изменение состояния пинов. После просыпания, боюсь, первые биты передачи будут утеряны - значит, первый байт в посылке должен быть незначащим.
С уважением,
Андрей

Поражаю масштабностью некопмпетентность (ц) из лички

i

RS485 старый промышленный стандарт, очень востребованный и по сей день. Микрухи такие применял для протокола DMX512 (часто используется в осветительных приборах для театральных шоу, все эти вращающиеся, моргающие приборы, что можно видеть по телику). Ничего плохого сказать не могу, работают устойчиво на сотни метров по витой паре (а у нас от силы пара метров наберется). Кстати, есть те же микрухи, но с гальванической развязкой, как оптической, так и магниторезистивной.
CAN  слишком много хочет за своё имя в спецификации микросхемы или устройства. Обойдёмся без него, но с его светлыми идеями.
UART еще древней и не всякий проц  имеет его на борту, чаще стал попадатся USI. А проца без таймера я не припомню. Скорости и объёмы данных нам не критичны, можно и программно подёргать ножками.
Есть микросхемы USB-UART, USB-LPT и прочие переходники с нового на старое, а есть программная реализация протокола USB на тиньке 26 (у меня на ней собран программатор для авэрок).


i

Цитата: zap от 06 Июнь 2011 в 19:13
Если уж ориентироваться на дифференциальную шину, то надо сразу брать CAN и не париться.
Можно взять готовый бентли и не парится, но мне охота попарится.
Цитата: zap от 06 Июнь 2011 в 19:13
По любому, если её делать то придётся городить довольно большое количество внешних компонентов. Хотелось бы для велосипеда обойтись как-нибудь минимумом внешних компонент.
Два резистора и конденсатор. Как в приложеной схеме.

Цитата: zap от 06 Июнь 2011 в 19:13
Для борьбы с помехами по шине есть CRC и запрос на повтор передачи. Думаете, этого не хватит?
Вполне может хватит. Пробовать надо.


detoxic

SN65HVD1050 CAN трансивер 40 рублей в платане. для работы один капаситор по питанию и пару супрессоров на линию - итого на link рублей 60 максимум
куда дешевле? при надежности CAN
минус лишь один - нужен камень с модулем can контроллера
трехфазный вентильный привод без магнитов - это реальность