Рубрики
Схемы на Arduino

Использование стандарта CAN в Arduino – полное руководство

Современные автомобили включают в себя несколько десятков разнообразных датчиков. И все эти датчики регулярно обмениваются информацией с другими датчиками/устройствами автомобиля. Причем автомобили с каждым годом становятся все «умнее» и поэтому количество датчиков в них все больше увеличивается. В автомобилях сегодняшнего дня находят широкое применение системы автономного вождения, системы безопасности с автоматически срабатывающими подушками безопасности, системы контроля давления в шинах, круиз-контроль и т.д. В большинстве случаев информация, поступающая от этих датчиков, является критически важной. Например, если сработает датчик столкновения, которому срочно нужно передать сигнал на раскрытие подушек безопасности, а ему это помешают сделать какие-либо сигналы/процессы в электронной системе автомобиля. В этом случае жизнь людей в автомобиле может оказаться под угрозой. Поэтому в автомобилях не используют такие широко распространенные в обычной электронике протоколы передачи данных как UART, SPI или I2C. Вместо них конструкторы автомобилей отдают предпочтение значительно более надежным протоколам передачи данных, таким как LIN, CAN, FlexRay и т.д.

Наибольшее распространение среди этих «надежных» протоколов получил стандарт (протокол) CAN. Этот стандарт широко применяется не только в электронных системах современных автомобилей, но и во многих других промышленных устройства, в которых критически важна надежная передача данных. Достаточно подробную информацию о стандарте CAN можно прочитать в соответствующей статье Википедии. Мы же в данной статье рассмотрим обмен данными между двумя платами Arduino с помощью протокола CAN.

Краткие сведения о протоколе CAN

CAN (Controller Area Network – сеть контролеров) представляет собой протокол (стандарт) последовательной связи, разработанный для промышленных и автомобильных приложений. Это ориентированный на обмен сообщениями протокол, используемый для связи между множеством (несколькими) устройств. Когда различные CAN устройства соединены между собой как показано на следующем рисунке, они формируют сеть, которая работает наподобие центральной нервной системы человека и позволяет любому устройству общаться с любым другим устройством в этой сети.

CAN-сеть состоит из двух проводников (CAN High и CAN Low) и обеспечивает двунаправленную передачу данных. На практике под CAN-сетью обычно подразумевается сеть топологии «шина» с физическим уровнем в виде дифференциальной пары. Передача ведется кадрами, которые могут принимать все узлы сети. Для доступа к такой шине выпускаются специализированные микросхемы (модули) – драйверы CAN-шины.

Обычно скорость передачи по CAN-шине варьируется от 50 Кбит/с до 1 Мбит/с, а дальность связи лежит в диапазоне от 40 метров (на скорости 1 Мбит/с) до 1000 метров (на скорости 50 Кбит/с).

Формат CAN сообщений

В CAN-сети данные передаются в виде сообщений определенного формата. Этот формат состоит из большого числа сегментов, но двумя основными сегментами является идентификатор (identifier) и данные (data), которые и позволяют передавать и принимать сообщения по CAN-шине.

Идентификатор (Identifier) – также известен под именами CAN ID и PGN (Parameter Group Number). Он используется для идентификации CAN устройств в CAN-сети. Длина идентификатора составляет 11 или 29 бит в зависимости от того какой тип протокола CAN используется:

  • Standard (стандартный) CAN: 0-2047 (11-bit);
  • Extended (расширенный) CAN: 0-229-1 (29-bit).

Data – это данные, которые необходимо передать от одного устройства другому. Длина данных может составлять от 0 до 8 байт.

Data Length Code (DLC) (длина поля данных): может принимать значения от 0 до 8 в зависимости от количества байт для передачи.

Проводники, используемые в CAN

CAN протокол работает по двум проводникам, именуемыми CAN_H и CAN_L, для передачи и приема информации. Оба проводника работают как дифференциальная линия, что означает что CAN сигнал (0 или 1) представляет собой разность потенциалов между CAN_L и CAN_H. Если эта разность положительна и больше определенного минимального уровня напряжения, то это 1, а если эта разность отрицательна – то это 0.

