19
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

UARTは遅すぎる!STM32G4「クリスタルレスUSB」による高速テレメトリ環境の構築と通信規格の技術比較

19
Posted at

Cubli(3次元倒立振子)のような高速なフィードバック制御システムにおいて、内部状態(姿勢角、角速度、制御入力など)の可視化は極めて重要です。制御周期が1ms(1kHz)の場合、データロギングシステムにはそれ以上のスループットが求められます。

本記事では、従来のUART通信が抱える帯域幅の限界を定量的に示し、その解決策としてSTM32G4シリーズの「クリスタルレスUSB機能」を用いたUSB CDC(Communication Device Class)の実装手法を解説します。また、実装に先立ち、UARTとUSBの通信プロトコル、物理層、および構造的な違いについて技術的な詳細を述べます。

1. 制御周期と通信帯域のボトルネック

本プロジェクトにおける倒立振子の制御ループは 1kHz(1ms周期) です。各周期ごとに、姿勢データやPID制御の内部変数をPCへ送信し、リアルタイムでモニタリングする必要があります。

UARTによる帯域幅の制限

組み込み開発で一般的に用いられるUART(Universal Asynchronous Receiver-Transmitter)の標準的なボーレートは 115,200 bps です。
UARTの通信フレームは、スタートビット(1bit) + データ(8bit) + ストップビット(1bit) の計10bitで1バイトを構成するため、実効転送速度 $V_{UART}$ は以下のようになります。

$$V_{UART} = \frac{115,200 \text{ [bps]}}{10 \text{ [bits/byte]}} = 11,520 \text{ [bytes/sec]}$$

一方、1回のログ出力に必要なデータ量を約40バイト(浮動小数点数8個分+区切り文字等)と仮定すると、1kHzの制御ループで要求されるデータ転送量 $D_{req}$ は以下の通りです。

$$D_{req} = 40 \text{ [bytes/sample]} \times 1,000 \text{ [samples/sec]} = 40,000 \text{ [bytes/sec]}$$

これより、$D_{req} > V_{UART}$ となり、UARTでは要求帯域の約1/4しか満たせないことがわかります。
実際に送信可能な最大周波数 $f_{max}$ は次のようになります。

$$f_{max} = \frac{11,520}{40} \approx 288 \text{ [Hz]}$$

1kHzの制御ループに対し、UARTを使用すると約3.5msに1回しかデータを送信できず、リアルタイム性が著しく損なわれます。このボトルネックを解消するため、より高速なUSB通信への移行を行います。

2. 技術解説:UARTとUSB CDCの構造と規格比較

実装の前に、UARTとUSB CDCの違いを物理層およびプロトコル層の観点から整理します。

2.1 UART (Universal Asynchronous Receiver-Transmitter)

UARTは「調歩同期式」と呼ばれる通信方式です。

  • 物理層: TX(送信)とRX(受信)の2本の信号線とGNDを使用します。電圧レベルはMCU直結の場合はTTL/CMOSレベル(3.3Vや5V)です。
  • 同期方式: クロック信号線を持ちません。あらかじめ双方が合意した通信速度(ボーレート)に従い、スタートビットの検出をトリガとしてタイミングを生成し、データを読み取ります。
  • フレーム構造: [Start Bit (1)] + [Data (5-9)] + [Parity (0-1)] + [Stop Bit (1-2)]
  • 課題: クロック信号がないため、高速通信(数Mbps以上)ではタイミング誤差が蓄積しやすく、通信エラーの原因となります。また、エラー訂正機能もパリティチェック程度しか持ちません。

2.2 USB (Universal Serial Bus)

USBはホスト主導のポーリング方式を採用したバス規格です。

  • 物理層: D+ と D- の2本の信号線を用いた「差動伝送(Differential Signaling)」を行います。これにより同相ノイズ(コモンモードノイズ)に強く、高速通信が可能です。また、NRZI(Non Return to Zero Invert)符号化により、データ自身にクロック成分を含ませることで同期を取ります。

  • 通信速度 (USB 2.0):

  • Low Speed: 1.5 Mbps

  • Full Speed: 12 Mbps (今回のSTM32での実装ターゲット)

  • High Speed: 480 Mbps

  • プロトコル構造: パケットベースで通信を行います。CRC(巡回冗長検査)による強力なエラー検出と、ハンドシェイクによる再送制御がハードウェアレベルで実装されています。

2.3 USB CDC (Communication Device Class)

USB CDCは、USB上で仮想的なシリアルポート(COMポート)をエミュレートするためのデバイスクラスです。

  • 仕組み: ホストPC側からは従来のCOMポートとして認識されますが、物理的にはUSBの Bulk Transfer(バルク転送) モードを使用しています。
  • バルク転送の利点: データの正確性が保証されます。帯域保証はありませんが、バスが空いている限り最大限のデータを送ることができます。
  • UARTとの違い: USB CDCにおける「ボーレート設定」は仮想的なパラメータに過ぎず、実際の通信速度には影響しません。USBバスの許容する最高速度(Full Speedなら理論値最大12Mbps程度)で通信が行われます。これが、今回の高速化の核心です。

3. ハードウェア実装:STM32G4におけるクリスタルレスUSB

通常、USB通信を行うためには、周波数偏差 $\pm 0.25%$ 以内という高精度なクロックが必要であり、外部水晶発振子(Crystal Oscillator)の実装が必須とされてきました。しかし、STM32G4シリーズは CRS (Clock Recovery System) を搭載しており、外部結晶なしでUSBを駆動可能です。

3.1 CRS (Clock Recovery System) の動作原理

