Одним ясным солнечным днем по работе понадобился недорогой преобразователь интерфейсов CAN в Ethernet. Естественно поиски начались с готовых решений, но, как нередко это бывает, в итоге было принято решение о разработке собственного образца. Естественно, энтузиазм автора не смог устоять и ограничиться столь «урезанным» функционалом. Что из этого вышло, каким образом и почему — под катом.

image

Общая сводка. На фото выше представлена 3D модель разработанной мной платы при помощи САПР Altium Designer. Основные характеристики и функционал:

  • 10\100 Mb Ethernet
  • RTC
  • MicroSD (FAT12, FAT16, FAT32) 4GB
  • RS232 \ RS485
  • CAN
  • Buzzer
  • 3 User LED
  • GPIO
  • EEPROM 32 KB
  • FLASH 2 MB
  • I2C
  • SPI
  • UART
  • SW \ JTAG
  • USB serial (COM Port)
  • Power: miniUSB 5V \ External 9..24V

Стоимость собранной платы ~ 5000 Р. Проект носит open source характер, исходники можно найти на github. То, что получилось в итоге, помимо основного функционала, можно считать неплохой отладочной платой для работы с микроконтроллером STM32.

А теперь к подробностям создания.

Hardware


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

  1. преобразование поступающих CAN2.0B фреймов в TCP\IP пакеты и наоборот;
  2. невысокая стоимость, как следствие реализация устройства на базе микроконтроллера.

У коллег из Китая есть несколько промышленных решений, но не из дешевых, поэтому в наш офис на тест был доставлен представитель отечественного производства «Преобразователь интерфейсов ПИРС CAN-Ethernet». По описанным возможностям и характеристикам устройство удовлетворяло скромное Т.З., оставалось лишь проверить работоспособность на деле, чем я и занялся, вооружившись Wireshark’ом и осциллографом. По неизвестной причине при отправке в девайс TCP пакетов на выходе устройства, там, где должны были появляться CAN фреймы, выплёвывались последовательности с физическими уровнями CAN (диф. пара), но логическим протоколом интерфейса UART (со стартовыми и стоповыми битами). Вскрыв корпус, открыв документацию микросхем и прозвонив дорожки платы, я обнаружил, что, действительно, пины RX и TX (UART) микроконтроллера соединены с трансивером CAN и с него выведены на внешний разъем. Таким образом, никакой аппаратной поддержки стандарта CAN2.0B ожидать не приходилось.

Вот, что я увидел на выводе CANL «ПИРС CAN-Ethernet» при отправке двух байт данных [0xF0] и [0x0A] по TCP\IP:

image

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

А вот как должен был выглядеть «истинный» CAN2.0B фрейм с теми же двумя байтами данных:

image

Как видно из осциллограммы, помимо байт данных в фрейме присутствует немало служебных бит протокола плюс биты стаффинга, а что самое главное – идут они непрерывно без всяких стартовых и стоповых! (Для тех, кому интересно, под спойлером детальное описание данной посылки).

Спойлер
image

Первые 4 байта – идентификатор фрейма. Подробнее о формате CAN можно узнать из [1]

Таким образом, решить проблему несоответствия CAN и UART фреймов программным способом мне не представлялось возможным и, окинув разочарованным взглядом промежуточные результаты исследований, было принято решение разработки собственного прототипа требуемого устройства.

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

3. Возможность питания от 12-24 В в транспортных системах;
4. Наличие внешней памяти для хранения логов;
5. Размеры платы не более 86х80мм.
6. Рабочий диапазон температур -40..85 °С

