📖

Arduinoで3相インバータのコードを作った話

2024/09/27に公開

注意:この記事はメモ用に作成していて,特に雑に作成しています.読み返しもしてません.

背景

前の記事のとおり,モータ選定のためにインバータを作成しました.そのときのコードでは,マイコンの処理能力の関係上60Hz位までしかVVVFでまわせませんでした.(モータの特性にも依存はするとは思う)
高速回転を実現したいなぁと思ったので,マイコンの処理ができるとこまではVVVFで,それ以降は矩形波で回すコードを作成しました.

環境

  • 使用マイコン:XIAO SAMD21
  • モータ:unknownの1400KVと書いてあるモータ
  • スイッチング素子:2SK3800

インバータの詳細は前の記事を見てください.

コード

仕様

  • 低周波数ではPWMでVVVFを実現
  • 高周波数では矩形波でなるべくマイコンの処理を小さくする
  • モータはいきなり高い周波数をながすと,すべって回らないので,次第にまわしていく

注意点

  • 使うインバータによってはスイッチング素子の速度がボトルネックになる可能性あります.

コード

作成したコードは以下の通りです.

  • "fsw+=15;"や"if(angle_cnt>fsw/3*SAMPLES)"のところを変えると,周波数を増加させる度合いを調節できます.
#define SAMPLES 64
#define AQUARE_THREASHOLD 128 // 0~255の範囲で指定
#define SPPEDMODE_CHANGE_FREQ 60
#define TARGET_FREQ 5000

const int pinA=2;
const int pinB=9;
const int pinC=10;
const int ledpin=13;//pullupなのでLOWで点灯

const int numSamples = 64;  // 生成するSin波のサンプル数

// 波形位置
int sinwavepoint_A = 0;  
int sinwavepoint_B = SAMPLES / 3;
int sinwavepoint_C = SAMPLES *2 / 3;
int squarewavepoint = 0;
int angle_cnt=0;
int change_cnt=0;

double sinwave[SAMPLES]={0};
const bool squarewave[3][4] ={{1, 1, 0, 0},
                           {0, 1, 1, 0},
                           {0, 0, 1, 1}};

enum State {
  lowspeed,//PWMでVVVF
  highspeed//矩形波
};

State state = lowspeed;
 
void setup() {
  // 波形の生成
  for (int i = 0; i < SAMPLES; i++) {
    sinwave[i] = sin(2 * PI * i / SAMPLES) * 127 + 128;
  }
  pinMode(pinA, OUTPUT);
  pinMode(pinB, OUTPUT);
  pinMode(pinC, OUTPUT);
  pinMode(ledpin, OUTPUT);
  digitalWrite(ledpin, 1);
}
 
void loop() {
  static int fsw=1;
  static int delay_time=1.0/(fsw * SAMPLES)*1000000;
  //周波数が高いときは矩形波に切り替える
  fsw>SPPEDMODE_CHANGE_FREQ?state=highspeed:state=lowspeed;
  (state==highspeed)?digitalWrite(ledpin, 0):digitalWrite(ledpin, 1);
   
  if(lowspeed){// PWMでアナログ出力
    // 各層配列の何個目を参照するか決める
    sinwavepoint_A = (sinwavepoint_A + 1) % SAMPLES;
    sinwavepoint_B = (sinwavepoint_B + 1) % SAMPLES;
    sinwavepoint_C = (sinwavepoint_C + 1) % SAMPLES;
    analogWrite(pinA, sinwave[sinwavepoint_A]);
    analogWrite(pinB, sinwave[sinwavepoint_B]);
    analogWrite(pinC, sinwave[sinwavepoint_C]);
    delay_time=1.0/(fsw * SAMPLES)*1000000;
  }else if(highspeed){
    // 矩形波でデジタル出力
    squarewavepoint = (squarewavepoint + 1) % 4;
    digitalWrite(pinA, squarewave[0][squarewavepoint]);
    digitalWrite(pinB, squarewave[1][squarewavepoint]);
    digitalWrite(pinC, squarewave[2][squarewavepoint]);
    delay_time=1.0/(fsw * 4)*1000000;
  }

  angle_cnt++;
  if(angle_cnt>fsw/3*SAMPLES){
    angle_cnt=0;
    if(fsw<TARGET_FREQ){
      if(lowspeed){
        fsw+=1;
      }else if(highspeed){
        fsw+=15;
      }
    }
  }
  delayMicroseconds(delay_time);
}

Discussion