これはVVVFインバータを作ろうとした過程で私が考えたものであり、あっている保証は全くない。むしろ詳しい方はどんどん指摘していただければ幸いです。

 VVVFインバータを作るというからには三相インバータを作るわけだが、ここではゲート波形をどのように生成するか、もう少しいうとゲートドライバにどのような信号を入力するかを考える。
 三相インバータはシングルレベル出力であれば6個のスイッチング素子(IGBT, MOSFET)があるので、信号も6種類ある。アナログ回路でこれらを生成するのはおそらく非常にめんどくさいうえ、特性の変化に悩まされるだろうから、マイコンを使う。つまり、この記事はそのプログラムをどう考えるかという内容である。

 まず、インバータが出力すべきものは、UVW相のsin波である。といっても、各アームは0~(バス電圧)までの電圧しか出力できないので、バイアスがかかることになるが、各相の線間電圧はバイアス分は消えるので問題ない。出力できる線間電圧は-(バス電圧)~(バス電圧)となる。ここで、どの相もHi-Zにする必要は基本的にないので、ローサイドへの信号はハイサイドへの信号の反転(※1)となる。また、VW相はU相に対して位相の遅れがあるだけである。この時点で、非同期制御ならアップダウンカウンタでsinテーブルの値を基に比較レジスタを設定してPWMを出力するだけと分かる。カウンタ周波数が出力の周波数に対して十分高ければこれでいい。今回使おうと考えているSTM32F103系マイコンは誘導機の数十Hzに対して十分なスピードがあり、カウンタに4つの比較レジスタがあるため簡単にできる。なお、この手の制御では位相のずれをなくすためアップダウンカウンタを使う。以後は単にカウンタと表記する。
※1: 実際にはデッドタイムが必要なので、マイコンのカウンタにデッドタイム生成機能があればそれでもいいし、なければシュミットトリガNOTとRCD回路等の非対称の遅延を発生する回路が必要。

 同期制御の場合は、出力する周波数の倍数の周波数にカウンタを設定する必要がある。これ自体はMCUに計算させてカウントのトップ値を設定するだけである。実際にはできるだけ高い分解能を保つため、プリスケーラの設定も周波数の変化とともにすべきである。式にすると
となる。設定すべきカウンタ周波数とカウンタのビット数、プリスケーラの設定可能な分周比からカウンタのトップ値とプリスケーラの分周比を決める。アルゴリズムは
・ビット数上の最大値にトップ値を設定した場合の分周比を計算
・それよりも小さく、設定可能な最大の分周比を選択
・選択した分周比からトップ値を計算
となる。なお、トップ値が変わるときは比較レジスタも併せて変えなければならない。カウンタのレジスタはプリロードされてトップやボトムの時に実際の値が変更されるので、非同期で計算するのはいいが、
・周波数の変更はU相の位相が0[rad]の時
・電圧の変更は各相、位相が0[rad]の時
・電圧と周波数の両方を同時に変更しない
とすれば不連続な出力にならないのでいいかもしれない。電圧の変更に関しては上記の方法だと変更後1周期は電圧が不平衡になるのでU相0[rad]ですべて変更するほうがいいかもしれないが・・・(わからん)。これらを実装するなら
・計算結果をバッファ
・変更されたしるしのフラグを立てる
・割り込み処理でフラグを確認
・フラグが立っているなら値を変更
みたいな感じになると思う。

 ここで、三相インバータのパルス数の話をする。パルス数とは出力の半周期をPWMのパルス何個でsinに近似するかという数で、結論から言うと3*(奇数)か、1が望ましい。それ以外でも出力できるが、パルス幅が左右非対称になり、パルス幅を制御しづらくなる。これは図を見ればよくわかる
(パルス数)=3
(パルス数)=4
振幅: 1.0
出力: UV間(下のグラフ)
横軸: U相の位相[rad]
というわけである。とりあえずは3パルスモードについて考える。
 最初の疑問は「比較レジスタの値はどう決めるか」である。3パルスでは「カウンタ周波数は出力周波数に対して十分高い」という前提は無理がある。このため、比較レジスタはその区間のsinの平均値を設定することになる。こうすることで電圧的にsinと等価な出力が得られるはずである。ちなみに、非線形関数fでは「f(xの平均値)=f(x)の平均値」とはならないので、カウンタ周期の中央の時刻におけるsinでは誤差がある。実際、3パルスでは位相π/6~π/2の平均値が必要だが、この平均値は3*sqrt(3)/(2*π)≃0.827で、sin(π/3)≃0.866である。なお、振幅最大でもduty比は1にはならない。これは、矩形波は基本波の振幅が4/π倍になることからも予想できる。
 次は、「値をいつ変更するか」である。奇数パルスでは対称的な波形を得るにはトップ、ボトムの両方で値の変更が必要である。つまり、それらのタイミングで割り込みで比較レジスタを設定すれば、その値をもとにしたPWM出力が得られる。ただし、ある割り込み処理内でレジスタを書き換えても、それが反映されるのは次に割り込みが入る瞬間になると考えられる。なので1ステップ先の値に書き換える必要がある。
 これらをまとめて図にすると、こんな感じになる。
各場合1~6の設定すべき比較レジスタ値は以下のようになる。
ちなみに
である。
この平均値のテーブルを保存しておけばそれを読み出して振幅をかけるだけで比較レジスタ値が決定できる。また、カウンタ周波数は出力周波数の3倍と決まる。VW相については、V相ならステップ3から、W相ならステップ5から始めればよい。

 こんな具合で、9パルス、15パルスなどの場合も考えたいところだが、実はもうほとんど完成している。9パルスの場合はsin波の平均値を計算する範囲を2π/9ずつにすればいい。カウンタ周波数は出力周波数の9倍・・・とまあ規則性は単純である。なお、sin波は0~π/2までの値で0~2πまで生成できるため、平均値も範囲は限定できる。また、最初の平均値は必ず0なので、実は3パルスモードなら1個の値で、9パルスなら4個で事足りる。このあたりはMCUのメモリ、処理能力等から考えてどうするか決めればよい。個人的には全部記憶しておいて呼び出し処理を簡単にしたほうがいい気がする。
 ところで、1パルスモードだとこの理論は破綻する。平均値が常に0になるからである。そもそも、1パルスモードでは振幅を制御できない。1パルスモードというのはいわゆる120°通電であり、各相の出力はduty比を50%に保たなければ波形の対称性がなくなり、真っ当な交流出力ではなくなってしまうからである。制御できないといっても、回転数が上がればそのうちこのモードを使うだろうから、一応矩形波の生成方法を考える。考えるといっても簡単で、上の図で、r*a_s=1とすればよい。要するに1パルスモードとはduty比100%の3パルスモードである。なお、1パルスならカウンタ1周期で出力も1周期にすることもできるが、高々120Hzとかの誘導機用の三相インバータでは必要はない気がする。ただし、MCUのタイマーは比較レジスタがカウント値の下限値、上限値でも非常に短いパルスが発生することがある。これを回避する意味では1周期で出力する価値はある。

 かなり長文になってしまったが、ここまで読んでくれた方に感謝。