Edited at

ROS講座96 カスタムmbedでrosserial+platformioを使う


環境

この記事は以下の環境で動いています。

項目

CPU
Core i5-8250U

Ubuntu
16.04

ROS
Kinetic

PlatformIO
3.6.0

インストールについてはROS講座02 インストールを参照してください。

またこの記事のプログラムはgithubにアップロードされています。ROS講座11 gitリポジトリを参照してください。


概要

ロボットの下回りの特にアクチュエーターは自作をする必要があるのが現状です。今回はmbedを用います。Arduinoほどはメジャーではありませんが、Arduinoで使われるAVRよりもIOなどの性能が高いARMベースのコアを使ったマイコンプラットフォームです。この記事では


  • カスタムmbedボードの作り方

  • mbed用のソースコードのオフラインでのビルド

  • カスタムmbedに書き込む方法

  • mbedでrosserialを使う方法

を説明します。


カスタムmbedボードの作り方

青mbedが一番メジャーですが、ロボット用としては自分で基板を起こしたくなります。そんな時はICだけを買って自分で基板を作りましょう。

接続
ピン番号

3.3V
10, 12, 19, 28, 42, 54, 71, 84, 96

GND
11, 15, 31, 41, 55, 72, 83, 97

水晶
22, 23

リセットIC
17

書き込みにはシリアル通信を使います。USBシリアル変換を使うとよいです。RTSとDTRはリセット&bootモードに入る設定を行うものです。

USBシリアル
LPC1768

TxD
99

RxD
98

RTS
53

DTR
17


mbed用のソースコードをオフラインでのビルド

platformioを用いてビルドをすることができます。platformio boards|grep lpc1768でplatformioでlpc1768が対応推しているか見れます。(結果はlpc1768 LPC1768 96MHz 512KB 64KB NXP mbed LPC1768ともう一行出る)


初期設定

roscd hard_lecture/platformio/mbed01 #プロジェクトのディレクトリに移動

platformio init -b lpc1768

ソースコードを編集します。これのプログラムはオンラインのコンパイラと同様に書けます。


hard_lecture/platformio/mbed01/src/main.cpp

#include "mbed.h"

#define SRSG_LED0 P0_16
#define SRSG_TX0 P0_2
#define SRSG_RX0 P0_3

DigitalOut l0(SRSG_LED0);
Serial pc(SRSG_TX0,SRSG_RX0);

int main() {
pc.baud(1000000);
while (true) {
l0 = !l0;
wait(500);
pc.printf("hellow mbed!\n");
}
}


最後にコンパイルです。


ビルドの実行

platformio run


これでhard_lecture/platformio/mbed01/.pioenvs/lpc1768/firmware.binにビルド済みのバイナリが生成されます。


カスタムmbedに書き込む方法

通常のmbedならplatformioでuploadオプションを付けると自動でダウンロードしてくれますが、カスタムmbedではそうはいきません。lpc21ispで書き込みを行います。


lpc21ispのインストール

sudo apt-get install lpc21isp


/dev/ttyUSB0にカスタムmbed用のライターがついているとします。


lpc21ispの書き込み

roscd hard_lecture/platformio/mbed01/.pioenvs/lpc1768/ 

sudo lpc21isp -control -bin firmware.bin /dev/ttyUSB0 115200 12000

わざわざ別のコマンドを打つのは面倒ですので、すべてplatformio runでやってくれるように設定を変えましょう。


hard_lecture/platformio/mbed01/platformio.iniに追加

[env:lpc1768]

platform = nxplpc
board = lpc1768
framework = mbed

targets = upload # デフォルトで書き込みを行う
extra_scripts = pre:lpc21isp_script.py # カスタム書き込みコマンドのロード
upload_protocol = custom # 標準ではなくカスタムの書き込みを行う
upload_port = /dev/ttyUSB0 # 書き込み先のポートの設定


以下のファイルを追加します。


hard_lecture/platformio/mbed01/lpc21isp_script.py

