SSR でゼロクロス制御 (サイクル制御) による電力調整をやってみています。
前回は SSRで電力調整をやってみた (回路図) で、実験回路を組み立てました。
回路ができましたので、今回は Arduino のスケッチを書きます。
基本的な制御方法
基本的な制御方法ですが、ゼロクロスパルスに同期して SSR をオンするトリガパルスを出したり、出さなかったりすることにします。
なお、当初は 18 半サイクル ( 60Hz で 150ms ) で考えていたのですが、18 って数字はコンピューター的には中途半端ですよね。16 にすれば 2 バイトのビット列で表現できますから、16 半サイクル ( 60Hz で 133ms ) を制御することにしました。
たとえば、電力を 50% にするには電圧を 71% にすればよいので、16 半サイクルの内 11 半サイクルをオンにし、残りの 5 半サイクルをオフにします。
オンオフは 2 バイトのビット列で指定します。電力 50% のときは「0b1111111111100000」って感じ。16 進数で表現すると「0xffe0」です。
できるだけオンオフを均等にするために「0b1110111011101100」ってしてもいいです。16 進数では「0xeeec」になります。今回はこちらを採用しましょう。
スケッチ
全体のスケッチは以下のようにしました。
- // AC-Dimmer-SSR v.1.1 2020.10.30 by meyon
- int interruptPin = 2;
- int outputPin = 4;
- volatile bool zero = false;
- int cycle = 0;
- int trigger = 0;
- unsigned int pattern[11] = {
- 0x0, // 0%
- 0xc8c0, // 31%
- 0xccc8, // 44%
- 0xeccc, // 56%
- 0xecec, // 63%
- 0xeeec, // 69%
- 0xeeee, // 75%
- 0xfeee, // 81%
- 0xfefe, // 88%
- 0xfffe, // 94%
- 0xffff //100%
- };
- void zeroCross() {
- zero = true;
- }
- void cycleControl(int level) {
- noInterrupts();
-
- if(zero) {
- trigger = bitRead(pattern[level], 15-cycle);
- cycle++;
- if(cycle > 15) {
- cycle = 0;
- }
- zero = false;
- }
- interrupts();
- }
- void setup() {
- pinMode(LED_BUILTIN, OUTPUT);
- pinMode(outputPin, OUTPUT);
- attachInterrupt(digitalPinToInterrupt(interruptPin), zeroCross, RISING);
- }
- void loop() {
- int inputValue = analogRead(A0);
- int dimmerLevel = map(inputValue, 0, 1024, 0, 11);
-
- cycleControl(dimmerLevel);
- digitalWrite(LED_BUILTIN, trigger);
- digitalWrite(outputPin, trigger);
- }
10 ~ 22 行はサイクル制御のパターンデータ、電力比でだいたい 10% 刻みになっています。
前述のように、たとえば 0xeeec はビット列で 0b1110111011101100 ですから、16 半サイクルの内の 11 半サイクルをオンにするという意味です。電圧比で 11/16 = 68.8% 、電力比では ( 11/16 )2 = 47.2% となります。
24 行の zeroCross() はゼロクロスパルスが入ったときの割り込みハンドラです。ここでは zero フラグをセットするだけです。
28 行 cycleControl() で SSR を駆動するトリガパルスを生成します。
最初のゼロクロス割り込みが入ると、制御データのビット列の左端の値を取り出します。ビットの取り出しには bitRead() という関数を使ってみました。そして zero フラグをリセット。
次のゼロクロス割り込みで、今度は制御データの左から 2 番めの値を取り出し、zero フラグをリセット、さらに次の割り込みを待ちます。
これを 16 回繰り返して、また制御データの先頭に戻ります。
loop() では最初に、49 ~ 50 行でボリュームからの入力を読み取って調整レベルを決めます。その値を cycleControl() に渡して、戻ってきた制御データ trigger にしたがって出力の HIGH 、LOW を設定しています。
ちなみに LED_BUILTIN も制御していますが、これはおまけです (^_^;)
LED_BUILTIN が繋がっている 13 番ピンは、Arduino の起動時にブートローダによって一時的に HIGH になります。そのときに SSR もオンしてしまうので、出力として使用するのは適当ではないです。
だからといって放置すると動作中に LED_BUILTIN がボヤッと点灯してしまうので、pinMode() を OUTPUT に設定し、ついでに出力インジケータとして点灯させてみました。
動作状況
では、実際に SSR を接続し動かしてみましょう。
オシロスコープは SSR へのトリガパルスを表示しています。上にあるのは出力確認用の 100V 40W の電球です。
右下の半固定ボリュームをゆっくり回していくと、トリガパルスが出力され電球が点灯します。
ボリュームを回すにしたがって、トリガパルスのオンの時間が多くなって、電球もより明るく点灯するようになっていきます。
最後はトリガパルスがオンのままになり、電球も 100% 点灯となります。
交流出力はもちろんゼロクロスでオンしています。
でも、制御中は交流の波形が一部欠けることになるので、見てのとおり電球は点滅してしまいます。こうした制御は電球の明るさを調整する方法としては適当ではありません。ヒーターのような負荷の制御であれば問題ないですね。
ただし、一般的にこうした負荷は温度が低いときに抵抗が小さい傾向がありますので、突入電流が発生して負荷を痛めてしまうことがあります。ちなみにこの 40W 電球の消灯時の抵抗値は 25Ω ほどですから、点灯した瞬間には定格の 10 倍の電流が流れます。このあたり、注意が必要です。
では次回は、この実験回路をさらに改造してみようと思います。