[Из песочницы] Rosserial & STM32

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

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

r3xo-ix7liahiwhpqfbrcqncg9c.png

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


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

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

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

vzj9psilnxbv70jt76mfjd2sqf4.png

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

er1edan5rp-bs93zy8pilw-od-y.png

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

sydbacocbufrmk9l22wle_hvpuy.png

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

tc3s_aixqy6w1nkdkozxvwclwii.png

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

owne4_udwfi9iih_vdu1bp0iarg.png

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

nmyvjsjhwx6dgrzfe-xjdwkzpq4.png

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

gmrmc_agfm2tyflepfoa0y0g56o.png

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


UART

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

dr40xgaz113_lo3rtadkfrkwnmg.png

Настройка DMA.

spk2ev7ycm_vl_479vnmiauxhqc.png

5pbjperakd3brrhxunktphz7ehu.png

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

ygrvgcoshvrwetba3nfgeo76rca.png

Настройка GPIO


i2cheyaelog_qpsrtwoclx5ig9k.png

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


zwlj_i4e7f0phoetsvdfbezigys.png

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

hywrz0g0d9hu0rqokae4lpihrhi.png

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

x8jliev2ccwcuf0wj9-tqvgkdmi.png

Создание проекта под 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) Нажмите «Далее»

pllledbfjtuwsaqwlj2vb2ndun8.png

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

6jm-gc_rykla5chzbymmfw-vxem.png

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

ky-zboy5nsakqwym1wgggs9mbqk.png

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

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


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

yuiwkyljb6jmjbrgywjc4axj8v0.png

Для проверки работоспособности самой 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 и закомментируем эту же функцию:

jbrq5wpklb-ztmqzuklqepwgh5g.png

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

Забыл упомянуть для прошивки контроллера понадобится утилита 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


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

c5a9yx2j6uf7wevljunc0bks0og.png

3_4hjhqbl-psljdqsrlikkqvsmy.png

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

usdp6l8xeq7qk5qvxu2fnbcqhdu.png

zxn7u_v5m9yvc2oupzjmy0a93we.png

cduvcfrjdw-xxniumtmlzbrxpdm.png

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

ppuxe_icwxsytenafdelbhzewzq.png

a4awt9_8ztkfqqjrusjrvcq0mfy.png

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

52dkvkhaq9_ql7fqbqxodty5mrw.png

odji_-8zr16qykp3cafrpy4a304.png

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

#include 
#include 
#include 


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

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 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();


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

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

_eimmxwleimawe2wtzilcvhgwe4.png

yywnfpvkeqjycws0cvtiqo6lulo.png

k0tjmm6aap31tbezwmuqoddtkq4.png

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

Теперь непосредственно само взаимодействие с 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 


goovfriahknpo0ep99v9h7ycqn4.png

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

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


И у нас должно изменится состояние светодиода.

© Habrahabr.ru