В качестве мозга нового устройства была выбрана небезызвестная платформа STM32F407VET6 [2], обладающая аппаратной поддержкой всех необходимых интерфейсов и неплохим запасом RAM и FLASH памяти. Пошерстив интернет, в качестве PHY Ethernet был выбран трансивер DP83848IVV [3], имеющий хорошую, на мой взгляд, документацию и достаточно примеров схем с подключением и трассировкой. В качестве внешней энергонезависимой памяти для хранения логов я выбрал SPI FLASH 2 MB и SPI EEPROM для хранения разнообразных настроек. Кроме того была добавлена защита питания от перенапряжения, переполюсовки. Через N вечеров и M выходных были составлены принципиальная схема и трассировка печатной платы устройства первой версии. Т.к. места на плате было достаточно, а незадействованные ножки МК оставлять не хотелось, помимо основного функционала на плату были добавлены:

  • средства для отладки SW, JTAG;
  • переключатель 8-DIP Switch;
  • micro-USB (USB Serial);
  • RS-232;
  • UART;
  • I2C;
  • GPIO

Идея была в том, чтобы при необходимости плата была готова к расширению функционала за счет монтажа дополнительных компонентов. Тем более на стоимость производства запасные посадочные места не влияют. На одной стороне, к сожалению, из-за этого уместить все не удалось, так что плата получилась двусторонняя 86х80мм, мин. ширина дорожки 0.25мм, мин диаметр отверстия 0.6мм.

image
Первая версия PCB-дизайна

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

image

При помощи STM32CubeMX я набросал тестовую прошивку с проверкой работоспособности основных периферийный модулей устройства и, в первом приближении, заработало все, кроме запуска МК от внешнего кварца 8 МГц. Оказалось, из-за моей ошибки в составлении спецификации, были напаяны не те нагрузочные конденсаторы. Но это не помешало STM32F407 работать от внутреннего RC-генератора. Когда же я смог пропинговать свое устройство, радости было не сдержать т.к. с трассировкой PHY Ethernet я провозился, наверное, дольше всего. Затем в браузере я увидел свою тестовую http страницу и с тестированием успокоился.

Производство первых образцов плат заказывали в Зеленограде. И, несмотря на то, что стоимость «с» маской и «без» отличалась почти в два раза, не рекомендую так делать даже на стадии прототипа, потому что, как правило, как раз на этом этапе всплывают ошибки трассировки и приходится что-нибудь перепаивать. А паяться на «голых» дорожках крайне неприятно, денег сэкономите, а вот нервов – вряд ли. Да и гадать потом коротнулось ли где-то или трассировка неверная – такое себе удовольствие. Я, в силу неопытности, перепаивая кварцевый резонатор и нагрузочные конденсаторы, один образец таки убил.

К тому времени, на работе, в закромах нашлась железка способная решить поставленную задачу конвертации в текущем проекте, но, помимо крупных габаритов и стоимости, сев писать для нее прошивку, я столкнулся с проблемами связанными с объемом RAM и урезанным функционалом TCP\IP стека МК LPC2368. Так что желание сделать свое устройство только усиливалось.
Внимательно изучив недостатки первой версии, я, долго не думая, приступил ко второй. И снова захотелось добавить «задел на будущее», вместив в прежний форм-фактор следующие компоненты:

  • поддержка RTC с батарейкой;
  • RS-485;
  • micro-SD;
  • пищалка buzzer;
  • возможность питания от USB;
  • SPI на внешний разъем;
  • питание 5V и 3.3V на внешний разъем.

Кроме прочего была добавлена защита питания по току и TVS диоды на пользовательские разъемы.

В итоге получился этакий dev-board с возможностью подключения внешних модулей. На этот раз плату заказал в Китае. Сборка производилась у нас.

image

image
Вторая версия платы

Ко второй версии я разобрался с 3D моделированием в Altium Designer, что очень помогло в избежании ошибок взаимного расположения компонентов по двум сторонам (оказалось, в интернете уже полно готовых моделек SMD компонентов [4]). Тем самым, все ошибки первой версии были исправлены, нововведения показали свою работоспособность, что очень меня порадовало.

Firmware