Обычно в протоколе CAN используется кабель с витыми жилами. Как показано на выше приведенном рисунке, на обоих концах CAN-сети включается 120-омный резистор для обеспечения баланса в линии.

Сравнение CAN с SPI и I2C

На нашем сайте мы ранее уже рассматривали использование в платах Arduino протоколов SPI и I2C, поэтому давайте сравним данные протоколы с протоколом CAN.

Параметр SPI I2C CAN
Скорость 3-10 Мбит/с стандарт: 100 Кбит/с;

быстрый: 400 Кбит/с;

быстрый: 3,4 Мбит/с;

10 Кбит/с — 1 Мбит/с (зависит от длины используемых проводов)
Тип синхронный синхронный асинхронный
Число проводов 3+ (MISO, MOSI, SCK, SS1, SS2…SS(n))
Дуплекс полный дуплекс полудуплекс полудуплекс

По скорости стандарт CAN не в лидерах, но его главным «козырем» является высокая надежность связи.

Применения CAN протокола

  1. В связи с чрезвычайно высокой надежностью и устойчивостью CAN протокола он широко применяется в автомобилях, промышленных механизмах, сельском хозяйстве, медицинском оборудовании и т.д.
  2. В связи с небольшим количеством используемых проводников CAN протокол исключительно удобен для применения в автомобилях.
  3. Устройства на основе CAN протокола отличаются низкой стоимостью.
  4. В CAN-сеть (шину) легко добавлять и удалять новые устройства.

Использование протокола CAN в Arduino

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

CAN модуль (контроллер шины CAN) MCP2515

Модуль MCP2515 включает в себя CAN контроллер MCP2515, который представляет собой высокоскоростной CAN приемопередатчик. Соединение модуля MCP2515 с микроконтроллером осуществляется с помощью интерфейса SPI, поэтому его легко подключить ко всем микроконтроллерам с данным интерфейсом.

Начинающим изучение CAN-шины целесообразно начинать именно с этого модуля ввиду его простоты и легкости подключения к большинству современных микроконтроллеров.

Основные технические характеристики модуля MCP2515:

  • включает в себя высокоскоростной CAN приемопередатчик TJA1050;
  • размеры модуля: 40×28mm;
  • управление по интерфейсу SPI с возможностью подключения к CAN-шине нескольких устройств;
  • кварцевый генератор на 8 МГц;
  • сопротивление на концах 120 Ом;
  • включает независимый ключ, светодиодный индикатор, индикатор мощности;
  • поддерживает скорости передачи данных до 1 Мбит/с;
  • низкий потребляемый ток в режиме ожидания;
  • возможность подключения до 112 устройств (узлов).

Назначение контактов (распиновка) CAN модуля MCP2515 представлено в следующей таблице.

Наименование контакта Назначение контакта
VCC контакт питания 5 В
GND общий провод (земля)
CS SPI SLAVE select pin (Active low) (выбор ведомого)
SO SPI master input slave output lead
SI SPI master output slave input lead
SCLK контакт синхронизации SPI
INT контакт прерывания MCP2515

В данном проекте мы будем передавать данные, считываемые с датчика температуры и влажности DHT11 платой Arduino Nano, плате Arduino Uno с помощью CAN модуля MCP2515.

Необходимые компоненты

  1. Плата Arduino Uno (купить на AliExpress).
  2. Плата Arduino Nano (купить на AliExpress).
  3. Датчик температуры и влажности DHT11 (купить на AliExpress).
  4. ЖК дисплей 16х2 (купить на AliExpress).
  5. MCP2515 CAN Module (контроллер шины CAN MCP2515) – 2 шт. (купить на AliExpress).
  6. Потенциометр 10 кОм (купить на AliExpress).
  7. Макетная плата.
  8. Соединительные провода.

Схема проекта

Схема проекта для связи между двумя платами Arduino с помощью протокола CAN и модулей MCP2515 представлена на следующем рисунке.

Соединения на передающей стороне:

Компонент — контакт Arduino Nano
MPC2515 — VCC +5V
MPC2515 — GND GND
MPC2515 — CS D10 (SPI_SS)
MPC2515 — SO D12 (SPI_MISO)
MPC2515 — S I D11 (SPI_MOSI)
MPC2515­ — SCK D13 (SPI_SCK)
MPC2515 — INT D2
DHT11 — VCC +5V
DHT11 — GND GND
DHT11­ — OUT A0