Import("env")

print("load lpc21")

env.Replace(
UPLOADCMD="lpc21isp -control -bin $SOURCE $UPLOAD_PORT 115200 12000"
)


これでplatformio runでコンパイルから書き込みまですべてをおこなえます。


mbedでrtosライブラリを使う

強力なmbedのライブラリとしてrtosがあります(逆にこれがないとプログラムがだいぶ難しい)。これは標準の設定だとplatformioでは使えません。


hard_lecture/platformio/mbed02/src/main.cpp

#include "mbed.h"

#include "rtos.h"

#define SRSG_LED0 P0_16
#define SRSG_LED1 P0_15
#define SRSG_LED2 P0_17
#define SRSG_LED3 P0_18

DigitalOut l0(SRSG_LED0);
DigitalOut l1(SRSG_LED1);
DigitalOut l2(SRSG_LED2);
DigitalOut l3(SRSG_LED3);

void blink1(void) {
while (1) {
l1=!l1;
Thread::wait(1000);
}
}
void blink2(void) {
while (1) {
l2=!l2;
Thread::wait(1000);
}
}

int main() {
Thread thread1;
thread1.start(blink1);
Thread thread2;
thread2.start(blink2);
while (true) {
l0 = !l0;
Thread::wait(500);
}
}


この状態でplatformio runをするとエラーになります。設定ファイルに書き加える必要があります。


hard_lecture/platformio/mbed02/platformio.ini

[env:lpc1768]

platform = nxplpc
board = lpc1768
framework = mbed
build_flags = -D PIO_FRAMEWORK_MBED_RTOS_PRESENT #この行を追加

これでplatformio runのビルドが通ります。


mbedでrosserialを使う方法


platformioワークスペースの作成

面倒なのでmbed01をコピーしてmbed03にします。


ライブラリの生成

ライブラリの生成のために以下が必要になります。

sudo apt-get install ros-kinetic-rosserial-mbed

以下のコマンドで生成します。ライブラリは<platformioワークスペース>/libに入れます。

roscd hard_lecture/platformio/mbed03/lib/

rosrun rosserial_mbed make_libraries.py ./

ros_lib以下には多数のファイルディレクトリが生成されます。ファイルは全て必要ですが、ディレクトリはBufferedSerialrosrosserial_msg、ソース中でincludeしているパッケージ以外は消去しても構いません。


ソースコード

文字を1秒単位でpublishする、msgをsubscribeするとLEDが点灯するというものです。LEDハP0_16につながっているとします。


hard_lecture/platformio/mbed03/src/main.cpp

#include <mbed.h>

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

DigitalOut led = P0_16;

ros::NodeHandle nh;

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

void messageCb( const std_msgs::Empty& toggle_msg) {
led=1;
wait(0.2);
led=0;
}
ros::Subscriber<std_msgs::Empty> sub("led", &messageCb );

int main() {

nh.getHardware()->setBaud(115200);
nh.initNode();
nh.advertise(chatter);
nh.subscribe(sub);

while (1) {
str_msg.data = "hello world!";
chatter.publish( &str_msg );
nh.spinOnce();
wait_ms(1000);
}
}



コンパイル&書き込み

roscd hard_lecture/platformio/mbed03/lib/

platformio run


実行

どうやらubuntuのデフォルトのUSB設定ではRST、DTRの設定のせいでこれらをlpc1768とつないでいると、通常の起動時でもbootモードに入って動かなくなってしまいます。動作時はこの2本の信号は物理的に切り離す必要があります。


1つ目のターミナル

roscore



2つ目のターミナル

rosrun rosserial_python serial_node.py _port:=/dev/ttyACM0 _baud:=115200


これでrostopic list/chatter/ledが見えます。後は普通のrosと同じように使うことができます。


参考

platformioでmbedを使う

lpc21isp

bin->hex変換ツール?

mbedシリアル書き込み

platformio mbedオプション

rosserial mbed


目次ページへのリンク

ROS講座の目次へのリンク