ROSとNucleoで通信してみる ~rosserial_stm32の導入~

 

みなさんこんにちは.まんぼーです. 

 

この記事はWMMC Advent Calendar 2020の25日目の記事です.

昨日はJackie君の今年の振り返りとAnalog Discovery2についてのお話でした。

ROSとNucleoで通信してみる ~rosserial_stm32の導入~
jackie39.hatenablog.com

Jackie君は僕の同期ですが、M1になってから1回も会ってない気がします。コロナめ…

AD2、秋月で売ってるのは見たことがありますが高くて手が出せません。

でも、お家でオシロやロジアナ・ファンクションジェネレータが欲しくなったらこれ1つ買っておけばよさそうですよね。

 

さて、今日はクリスマスですが、皆さんはどうお過ごしでしょうか??

WMMCのクリスマスに出てくる記事やばそう、とか思った皆さん。

僕がクリスマス枠をとってしまいごめんなさい!!!

代わりに今までのクリスマスで面白かった記事でも貼っておくのでユルシテ


judge.hatenadiary.com

titech-ssr.blog.jp

 

言うのも悲しくなってきますが、今日(というかもう昨日)の夕方はバイトに行き、この記事が書き終わったらロボットのプログラムと睨めっこしたいと思います。つまり、この記事が投下された瞬間から

製 の 6 時 間 開 幕  

です。はぁ。

 

さて、今回はROSのシリアル通信機能であるrosserialを使ってSTM32と通信してみる、というのをやってみます。目次はこちら。

Advent Calendarから来た人はROSを知らない人もいると思うので軽く説明すると、ROSとはロボットのソフトウェアプラットフォームです。ロボットを開発する際に必要なツールやライブラリが豊富に存在し、ロボットの開発が容易にできるようになっています。

 

rosserialとは、シリアル通信を用いてROSとマイコン間の通信を実現するためのパッケージで、強い人がそれをSTM32マイコンに拡張してくれたrosserial_stm32というパッケージを使います。(やっている人はちらほらいるのですが、初見だと詰まる箇所があったのでまとめておこうと思いました)

 

動作確認済の環境

・Nucleo STM32F401RE/STM32F446RE

・Ubuntu16.04(kinetic) / Ubuntu18.04(melodic)

・STM32CubeIDE(ver1.4.0)

CubeIDEのインストール・プロジェクト作成

まず、UbuntuにSTM32CubeIDEをインストールします。

https://www.st.com/ja/development-tools/stm32cubeide.html

このサイトの

を入手します。インストーラーのあるディレクトリまで移動し、↓のコマンドでインストールします。

sh st-stm32cubeide_1.4.0_7511_20200720_0928_amd64.deb_bundle.sh 

※バージョンによって違います。 

 

terminal上で利用規約を読まされますが、ctrl+Cで飛ばせます。

Enterをずっと押しているとNo/Yesを選択するときにNoが選択され、このコマンドを知らなかったときはひたすら良い感じのタイミングでEnterを離す…みたいなことをやってました。アホ。

 

 

ちなみに投稿時点で最新バージョンは1.5.0ですが、私のPCではバージョン1.5.0だとうまく動作してくれませんでした。プロジェクトをインポートしようとするとクラッシュするみたいな。解決方法探すのもだるかったので1.4.0を入れました。

 

インストールが終わったらSTM32CubeIDEを起動し、ボードを選択します。

そしてプロジェクトを作成します。

Targeted LanguageはC++でないといけないので注意。

f:id:manboo17:20201222233257p:plain

 

ピン設定ファイル(.ioc)を以下のように設定します。

いじる箇所はUSART2,TIM2です。

①USART2の設定

・Parameter SettingsでBaudRateを57600に設定(最後に記述するコマンドでBaudRateが統一されていればOK)

・NVIC SettingsのUSART Global Interruptをチェック

・DMA SettingsにてUSART2_RXをDMA1 Stream 5に紐付け、 DMA Request Settings のModeを Circularにする

・USART2_TXをDMA1 Stream 6に紐付け

f:id:manboo17:20201223000639p:plain

②TIM2の設定

Clock SourceをInternal Clockに設定

f:id:manboo17:20201223000748p:plain

