VBCores Документация
СайтGitHub
  • VBCores
  • Hardware
    • VBCore VB32G4
    • VB STM32 программатор
    • BLDC драйвер 30A
    • DC драйвер 15A
    • Stepper драйвер 10A
    • CAN-FD - Raspberry PI
      • Настройка CAN на RPI
      • Часто возникаемые ошибки при работе с CAN/CAN FD
      • Работа с CAN FD через Python
    • Power board 30A
    • SBus-HID
    • DC-DC преобразователь
    • Ethernet - CAN-FD
    • USB-HUB
    • IMU BNO055
    • IMU BHI360
    • Т-Энкодер
  • Настройка ПО
    • Arduino IDE
      • Подготовка модуля VBCore
      • Установка среды программирования на Windows
      • Установка среды программирования на Ubuntu
        • Возможные ошибки в Ubuntu при работе с Arduino
      • Выбор платы в Arduino IDE
      • Установка базовой библиотеки
      • Структура ПО для Arduino
      • Примеры
        • Работа с CAN и CAN FD на Arduino
        • Работа с I2C
        • I2C detect
        • Датчик BNO055 / I2C
        • Датчик AS5047P / SPI
        • Датчик AS5600 / I2C
        • Работа с бесколлекторными двигателями
          • Simple FOC. Управление скоростью. Нахождение количества пар полюсов.
          • Simple FOC. Управление моментом
          • Чтение данных с датчика тока
        • Работа с коллекторным двигателем
          • Вращение DC мотором
          • Чтение угла по энкодеру. Управление DC мотором по углу
          • Чтение скорости вращения мотора по энкодеру
        • Работа с шаговым двигателем
          • Вращение шагового двигателя.
          • Контроль двигателя по интерфейсу SPI
    • STM32 CUBE IDE
      • Типовые настройки
      • Подсказки начинающим
        • Cube IDE для начинающих
        • Clock configuration
        • Таймеры - прерывания
        • Таймеры - ШИМ
        • Отладка программ
        • Коммуникации - FDCAN
        • Управление DC-мотором
        • Backup программы
  • Cyphal CAN
    • Cyphal CAN
    • PyCyphal
    • Yakut
    • Cyphal Arduino
      • Отправка и получение сообщений по cyphal
  • Работа с ROS
    • Установка Ubuntu, ROS и Arduino
    • ROS_LIB
    • Примеры
      • Publisher. Hello World!
      • Publisher with Subscriber
      • Rotation by DC motor
  • Работа с научным ПО
    • TCP Server
    • LabView
    • Matlab
  • Инструкции
    • Стенд управления двигателями
    • Переделка датчика мотор-колеса
    • Стенд мотор-колеса
    • iPower Motor
    • AS5047p OEM
  • Практические занятия
    • Коллекторный двигатель
      • Устройство коллекторного двигателя
  • RPI Display
Powered by GitBook
On this page
  1. Hardware
  2. CAN-FD - Raspberry PI

Работа с CAN FD через Python

PreviousЧасто возникаемые ошибки при работе с CAN/CAN FDNextPower board 30A

Last updated 1 year ago

В данном разделе мы рассмотрим пример кода программ для отправки и получения сообщения через CAN FD, написанных на языке программирования Python. Для работы с CAN у Python есть отдельная библиотека python-can, которая устанавливается с помощью pip3:

$ pip3 install python-can

Импортируем три библиотеки:

import can
import struct
import time

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

Далее создадим управляющую can-ом структуру, назовем ее can0 и сообщение, которое будем отправлять - число типа float, например 2.5 в байтах это 0х00002040:

can0 = can.interface.Bus(channel = 'can0', bustype = 'socketcan', fd=True)
msg = 2.5 # 00 00 20 40

можно найти очень удобный конвертер, который легко переведет float в hex и обратно, самое главное не забыть поставить галочку рядом с Swap to use big-endian

Дальше в бесконечном цикле формируем массив байтов, используя функцию pack модуля struct, переводим его в тип сообщения, понятного для CAN и отправляем это сообщение. В качестве ID укажем 101, в hex это 0х065. По аналогии с программой, написанной на ардуино, в конце добавим задержку на все оставшееся время до 1 милисекунды.

while(1):
     t = time.time()
     data = bytearray(struct.pack("f", msg))
     msg_to_send = can.Message(arbitration_id=0x065, data = data)
     can0.send(msg_to_send)
     time.sleep(0.001 - (time.time()-t)) #время работы тела цикла - 1 мс

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

import can
import struct
import time


can0 = can.interface.Bus(channel = 'can0', bustype = 'socketcan', fd=True)
msg = 2.5
while(1):
     t = time.time()
     data = bytearray(struct.pack("f", msg))
     msg_to_send = can.Message(arbitration_id=0x065, data = data)
     can0.send(msg_to_send)
     time.sleep(0.001 - (time.time()-t)) # время работы тела цикла - 1 мс

Чтобы убедиться в корректной работе, в первом окне запустите программу (у нас она называется can_send.py)

python3 can_send.py

В соседнем терминале воспользуйтесь утилитой candump, вы должны увидеть пакет из 4 байтов 00 00 20 40

Теперь напишем программу для получения сообщений. Подключаем все те же модули, создаем управлющую can-ом структуру. В бесконечном цикле получаем сообщение и если его ID = 101 (см. пример выше), распаковываем пакет и печатаем полученные данные.

import can
import struct
import time


can0 = can.interface.Bus(channel = 'can0', bustype = 'socketcan', fd=True)
while(1):
     t = time.time()
     msg = can0.recv()
     if msg.arbitration_id == 101:
          data = struct.unpack('f', msg.data)
          print(data)
     time.sleep(0.002 - (time.time()-t)) # время работы тела цикла - 2 мс

Эту программу назовем can_recv и запустим ее в терминале. А в соседнем запустим программу, которая отправляет число 2.5, написанную ранее.

import can
import struct
import time


can0 = can.interface.Bus(channel = 'can0', bustype = 'socketcan', fd=True)
while(1):
     t = time.time()
     msg = can0.recv()
     if msg.arbitration_id == 101:
          data = struct.unpack('f', msg.data)
          print(data[0]) # первый элемент кортежа
     time.sleep(0.002 - (time.time()-t)) # время работы тела цикла - 2 мс

И теперь мы видим то число, которое и отправляем.

В данном разделе мы рассмотрели примеры программ для передачи и получения сообщений по CAN FD. Для обычного CAN в коде поменяется только одна строчка - создание управляющей can-ом структуры. Вместо

 can0 = can.interface.Bus(channel = 'can0', bustype = 'socketcan', fd=True)

необходимо написать

can0 = can.interface.Bus(channel = 'can0', bustype = 'socketcan')

Как видим мы получили немного не то, что ожидали (а ожидали мы увидеть просто число 2.5). Дело в том, что результатом struct.unpack() является кортеж, даже если он содержит ровно один элемент. Об этом подробнее можно прочитать в . Давайте немного скорректируем наш код:

документации
документации
По ссылке