Loading [MathJax]/extensions/tex2jax.js

モーター制御 ~正弦波駆動

2025年3月10日月曜日

18. モーター制御

t f B! P L

矩形波駆動で始動後、正弦波駆動に切り替える制御にしました。


はじめに

制御的には強制転流のまま単純にPWMを正弦波DUTYにしただけです。回っているものの、励磁電流波形を確認すると改善の余地も多くありそうですが、取り敢えずここまでについて書いていこうと思います。

使用している機材

使用している機材は、STマイクロエレクトロニクスのモーター制御基板セットP-NUCLEO-IHM001と、ホールセンサ、基板、ケーブルがセットになったもので、CQ出版社から購入できます。
モーター制御基板セットP-NUCLEO-IHM001には、DCブラシレスモーターも付属しています。マイコンはSTM32F302R8。コアはCortex-M4で、開発環境はSTM32CubeIDEです。

励磁電流の制御

矩形波駆動では、3相のうち2相の組み合わせを切り替えて通線制御していましたが、正弦波駆動では、常時3相同時通電になり、励磁コイルに流れる電流を連続的にプラスからマイナス、マイナスからプラスに制御します。
このとき、U/V/W 3相の電流のモーターへのIN/OUTは、2相/1相 または 1相/2相 の組み合わせになるので、励磁電流のPWM制御は2相側で行い、残りの1相はON状態にします。
具体的な通電制御は下図のようにしています。


   PWM   PWM作動
相補作動 PWMの相補作動。スイッチングに伴う誘導電流をローサイドアームで還流。
    ON     ローサイドアームをONして励磁電流、誘導電流をGNDに流す。
相補作動 PWMの相補作動。スイッチングに伴う誘導電流をハイサイドアームで還流。
    ON     ハイサイドアームをONして給電及び誘導電流を流す。

常にいずれか1相のハイサイドアームまたはローサイドアームがON状態になっているため、残りの2相のPWMスイッチングに伴う還流電流の経路も確保され、不要なフライバックも発生しません。

ソフトウエアと正弦波駆動の構成方法

ベクトル制御も想定してFPUがあるマイコンにしていますが、安易に浮動小数点演算は使いません。正弦波駆動であれば全て整数演算で実装していきます。以下に出てくる LSB は各変数の分解能で、LSB 1/1000deg では 1000 が 1deg に相当することを表します。

1ms処理

回転数指示値 NmotObj [rpm] より、PWM周期 50μsで進む機械角の更新値 dMchAngle(LSB 1/1000deg) を算出する。

 dMchAngle = NmotObj /60 *360 *50 /1000

分かり易い式を記載していますが、実際のコードでは桁落ちを考慮した演算順序にします。

PWM周期割り込み処理

Timer1 PWMのセンターアラインモード(mode1)では山と谷で割り込みが発生。PWMの周期である谷(Timer1_CR DIRビット=0 で判定)でPWM Duty制御を実施する。

機械角の更新

機械角 MchAngle (LSB:1/1000deg) にPWM周期 50μsで進む角度 dMchAngle を加算して機械角を更新する。今回のモーターは、14極7ペアなので、電気角の 360deg に相当する機械角 360/7 =51.429deg で折り返す。

  MchAngle = MchAngle + dMchAngle;
  if ( MchAngle>=51429 ) MchAngle = MchAngle - 51429;

電気角とSTAGEの更新

電気角 EleAngle (LSB:1deg) を機械角 MchAngle から求める

  EleAngle = MchAngle *7 /1000;

更に電気角から、60deg毎に決まるSTAGE(slotNo)を決定する

  if ( EleAngle < 60 ) slotNo = 1;
  else if ( EleAngle < 120 ) slotNo = 2;
  else if ( EleAngle < 180 ) slotNo = 3;
  else if ( EleAngle < 240 ) slotNo = 4;
  else if ( EleAngle < 300 ) slotNo = 5;
  else slotNo = 6;

電気角からU/V/WのPWM Dutyを算出

