0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Day 15: FOC実装編(2) 電流センシング(触覚)の実装

0
Last updated at Posted at 2025-12-14

FOC(ベクトル制御)の実装プロジェクト、第15日目です。
前回(Day 14)は、SVPWM(空間ベクトル変調)の実装により、STM32から任意の電圧ベクトルを出力することに成功しました。これは人間で言えば、脳からの指令を手足に伝える「運動神経」が繋がった状態です。

今回は、その対となる 「電流センシング」 の実装です。
モーターのコイルに実際にどれだけの電流が流れているかを正確にフィードバックすることは、ロボットが負荷や反力を感じる「触覚」の実装に等しく、FOCの制御ループを閉じるための最重要工程となります。

1. 今回のミッション:マイクロ秒の静寂を狙う

FOCにおける電流計測は、単に HAL_ADC_Start() を呼べば良いというものではありません。インバータ回路特有の過酷なノイズ環境下で、正確なアナログ値を取得する必要があります。

PWM制御されたインバータは、高速でスイッチング(ON/OFF)を繰り返しています。スイッチングの瞬間(エッジ)には強烈なリンギングノイズが発生するため、このタイミングでAD変換を行うとデータは使い物になりません。
したがって、「スイッチングノイズが収まり、かつ電流が安定して流れている一瞬の静寂」 をマイクロ秒単位で狙い撃ちする必要があります。

本日の目標は以下の通りです。

  1. ローサイド・シャント抵抗方式における「計測可能なタイミング」を理論的に特定する。
  2. STM32のタイマー設定(PWM Mode 2)を駆使し、そのタイミングで自動的にADCを起動させる。
  3. オシロスコープと内部カウンタ値を用いて、同期タイミングが完璧であることを証明する。

2. 理論:どこで測るべきか?

ハードウェア構成:ローサイド・シャント方式

今回の回路構成は、インバータの下側アーム(GND側)に電流検出用のシャント抵抗を配置する 「ローサイド・シャント方式」 です。

この方式には物理的な制約があります。シャント抵抗にモータ電流が流れるのは、「下側のFETがONになっている時」 だけです。
インバータの動作原理上、上側FETと下側FETは相補的に動作します(デッドタイムを除く)。
つまり、PWM信号(上側FET駆動信号)が LOW の期間だけ、下側FETがONになり、シャント抵抗に電流が流れます。
image.png

理想の計測ポイント

PWM信号がLOWの期間中ならいつでも良いわけではありません。
LOWに落ちた直後や、HIGHに上がる直前はスイッチングノイズが含まれます。最も電流波形が安定し、かつPWMのDuty比が変化しても確実に確保される時間は、「PWMがLOWになっている期間の、ど真ん中」 です。

STM32のタイマーカウンタ(TIM1)は、Center Aligned Mode(三角波動作)を使用しています。カウンタ値が 0(谷底)と ARR(山頂)を行き来する中で、どちらが「LOWのど真ん中」になるでしょうか?

  • PWM Mode 1 の場合: カウンタ値 < CCR で HIGH となります。つまりカウンタ 0 付近は HIGH(上側ON)となり、電流は流れません。
  • PWM Mode 2 の場合: カウンタ値 < CCR で LOW となります。つまりカウンタ 0 付近は LOW(下側ON)となります。

結論として、PWM Mode 2 を使用し、カウンタが 0(谷底)になった瞬間にADCのトリガを引く のが正解となります。

3. STM32の実装 (CubeMX & Code)

理論に基づき、STM32の Advanced Control Timer (TIM1) を設定します。手動でタイミングを微調整する必要はありません。ハードウェアの機能を論理的に組み合わせるだけで、完璧な同期が実現できます。

3.1 タイマー設定 (TIM1)

最も重要な変更点は、PWM Generation のモード設定です。

  • Counter Settings

    • Counter Mode: Center Aligned Mode 1
      • カウンタがアップ・ダウンカウント(三角波)を繰り返します。
    • Repetition Counter (RCR): 1
      • Update Event (UEV) の発生頻度を制御します。Center Aligned Mode 1 と組み合わせることで、カウンタがアンダーフロー(0)したタイミングでのみイベントを発生させ、ADCトリガ(TRGO2)として利用します。
  • PWM Generation Channel 1-3

    • Mode: PWM mode 2
      • ここが最大のポイントです。CNT < CCR の条件で Inactive (LOW) を出力します。
      • これにより、カウンタの谷底(0)付近が常に「LOW(電流計測可能区間)」の中心となります。
  • Trigger Output (TRGO2)

    • Trigger Event Selection: Update Event
      • カウンタが 0 になった瞬間に発生する更新イベントを、ADCへのトリガ信号として出力します。
        image.png