Соединения на приемной стороне:

Компонент — контакт Arduino Uno
MPC2515 — VCC +5V
MPC2515 — GND GND
MPC2515 — CS 10 (SPI_SS)
MPC2515 — SO 12 (SPI_MISO)
MPC2515 — SI 11 (SPI_MOSI)
MPC2515 — SCK 13 (SPI_SCK)
MPC2515 — INT 2
LCD (ЖК дисплей) — VSS GND
LCD — VDD +5V
LCD — V0 к среднему контакту потенциометра 10 кОм
LCD — RS 3
LCD — RW GND
LCD — E 4
LCD — D4 5
LCD — D5 6
LCD — D6 7
LCD — D7 8
LCD — A +5V
LCD — K GND

Соединения между двумя CAN модулями MCP2515:

H – CAN High
L – CAN Low

MCP2515 (Arduino Nano) MCP2515 (Arduino UNO)
H H
L L

После сборки всей схемы на макетных платах у нас получилась следующая конструкция.

Объяснение программы для Arduino

Первым делом нам необходимо установить библиотеку для работы с протоколом CAN в Arduino IDE. Сначала скачайте ZIP файл библиотеки по следующей ссылке — Arduino CAN MCP2515 Library. Затем установите ее в Arduino IDE с помощью пункта меню Sketch -> Include Library -> Add .ZIP Library.

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

Инициализация CAN модуля MCP2515

Для установления соединения платы Arduino с модулем MCP2515 выполните следующую последовательность шагов. Но перед этим убедитесь в том, что указанная выше библиотека CAN MCP2515 установлена в вашу Arduino IDE.

Шаг 1. Установите номер контакта, к которому подключена линия CS интерфейса SPI (10 по умолчанию).

Шаг 2. Установите скорость передачи и частоту кварцевого генератора.

Доступные скорости передачи:
CAN_5KBPS, CAN_10KBPS, CAN_20KBPS, CAN_31K25BPS, CAN_33KBPS, CAN_40KBPS, CAN_50KBPS, CAN_80KBPS, CAN_83K3BPS, CAN_95KBPS, CAN_100KBPS, CAN_125KBPS, CAN_200KBPS, CAN_250KBPS, CAN_500KBPS, CAN_1000KBPS.

Доступные частоты кварцевого генератора:
MCP_20MHZ, MCP_16MHZ, MCP_8MHZ

Шаг 3. Установите режимы.

Объяснение программы для передающей части (Arduino Nano)

В передающей части к плате Arduino Nano подключен CAN модуль MCP2515 по интерфейсу SPI, а данные температуры и влажности, считываемые с датчика DHT11, передаются далее по CAN-шине.

Первым делом в программе подключим необходимые библиотеки: библиотеку SPI для использования интерфейса SPI, библиотеку MCP2515 для использования связи с помощью протокола CAN и библиотеку DHT для работы с датчиком DHT11. Ранее на нашем сайте мы уже рассматривали подключение датчика DHT11 к плате Arduino.

Дадим название контакту, к которому подключен датчик DHT11 – это контакт A0 платы Arduino Nano.

Также определим DHTTYPE как DHT11.

Определим переменную canMsg типа данных структура для хранения сообщений CAN формата.

Установим номер контакта, к которому подключена линия CS интерфейса SPI (10 по умолчанию).

Также создадим объект dht класса DHT с параметрами DHT pin и DHTTYPE.

В функции void setup():

Инициализируем связь по протоколу SPI.

Начнем считывание данных температуры и влажности с датчика DHT11.

Сбросим в исходное состояние (RESET) модуль MCP2515 с помощью следующей команды:

Установим для модуля MCP2515 скорость передачи 500 кбит/с и частоту кварцевого генератора 8 МГц.

Установим модуль MCP2525 в обычный режим (normal mode).

В функции void loop():

Считаем значения температуры и влажности с датчика DHT11 и сохраним их в переменных целого типа h и t.

