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のクリスマスに出てくる記事やばそう、とか思った皆さん。
僕がクリスマス枠をとってしまいごめんなさい!!!
代わりに今までのクリスマスで面白かった記事でも貼っておくのでユルシテ
言うのも悲しくなってきますが、今日(というかもう昨日)の夕方はバイトに行き、この記事が書き終わったらロボットのプログラムと睨めっこしたいと思います。つまり、この記事が投下された瞬間から
製 の 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
このサイトの
STM32CubeIDE-DEB | STM32CubeIDE Debian Linux Installer |
を入手します。インストーラーのあるディレクトリまで移動し、↓のコマンドでインストールします。
※バージョンによって違います。
terminal上で利用規約を読まされますが、ctrl+Cで飛ばせます。
Enterをずっと押しているとNo/Yesを選択するときにNoが選択され、このコマンドを知らなかったときはひたすら良い感じのタイミングでEnterを離す…みたいなことをやってました。アホ。
規約読みながらEnterを適切なタイミングで離さないといけないクソゲーやってる pic.twitter.com/xWnCwPLgDE
— まんぼー (@was3to4) 2020年11月3日
ちなみに投稿時点で最新バージョンは1.5.0ですが、私のPCではバージョン1.5.0だとうまく動作してくれませんでした。プロジェクトをインポートしようとするとクラッシュするみたいな。解決方法探すのもだるかったので1.4.0を入れました。
インストールが終わったらSTM32CubeIDEを起動し、ボードを選択します。
そしてプロジェクトを作成します。
Targeted LanguageはC++でないといけないので注意。
ピン設定ファイル(.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に紐付け
②TIM2の設定
Clock SourceをInternal Clockに設定
設定が終わったらコードを生成して一旦閉じます。
rosserial、rosserial_stm32の準備準備
次にrosserialのパッケージをインストールします。
続いてワークスペースを作り、src内に移動します。
開発者様のgitからクローンしてきて、ビルドします。
続いてterminalで生成したSTM32コードのディレクトリに移動します。
ワークスペースの場所によってコマンドが変わると思います。
Srcがあるディレクトリまで移動してください。
Srcがあるディレクトリまで移動してください。
を実行します。すると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に書き換えます。
ここまでできたらプログラムをコンパイル・書き込み、Nucleo側は準備完了です。
terminalを開き、1つめのターミナル上で
2つめのターミナル上で
3つめのターミナル上で
うまくいけば↓の右のターミナルのようにtopicが表示されます。
無事、Hello World!が表示されました!
最後に、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君、参加してくれたサークルメンバー、読んでくださった皆さん、ありがとうございました。よいクリスマス・よいお年を!