まず、電気角 EleAngle からU/V/Wの各電気角を求めます。

  EleAngleu = EleAngle;
  if ( EleAngleu >= 180 ) EleAngleu = EleAngleu - 180;
  EleAnglev = EleAngleu + 60;
  if ( EleAnglev >= 180 ) EleAnglev = EleAnglev - 180;
  EleAnglew = EleAngleu + 120;
  if ( EleAnglew >= 180 ) EleAnglew = EleAnglew - 180;

正弦波データは、0~179 degの範囲で、1degごとに LSB 1/255 のテーブルデータとして持ちます。

  SinTbl[180] = { 0,4,9,13,18,22,27,31,・・・・・,31,27,22,18,13,9,4 };

U/V/Wの各電気角で正弦波データを検索。

  WaveValu = SinTbl[ EleAngleu ];
  WaveValv =  SinTbl[ EleAnglev ];
  WaveValw = SinTbl[ EleAnglew ];

U/V/Wの各正弦波データで、U/V/WのPwm Duty値を算出します。

  PwmDutyu = PwmDuty *WaveValu /255;
  PwmDutyv  = PwmDuty *WaveValv /255;
  PwmDutyw = PwmDuty *WaveValw /255;

PWM Dutyの設定

U/V/WのPWM Duty値をSTAGE(slotNo)に応じて設定します。
PWM_ON はDuty100%値(1600-1)、PWM_OFF はDuty0%値(0)です。

     switch ( slotNo ) {
       case 1:
    TIM1 -> CCR1 = PwmDutyu; // U PWM
  TIM1 -> CCR2 = PWM_OFF; // V OFF
  TIM1 -> CCR3 = PwmDutyw; // W PWM
  break;
      case 2:
  TIM1 -> CCR1 = PWM_ON; // U ON
  TIM1 -> CCR2 = PWM_ON - PwmDutyv; // V nPWM
  TIM1 -> CCR3 = PWM_ON - PwmDutyw; // W nPWM
  break;
      case 3:
  TIM1 -> CCR1 = PwmDutyu; // U PWM
  TIM1 -> CCR2 = PwmDutyv; // V PWM
  TIM1 -> CCR3 = PWM_OFF; // W OFF
  break;
      case 4:
  TIM1 -> CCR1 = PWM_ON - PwmDutyu; // U nPWM
  TIM1 -> CCR2 = PWM_ON; // V ON
  TIM1 -> CCR3 = PWM_ON - PwmDutyw; // W nPWM
  break;
      case 5:
  TIM1 -> CCR1 = PWM_OFF; // U OFF
  TIM1 -> CCR2 = PwmDutyv; // V PWM
  TIM1 -> CCR3 = PwmDutyw; // W PWM
  break;
      case 6:
  TIM1 -> CCR1 = PWM_ON - PwmDutyu; // U nPWM
  TIM1 -> CCR2 = PWM_ON - PwmDutyv; // V nPWM
  TIM1 -> CCR3 = PWM_ON;                    // W ON
  break;

    case 0 :   // 停止処理 ローサイドアームを全てONにして誘導起電力の還流経路を確保
  TIM1 -> CCR1 = PWM_OFF; // U phase OFF
  TIM1 -> CCR2 = PWM_OFF; // V phase OFF
  TIM1 -> CCR3 = PWM_OFF; // W phase OFF
  break;
    default :  // ゲートOFF
  HAL_GPIO_WritePin(EN1_GPIO_Port, EN1_Pin, GPIO_PIN_RESET);
  HAL_GPIO_WritePin(EN2_GPIO_Port, EN2_Pin, GPIO_PIN_RESET);
  HAL_GPIO_WritePin(EN3_GPIO_Port, EN3_Pin, GPIO_PIN_RESET);
  break;
  }

実装結果 ~励磁電流波形

正弦波駆動といっても最初にも書いたように基本的には強制転流のまま PWM DUTY を正弦波状にしているだけです。