Далее установим идентификатору (CAN ID) значение 0x036 (на ваш выбор), DLC (длина поля данных) присвоим значение 8 (8 байт), запишем значения температуры и влажности в поля данных data[0]  и data[1], в остальные поля данных запишем значения 0.

После всего этого передадим сообщение по CAN-шине с помощью команды:

После выполнения этой команды значения температуры и влажности передадутся в виде сообщения по CAN-шине.

Объяснение программы для приемной части (Arduino Uno)

В приемной части нашего проекта к плате Arduino Uno подключены модуль MCP2515 и ЖК дисплей 16х2. Здесь плата Arduino Uno принимает значения температуры и влажности по CAN шине и отображает их на экране ЖК дисплея 16х2.

Первым делом в программе подключим используемые библиотеки: библиотеку SPI для использования интерфейса SPI, библиотеку MCP2515 для использования связи с помощью протокола CAN и библиотеку LiquidCrsytal для работы с ЖК дисплеем 16х2.

Далее сообщим плате Arduino, к каким ее контактам подключен ЖК дисплей 16х2.

Определим переменную canMsg типа данных структура для хранения сообщений CAN формата.

Установим номер контакта, к которому подключена линия CS интерфейса SPI (10 по умолчанию).

В функции void setup ():

Установим ЖК дисплей в режим работы 16×2 и отобразим на его экране приветственное сообщение.

Инициализируем связь по протоколу SPI.

Сбросим в исходное состояние (RESET) модуль MCP2515 с помощью следующей команды:

Установим для модуля MCP2515 скорость передачи 500 кбит/с и частоту кварцевого генератора 8 МГц.

Установим модуль MCP2525 в обычный режим (normal mode).

В функции void loop():

Следующая команда (с использованием оператора условия If) используется для приема сообщения из CAN-шины.

Если записанное условие if выполняется, данные принимаются и сохраняются в переменной canMsg, поле data [0] этой переменной будет содержать значение влажности, а поле data [1] – значение температуры. Мы будем сохранять эти значения в переменных целого типа (integer) x и y.

После успешного приема значений температуры и влажности мы выводим их на экран ЖК дисплея.

Тестирование работы проекта

После того, как аппаратная часть проекта будет готова, загрузите коды программы в платы Arduino в передающей и приемной частях проекта. После этого при подаче питания на схемы вы должны увидеть, как значения температуры и влажности, считанные одной платой Arduino с датчика DHT11, передаются по CAN-шине другой плате Arduino, которая выводит эти принятые значения на экран ЖК дисплея. Мы для проверки правильности значений температуры использовали пульт от кондиционера, с помощью которого устанавливали температуру в комнате.

Исходный код программы (скетча)

Код программы для передающей части (Arduino Nano)

Код программы для приемной части (Arduino Uno)

Видео, демонстрирующее работу проекта

47 ответов к “Использование стандарта CAN в Arduino – полное руководство”

Добрый день. Все примеры, которые мне удалось посмотреть в сети, работают только с целыми числами, но если смотреть расшифровку данных с шины CAN с конкретного автомобиля, то можно увидеть что там присутствуют и числа float. Как это точно сделать, я не знаю, возможно у производителей электроники для автомобилей есть какие то свои проприетарные решения. Но, в любом случае, вы можете разбивать число типа float на два числа типа int, одно из которых будет представлять собой мантиссу числа float, а второе — его экспоненту, а на приеме из этих двух принятых чисел int конструировать уже исходное число float. Есть различные способы представления чисел float и их преобразования в числа int, я думаю вы эту информацию легко найдете в сети и выберете для себя приемлемый способ подобного преобразования

Не знаю как у вас, у меня данные принимаются с любым id
Есть код в котором прописано что по id 0x100 нужно выполнять то что прописано, включать или выключать выходы.
К примеру
canMsg.data[0] == EEPROM.read(0) {
digitalWrite(vihod1, HIGH);
}
canMsg.data[0] == 0x00{
digitalWrite(vihod1, LOW)
}

И не важно какой id, если есть данные в Кан шине кпримеру 0х10, выход1 будет активен

Посмотрите ниже комментарии, там есть пример кода как поставить для данного проекта фильтр по id