設定が終わったらコードを生成して一旦閉じます。

rosserial、rosserial_stm32の準備準備

次にrosserialのパッケージをインストールします。

sudo apt-get install ros-kinetic-rosserial

 続いてワークスペースを作り、src内に移動します。

mkdir ~/catkin_ws/src
cd ~/catkin_ws/src

 開発者様のgitからクローンしてきて、ビルドします。

git clone https://github.com/yoneken/rosserial_stm32.git
catkin build
cd ~/catkin_ws
source devel/setup.bash

 

続いてterminalで生成したSTM32コードのディレクトリに移動します。

ワークスペースの場所によってコマンドが変わると思います。

Srcがあるディレクトリまで移動してください。

cd  ~/ STM32CubeIDE/workspace_1.4.0/rosserial_test/Core

Srcがあるディレクトリまで移動してください。

 rosrun rosserial_stm32 make_libraries.py .

を実行します。するとtopic通信に必要なメッセージライブラリたちがインポートされます。

 

次に、mainpp.cppとmainpp.hを追加します。

・catkin_ws/src/rosserial_stm32/src/roslib/chatter/Srcの中のmainpp.cppをIDEプロジェクト内のCore/Srcに

・catkin_ws/src/rosserial_stm32/src/roslib/chatter/Incの中のmainpp.hをIDEプロジェクトのCore/Incに

コピペします。

これらのコピーが終わったらCubeIDEを開き、再度STM32のプロジェクトをインポートし直します。

 

・main.cを書き加えます。

main.cのwhileの手前でsetup();と記述

main.cのwhile内でloop();と記述

 

・STM32F4xxを使用する場合、STM32Harware.h内の

#define STM32F3xxをSTM32F4xxに書き換えます。

f:id:manboo17:20201223000038p:plain

 

ここまでできたらプログラムをコンパイル・書き込み、Nucleo側は準備完了です。

terminalを開き、1つめのターミナル上で

roscore 

2つめのターミナル上で 

sudo chmod o+wr /dev/ttyACM0
rosrun rosserial_python serial_node.py _port:=/dev/ttyACM0 _baud:=57600

3つめのターミナル上で 

rostopic echo /chatter 

 うまくいけば↓の右のターミナルのようにtopicが表示されます。

無事、Hello World!が表示されました!

f:id:manboo17:20201223213514p:plain

terminalの番号は左上、左下、右の順に1,2,3

 

最後に、mainpp.cppとやらに書かれているコードを記載しておきます(自分が書いたやつじゃないけど)。基本的にはココにrosのコードが書かれているみたいですね。私はもう色々いじっちゃいましたけど

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

ros::NodeHandle nh;

std_msgs::String str_msg;
ros::Publisher chatter("chatter", &str_msg);
char hello[] = "Hello world!";

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart){
nh.getHardware()->flush();
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){
nh.getHardware()->reset_rbuf();
}

void setup(void)
{
nh.initNode();
nh.advertise(chatter);
}

void loop(void)
{
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_3);

str_msg.data = hello;
chatter.publish(&str_msg);
nh.spinOnce();

HAL_Delay(1000);
}

コードを見るとわかる(わかる人には)と思いますが、 ほぼROSでのコーディングと同じ勝手で記述されています。とても便利ですね。

 

おわりに

いかがでしたでしょうか。書ききってから思ったのですが、これ…マウスのカレンダー向きじゃないな。まぁいっか。

 

今日でWMMC Advent Calendar 2020は終了となります。

私も一通り記事に目を通してきましたが、記事の更新で生存を確認できた人がいたり、まだ見たことのない1年生も参加してくれていました。コロナで新歓が潰れ、今年は誰も入らないんじゃないかってみんなで騒いでましたが、無事1年生が入ってくれたようで安心しました。今後の彼らの活躍に期待です。

 

私はAdvent Calendarに2回投稿しましたが、1回めの記事を投稿した5日目から20日、あっという間すぎてビビってます。本当はもっとロボットっぽいことを記事にしたかったのですが、もう少し時間と心に余裕があるとき(あれば)に改めて書きたいと思います。

 

企画してくれたJG君、参加してくれたサークルメンバー、読んでくださった皆さん、ありがとうございました。よいクリスマス・よいお年を!