CRSは、USBホスト(PC)から1msごとに送信される SOF (Start Of Frame) パケットを基準信号として利用します。
マイコン内部のHSI48(48MHz 高速RC発振器)を、受信したSOFパケットのタイミングに合わせてトリミング(微調整)することで、USB通信に必要なクロック精度を動的に維持します。これにより、外付け部品を削減しつつUSB通信が可能になります。

3.2 ハードウェア構成

Nucleo-G474REにはユーザー用USBコネクタがないため、USBケーブルを加工して直接配線を行います。
ちょっと乱暴ですがそのあたりにあったUSBケーブルに犠牲になってもらって実験を進めました。

image.png

配線仕様:

  • VBUS (赤): 未接続(絶縁処理)

  • 理由: Nucleoボードは既にST-LINK経由で給電されており、PCからの5Vを直接印加すると電源競合によりボードまたはPCのポートを破損する危険性があるためです。

  • D- (白): PA11

  • D+ (緑): PA12

  • GND (黒): GND

4. ソフトウェア実装

STM32CubeMXを用いて、USB DeviceスタックとCRSの設定を行います。

4.1 STM32CubeMXの設定

  1. Connectivity: USB を有効化し、Device (FS) を選択。

  2. Middleware: USB_DEVICE を選択し、Class For FS IP を Communication Device Class (Virtual Port Com) に設定。

  3. Clock Configuration: CRS を有効化し、HSI48がUSBクロックソースとなるよう設定します。
    image.png

  4. LinkerSettings: USB CDCドライバは内部で多量のバッファを使用するため、Heap Size0x600 以上、Stack Size0x800 以上に拡張します。これを行わないと、動作不安定やハングアップの原因となります。
    image.png

4.2 コード実装:標準出力のリダイレクト

printf 関数の出力をUARTからUSB CDCへ変更するため、システムコールである _write 関数をオーバーライドします。

main.c / usbd_cdc_if.h のインクルード

/* USER CODE BEGIN Includes */
#include <stdio.h>
#include <string.h>
#include "usbd_cdc_if.h" // USB送信関数へのアクセスに必要
/* USER CODE END Includes */

_write関数の実装
CDC_Transmit_FS 関数は、ユーザーバッファのデータをUSBの送信エンドポイントバッファへコピーし、送信リクエストを発行します。

/* USER CODE BEGIN 0 */
// printf等の標準出力をUSB CDCへリダイレクトする
int _write(int file, char *ptr, int len) {
    CDC_Transmit_FS((uint8_t*)ptr, len);
    //HAL_UART_Transmit(&hlpuart1, (uint8_t *)ptr, len, 100);//UARTで通信する場合は切り替える
    return len;
}urn len;
}
/* USER CODE END 0 */

4.3 ベンチマーク用コード

スループットを計測するため、1秒間に何回データ送信ループを実行できるかをカウントするプログラムを作成しました。

  /* USER CODE BEGIN 2 */
  printf("USB Speed Test Start!\r\n");
  HAL_Delay(1000); 

  uint32_t loop_count = 0;
  uint32_t start_tick = HAL_GetTick();
  /* USER CODE END 2 */

  /* USER CODE BEGIN WHILE */
  while (1)
  {
      // --- 計測フェーズ (1000ms間) ---
      if (HAL_GetTick() - start_tick < 1000)
      {
          // 実運用を想定した約40バイトのCSVデータ送信
          printf("1.11,2.22,3.33,4.44,5.55,6.66,7.77,8.88\r\n");
          loop_count++;
      }
      // --- 結果表示フェーズ ---
      else
      {
          HAL_Delay(50); // 送信バッファのフラッシュ待ち
          
          printf("\r\n");
          printf("==================================\r\n");
          printf(" Speed: %lu Hz (Lines/sec) \r\n", loop_count);
          printf("==================================\r\n");
          printf("\r\n");
          
          HAL_Delay(3000); // 結果確認用ウェイト
          
          // カウンタとタイマーのリセット
          loop_count = 0;
          start_tick = HAL_GetTick();
          printf("Go!\r\n");
      }
  }

5. ベンチマーク結果:UART vs USB CDC

同一のデータペイロードを用い、_write 関数内の送信先を切り替えて速度比較を行いました。

ラウンド1:従来の UART (115200 bps)

  • 実測値: 280 Hz
  • 考察: 理論値(288 Hz)に近く、1kHz制御ループではデータのドロップ(欠落)あるいは制御遅延が避けられない結果となりました。

ラウンド2:USB CDC (Full Speed)

  • 実測値: 約 42,000 Hz
  • 考察: UART比較で約150倍の速度向上を確認しました。これは、物理層の高速化に加え、パケットによるまとめての転送(バルク転送)が効率的に機能しているためです。

6. 結論

本記事では、Cubliの制御システムにおける通信ボトルネックを解消するため、STM32G4のCRS機能を活用したクリスタルレスUSB CDCを実装しました。

通信方式 実測ループ速度 1kHz制御への影響 判定
UART (115.2kbps) 280 Hz 致命的 (3ms以上の送信時間により制御周期破綻) ×
USB CDC (FS) 42,000 Hz 無視可能 (負荷数%以下で全データ送信可能)

USB CDCの導入により、40kHz以上のスループットを確保しました。これにより、1msの制御周期ごとに全ての内部変数をログ出力しても、通信処理がCPU負荷や制御周期に与える影響は軽微です。

UARTとUSB CDCの技術的な差異、特にポーリングベースのパケット通信とバルク転送の特性を理解することで、組み込みシステムにおける適切な通信インターフェースの選定が可能となります。
次回は、この高速テレメトリ環境を用いて、物理的な筐体製作とモータ制御の統合へ進みます。


アドベントカレンダー参加中
STM32×AIで「3軸倒立振子」を作る25日間(ひとりアドカレ)Advent Calendar 2025

19
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?