CAN (Controller Area Network) — шина контроллеров — широко используется в автомобильной промышленности и других промышленных приложениях. В автомобилях блоки управления (ЭБУ) соединяются по шине CAN, которая выступает в качестве управляющей нервной системы. Блоки управления двигателем (ECU) могут включать в себя блок управления двигателем, блок управления подушками безопасности, систему Audi, блок управления положением дверей, тормозную систему, датчики и другие. Каждой функции может быть назначен отдельный узел (NODE) или блок управления двигателем (ECU). В современном автомобиле может быть до 100 электронных блоков управления. Технология CAN позволяет блокам управления обмениваться данными друг с другом без сложной специализированной проводки между ними.
Любой блок управления двигателем (ЭБУ) может взаимодействовать со всей системой, не вызывая перегрузки управляющего компьютера.
CAN — это многомастерская конфигурация. Любой узел может быть мастером. CAN работает по принципу обмена сообщениями, и для связи с узлом не используется адрес ведомого устройства. Каждый узел получает сообщение, а соответствующие данные обрабатываются узлом-получателем. Это как система оповещения в аэропорту. Сообщение услышат только заинтересованные пассажиры. Для балансировки шины CAN и снижения уровня шума в качестве оконечного резистора используется резистор 120 Ом. Это обязательно для конечных узлов. Узлам, добавленным между ними, этот резистор не требуется.
В этом проекте мы используем плату CAN2515. На этой плате установлены 2 микросхемы. Одна из них — контроллер CAN MCP2515, который взаимодействует с Arduino или любым другим микроконтроллером по протоколу SPI. MCP2515 выдает однополярный цифровой сигнал (высокий, низкий).
TX-CAN и RX-CAN работают на цифровом уровне и подключены к другой микросхеме — приемопередатчику.
Здесь используется трансивер TJ1050. Microchip MCP 2551 также является трансивером, обычно используемым с микроконтроллерами, имеющими встроенный CAN-контроллер. Например, модуль ESP32 имеет встроенный контроллер, но ему нужен трансивер, такой как MCP2551 или TJ1050. Не путайте эти цифры. 2515 — это контроллер, 2551 — это приемопередатчик. TJ1050 принимает цифровой сигнал от CAN2515 и преобразует его в дифференциальный сигнал, допустимый на шине CAN.
Обратите внимание на связь между TJA1050 и CAN 2515. TX-CAN к TXD, RX-CAN к RXD (не наоборот). В используемом нами модуле обе микросхемы уже установлены, поэтому нам не нужно беспокоиться об этом соединении.
Формат CAN-сообщения представлен ниже:
Идентификатор CAN может быть 11-битным или 29-битным. 11-битный адресный модуль может адресовать 2048 узлов (2 степени 11) в шестнадцатеричном формате от 0x000 до 0x7FF. Расширенная версия с 29-битной архитектурой может вмещать до 536 миллионов символов. Допустимая длина DAT-файла составляет максимум 8 байт или 64 бита.
Чтобы узнать больше о CAN-сообщениях, посетите эту страницу.
На следующем рисунке показан дифференциальный уровень сигнала CAN.
Когда на шине отсутствует информация, напряжение на каналах CAN-H и CAN-L составляет половину напряжения питания (в данном случае 2,5 вольта в 5-вольтовой системе).
Это рецессивное состояние или бит 1.
Когда напряжение на CAN-H достигает 5 В, а на CAN-L — 0 В, это состояние ДОМИНАНТНОЕ или БИТ 0.
Для начала работы над проектом подключите потенциометр (центральный контакт) к выводу A0 платы Arduino.
Один конец потенциометра подключен к 5 В, а другой — к земле.
На схеме показаны соединения платы CAN, а также SPI-соединения между Arduino и платой CAN.
Прежде чем начать, нам нужна хорошая библиотека для работы с CAN.
В SEEED Studio есть библиотека, которая отлично работает с их Shield.
Также модифицированная версия доступна на сайте Cryjfowler.
Я предпочитаю использовать один из вариантов от AUTOWP.
arduino-mcp2515
Этот метод использует структуру (STRUCT) для отправки сообщений. Он очень прост и удобен в использовании.
Обратите внимание, что библиотека Seed Studio и библиотека coryjfowler имеют одинаковое имя заголовочного файла mcp_can.h. Если вы установите обе эти библиотеки, возникнет конфликт при объявлении объектов, что приведет к ошибкам. Используйте только одну из них.
В этой демонстрации мы используем библиотеку arduino-mcp2515. Скачайте её в виде ZIP-файла.
Библиотека CAN
https://github.com/autowp/arduino-mcp2515
В Arduino IDE: Скетч -> Включить библиотеку -> Добавить ZIP-библиотеку
Перейдите к месту расположения загруженной библиотеки. Выберите её для установки.
Файл будет скопирован в папку Documents/Arduino/Libraries.
На стороне приемника мы используем ЖК-дисплей с интерфейсом I2C.
Библиотеку для этого можно скачать и установить по следующей ссылке:
Библиотека i2c:
https://github.com/fdebrabander/Arduino-LiquidCrystal-I2C-library
Код для Arduino, используемый в этом проекте, можно скачать по ссылке:
http://www.alselectro.com/files/CAN_2515.zip
На следующем рисунке показаны соединения со стороны передатчика.
Подключение потенциометра к выводу A0 Arduino, платы CAN к интерфейсу SPI.
Код для передающей стороны выглядит следующим образом:
Здесь мы приводим заголовочный файл mcp2515.h.
Мы создаём неинициализированную переменную структуры can_frame с именем canMsg.
can_frame — это имя типа структуры.
canMsg — это имя переменной.
Присваивание значений членам структуры осуществляется с помощью точечного оператора.
Как видно из документации библиотеки, в ней три элемента: can_id, can_dlc и data[].
Объект mcp2515 инициализируется из класса MCP2515 путем передачи в качестве аргумента вывода CS (контакт выбора микросхемы 10).
MCP2515 mcp2515(10);
В разделе setup мы вызываем функции объекта mcp2515.
Сначала вызывается функция reset().
Затем используйте функцию setBitrate(), чтобы установить скорость CAN на уровне 500 Кбит/с и частоту 8 МГц.
Функция setNormalMode() устанавливает режим работы модуля в обычном режиме.
mcp2515.reset();
mcp2515.setBitrate(CAN_500KBPS,MCP_8MHZ);
mcp2515.setNormalMode();
С помощью оператора точки элементы добавляются в структуру.
can_id — это шестнадцатеричный идентификатор, предоставленный пользователем. Вы можете указать свой собственный идентификатор в шестнадцатеричном формате.
can_dlc — это длина данных. Максимально допустимая длина — 8 байт. Здесь мы указываем длину данных всего в один байт.
В функции loop() значение аналогового потенциометра сопоставляется со значением в диапазоне от 0 до 255.
и данные, передаваемые по шине CAN с помощью функции sendMessage() модуля mcp2515.
Ниже приведено изображение подключения со стороны приемника.
ЖК-дисплей с интерфейсом I2C имеет два контакта, помимо Vcc и Gnd.
SDA подключен к A4, SCL подключен к A5.
Плата CAN передатчика подключена к плате CAN приемника.
CAN_H к CAN_H
CAN_L в CAN_L
Обычно используется витая пара проводов с экраном. Экран подключается к земле (GND).
Максимальная допустимая длина составляет 40 метров.
Ниже приведён код со стороны приёмника:
Здесь мы добавили разъем I2C для ЖК-дисплея.
При создании объекта LCD мы передаем I2C-адрес и размер LCD (16 x 2).
Чтобы узнать I2C-адрес, вы можете использовать сканер I2C, доступный здесь.
В пустом цикле
Для проверки входящего сообщения мы используем функцию readMessage() модуля mcp2515.
Затем мы сравниваем идентификаторы и извлекаем сообщение для отображения на ЖК-дисплее.
В проект можно добавить больше датчиков.
В точке A3 можно установить датчик температуры LM35, а в точке D6 — выключатель включения/выключения двери.
Код для Arduino, используемый в этом проекте, можно скачать по ссылке:
http://www.alselectro.com/files/CAN_2515.zip