Добрый день у меня есть вопрос, у меня на машине была штатная магнитола она принимала сигнал парктроников с другой шины вроде lin, а при установки другой магн толы не передаються сигнала той шины и магнитола их не распознает а кан бус принимает сигналы только с ммс шины как зделать через ардуино чтобы считывал сигналы с lin шины и передовал на ммс шыну чтобы магнитола распозновала сигналы?

Добрый вечер. К сожалению, с lin шиной не работал, не могу по ней подсказать что то конкретное. Но если вы введете в поисковике «подключение lin шины к ардуино», то он вам выдаст достаточно много тематических ссылок по данному вопросу. К примеру, на гитхабе есть даже библиотека для работы с этой шиной — https://github.com/macchina/LIN. И в ней есть примеры, с помощью которых, я думаю, можно освоить работу с данной шиной.

Здравствуйте.
Нужна помощь или совет дельный.
Задача подключить селектор от BMW 3 (F30) к Arduino Uno R3 через CAN модуль, чтобы управлять АКПП от TOYOTA при помощи простого актуатора. И все это на фургоне Mercedes ))
Интересная задачка.
Вся сложность для меня в тех.информации приема-передачи селектора и АКПП,
чтоб понимать, что писать в скетче.
Заранее благодарен за любую полезную информацию.
Спасибо.

Добрый вечер. К сожалению у меня опыта таких проектов нет, но если у вас будет более конкретный вопрос по использованию CAN модуля и Ардуино, то могу попробовать помочь

Добрый день.

В данном примере если отправить CAN ID больше чем 2047(0х7FF) приемная сторона получает неверный CAN ID. Т.е. пример использует 11-битный идентификатор, однако CAN может использовать Extended (расширенный) ID: 29bit. Как надо изменить проект, чтобы это заработало?
Спасибо

Добрый вечер, попытался изучить данный вопрос данный вопрос и вот что я обнаружил. Смотрите описание библиотеки Arduino CAN MCP2515. В тексте этого описания найдите строку frame.can_id = 0x12345678 | CAN_EFF_FLAG; То есть, насколько я понял, чтобы задействовать Extended (расширенный) ID с помощью данной библиотеки его необходимо сложить операцией ИЛИ с флагом CAN_EFF_FLAG. Значение этого флага вы можете найти в файле can.h данной библиотеки. У меня сейчас нет доступа к оборудованию чтобы проверить это на практике, но если у вас это получится сделать, просьба отписаться нам здесь о своих успехах в данном направлении

Добрый день.
Спасибо за правильное направление.
Для использования Extended ID (29bit) надо в отправляющем скетче задавать ID как:
frame.can_id = 0x12345678 | CAN_EFF_FLAG;
при этом на принимающей стороне из frame.can_id надо вычесть 0x80000000, либо применить операцию И(&): frame.can_id & 0x7FFFFFFF для получения правильного ID. Это актуально при отправке с arduino, на реальном железе пока не пробовал.

Доброе утро. Да, спасибо и вам за уточняющий комментарий. Надеюсь, на реальном железе у вас все получится

Я использую другую библиотеку: https://github.com/Longan-Labs/Arduino_CAN_BUS_MCP2515 (частично подправленную для уменьшения размера и удобства своего кода).
Лучшей из протестированных считаю эту: https://github.com/Seeed-Studio/Seeed_Arduino_CAN
Формат: CAN.sendMsgBuf(0x00, 0, 8, stmp); где: ID это номер пакета, 0-1 это 11бит или 29bit, 8 -это размер передаваемых данных, smtp — массив данных.
При приёме (Read), будете получать то, что отправили.
Best regards.

Да, спасибо за полезный комментарий. Я думаю те, кто захочет изучить описанные в статье процессы более подробно, попробуют рекомендованные вами библиотеки

Добрый день! Давайте попробуем разобраться со следующей штукой: читаем по can шине пакет, из него выделяем данные, (к примеру 2 байта) и перекладываем их в другой пакет и отправляем в can шину. Собственно приемопередатчик должен получиться. Возможно такое?

