トホホな疑問(28) Nucleo、Arduino環境でUartを使う

Joseph Halfmoon

STマイクロエレクトロニクス社のNucleo F072RBボード、Arm社のMbed環境で大分お世話になったのですが、このところ「遊休」状態。IoTネットワークに接続できる装置(ラズパイ)などとバディを組ませて復活を目論見ます。今回はよりお手軽なAruduino環境でプログラミング。STM32、Uart沢山あるけど一体何番がつかえるのですか?

※「トホホな疑問」投稿順Indexはこちら

アイキャッチ画像に掲げましたのはいずれもArduino環境でビルドできるボード5品でございます。その中で中央の白いボードがNucleoボードです。Nucleoボードにもいくつか型式があるのですが、同一ボード型式であると搭載マイコン以外は皆同じに見えます(マイコンのスペックはかなり異なります。)手元には同一型式のNucleoボードがF401REとF072RBの2種あり、いずれも

    • Arm Cortex-M系マイコンボード+ST-LINKデバッグアダプタ結合
    • Arduino互換配列の拡張端子とST社仕様(Morpho)の拡張端子つき
    • 出来の良いボード、お求めやすい価格

であります。そして、Arm社のMbed開発環境以外にもST社の自社開発環境、IAR社などのサードベンダの開発環境など充実、なのであります。しかし、Arm Cortex M4F搭載のR401REはまだしも、ぶっちゃけ

スペックの低いF072RBはだんだん肩身が狭くなっている

感じがいたします。32bit Arm Cortex-M0, 48MHz, 128KB Flash, 16KB SRAM。それでもArduino業界標準機?のUno、AVR 8bit ATmega328P, 16MHz, 32KB Flash, 2KB SRAMと比べたらかなり強力。Arduinoとしてならまだまだやれる?

ということで、ArduinoIDEにSTM32マイコンの環境を追加しArduinoでプログラミングを始めました。環境設定自体は、Arduino環境でESP32やSAMD51などのAVR以外のマイコンを使う場合と変わりありません。GitHubの以下のページに説明があるとおり、

stm32duino/Arduino_Core_STM32

ArduinoIDEのボードマネージャに以下を設定し、STM32マイコンを使えるようにするだけです。

https://github.com/stm32duino/BoardManagerFiles/raw/master/STM32/package_stm_index.json

これにより大量の種類のSTM32マイコン搭載ボードをArduino環境で開発可能になります。その中 Nucleo 64のカテゴリの中にR072RBもふくまれております。ArdinoIDEで新たなプロジェクトを始め、ボードを設定すれば、即座にNucleo R072RB用のコードをビルド可能。Nucleoは元々Arduino互換の拡張端子を備えているくらいなのでかなり互換性が高く、Arduino Unoのコードをコピペしても大抵のことはできてしまいそうです。ただし、STM32の方が仕様が大きいのでArduino Unoを上回るところを使いたい場合は変更しないとなりません。今回の疑問はまたしてもシリアルポートです(他のボードと接続するために。)

    • Arduino UnoはUART一つ
    • F072RBはU(S)ART4つ

4つもあるので

    • USBシリアルに接続しているUARTはデバッグ用にとっておきたい。
    • 残り3つのうち取り扱い易いArduino拡張端子で接続できる1チャンネルを選びたい。(Morpho端子は、数が多すぎて端子数えるのがメンドイのでなるべくパス)

という方針であります。まずは、Arduino環境でSTM32のSerial通信使うためのコアライブラリを探して中身を拝見いたしました。HardwareSerial.hというヘッダの中で

Serial1からSerial10、そして SerialLP1

などというオブジェクトが外部参照されていました。この定義はSTM32の各機種のORとった定義であろうと思われますが、11個は多いね。多分そのうちのいくつかがF072RBでも使える筈。ヘッダファイル類をさらっと調べた限り

    • USART2という物理インタフェースがArduino UnoでSerialというお名前で使えるのRX(D0), TX(D1)に接続されているように見える
    • USART2はHardwareSerial.h上はSerial2という名前で呼べる

ように見受けられました。早速、Serial2に対して、ダラダラと数字を垂れ流すテストコードを書いて動作させてみました。結論からいうと

Serial2に出力すると

USBシリアルには出力されるが、TX(D1)には出力されない。

です。Unoとちょっと挙動が違うよね、と思ってマニュアルを読んでみると、ちゃんと書いてありました。以下がその説明など記載されているボードマニュアルへのリンクです。

STM32 Nucleo-64 boards (MB1136) – UM1724

肝心な部分を引用さてていただくと以下のようです。ここでPA2がTX(D1)、PA3がRX(D0)端子に接続しているSTM32マイコンの実端子名です。

The USART2 interface available on PA2 and PA3 of the STM32 microcontroller can be connected to ST-LINK MCU, ST morpho connector, or to ARDUINO® connector. The choice can be changed by setting the related solder bridges.

確かにUSART2はUnoのTX/RXと同じ拡張端子に接続可能。しかし、半田ブリッジ(ボードの裏面に用意されています)を盛らないとつながらないようになってました。デフォルトではデバッグ用のST-LINKのコントローラを介してUSBシリアルに接続しているようです。Serial2は駄目だ、デバッグ用にとって置かないと。そこでもっとソースを深く読み込めば立派なのですが、面倒なので、端から確かめてみました(そんなことで良いのか。)無印のSerialを含めSerial1, Serial2, Serial3とトライしてみた結果が以下のようです。

    • Serial(番号無)、Serial2と実体同じ、USBシリアルに接続。「伝統の」printf的デバッグにはこれだね。
    • Serial1、ビルド時にエラー発生。
    • Serial2、番号無のSerialと同じUSBシリアルに接続
    • Serial3、ビルド時にエラー発生。

全部で11個あったですが、4個目で早くも諦めました。沢山ある筈なのに使えないじゃん!気を取り直しました。「既定のオブジェクト」にたよらず自分でHardwareSerialオブジェクトを初期化して使ってみればいいじゃん!大した手間じゃないし。。。

データシートで接続している筈の端子とUARTをインスタンス化、こんな感じ。

HardwareSerial serialX(PA_10, PA_9);

これは動作しました。なお、第一引数がRX, 第2がTXです。PA_10はArduino環境のD2端子、PA_9はD8端子。実際に結線したところがこちら。配線の行先はRaspberry  Piの拡張端子に出ているUART、ttyS0です。Nucleo F072RB uart connected to Raspberry Pi

実際に動作した 「Lチカ+シリアル垂れ流し」のテストコードがこちら。インスタンス名はSerial1などとすると被るので、とりあえずserialXなどとしてありますが、何でも良いでしょう。実体ハード的にはUSART1の筈。

#include "HardwareSerial.h"

HardwareSerial serialX(PA_10, PA_9);
int count;

void setup() {
  serialX.begin(115200);
  while(!serialX) {};
  serialX.println("Start Serial");
  pinMode(D13, OUTPUT);
  digitalWrite(D13, LOW);
  count = 0;
}

void loop() {
  serialX.println(count);
  if ((count % 2) == 0) {
    digitalWrite(D13, HIGH);
  } else {
    digitalWrite(D13, LOW);
  }
  count += 1;
  delay(5000);
}

Raspbian OSのttyS0で接続していてF072RBから送られてきた文字列がこちら。ちゃんと接続されておりますで。

cu command resultま、動いたから良いけれど。御馴染みの開発環境、御馴染みのボードでも、組み合わせかえると、またいろいろあるのね。トホホ。

トホホな疑問(27) M5StickC、Uartを使う に戻る

トホホな疑問(29) Wio Terminal、esp_system.h not found に進む