1年(実装してからは2年)くらい放置していたmicro-ROSの記事です。
STM32マイコンとSPI接続のEthernetチップ「W5100」を接続してmicro-ROSで通信させてみました。
STM32F446REとSTM32L432KCで動作確認したのでArduino_Core_STM32がサポートしていれば動きます。
STM32F7系でサポートされているEthernet以外でも動くようになると、ボードの選択肢が増えて便利だと思います。
ARM CoreかつArduinoプラットフォームでサポートされていればコンパイルは通りそうですが、RaspberryPi picoはリンカー関連、Arduino R4はEthernetとの通信がうまくいっておらず断念しました😢
以前のmicro-ROSの記事
micro-ROSとは
micro-ROSはマイクロコントローラを接続するためのプロジェクトで、rclcをベースにPub-Sub接続を実現します。 サポートされているボードやIDEがとても広いです。
micro-ROS自体にはノード探索機能が搭載されていないため、micro-ROS-agentをホスト側に用意してそこに接続する必要があります。
SPI-Ethernetチップ「W5100」
W5100はSPI接続が可能なEthernet処理チップです。複雑な処理が必要なTCP/IP・UDP処理を単純な命令およびそのコールバックで済ませることができ、Arduino + ネットワーク接続を実現することができます。チップ自体は600円程度で購入できます。
今回は、Switch-Scienceで購入したものを使用します。
この製品はPico用のシールドとなっており、Picoと一体になっているモデルも購入しています。
環境構築
Ethernetライブラリ
STM32のネイティブEthernet用のライブラリはSTM32Ethernetですが、SPI接続のW5100は別のライブラリが必要です。
ArduinoのデフォルトEthernetライブラリやSTM32DuinoのEthernetライブラリは使わないでください。
配線については、SPIの4線と電源として3.3V・GNDを接続します。
開発環境にはPlatformIO (arduino) を使用します。
コンパイラを一括で設定できるので、開発環境を固定できない趣味開発との相性が抜群にいいです。
依存関係の記述(STM32)
L432とF446どちらでも使えます。
;; ============================== ;; STM32L4, F4 SPI-Ethernet Model ;; ============================== [env:nucleo] platform = ststm32 framework = arduino ;; L432 board = nucleo_l432kc board_build.f_cpu = 80000000L board_build.mcu = stm32l432kcu6 ;; F446 ; board = nucleo_f446re ; board_build.f_cpu = 180000000L ; board_build.mcu = stm32f446re monitor_speed = 115200 upload_speed = 115200 upload_device = /dev/ttyACM0 lib_deps = ;; microros --------------------------------------------------------------- https://github.com/NITKK-ROS-Team/micro_ros_arduino.git#humble_custom https://github.com/NITKK-ROS-Team/micro_ros_arduino_simpler.git#main https://github.com/WIZnet-ArduinoEthernet/Ethernet.git build_flags = -L ./.pio/libdeps/pico/micro_ros_arduino/src/cortex-m4/ -l microros
Arduinoコード
bool型のメッセージをsubしてtrueを送ったらマイコン内でカウントアップしてintデータをpubするプログラムです。
#include <Arduino.h> // executor ------------------ #include <micro_ros_arduino.h> #include <stdio.h> #include <rcl/rcl.h> #include <rcl/error_handling.h> #include <rclc/rclc.h> #include <rclc/executor.h> rclc_executor_t executor; rclc_support_t support; rcl_allocator_t allocator; rcl_node_t node; # message ----------------------- #include <std_msgs/msg/bool.h> #include <std_msgs/msg/int32.h> rcl_publisher_t publisher; std_msgs__msg__Int32 msg_int32; rcl_subscription_t subscription; std_msgs__msg__Bool msg_bool; // timer ---------------------- rcl_timer_t timer; int counter = 0; // subscription callback ("/bool_data", "std_msgs/msg/bool") void bool_callback(const void *msgin) { const std_msgs__msg__Bool *_msg = (const std_msgs__msg__Bool *)msgin; counter += _msg->data; } // timer callback (10ms) void timer_callback(rcl_timer_t *timer, int64_t last_call_time) { (void)last_call_time; (void)timer; msg_int32.data = counter; rcl_publish(&publisher, &msg_int32, NULL); } // setup micro_ros_arduino =============================================== void setup() { #if !defined(STM32L4xx) #error "This example is only for STM32L4xx" #endif byte arduino_mac[] = {0xAA, 0xBB, 0xCC, 0xEE, 0xDD, 0xFF}; IPAddress arduino_ip(192, 168, 0, 10); IPAddress agent_ip(192, 168, 0, 5); int agent_port = 2000; int cs = 6; set_microros_native_ethernet_udp_transports(arduino_mac, arduino_ip, 2, agent_ip, cs); get_default_allocator(); rclc_init("uros_node", "ns"); init_executor(2); // rclc-publisher-subscriber-timer ====================================== rclc_publisher_init_default(&publisher, &node, ROSIDL_GET_MSG_TYPE_SUPPORT(std_msgs, msg, Int32), "int32_data"); rclc_create_timer_and_add(&timer, 10, timer_callback); rclc_create_subscription_and_add(&subscription, ROSIDL_GET_MSG_TYPE_SUPPORT(std_msgs, msg, Bool), &msg_bool, &bool_callback, "bool_data"); } // loop micro_ros_arduino =============================================== void loop() { rclc_delay(10); }
コンピュータ側の設定
コンピュータはx86のものを使ってください。(MacやRaspberryPi OSだとうまくうごかないかもしれないです)
コンピュータ側のEhernetポートはデフォルトでついているものでもUSBで拡張したものでもいいです。
まず、マイコンと接続するEthernetソケットのIPアドレスを agent_ip
と同じにします。(この場合は 192.168.0.5
)
IPアドレスを設定したら、マイコンとPCをLANケーブルで接続します。CAT5e対応とかであれば問題ないと思います。
dockerでmicro-ros-agentを動かします。
docker run -it --rm -v /dev:/dev --privileged --net=host microros/micro-ros-agent:humble udp4 --port 2000
fastrtpsで DOMAIN_ID=0
の設定を忘れないでください!
Arduino UNO R4
Arduino UNO R4でも使ってみます。
Arduino UNO R4にはWi-FiモデルがあるのでEthernet対応の必要性は微妙ですが、USB-Serialでとりあえず動かせることを確認しました。
感謝🙏
micro_ros_arduino_simplerへの組み込みも終わっており、platformioで ARDUINO_ARCH_RENESAS
フラグを立てればUSB-SerialもEthernetもコンパイルは通ります。
micro-ros-arduinoのUSB-Serialはうまく動くようになりました。
一方、EthernetはまさかのMACアドレスの設定が失敗するトラブルで断念。
Arduino UNO R4向けの設定とWiFiS3をlib_ignoreに含めるよう先程のplatformio.iniに変更すればビルドができるようになります。
実は、Arduino UNO R4とSPI通信の相性は悪いようで、UNO R3より性能低下するとの話題も上がっているようです😢
Uno R4 Poor SPI Performance - #5 by fat16lib - UNO R4 Minima - Arduino Forum
誰か助けてー