Доброе утро. Ну так модуль MCP2515, использованный в данном проекте, фактически является приемопередатчиком, работающим по can шине. Поэтому естественно что с его помощью можно как принимать, так и передавать данные. А на основе двух приведенных в данной статье программ можно сделать одну, в которой будет осуществляться передача и прием данных по шине CAN. А то, что вы предалагаете, это, фактически ретранслятор, только нужен ли он в CAN шине? Дальность передачи по ней достаточно внушительна по сравнению с протоколами SPI и I2C, а там, где дальность нужна еще больше, используются уже другие протоколы связи.

Да, нужен, в автомобильной CAN шине. Если есть возмоность, покажите пример как это реализовать

К сожалению, пока не могу потому что нахожусь в отпуске

Здравствуйте, CAN шина отличается тем, что к ней мы можем подключить большое количество устройств. Как нам подключить, собственно 3+ устройств к одной шине, чтобы они могли общаться между собой?

Добрый вечер. А в чем, собственно, состоит проблема? Физически к ней не можете столько устройств подключить или идентификаторы не получается назначить?

Здравствуйте! Не подскажите, как переставить на другие пины so,si,sclk?

Добрый вечер. К сожалению в данном случае никак нельзя переставить потому что у платы Ардуино для связи по протоколу SPI используются только эти контакты

В приемной части не увидел где вы читаете конкретный пакет, в нашем случае id 0x036. В реальной can шине данные передаются с разными id в таком случае фильтра по id не будет? Будут читаться нулевой и первый байт каждого пакета?

Да, в представленном примере фильтра по id нет поскольку мы все время передаем пакет с одним и тем же id. А какие байты пакета считывать мы указываем в явном виде — посмотрите строки 29 и 30 для приемной части

К сожалению, пока не могу ответить на ваш вопрос. Может быть немного позже попробую разобраться с этим, если вам не срочно

void loop() {

if (mcp2515.readMessage(&canMsg) == MCP2515::ERROR_OK)
{
if (canMsg.can_id==0x329)
{
int x = canMsg.data[1];
int y = canMsg.data[5];

Сам нашел ответ на свой вопрос.

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

Здравствуйте. А можете сказать как получать и отправлять пакеты с расширенным объемом данных? У меня задача подружить ридер с устройством которое передает сообщения с длинной блока данных — 37 байт.

Добрый вечер. К сожалению, точного ответа на ваш вопрос я не знаю. А если просто увеличить длину поля данных (переменная canMsg.can_dlc в программе) не получается?

здравствуйте! подскажите как подключить ручку газа на ардуино уно чтобы можно было управлять мотором на другом конце также через каншину

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

здравствуйте, подскажите что надо изменить в коде, чтоб id отправлял 29 бит Extended ?

Добрый вечер. Не совсем понял ваш вопрос, к сожалению. У вас не получается изменить длину поля данных до 29 бит или вам нужно в качестве can_id передать значение равное 29?

Здраствуйте не могли бы вы подсказать как соединить 3 ардуины в сеть на примере скетчей 2 передатчика 1 приёмник

Добрый день. Лично я так делать не пробовал, но думаю для каждой передающей части нужно установить свой CAN адрес (в программе это строка canMsg.can_id = 0x036), а в программе при приеме данных проверять значение этого адреса чтобы определить с какой передающей части пришло сообщение.

Добрый вечер.С наступающим Праздником Победы! Схема заработала после того как поставил перемычки на MCP2515.

Добрый вечер. Спасибо за поздравления, и вас тоже с наступающим. Я рад что у вас получилось. Спасибо за полезный комментарий, может быть, он будет полезен другим посетителям нашего сайта, которые будут сталкиваться с такой же проблемой как у вас. Все таки в современной электронике так много нюансов

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

Доброе утро, честно говоря, даже не знаю. А вы уверены в том что отправляете это сообщение однократно? При смене содержания/длины сообщения проблема не устраняется?

У меня такая же ситуация. Сообщение по прерыванию должно отправляться каждые 1000мс. В COM-порт оно дублируется все правильно и данные соответствуют действительности, а в шину отправляется первоначальные данные и с максимальной частотой. А Вы решение не нашли?

Нет, к сожалению пока не нашел. Сейчас нахожусь в отпуске, поэтому пока не могу работать над сайтом

Заводите переменную Uint32_t timer.
if ((millis() — timer) >= 100)
{
mcp2515.sendMessage(&canMsg);
timer = millis();
}

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *