Pull to refresh

Rosserial & STM32

Reading time4 min
Views12K
Робототехническая операционная система ROS является довольно мощной платформой для создания робототехнических систем, которая включает все необходимое для разработки своих проектов от простейших программных компонентов, называемых “узлами”, и протокола обмена данными до среды симулирования реальной робототехнической платформы Gazebo. В основном ROS используется в связке с такими микроконтроллерами на платформе Arduino. Интернет переполнен всевозможными туториалами о связке ROS и Arduino.

В данный момент не существует информации об использовании робототехнической операционной системы ROS в связке с микроконтроллером STM32. Интернет переполнен только вопросами.



Начнем работу


Для работы с STM32 нам понадобится STM32CubeMX и SystemworkbenchforSTM32. Информации об их установке в сети предостаточно, не будем на этом останавливаться.

Для конфигурации контроллера зайдем в STM32CubeMX

Создадим новый проект.



Выберем микроконтроллер, у меня STM32f103c8t6.



В периферии указываем, что у на подключен внешний кварцевый резонатор, у нас их 2



Настраиваем выводы, через которые можно включать отладку контроллера, (забегая вперед, если проект будет на С++, отладка может не работать)



Настроим 13 вывод порта С, к нему подключен встроенный светодиод.



Настроим выводы UART.



Перейдем в Сlock_configuration и выполним настройки как на картинке.



Перейдем к более детальной настройке периферии


UART

Настройка скорости обмена данных.



Настройка DMA.





Настройка прерывания, нужно указать глобальное прерывание по UART



Настройка GPIO




Настройка сборки проекта




Ждем пока соберется



Открываем проект,



Создание проекта под System Workbench For STM32


Открыв данный проект в SW4STM32, дописав некоторое управление периферией, собрав его, и прошив контроллер, я не получил никакого результата.

Поэтому создаем новый проект по следующей инструкции, и переносим конфигурацию полученную STM32CubeMX.

Создание проекта под System Workbench For STM32


1) Нажмите File > New > C Project

2) C Project
1) Введите название проекта
2) Выберите тип проекта: Executable > Ac6 STM32 MCU Project
3) Выберите Toolchains: Ac6 STM32 MCU GCC
4) Нажмите «Далее»



3) Выбираем микроконтроллер
1) Нажмите «Create a new custom board»
1) Сохранить Определение новой платы
2) Введите имя новой платы: STM32F103
3) Выберите чип платы: STM32F1
4) Выберите МСU: STM32F103RCTx
5) Нажмите «ОК».
2) Выберите плату, которое вы только что создали!
1) Выбрать серию: STM32F1
2) Выберите плату: STM32F103
3) Нажмите «Далее»



4) Подключаем библиотеки HAL



5) Нажмите «Finish»

Добавление файлов


Копируем содержимое файлов src и inc, созданных кубом в наши файлы, также копируем STM32F103C8Tx_FLASH.ld



Для проверки работоспособности самой STM32 и кода в цикл while прописываем следующие строки

      HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
      HAL_Delay(100);

Тут мы просто моргаем светодиодом.

При сборке могут возникнуть проблемы в файле stm32f1xx_hal_msp.c

Ошибку связанную с функцией void HAL_MspInit(void) исправляем следующим образом.
Открываем папку с библиотекой HAL_Driver, идем /src открываем файл stm32f1xx_hal_msp_template.c и закомментируем эту же функцию:



Собираем заново (должно собраться без ошибок)

Забыл упомянуть для прошивки контроллера понадобится утилита st-flash.

$ sudo apt-get install cmake 
$ sudo apt-get install libusb-1.0.0 
$ git clone github.com/texane/stlink.git 
$ cd stlink 
$ make release 
$ cd build/Release; sudo make install 
$ sudo ldconfig 

Использование ST link

Проверка обнаружения ST link:

$ st-info —probe 

В ответ мы должны увидеть что-то вроде:

Found 1 stlink programmers 
serial: 563f7206513f52504832153f 
openocd: "\x56\x3f\x72\x06\x51\x3f\x52\x50\x48\x32\x15\x3f" 
flash: 262144 (pagesize: 2048) 
sram: 65536 
chipid: 0x0414 
descr: F1 High-density device 

Для прошивки контроллера переходим в папку нашего проекта и и прошиваем контроллер через следующий команду:

cd workspace/ros_stm32_2/
st-flash write Debug/ros_stm32_2.bin 0x8000000

Проверили. Все работает. Двигаемся дальше.

Так как библиотеки ROS написаны на C++, переводим наш проект в проект С++, и изменяем формат файлов main.c, stm32f1xx_hal_msp.c, stm32f1xx_it.c в .cpp

Клонируем мой репозиторий с библиотеками рос и нужными файлами для работы rosserial на STM32.

git clone https://gitlab.com/ivliev123/ros_lib

Вставляем склонированную папку в проект





Перейдем в настройки проект (Properties), первым делом подключаем библиотеку, переходим…







Изменяем компоновщик





Выполняем оптимизацию





Ну теперь внесем некие изменения в main.cpp, так как он почти пустой, первое что делаем подключаем библиотеку ROS, и библиотеки для взаимодействия с топиками ROS, а точней с типами данных этих топиков.

#include <ros.h>
#include <std_msgs/String.h>
#include <std_msgs/UInt16.h>

Создадим узел, топик публикующий данный и принимающий

void led_cb( const std_msgs::UInt16& cmd_msg){
          HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
}

ros::NodeHandle nh;
std_msgs::String str_msg;
ros::Publisher chatter("chatter", &str_msg);

ros::Subscriber<std_msgs::UInt16> sub("led", led_cb);

Инициализируем узел и топики в main.

        nh.initNode();
        nh.advertise(chatter);
        nh.subscribe(sub);

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

const char * hello = "Hello World!!";

int chatter_interval = 1000.0 / 2;
int chatter_last = HAL_GetTick();

В цикле while у нас будет следующее. Будем публиковать нашу фразу через определенное время.

        if (nh.connected())
        {
            if(HAL_GetTick() - chatter_last > chatter_interval)
            {
                str_msg.data = hello;
                chatter.publish(&str_msg);
                chatter_last = HAL_GetTick();
            }
        }

        nh.spinOnce();

Собираем проект.

Могут появится следующие ошибки:







Собираем заново и прошиваем.

Теперь непосредственно само взаимодействие с ROS.
В одном терминале запускаем ROS.

roscore

В следующем запускаем узел.

rosrun rosserial_python serial_node.py /dev/ttyUSB0

Получаем следующее

[INFO] [1551788593.109252]: ROS Serial Python Node
[INFO] [1551788593.124198]: Connecting to /dev/ttyUSB0 at 57600 baud
[INFO] [1551788595.233498]: Requesting topics...
[INFO] [1551788595.258554]: Note: publish buffer size is 2048 bytes
[INFO] [1551788595.259532]: Setup publisher on chatter [std_msgs/String]
[INFO] [1551788595.275572]: Note: subscribe buffer size is 2048 bytes
[INFO] [1551788595.276682]: Setup subscriber on led [std_msgs/UInt16]

Далее в новом окне терминала, смотрим, топики

rostopic list 

Получаем следующие топики:

/chatter
/diagnostics
/led
/rosout
/rosout_agg

В топик chatter контроллер публикует фразу.

Можем его послушать через команду

rostopic echo /chatter 



Теперь отправим данные в топик led.

rostopic pub /led std_msgs/UInt16 "data: 0" 

И у нас должно изменится состояние светодиода.
Tags:
Hubs:
If this publication inspired you and you want to support the author, do not hesitate to click on the button
+27
Comments17

Articles