僕はといえば、他の班の発表のポスターの出来が凄くて発表前ちょっと焦りました^^;
さて、今回は、僕達が制作したリニアモーターカーを駆動する回路、即ち三相インバータの回路図とプログラム(スケッチ)をこちらで紹介しようと思います。なお、語句の説明は記事の最後を参照してください。
1. 回路図
回路図を下に示します。
図1 三相インバータ回路図
今回、僕が作成した三相インバータは、直流電源からPWM(パルス幅変調)を用いてMOSFETのスイッチングを行うことで三相交流を作り出す、ごく一般的なインバータです。
2つのNch型MOSFETが1つのスイッチを構成しており、それを3つ用意することで1つの直流電圧から3つの独立した出力電圧を発生させることが出来ます。3つのスイッチを適切なタイミングで切り替えていくことで位相差が120度の3つの交流を発生させます。
スイッチングをするための信号はArduino(マイコン)とハーフブリッジドライバによって生成されます。Arduinoの出力ピンから3つの信号線が出ており、それらはMOSFETに接続されているハーフブリッジドライバのV_INに接続されています。ハーフブリッジドライバはV_INからの入力を元にHOとLOから信号を出力し、2つのMOSFETを同時に制御します。
各MOSFETのドレイン・ソース間に接続されているダイオードは還流ダイオードと呼ばれ、モータのような誘導性負荷を出力に接続した場合に発生する逆起電力によるMOSFETの破壊を防止します。誘導性負荷は電流の急激な変化をすることができず、スイッチングをしたときにソースに電流が流れ込んでくる可能性があるため、電流の逃げ道として接続してあります。
3つの出力端子(U/V/W)には三相交流を用いる負荷(ここではリニアモータを指す)を接続します。詳しい話は省略しますが、リニアモータは三相誘導電動機を切り開いた形となっているので配線も切り開いた形で行います。
ちなみに、直流電源に並列に接続してあるコンデンサはバイパスコンデンサの役割を持たせています。電圧の急激な変化を平滑化する働きがあります。
2. プログラム(スケッチ)
Arduinoでは、プログラムのことをスケッチと呼びます。(以下スケッチと呼ぶ)
スケッチを以下に記します。
//使用するピンの指定 13番ピンは内部LEDによるクロック表示用
int Uout=3;
int Vout=9;
int Wout=11;
int Clock=13;
int tsumamiPin = 0;
//各種変数の宣言
int sinw[360];
int InductorU = 0;
int InductorV = 120;
int InductorW = 240;
int ang;
int MODE;
int mag;
double f, d;
double tsumamiHenkan = 1.0;//出力電圧の振幅の大きさの倍率
long t1, i;
//初期化
void setup() {
t1=millis();
Serial.begin(9600);
//1度単位のsinのテーブルを作成
mag = 96;//0~127の範囲で設定
for(ang=0;ang<360;ang=ang+1){
sinw[ang]=mag*(sin(ang * 3.14/180)+1);
}
//各出力ピンのモードを出力に設定
pinMode(3, OUTPUT);//インダクタ接続
pinMode(9, OUTPUT);//
pinMode(11, OUTPUT);//
pinMode(13, OUTPUT);//内部LED接続
}
//メインプログラム
void loop() {
//6周期(2160/360=6)ごとに方向を転換する
if(i % 4320 == 2160){
InductorU=0;
InductorV=120;
InductorW=240;
Serial.println("GO");
Serial.print(f);
Serial.println("Hz");
}
else if(i % 4320 == 0){
InductorU=0;
InductorV=240;
InductorW=120;
Serial.println("BACK");
Serial.print(tsumamiHenkan*12*mag/127);
Serial.println("V");
}
f = (double)analogRead(tsumamiPin) * 0.007595308;//可変抵抗の値から周波数を計算する
//f = (double)analogRead(tsumamiPin) * 0.01;
if(f >= 0.001){
d = 1.0/(f * 360.0);
}
else if(f < 0.001){
d = 0.01;
}
//v/f制御 周波数に比例して電圧を変化させる
if(analogRead(tsumamiPin) > 256){
tsumamiHenkan = analogRead(tsumamiPin)/1023.0;
}
else{
tsumamiHenkan = 0.25;
}
//PWMで出力ピンから電圧を出力する
analogWrite(Uout, sinw[InductorU] * tsumamiHenkan);
analogWrite(Vout, sinw[InductorV] * tsumamiHenkan);
analogWrite(Wout, sinw[InductorW] * tsumamiHenkan);
//1周期ごとに内部LEDを点灯させる
if(InductorW == 0){
digitalWrite(Clock, HIGH);
}
else{
digitalWrite(Clock, LOW);
}
//U,V,Wの角度を進める
InductorW = update_phase(InductorW);
InductorV = update_phase(InductorV);
InductorU = update_phase(InductorU);
//設定した周波数に応じて遅延させる 遅延関数の仕様により使い分ける
if(d * 1000000.0 > 16383.0){
delay(d * 1000.0);
}
else{
delayMicroseconds(d * 1000000.0);
}
//delay(d);
i++;//角度をカウントアップする
}
//角度を進める
int update_phase(int Inductor){
Inductor = Inductor+1;
if(Inductor>=360) Inductor=0;
return Inductor;
}
コメントに沿ってスケッチを見ていきましょう。
最初に、ピンの指定を行います。使用するピンは出力3,9,11,13番、入力0番ピンです。
インバータ駆動用の信号線は3,9,11番ピンです。これらのピンはPWM出力が可能で、周波数は約490Hzです。
13番ピンは交流電圧が一周期変化した時にArduino内部のLEDを点灯させるためのものです。
入力0番ピンは可変抵抗の値を読み取る為に用います。(後述)
続いて変数を幾つか宣言していますが、後ほど正体がわかりますので割愛します。
初期化のブロックでは、PCとのシリアル通信の開始、正弦波の値の計算、出力ピンのモード設定を行います。
PCとの通信は主にデバッグ用で、車両の向き、交流の周波数、出力電圧をPCに表示させます。
正弦波の値を1度刻みで360度まで計算し、配列に代入します。Arduinoの性能的にリアルタイムで値を計算させると処理落ちする可能性があるため、それを回避するためにここで事前に計算させます。
出力ピンのモード設定はお忘れなく。
さて、メインプログラムに入ります。が、ここで三相交流について軽く触れましょう。
三相交流において、U相、V相、W相から出力される電圧は位相差が120度です。位相の正負を変えることで回転磁界の方向(≒モータの回転方向)を変えることが出来ます。ちなみに普通の交流でもモータを動作させることが出来ますが、回転方向は起動時の方向に固定されてしまいます。
さて、各相の角度は先程の変数の宣言のブロックで初期化を行っていました。初期値は0度、120度、240度にしてありますので、この角度から1度ずつ進めていきます。角度が2160度(6周期)進んだときに、各相の角度は0度、-120度、-240度で初期化され、車両の走行方向が逆転します。これを繰り返すことで周期的な往復走行を実現します。
周波数の設定は入力ピンに接続された可変抵抗の値から計算します。適切なレンジに設定しましょう。なお、f=0のときに周期が∞にならないように適当な値を代入しています。
今回のミソである、V/f制御のブロックです。ここでは周波数に応じて出力電圧の倍率を変化させます。
V/f制御とは、出力電圧と周波数を1次関数的に変化させることで低速から高速までトルクを一定に保ったままモータを動作させることを可能にする制御方式です。今回は比較的滑らかに走行する電圧と周波数のデータを取り、それを元に関数を決定しました。なお、低速時には大きなトルクが必要となる(トルクブースト)ので、電圧を固定するようにしてあります。
そして、PWMで出力ピンから電圧を出力します。初期化ブロックで計算した正弦波の値と先程の倍率を掛け合わせることでリアルタイムで出力電圧を変化させます。(まぁこっちの方がマイコンの負荷も軽いでしょう^^;)
これまでの動作が終了したところで角度を一度進め、遅延させます。
遅延させるというのはArduinoではよく使われる手法ですが、○秒電圧を出力するというときに使います。周波数の設定でお気づきの方もいるとは思いますが、周波数から周期を計算し、それを360で割った値を変数dに代入しています。dは”角度が1度進むときに電圧を出力する時間”というわけです。まぁあれですよね。連続関数もコンピュータで離散的に処理する必要があるってわけです。
遅延関数は仕様の関係で使い分けています。
ざっと説明しましたが、いかがでしょうか。何か意見がありましたらコメントをよろしくお願いします。
※PWM(パルス幅変調)・・・電圧のオンオフの時間の比率(デューティ比)を変化させ、平均的に任意の電圧を出力する手法
※MOSFET・・・金属酸化物半導体を用いた電界効果トランジスタ。ソース、ゲート、ドレイン端子を持ち、ゲートに電圧をかけることでソースからドレインに電流の通り道が生成され、導通する。
※インバータ・・・直流を交流に変換する回路。対して交流を直流に変換する回路はコンバータと呼ばれる。なお、NOT回路のことではない。
もし往復走行させないのであればどのようなプログラムになるか知りたいのですが
返信削除void loop()のすぐ下にあるifとelse ifによる分岐を削除すれば片道走行になります。電圧の位相を再び初期化しない限り向きは変わりません。
削除インバータ回路の自作を調べていてこちらのページを見つけました。Arduinoのスケッチの部分で
返信削除//1度単位のsinのテーブルを作成
の下にあるforループ文の表示がうまく表示されない(こちらのブラウザの所為?)為かスケッチのコンパイルができません。表示の修正が可能であればお願いします。
コメントありがとうございます!
削除スケッチの表示にミスが有りました。修正しましたので動作の確認をお願いします。
返信ありがとうございます!
削除無事コンパイルすることができました!
当方電子回路初心者で大変参考になります。
arduinoとは別のSHマイコンを使い、V/F制御でモータを制御しようと思っているのですが、「v/f制御 周波数に比例して電圧を変化させる」という処理の内容を具体的に教えて頂けないでしょうか。
返信削除コメントありがとうございます!
削除スケッチのコメントの位置が良くなかったですね。
f = (double)analogRead(tsumamiPin) * 0.007595308;//可変抵抗の値から周波数を計算する
ここがV/f制御の実質的な計算式です。右辺は可変抵抗の値をPWMの電圧とし、それに定数をかけ合わせたものです。周波数fを電圧vに比例させているということです。
詳しい解説をありがとうございます!今自分もVVVFインバータを製作している途中なので、大変参考になりました。
削除http://www13.plala.or.jp/sunaverter/
返信削除を参考にリニアモーターを作成したいと思って、
色々検索していたら此方に辿り着きました。
コイルは自作ですか。それとも市販品ですか。
自作であれば、
導線の直径、長さ、
鉄心の直径、長さ、
鉄心への導線の巻数などを
教えて頂けますでしょうか。
また、市販品の場合、
メーカー名や型番を教えて頂けますでしょうか。
コメントありがとうございます!
削除二年前に制作したもので細かい仕様を覚えていないので、申し訳ないのですが詳しくはお話できません。
覚えている範囲でお話しますと、コイルは自作でネジに100回程度銅線を巻いたと思います。当初はLHL10NB104Jを使用することを考えていましたが、車両を十分駆動できる電磁力を得られなかったので見送りました。
後ほどこちらの記事に写真を追加しておきますので、参考にして下さい。
三相誘導電動機は何ボルトで駆動させましたか?
返信削除また、その際の回路とプログラムは記載されているものを使用しましたか?
返答よろしくお願いします。
あの、初歩的な質問になってしまったのですが、部品は何をいくつ使うのでしょうか?教えて下さい
返信削除