Большинство людей ассоциируют семейство микроконтроллеров ESP с технологией WiFi, что вполне логично, поскольку они стали основным решением для быстрого и легкого вывода вашего проекта в онлайн. Однако, хотя возможности WiFi могут быть звездой шоу, ESP32 также и оснащен контроллером CAN. Просто мы не видим, чтобы он использовался так часто. Но изучение того, как читать и анализировать сообщения CAN на вашем ESP32, может быть невероятно полезным. Например, вы можете получать данные из вашего автомобиля, такие как температура охлаждающей жидкости, положение дроссельной заслонки, скорость автомобиля и обороты двигателя, и отображать их на собственной веб-странице, доступной через WiFi. Или вы можете создать свою собственную сеть CAN на основе микроконтроллеров ESP32.
В этом уроке мы рассмотрим основы функционирования шины CAN, как настроить встроенный контроллер шины CAN ESP32, как подключить ESP32 к внешнему трансиверу CAN TJA1050 и, что важно, как заставить две платы ESP32 взаимодействовать через шину CAN.
Недавно на нашем сайте мы рассматривали использование шины CAN в ESP32 с помощью модуля MCP2515, однако решил опубликовать и эту статью потому что в ней максимально подробно описаны все внутренние аспекты работы модуля ESP32с шиной CAN (чем не может похвастаться предыдущая статья), а вместо модуля CAN MCP2515 в этой статье мы будем использовать CAN-трансивер TJA1050.
Также теорию про то, как работает шина CAN и ее отличия от интерфейсов I2C и SPI, вы можете прочитать в статье про подключение контроллера шины CAN MCP2515 к плате Arduino.
Необходимые компоненты
- Модуль ESP32 — 2 шт. (купить на AliExpress).
- CAN-трансивер TJA1050 – 2 шт. (купить на AliExpress).
- Макетная плата.
- Соединительные провода.
Реклама: ООО «АЛИБАБА.КОМ (РУ)» ИНН: 7703380158
Основы работы CAN-шины
В старые времена в автомобилях было более 2000 метров кабеля, соединяющего переключатели на панели приборов напрямую с фарами и задними фонарями, например. По мере того, как автомобили становились все сложнее, эта простая логика больше не работала.
В 1986 году компания Bosch представила систему CAN-шины, которая решила эту проблему и сделала производство автомобилей более дешевым и простым. В настоящее время CAN является отраслевым стандартом и используется во всем: от автомобилей и грузовиков до автобусов и тракторов, и даже самолетов и кораблей.
Чтобы лучше понять шину CAN, представьте, что ваш автомобиль — это человеческое тело. В этом контексте шина CAN — это нервная система.
Подобно тому, как нервная система обеспечивает связь между различными частями тела, шина CAN обеспечивает связь между различными узлами шины CAN , также известными как электронные блоки управления (или ЭБУ).
Современный автомобиль имеет более 70 ЭБУ, каждый из которых отвечает за выполнение определенной задачи. Хотя эти ЭБУ могут эффективно выполнять одну задачу, они должны обмениваться информацией друг с другом. Например, модуль управления двигателем отправляет текущую скорость двигателя на панель приборов, где она отображается на тахометре; аналогично, контроллер двери водителя отправляет сообщение контроллеру двери пассажира, чтобы привести в действие стеклоподъемник.
ЭБУ подключаются к шине в конфигурации с несколькими мастерами (то есть ведущими устройствами). Это означает, что каждый ЭБУ может взять под контроль шину и транслировать по ней информацию (например, данные датчиков). Транслируемые данные принимаются всеми другими ЭБУ на шине CAN. Затем каждый ЭБУ может считывать данные и решать, принимать их или игнорировать.
Топология шины CAN
Физическая связь осуществляется через жгут проводов шины CAN, состоящий из двух проводов, CAN low и CAN high. Оба провода плотно скручены вместе, так что электромагнитные помехи равномерно влияют на сигнал в обоих проводах, тем самым сводя к минимуму ошибки.
Дальние концы кабеля заканчиваются резисторами сопротивлением 120 Ом. Поскольку шина CAN является высокоскоростной шиной данных, если шина не будет остановлена, сигнал будет отражаться и мешать следующему сигналу данных, проходящему по линии, что может привести к нарушению связи и отказу шины.
CAN-сигнализация
Для обеспечения передачи данных по этим проводам изменяются уровни их напряжения. Затем эти изменения в уровнях напряжения транслируются в логические уровни, позволяя узлам сети общаться друг с другом.
Для передачи «логической 1» по шине CAN напряжение на обеих линиях устанавливается на уровне 2,5 вольт (т.е. нет разницы напряжений). Это состояние известно как рецессивное состояние, и оно указывает на то, что шина CAN доступна для использования любым узлом.
Напротив, для передачи «логического 0» линия CAN high устанавливается на 3,5 вольта, а линия CAN low на 1,5 вольта (т.е. разница напряжений составляет 2 В). Это состояние шины известно как доминантное состояние, которое сообщает каждому узлу на шине, что другой узел передает данные и что он должен дождаться завершения передачи, прежде чем передавать свое сообщение.
Узел шины CAN
Каждый узел CAN содержит CAN-трансивер, CAN-контроллер и микроконтроллер.
CAN-трансивер
-
- При приеме: преобразует уровни напряжения на шине CAN в уровни, понятные контроллеру CAN.
- При передаче: преобразует поток данных от CAN-контроллера на уровни CAN-шины.
Контроллер CAN
- При передаче: передает сообщение с микроконтроллера последовательно на шину, когда шина свободна.
- При приеме: сохраняет полученные последовательные биты с шины до тех пор, пока не станет доступно все сообщение, и дает команду микроконтроллеру извлечь его (обычно путем запуска прерывания).
Микроконтроллер
Он решает, что означают полученные сообщения и какие сообщения он хочет передать. К нему подключены датчики, исполнительные механизмы и устройства управления.
Стандартный фрейм CAN
Связь по шине CAN осуществляется через CAN-фреймы. На следующем рисунке показан стандартный CAN-фрейм с 11-битным идентификатором. Давайте быстро рассмотрим каждое из восьми полей этого сообщения:
-
- SOF: Начало кадра — это «доминантный 0», сообщающий другим узлам, что узел CAN намерен обмениваться данными.
- ID: ID — это идентификатор кадра. Он используется для указания значения сообщения и того, кто его отправляет. ID также определяет приоритет: чем ниже ID, тем выше приоритет сообщения.
- RTR: Запрос на удаленную передачу указывает, отправляет ли узел данные или запрашивает данные у другого узла.
- Control: Control содержит бит расширения идентификатора (IDE), который является «доминантным 0» для 11-битного идентификатора. Он также содержит 4-битный код длины данных (DLC), который определяет, сколько байт данных будет в сообщении.
- Данные: 8 байт данных содержат фактическую информацию.
- CRC: Циклический контроль избыточности предназначен для обнаружения ошибок.
- ACK: Слот ACK указывает, подтвердил ли узел получение данных и правильно ли он их получил.
- EOF: EOF отмечает конец CAN-кадра.
Примечание: шина CAN уникальна тем, что является протоколом на основе сообщений. Обычно в распределенной сети каждое устройство имеет уникальный идентификатор, чтобы отличать его от других устройств на той же шине, и сообщения отправляются с устройства A на устройство B на основе их идентификаторов.
Напротив, узлы на шине CAN не имеют идентификаторов. Вместо этого каждому сообщению назначается уникальный CAN ID, который указывает, о чем сообщение. Все узлы получают все сообщения, и каждый узел фильтрует сообщения, которые имеют к нему отношение.
Контроллер ESP32 CAN, он же контроллер TWAI
Компания Espressif Systems называет свой контроллер, совместимый с шиной CAN, TWAI (Two-Wire Automotive Interface), что означает двухпроводной автомобильный интерфейс.
Теперь вы можете задаться вопросом, почему они сделали это изменение с более привычного термина CAN на TWAI. Это распространенный вопрос, который многие задавали с тех пор, как Espressif решила переименовать его.
Ранее Espressif использовал термин CAN во всей своей документации для описания этой функции. Однако в своей последней документации они начали использовать термин TWAI. Это изменение может показаться немного запутанным на первый взгляд, но имейте в виду, что TWAI и CAN по сути означают одно и то же, когда речь идет об ESP32.
Контроллер TWAI разработан для совместимости с протоколом CAN 2.0. Он поддерживает как стандартный формат кадра (11-битный ID), так и расширенный формат кадра (29-битный ID).
Он включает в себя функции обнаружения и обработки ошибок, обеспечивая надежную связь в шумной обстановке, что особенно важно в автомобильной промышленности.
Контроллер TWAI также поддерживает связь на основе прерываний, что позволяет эффективно обрабатывать сообщения и события на шине CAN без необходимости постоянного опроса состояния.
Блок-схема контроллера TWAI
На схеме ниже показаны основные функциональные блоки контроллера TWAI.
Сигнальные линии
Интерфейс контроллера TWAI состоит из четырех сигнальных линий: TX, RX, BUS-OFF и CLKOUT. Приятной особенностью ESP32 является то, что все четыре сигнала могут быть сопоставлены с любым выводом GPIO.
-
- TX и RX: Сигнальные линии TX и RX должны быть подключены к внешнему трансиверу. Обе сигнальные линии представляют/интерпретируют доминантный бит как низкий логический уровень (0 В), а рецессивный бит как высокий логический уровень (3,3 В).
- BUS-OFF: Сигнальная линия BUS-OFF не всегда необходима, но полезна в определенных ситуациях. Эта линия устанавливается на низкий логический уровень (0 В), когда контроллер TWAI переходит в состояние отключения шины, что указывает на нарушение связи. В нормальном режиме работы линия BUS-OFF поддерживает высокий логический уровень (3,3 В).
- CLKOUT : Сигнальная линия CLKOUT — еще одна дополнительная функция. Она обеспечивает вывод предварительно масштабированной версии исходного тактового сигнала контроллера.
Режимы работы
TWAI поддерживает следующие режимы работы:
-
- Normal Mode (Обычный режим): В этом режиме контроллер TWAI может участвовать в действиях шины, таких как передача и получение сообщений/кадров ошибок. При передаче сообщения требуется подтверждение от другого узла.
- No Ack Mode (Режим без подтверждений): этот режим похож на обычный режим, но с одним ключевым отличием: передачи считаются успешными без необходимости подтверждения. Этот режим особенно полезен для самотестирования контроллера TWAI, поскольку он позволяет осуществлять обратную петлю передач без внешних подтверждений.
- Listen Only Mode (Режим «Только прослушивание»): в этом режиме контроллер TWAI играет пассивную роль. Он не влияет на шину, то есть не будет передавать никаких сообщений, подтверждений или кадров ошибок. Контроллер все равно может получать сообщения, но не будет их подтверждать. Этот режим подходит для приложений мониторинга шины.
Функции
Основные характеристики контроллера ESP32 TWAI:
-
- Совместимость с протоколом ISO 11898-1 (спецификация CAN 2.0).
- Поддерживает стандартный формат кадра (11-битный идентификатор) и расширенный формат кадра (29-битный идентификатор).
- Скорость передачи данных:
-
- от 25 Кбит/с до 1 Мбит/с в версии чипа v0.0/v1.0/v1.1.
- от 12,5 Кбит/с до 1 Мбит/с в версии чипа v3.0/v3.1.
-
- Несколько режимов работы:
-
- Нормальный.
- Только слушать (никакого влияния на CAN шину).
- Самотестирование (передачи не требуют подтверждения).
-
- 64-байтовый приемный FIFO.
- Специальные трансмиссии:
-
- Одиночные передачи (не передаются автоматически в случае ошибки).
- Самоприем (контроллер TWAI одновременно передает и принимает сообщения).
-
- Фильтр приема (поддерживает режимы одинарного и двойного фильтра).
- Обнаружение и обработка ошибок:
-
- Счетчики ошибок.
-
- Настраиваемый предел предупреждений об ошибках.
- Захват кода ошибки.
- Захват потерянных фреймов.
-
Превосходным ресурсом для изучения контроллера ESP32 TWAI является техническое справочное руководство (даташит) по ESP32. Оно включает раздел, посвященный TWAI, предоставляя обширную информацию о нем.
Высокоскоростной CAN-трансивер TJA1050
Хотя ESP32 имеет встроенный контроллер, совместимый с шиной CAN, у него нет встроенного CAN-трансивера, поэтому для подключения к сети CAN необходимо использовать внешний трансивер.
Тип внешнего трансивера, который вам понадобится, зависит от конкретных требований вашего проекта. Например, если вам нужна совместимость со стандартами ISO 11898-2, то что-то вроде высокоскоростного трансивера CAN TJA1050 от NXP или SN65HVD23x от Texas Instruments будет отличным выбором.
В этом проекте мы будем использовать модуль приемопередатчика CAN-шины TJA1050.
Этот модуль служит интерфейсом между ESP32 и физической двухпроводной шиной CAN и соответствует требованиям автомобильной промышленности к высокой скорости (до 1 Мбит/с), низкому току покоя, электромагнитной совместимости и электростатическому разряду.
Более подробную информацию о CAN-трансивере TJA1050 можно найти в его техническом описании.
Подключение оборудования
Теперь, когда мы все знаем о контроллере TWAI, давайте построим собственную сеть CAN на основе микроконтроллеров ESP32.
Пример 1: Простая двухузловая сеть CAN
В этом примере строится простая двухузловая сеть CAN-шины — один узел передает сообщение, другой его получает.
Для начала возьмите модуль трансивера CAN TJA1050 и подключите его вывод VCC к VIN на вашем ESP32. Затем подключите вывод GND к земле. Затем подключите TX к GPIO5 и RX к GPIO4 на ESP32.
Вам нужно будет создать две такие схемы. Они будут идентичны по схеме. Одна будет работать как передатчик, отправляя сообщения, а другая будет служить приемником, принимая эти сообщения.
Подключение модулей простое: CAN L подключается к CAN L, а CAN H подключается к CAN H. В идеале провода должны быть витой парой, но для простого тестирования макетной платы или других коротких соединений это не требуется.
Схема простой двухузловой сети CAN на основе микроконтроллеров ESP32 показана на следующем рисунке.
Важно помнить, что по мере увеличения длины шины или увеличения электрических помех окружающей среды использование витой пары и добавление экранирования становятся более важными.
Пример 2: Многоузловая CAN-сеть
В этом примере создается более крупная сеть CAN — несколько узлов отправляют сообщения, а один узел ретранслирует их на ПК через последовательный порт.
Другие узлы могут быть добавлены между двумя конечными узлами. Они могут быть соединены в линию или присоединены к основной шине с помощью короткого кабеля-заглушки, при условии, что длина не превышает 12 дюймов.
Важное замечание о модуле трансивера CAN TJA1050 заключается в том, что он поставляется с уже припаянным оконечным резистором 120 Ом. Поэтому для этих дополнительных узлов в вашей сети вам нужно будет удалить этот резистор.
Схема простой многоузловой сети CAN на основе микроконтроллеров ESP32 показана на следующем рисунке.
Установка библиотеки
Библиотека Arduino CAN от Sandeep Mistry действительно отличная библиотека для работы с контроллером TWAI. Вам нужно будет скачать и установить ее в Arduino IDE.
Чтобы установить библиотеку, перейдите в Sketch > Include Library > Manage Libraries… Подождите, пока менеджер библиотек загрузит индекс библиотеки и обновит список установленных библиотек.
Отфильтруйте свой поиск, введя «mcp2515». Найдите CAN от Sandeep Mistry. Щелкните по этой записи и выберите Install («Установить»).
Пример кода
В этом простом тесте мы попытаемся передать сообщение «Hello World» по шине CAN, чтобы проверить, можно ли его расшифровать. Это поможет вам научиться использовать модули и может послужить основой для более практических экспериментов и проектов.
Код для узла-передатчика
Загрузите этот скетч в узел передатчика.
Примечание: если у вас несколько узлов на шине CAN, загрузите этот скетч на каждый из узлов-передатчиков. Обязательно измените идентификаторы сообщений на уникальные значения для каждого узла.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
#include <CAN.h> #define TX_GPIO_NUM 5 #define RX_GPIO_NUM 4 void setup() { Serial.begin (115200); while (!Serial); delay (1000); Serial.println ("CAN Sender"); // Set the pins CAN.setPins (RX_GPIO_NUM, TX_GPIO_NUM); // start the CAN bus at 500 kbps if (!CAN.begin(500E3)) { Serial.println("Starting CAN failed!"); while (1); } } void loop() { // send packet: id is 11 bits, packet can contain up to 8 bytes of data Serial.print("Sending packet ... "); CAN.beginPacket(0x12); CAN.write('h'); CAN.write('e'); CAN.write('l'); CAN.write('l'); CAN.write('o'); CAN.endPacket(); Serial.println("done"); delay(1000); // send extended packet: id is 29 bits, packet can contain up to 8 bytes of data Serial.print("Sending extended packet ... "); CAN.beginExtendedPacket(0xabcdef); CAN.write('w'); CAN.write('o'); CAN.write('r'); CAN.write('l'); CAN.write('d'); CAN.endPacket(); Serial.println("done"); delay(1000); } |
Код для приемного узла
Загрузите этот эскиз в узел-приемник.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
#include <CAN.h> #define TX_GPIO_NUM 5 #define RX_GPIO_NUM 4 void setup() { Serial.begin (115200); while (!Serial); delay (1000); Serial.println ("CAN Receiver"); // Set the pins CAN.setPins (RX_GPIO_NUM, TX_GPIO_NUM); // start the CAN bus at 500 kbps if (!CAN.begin(500E3)) { Serial.println("Starting CAN failed!"); while (1); } } void loop() { // try to parse packet int packetSize = CAN.parsePacket(); if (packetSize) { // received a packet Serial.print ("Received "); if (CAN.packetExtended()) { Serial.print ("extended "); } if (CAN.packetRtr()) { // Remote transmission request, packet contains no data Serial.print ("RTR "); } Serial.print ("packet with id 0x"); Serial.print (CAN.packetId(), HEX); if (CAN.packetRtr()) { Serial.print (" and requested length "); Serial.println (CAN.packetDlc()); } else { Serial.print (" and length "); Serial.println (packetSize); // only print packet data for non-RTR packets while (CAN.available()) { Serial.print ((char) CAN.read()); } Serial.println(); } Serial.println(); } } |
Тестирование работы проекта
После загрузки скетча откройте последовательный монитор на скорости передачи данных 115200 бод. Узел-передатчик отправляет стандартный CAN-пакет и расширенный CAN-пакет каждую секунду.
Узел-приемник получает его и передает на ПК через последовательный порт.