Описание кода выходит за рамки данной части, однако пару слов о программной составляющей сказать хочется. В своем устройстве я решил использовать связку FreeRTOS + LwIP стек. Статей про них в достаточном количестве, например, [5] и [6], поэтому прикрутить их к своему проекту не должно составить трудностей. Вкратце, LwIP – TCP\IP стек для встраиваемых систем, характеризующийся малым потреблением RAM и удобным API (есть даже BCD socket оболочка). Я использовал netconn API. Средствами FreeRTOS, вся работа TCP\IP стека помещается в поток отдельный от приложения. Помимо основной работы (соединение внешнего TCP-сервера с CAN шиной) в самостоятельном потоке крутится отдельный веб-сервер для доступа к настройкам устройства. Такой веб-интерфейс предназначен для мониторинга и конфигурации настроек устройства – установки разных режимов работы, скоростей передачи, адресов и т.д. Пока не знаю получится ли сделать и обновление прошивки через него.

Заключение


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

Используемые источники


1. Wikipedia/Controller_Area_Network
2. STM32F407VET6 datasheet
3. DP83848 datasheet
4. 3D Models
5. Введение в FreeRTOS
6. Введение в LwIP

Комментарии (34)


  1. da-nie
    17.08.2019 22:43

    Мы такое на отечественных контроллерах (от Миландра) и микросхемах делали. :)


  1. NordicEnergy
    17.08.2019 23:50

    Уровень трассировки конечно трындец… Надеюсь это делал студент. Интересно, что там такого в эзернете долго разводилось, когда 100 Мбит поднимаются на макетке с МГТФом.


    Кстати, если это открытый проект, то залейте его на github, а то писать/отвечать в личку и на почту это утомительно и вам и интересующимся.


    1. bazooka_easter
      18.08.2019 00:00

      Не могли бы Вы подробнее описать проблемы с трассировкой?


      1. ClownMik Автор
        18.08.2019 01:02

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


        1. NordicEnergy
          18.08.2019 08:23

          Какие вами рекомендации то нужны? Берете любой калькулятор типа SaturnPCB и считаете стек своей платы и узнаете параметры проводников для нужного импеданса, затем переносите его в правила altium designer и просто прокидываете 2 дифпары. Это базовые понятия, тут даже не нужно даташит от производителя открывать.


        1. Inanity
          18.08.2019 13:24
          +1

          Несколько замечаний и от меня:

          1. Пожалуй наиболее важное замечание это использование 2-х слойной платы. Я ещё могу понять самодельщиков, которые из кожи лезут вон, чтобы уложиться в 2 слоя для удобства ручного изготовления ПП (сам был таким давно), но раз уж вы так или иначе связываетесь с производством, то тем более для такой платы просто необходимо было заложить 4 слоя. И отдать на внутренние два — питание с землёй. Шинное соединение питания и земли, как это сделано у вас, крайне не приветствуется. В данном случае сплошные полигоны значительно увеличили бы качество ПП и упростили бы разводку. К примеру, конденсаторы по питанию нужно устанавливать максимально близко к микросхеме. Это очень удобно и эффективно делать на 4-х слоях с обратной стороны компонента. Все расчёты импеданса дифф. пары, которые вы возможно делали скорее всего бесполезны, т.к. у вас нет опорного слоя, хотя и длина проводника (неоднородности) достаточно мала, чтобы на что-то сильно повлиять. Возможно вам покажется это избыточным, но для ваших будущих проектов, если частоты интерфейсов будут достигать >50-100МГц, то с подобным конструктивом питания и земли с большой вероятностью будут проблемы. Я понимаю, что оно и так работает. Собственно говоря, работает потому, что частоты небольшие и хорошо, если вы, понимая это, осознанно проектируете в двух слоях. Хотя для продакшена такой платы эта экономия опасна и может выйти боком, лучше иметь запас по качеству.

          2. У Ethernet PHY под брюхом микросхемы есть термопад, который у вас, судя по всему никуда не подключён. Через этот пад чип рассеивает тепло. Если бы у вас была 4-х слойная плата, то соединив этот пад с внутренним полигоном земли вы могли бы максимально эффективно охлаждать чип под высокой нагрузкой.

          Картинка
          image


          1. ClownMik Автор
            18.08.2019 16:21

            Большое спасибо за замечания и советы, учту на будущее. По пункту 3. — корпуса разъемов соединены с землей через 1 МОм резистор и 1 кВ конденсатор в параллель.


      1. NordicEnergy
        18.08.2019 08:19

        1) Дороги выводятся из падов какими-то неимоверными способами. Там, где дорогу можно вывести из центра площадки и перпедикулярно, выводят под 45 градусов и от края пада… Ладно если бы это было в одном-двух местах, там вся плата такая. Этот вот классический «хуяк хуяк и в продакшен».

        Примеры


    1. ClownMik Автор
      18.08.2019 22:43

      В трассировке я действительно новичок и буду рад дельным советам. На github выложил.


      1. NordicEnergy
        18.08.2019 23:14

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

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


    1. ClownMik Автор
      18.08.2019 22:45

      В трассировке я действительно новичок и буду рад дельным советам. На github выложил.


  1. Javian
    18.08.2019 06:08

    Для достижения целей не подошла бы только hat для Raspberry PI?


    1. gosha-z
      18.08.2019 12:00

      Я больше скажу: Beaglebone Black+CAN/RS485 капа к ней…


  1. ktod
    18.08.2019 06:39

    действительно, пины RX и TX (UART) микроконтроллера соединены с трансивером CAN и с него выведены на внешний разъем.

    Серьезно? Кто то такое производит? Это же профанация. Или этому таки можно найти применение?


    1. ClownMik Автор
      18.08.2019 13:10

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


  1. GarryC
    18.08.2019 13:49

    Меня просто потрясают подобные решения, особенно «недорого».
    Про связку преобразователя со стандартной платой Вам уже написали, вот еще вариант.
    Не для рекламы, хотя лично я эти модули использую и претензий к ним, ну не то, чтобы совсем нет, но немного zao-zeo.ru/catalog/sbc/118-tion-pro28 — 5830 рублей и это не STM, так какого фига?


  1. dobrev
    18.08.2019 13:57

    Если это не обман зрения, то на первой версии разъём microUSB, а на второй — miniUSB. Почему так?


    1. ClownMik Автор
      18.08.2019 14:12

      Все верно. Это не обман зрения. Заметил, что miniUSB разъемы доступнее в магазинах РЭИ (во всяком случае известных мне Чип-Дипе и Элитане) чем microUSB, да и кабелей таких много и габариты позволяют.


      1. gosha-z
        18.08.2019 14:29

        Электронщик (Compel & Co) — аж три варианта со склада


  1. KonstantinSpb
    18.08.2019 15:53

    1. ClownMik Автор
      18.08.2019 16:21

      Благодарю


  1. ianzag
    18.08.2019 19:06
    +1

    Как-то мягко говоря дороговато — 5000 рублей — для такой в общем то немудреной вещи. Любой пай на A20 сделает все тоже самое, а стоить на али будет в два раза меньше. И это с точки зрения «а не прикрутить ли нам ещё XXX» будет совсем не STM.


    1. checkpoint
      18.08.2019 22:50

      С этого места поподробнее пожалуйста, какая такая «пай на A20» имеет CAN интерфейс? И что это такое «пай на A20»?

      Недавно с коллегой прикупили комплект конвертеров Ethernet-CAN на Али (как раз по 5000 руб за штуку) с целью «удлинить» OBD II от Nissan Leaf. Искомый результат не достигнут, так как инкапсуляция CAN фрэймов в UDP выполнена с достаточно высокой задержкой (как мне это показалось), точнее вообще непонятно как она выполнена — Leaf Spy обрывает соединение где-то в середине попытки получить данные о состоянии автомоильной батареи.


      1. ianzag
        19.08.2019 00:00

        Под A20 имеется виду платы на базе SoC Allwinner A20. У него на борту уже есть CAN контроллер (описан в A20 User Guide). Возьмем к примеру первую попавшуюся Xunlong Orange Pi Mini. На 40pin гребенке я вижу CAN_RX/TX. Да, там нет видимо опторазвязки и ещё каких приятных ништяков, но на сколько я могу судить это вполне себе обычный CAN.

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


        1. checkpoint
          19.08.2019 00:09

          Простите, а кто софт писать будет для этого «пай на A20» непосредственно инкапсуляции и декапсуляции CAN в TCP или UDP? Или вы думаете, что CAN это почти как UART который можно перенаправить командой cat из shell-а?

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


          1. KonstantinSpb
            19.08.2019 01:01

            Xunlong Orange Pi Mini и отдельные копеечные CAN трансиверы за 60р
            SN65HVD230 CAN bus transceiver
            www.aliexpress.com/item/32686393467.html

            Простите, а кто софт писать будет для этого «пай на A20» непосредственно инкапсуляции и декапсуляции CAN в TCP или UDP?

            Всё уже придумано до нас и гуглится на раз, есть готовое софтверное решение github.com/mguentner/cannelloni или rtime.felk.cvut.cz/can/can-eth-gw.pdf


          1. ianzag
            19.08.2019 09:26

            > Простите, а кто софт писать будет для этого «пай на A20» непосредственно инкапсуляции и декапсуляции CAN в TCP или UDP? Или вы думаете, что CAN это почти как UART который можно перенаправить командой cat из shell-а?

            Берем can4linux и пишем? Навскидку не вижу в этом ровным счетом ничего сложного. Если вдруг A20 или его аналога нет в can4linux дописываем поддержку (тоже тривиально).

            И таки вспоминаем, что CAN конечно CANом, но это ещё и сетевое устройство. Которое каким то образом должно интегрироваться в локальную сеть. Со всеми вытекающими из этого мелкими геморроями типа настройка/получение IP адреса, если адрес получается динамически то поиск устройства в сети и вот это вот все. И для таких развлечений IMHO куда приятнее работать с обычной линуксой.


          1. Hewdin
            19.08.2019 12:24
            +2

            Я когда-то тоже делал подобное устройство. Далее прототипа не пошло, т.к. софт не осилил. Пошел по пути изготовления «свистка» UART-CAN. Независимость от платформы и работа в терминале, в том числе.
            image


      1. KonstantinSpb
        19.08.2019 00:01

        В Ethernet могут быть задержки в силу работы доступа к среде передачи и эти задержки перед доступом к среде носят случайный характер. CSMA/CD


        1. checkpoint
          19.08.2019 00:14

          Разумеется, но не более 0.5мс. Более того, сборка/разборка TCP добавит еще задержку особенно при загруженной сети. Но мы все это знаем и понимаем. Купленные девасы не достигают эффекта даже будучи воткнуты друг в друга метровым кабелем.


  1. checkpoint
    18.08.2019 22:57
    +1

    Скажите, вы продаете это изделие или оно «open source»? Если последнее, то не могли бы Вы выложить исходники (схему, гербера, исходники прошивки). Хотим повторить ваш опыт для одного хоббийного проекта с участием электрокара Nissan Leaf.

    Достаточно схемы и исходников прошивки. Плату накидаем свою под размеры корпуса.


    1. ClownMik Автор
      19.08.2019 00:14

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


      1. checkpoint
        19.08.2019 00:15

        Благодарствую!


  1. IronHead
    20.08.2019 17:25

    Из аналогов есть еще spb.terraelectronica.ru/product/1048019
    По моему они скопипастили эту плату с какой то olimex, то есть при желании можно купить за те же деньги уже готовую плату с Eth и CAN