[Из песочницы] Rosserial & STM32
Робототехническая операционная система 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
#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();
Собираем проект.
Могут появится следующие ошибки:
Собираем заново и прошиваем.
Теперь непосредственно само взаимодействие с 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"
И у нас должно изменится состояние светодиода.