下図は、各相のシャント抵抗の電圧をデジタルオシロで観測した結果です。
シャント抵抗は、ローサイドアーム側にあるので、U相では Stage4,5,6 でのみ正確な励磁電流の観測が可能です。ローサイドアームからGNDに流れる励磁電流の方向がプラス値になります。

黄色 : U相の励磁電流
青色 : W相の励磁電流
緑色 : STAGE DAC出力 (STAGE数×480mV)
オレンジ : U相のPWM信号(ハイサイドアーム)


単純にPWM DUTYを正弦波状にして相補駆動しただけでは、ところどころ励磁電流が想定外の挙動になっています。
矩形波駆動では必ず1相はゲートオフしているので単純でしたが、正弦波駆動では3相同時通電となって、通電相間の干渉が起こっているのが原因のようです。

今回のドライバーL6230が相補駆動してしまうのが問題かもしれません。また、現状の20kHzのスイッチングをもっと速くした方が良いというのもありますが、ベクトル制御に行く前に、もう少し励磁電流の制御を見直した方が良さそうです。

STM32の設定

STM32の設定について、概要を記載しておきます。

入出力信号


PWM出力の設定

PWM出力はTimer1 CH1~3 を使用しています。CH4は、励磁電流のシャント抵抗電圧をADするトリガとして設定しています。

CH1~3は同じ設定。CH4はmode2に設定しています。
クロックは64MHzなので、3200カウントで20KHz(50μsec)周期のPWMにしますが、センターアラインモードに設定しているので、カウント値は半分の1600になります。


ADCの設定

ADCは、Timer1 CH4をトリガとして、3相の励磁電流のシャント抵抗電圧を取得します。
動作モードはInjected Conversionモード。

ADCの ch1にU相、ch6にV相、ch7にW相 が入力されています。また、同時にch12はドライバー基板に実装された可変抵抗ボリュームの出力です。

例えば、STAGE5では、V,W相のハイサイドアームからの励磁電流をU相のローサイドのシャント抵抗で検出するので、ADのトリガタイミングは下図のタイミングになります。

AD変換が完了するとAD完了割り込みが発生するので、AD値を取得します。


回転数計測

Timer2のch1,ch3,ch4を使って、電気角120deg間隔で実装された3つのホールセンサ出力から、U相、V相、W相の回転数を計測しています。タイマーの分解能は、64MHzを64分周して 1μs です。


検出される回転数のバラつきが結構大きい。
ホールセンサのレイアウトも含め、精度の高いローターの位置検出は難しそう。


1ms処理タイマー

Timer6で1ms周期の割り込み処理を起動しています。


初期化処理

HALライブラリ関数を使った main() の初期化処理です。

  // DAC初期化
  HAL_DAC_Start(&hdac, DAC_CHANNEL_1);

  // AD Injected Start
  HAL_ADCEx_InjectedStart_IT(&hadc1);

  // Timer Start
  HAL_TIM_Base_Start_IT(&htim1);
  HAL_TIM_Base_Start_IT(&htim2);
  HAL_TIM_Base_Start_IT(&htim6);

  // L6230 EN1,2,3 
  HAL_GPIO_WritePin(EN1_GPIO_Port, EN1_Pin, GPIO_PIN_SET);
  HAL_GPIO_WritePin(EN2_GPIO_Port, EN2_Pin, GPIO_PIN_SET);
  HAL_GPIO_WritePin(EN3_GPIO_Port, EN3_Pin, GPIO_PIN_SET);

  // PWM Start
  HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
  HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2);
  HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_3);

  // PWM周期同期ADトリガ
  TIM1 -> CCR4 = 10;

  //インプットキャプチャの設定と割り込みの有効化
  HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);  // HALL A
  HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_4);  // HALL B
  HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_3);  // HALL Z


最後までお読みいただきありがとうございます。
途中でも書きましたが、ベクトル制御に行く前に、もう少し励磁電流の制御を見直した方が良さそうです。


Translate

このブログを検索

ページビュー

22491

QooQ