3.2 コード実装 (main.c)

設定が正しければ、コードは非常にシンプルになります。以下は MX_TIM1_Init の抜粋と、検証用のコールバック関数です。

/* TIM1 Initialization (抜粋) */
static void MX_TIM1_Init(void)
{
  // ... (省略) ...
  
  // 三角波モード設定
  htim1.Init.CounterMode = TIM_COUNTERMODE_CENTERALIGNED1;
  // アンダーフロー(0)のみでイベントを発生させるための設定
  htim1.Init.RepetitionCounter = 1; 
  
  // ... (省略) ...
  
  // ★重要: 谷底(CNT=0)でLOWになるモードを選択
  sConfigOC.OCMode = TIM_OCMODE_PWM2; 
  sConfigOC.Pulse = 0;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  
  // ... (省略) ...
}

次に、ADC変換完了時に呼ばれるコールバック関数で、タイミング検証用の処理を記述します。

/* ADC変換完了割り込み (Injected Group) */
void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef* hadc)
{
    // 1. 割り込みが入った瞬間のカウンタ値を記録 (デバッグ用)
    // 理論上、0に近い小さな値になるはず
    debug_cnt = TIM1->CNT;

    // 2. オシロスコープ確認用にGPIOピンを反転 (赤線)
    HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); 
    
    // (本番ではここに電流値の工学単位変換やFOC計算処理が入ります)
}

4. 検証結果:完璧な同期

実装したコードをSTM32G474に書き込み、オシロスコープで波形を確認しました。

  • 黄色 (CH1): TIM1 PWM出力波形
  • 赤色 (CH2): ADC完了割り込みタイミング (GPIOトグル)

オシロスコープ波形

スクリーンショット 2025-12-14 001829.png

(※黄色いPWM波形がLOWになっている区間の中心で、赤色の信号がトグルしている様子)

確認結果は明白です。
黄色の波形が LOW(0V) になっている区間の、まさに 「ど真ん中」 で赤色の信号が変化しています。
デジタルオシロスコープを「Single」または「Stop」させて波形を拡大すると、ジッター(揺らぎ)のない正確な同期が見て取れます。

  1. PWM波形: Center Aligned Mode + PWM Mode 2 により、カウンタ 0 を中心としたLOW区間が生成されている。
  2. トリガ位置: Update Event (CNT=0) でADCが開始され、変換時間経過後にLOW区間の中央付近でデータ取得が完了している。

数値による裏付け

さらに、デバッガを通して変数 debug_cnt(割り込み発生時のTIM1カウンタ値)を確認しました。

CNT: 470

この数値の意味を検証します。
STM32G4のクロックは 170MHz です。カウンタ値 470 は、時間にして約 $2.76 \mu s$ に相当します。

$$\frac{470}{170 \times 10^6} \approx 2.76 \times 10^{-6} , [s]$$

  • ADCサンプリング + 変換時間: 約 $1 \sim 1.5 \mu s$ (設定依存)
  • 割り込み遅延 + GPIO操作: 数百 $ns$ 〜 $1 \mu s$

合計すると、カウンタが 0(谷底)でトリガされてから、処理が完了して CNT を読み取るまでの時間として非常に妥当な値です。
もし設定を誤り、カウンタの山頂(ARR = 4250)やエッジでトリガがかかっていれば、この値は 2125 付近や 4000 付近になるはずです。「470」という数値は、システムが 「谷底(0)で正確にトリガをかけ、最短時間でデータを取得した」 ことの数学的な証明です。

5. まとめ

これで、FOC制御における「目(センサ)」と「触覚(電流計測)」が揃いました。

  • PWM Mode 2Update Event を組み合わせることで、ローサイド・シャント抵抗に電流が流れる 「LOW区間の真ん中」 をハードウェア的に捉えることに成功しました。
  • この同期制御に、CCR4等の余計なコンペアマッチ機能は不要です。STM32のタイマーモードの本質を理解し、正しく設定するだけで、理想的なセンシングタイミングは実現できます。

次回(Day 16)は、いよいよ取得した生の電流値(AD値)を物理量(アンペア)に変換し、モーターを回すためのトルク制御計算(クラーク変換・パーク変換)を実装していきます。
ついに、モーターが「力」を持ちます。お楽しみに。

0
1
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
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?