- PIC Controlled Dimmer, PICBasic Pro -
概要
いつの間にやら手元に5台、重宝している調光器。それに使われているトライアックとはなんぞや。3ピン構成で、そのゲートに電流を流すと他の2ピン間で交流が流れるという、いわば交流のSWの役目を果たすデバイスということである。今回はこのトライアックをPIC(12F675)で制御する実験をしてみた。もちろんPICのプログラム作成にはいつもの様にPICBasic Pro (BASICコンパイラ) を使った。
回路図
Web上のいろいろな記事を参考に以下のような回路を組んでみた。
1) AC100Vのトランスから電源DC+5Vをつくり、同時にAC50Hzの波形を取ってホトカプラに入れる。
2) ホトカプラではAC50Hzの波形がゼロになる時点(ゼロクロス)で、そのピン4が“L”から“H”になり、PICのGP1に入る。
3) このGP1に入る“H”パルスはAC50Hzの1サイクル毎に2個でき、その間隔は10msである。
4) この10ms毎に入るパルスをベースにPICの内部でソフト的に遅れパルスを作成し、GP0よりホトトライアックに送る。
5) ホトトライアックはそのパルスに反応し、トリガパルスをトライアックのゲート(G)に送り、T1とT2間を導通させる。
最初うまく動作しないので、一般に行われているPICのGP0を“L”に落としてホトトライアックのLEDを点灯させる方式の代わりに、GP0からLEDに“H”パルスを送ってLEDを点灯させる方式に変えた。そうしないとダメだった。
PICのGP0から出てホトトライアックに入るパルスとAC100V出力の波形との関係を知るために、負荷として60W電球をつなぎ、また小型のAC100Vトランス(安全とオシロを壊さないため)もつなぎ、その2次線側(10V)の波形をオシロで観察した。
実験の様子: 右下に大いに役立ったUSB式のオシロが見える
プログラム
PICBasic Pro派としては、トライアックの制御(ここでは位相制御という方法を使う)を出来ればその中の特有なコマンドを使ってやりたいと探したところ、Pulsin、Pulsout、さらにPauseusという便利なものが見つかった。以下がそれらの機能である。
例えば;
1) Pulsin: Pulsin GPIO.1, 1, InPulsW - PICのGPIO.1(GP1)より“H”の部分のパルス幅を測り、メモリInPulsWに保存する。
2) Pulsout: Pulsout GPIO.0, 2 - PICのGPIO.0(GP0)より“H”のパルスを2us(実際は、2 x 10us=20us for 4MHz clock)送る。
3) Pauseus: Pauseus 7000 - 7000usの間だけ待て(delay、遅れ値/Pauseus値と呼ぶ)というコマンド。ただし、あまり正確ではない。
‘************* 'プログラミング備忘録 ************
'Name of program: DimmerA.bas 2008.9.12 works at last!
'12F675 at 4MH (internal clock used)
'Program to control an AC 100V output by using a triac
'Its circuit was built up on a breadboard on 2008.9.12
'********* Pin connection ********
'Pin 1: Vdd (+5V)
'Pin 8: Vss (GND)
'Pin 7: GPIO.0: output - connected to Photo Triac's Pin 1 via R330 (its Pin 2 to GND)
'Pin 6: GPIO.1: input - connected to Photo Coupler's Pin 4
'Pin 5: GPIO.2: NC
'Pin 4: GPIO.3: input - MCLR/Reset
'Pin 3: GPIO.4: NC
'Pin 2: GPIO.5: NC
'*************** プログラム本体 ******************
TRISIO=%001010 'Set all pins except GPIO.1 & 3 as outputs
CMCON=7 'Turn off comparator function
ANSEL=%00000000 'All GPIOs=digital
InPulsW var Word 'Storage of Input Pulse Width (16 bits – up to 65536)
Repeat1:
GPIO.0=0
GPIO.1=0
Pulsin GPIO.1, 1, InPulsW 'Read the width of coming-in pulse and store it in InPulsW GPIO.1からのパルス幅を測り保存する
If 300 <InPulsW < 700 Then 'Restrict the width of pulse 異常なパルスを除く
Pauseus 7000 ‘Wait 7000us = 7ms: Delayをここでつくる。ゼロクロス点より7ms遅れた点でトリガパルスを出すを意味する.
Else
Goto Repeat1
Endif
Pulsout GPIO.0, 2 'Output "H" pulse for 20 us (2 x 10us=20us) GPIO.0より20usのパルスを送り出す
Goto Repeat1
End
'*************** プログラムの終わり ******************
'Note:
'AKI Programmer's configurations:
'FOSC – INTOSC (GP4:I/O); WDTE - Enable; PWRTE - Enable
'MCLR – MCLRpin, BODEN - Enable; CD - Disable; CDP – Disable
パルスの観察
電子工作20で使ったUSBデジタルオシロ(PicoScope 2105)を用いて関連する波形を測定した。最初、例によって回路やプログラムがうまく動作せず波形の測定をせざる得なかったというのが実際の話。おかげで以下の様にいろんなことが分かってきた。
1) ホトカプラのピン4から出てくるパルス(2pulses/cycle)でAC50Hzのゼロクロス点で立上り、その基底部での幅は約400usできれいである。
2) PICのGP0からホトトライアックのピン1に入るパルスで、理論上は20usのはずだが、実測では約37usあった。きれいである。パルス間距離は10msであるが、遅れ値(Pauseus値)によってゼロクロス点から一定時間づれた点で立上っている。
3) Pauseus値=850にした時のAC100V出力の波形である。ほぼ完全な50Hz波形である。この場合はもちろんAC出力は100Vで電球は明るく点灯する。
4) Pauseus値=1000 us: まだ出力の波形はほぼ完全な50Hz波形で、出力も100Vであった。
5) Pauseus値=2000 us: 出力の波形に欠けが見られる。出力は96Vであった。
6) Pauseus値=3000 us:欠けが目立つようになり、出力は83Vであった。電球も少し暗くなってきた。
7) Pauseus値=4000: 波形が半分近く欠けいるのが分かる。出力は65Vであった。
8)Pauseus値=5000:: 波形が半分以上欠けいるのが分かる。出力は38Vであった。
9) Pauseus値=6000: 波形の欠けがさらに進む。出力は25Vであった。
10) Pauseus値=7000: 波形の欠けがさらに大幅に進む。出力は3.6Vで、点灯がやっと認められる。
11)Pauseus値=8000: 波形の欠けがさらに進む。出力は1.7Vで、点灯もはや確認出来ず。
12) Pauseus値=8500: +側パルス消滅。出力は0.54Vで、点灯は確認出来ず。
13) Pauseus値=9000: 位相制御からはずれた場合。出力は59Vで、安定して点灯。
パルスの観察のまとめ
遅れ値(Pauseus値) us |
AC
出力 V |
備考:出力安定性、波形、電球の状態 |
500 |
60位 |
かなり安定、異常な波形、薄暗く点灯 |
700 |
60-90 |
不安定、異常な波形、点滅 |
800 |
100 |
安定、きれいな波形、フル点灯 |
850 |
100 |
安定、きれいな波形、フル点灯 |
1000 |
100 |
安定、ほぼ完全な波形、フル点灯 |
2000 |
96 |
安定、波形に欠け、フル点灯 |
3000 |
83 |
安定、波形の欠け拡大、明るさ多少低下 |
4000 |
65 |
安定、波形の欠けさらに拡大、明るさ多少低下 |
5000 |
38 |
安定、波形の欠け半分以上、明るさ大きく低下 |
6000 |
25 |
安定、波形の欠けさらに進む、明るささらに低下 |
7000 |
3.6 |
安定、波形の欠けの残り部分わずか、微かに点灯 |
8000 |
1.7 |
安定、波形の欠けの残り部分わずか、点灯確認できず |
8500 |
0.54 |
安定、波形の+側欠け残り部分消滅、点灯確認できず |
9000 |
59位 |
かなり安定、異常な波形、薄暗く点灯 |
上の結果から、遅れ値 (Pauseus値) を800 - 8500 usの間 (8500-800=7700, 7700/255=30.2us/step) で変化させてやれば、AC出力を AC100 - 0.5V に変化出来ることが分った。
このようにトライアックのコントロールの仕方が少し分かってきたので、今後次のようなことをしてみたい。
1) PICに2個のスイッチを追加し、AC出力のUP/DOWNを可能にする。
2) さらにリモートコントロール化する。
余談
最初、プログラムをいじってもうまく動作しないので、これはAC100Vも扱える2チャンネルのオシロが必要かと昔買った大きなアナログオシロをセットアップ。しかしマニュアル読んでも使い方よく思い出せず。そのうちトランスで電圧を落として交流を測ることを思いつき。今回使ったデジタルオシロ(最大±20V)で波形観察に及んだ。このオシロはPCのUSBにつないでソフトを立ち上げるだけで使え、得られた波形の保存や加工も自由自在。あらためてその素晴らしさ実感! 12F675を使った理由は12F629が手元になかったから。
2個のスイッチでAC出力のUP/DOWNが可能になった(2008.9.24) − これで決まり?
上記の回路図に、AC出力を上げたり下げたりする2個のUP/DOWNスイッチを下図のように取り付けた(写真中で左手上方の2つの青色の押しボタンスイッチ)。いずれのスイッチも通常は開放になっていて押すと導通する。例えば、AC出力に白熱電球をつないである場合、UPスイッチを押し続けると徐々に明るさが増し、DOWNスイッチを押し続けると徐々に暗くなる(別の写真に暗く点灯する電球が見える)。2個のスイッチを交互に押すことで適当な明るさに調整できる。
プログラム
上記のプログラムDimmerA.basをもとに、2個のスイッチに反応するようにこのプログラムを作成した。 スイッチを押している間AC50サイクルの1/2サイクル毎に”10” (プログラムの中のC=C+10またはC=C-10で使われている値)だけ遅れ値 (Pauseus値C)を上下させる。この値を大きくとるとAC出力の変化速度が速くなる。実験で”10”位が適当であることが分かった。この設定で、スイッチを押し続けてAC出力が0.72V(最少)から100V(最大)に達するまで約6秒間かかる。一回の早押しで約1Vの電圧上昇・下降が可能になる。システムの電源を入れると1秒間して(プログラムの中のPause 1000により)100V のAC出力が出る。この1秒間の待ち時間はシステムを安定化させるためで、無いと時折 61V位の不安点な出力が出てリセットが必要になる。
‘********* 'プログラミング備忘録 *********
'Name of
program: DimmerIn1.bas 2008.9.24 works very well.
'Program
to control an AC 100V output by using a triac
‘This
time UP/DOWN SWs were added.
'AC
output range to be controlled: 0.72V (C=8300) - 100V (C=850)
'12F675
at 4MH (internal clock used)
'*********
Pin connection ********
'Pin 1:
Vdd (+5V)
'Pin 8:
Vss (GND)
'Pin 7:
GPIO.0: output - connected to Photo Triac's Pin 1 via '330 (its Pin 2 to GND)
'Pin 6:
GPIO.1: input - connected to Photo Coupler's Pin 4
'Pin 5:
GPIO.2: NC
'Pin 4:
GPIO.3: input - MCLR/Reset
'Pin 3:
GPIO.4: UP SW to increase AC output
'Pin 2:
GPIO.5: DOWN SW to decrease AC output
'***************
プログラム本体 ******************
TRISIO=%111010 'Set all pins except GPIO.0 & 2 as inputs
CMCON=7 'Turn
off comparator function
ANSEL=%00000000 'All GPIOs=digital
InPulsW
var Word 'Storage of Input Pulse
Width
C var
word
'C=Delay value in us for controlling AC output 遅れ値で 16-bit長のデータである
Pause 1000 '1 sec for stabilizing 電源ON時の不安定な点灯を防ぐため。無いと時折AC出力が61V位に下がりリセットが必要になる
C=850
'AC output のfull 100Vに相当、システムの電源ONでAC出力は100Vになる
Repeat1:
GPIO.0=0
GPIO.1=0
Pulsin GPIO.1, 1, InPulsW 'Read the width of coming-in
pulse and store it in InPulsW
If 300 <InPulsW < 700 then 'Restrict the width of pulse
Gosub DelayValue
'ここでCの値を求めるSubroutine DelayValueに飛ぶ
Pauseus C
'C=Delay value in us この遅れ値がAC出力の大きさを決める
Else
Goto Repeat1
Endif
Pulsout GPIO.0, 2
'Output "H" pulse for 20 us (2 x 10us=20us)
Goto Repeat1
DelayValue: ‘Subroutine – この内部のロジックがキーポイント!
If GPIO.5=0 then Countup ‘DOWN SWの入力(when H->L)を読込んで Countupへ飛ぶ
If GPIO.4=0 then
Countdown 'UP SWの入力(when H->L)を読込んで Countdownへ飛ぶ
Goto Jump1 ‘そうでなければ(どのSWも押されてない)Returnへ飛ぶ。前のCの値がそのまま使われる。
Countup: 'Count-up routine of C value
C=C+10 '最初のC=850または現在のCにDOWN SWを押している間 AC 1/2 サイクルにつき10(実験で決定)を加える
If C>8300 then 'C>8300 (0.72Vに相当)なら, C=8300と固定せよ(0.72V以下にならないようにする)
C=8300
Goto Jump1
Else 'しかしC<8300なら、現在保存されている C の値を使い続けよという意味
Goto Jump1
Endif
Countdown:
'Count-down routine of C value
C=C-10 '最初のC=850または現在のCからにUP SWを押している間 AC 1/2 サイクルにつき10だけひく
If C<850 then 'C<850(100Vに相当)なら、 C=850 と固定せよ(100V以上にならないようにする)
C=850
Goto Jump1
Else 'しかしC>850なら、現在保存されている C の値を使い続けよという意味
Goto Jump1
Endif
Jump1:
Return
‘Subroutine DelayValue へ戻る
End
'***************
プログラムの終わり ******************
'Note:
'AKI Programmer's configurations:
'FOSC – INTOSC (GP4:I/O); WDTE - Enable; PWRTE - Enable
'MCLR – MCLRpin, BODEN - Enable; CD - Disable; CDP – Disable
結論・余談
1) UP/DOWNスイッチ2個でAC出力を自由にスムースに変えられるようになった。
2) AC出力の変化速度は、C=C+10やC=C−10の“10”の値を変えて調整できる。
オシロで波形を見て、UP/DOWNスイッチを押している時のAC出力が大変スムースに変化する様子が分かった。海外フォーラムで割込みやTIMER1を使ったPBPプログラムもあるが小生には難しく、しかも大きく良く分からなかった。実際、プログラムはこんなに簡単に出来るとは思わなかった。さらにリモートコントロール化するにはリレーか何かで、2つのスイッチを押すと同じような動作をさせるようにすればよい。 ジジイの久し振りの会心作?
問題発生したので改良(2008.10.5)
完ぺきと思っていたのだが次のような問題発生した。
1) 最大に明るく点灯している電球に振動を与えると、100Vより70V位に急に低下する現象(この状態でも比較的安定して点灯)が発生した。さらに振動を続けると元に戻ったり。この現象は100V (遅れ値 C=850) 近辺で起こり、DOWN SWを押してAC出力を下げた状態では起こりにくい。
2) 小型扇風機につないでも直ぐには回らない。UP/DOWN SWを調節するとなんとか回るがそのAC出力範囲は70ー99Vであった。オシロで見ると回らない範囲では波形がくずれていた。
結局、上記プログラム(DimmerIn1.bas)を下のように改良した。
1)
電源ON直後には、AC出力が60−70V位になるように遅れ値をC=4000に設定した。
2)
AC出力の上限付近で不安定な状態が発生するので、遅れ値をC=850 から C=930 に大きくした。
3)
AC出力の下限値も少し上げた。すなわち遅れ値をC=8300 から C=8000 に小さくした。
4)
トリガー用パルスの幅を200mS に広げた。
‘********* 'プログラミング備忘録 *********
'Name of program: DimmerIn2.bas 2008.9.21,24, 10.2 .works OK!
'AC output observed: 1.3V - 100V
'The other conditions are the same as those
of DimmerIn1.bas
'*************** プログラム本体 ******************
TRISIO=%111010 'Set all pins except GPIO.0 & 2 as inputs
CMCON=7 'Turn off comparator function
ANSEL=%00000000 'All GPIOs=digital
InPulsW var Word 'Storage of Input Pulse Width
C var word 'C=Delay value in us
Pause 500 '0.5 sec 電源ON時の不安な点灯(要リセット)を防ぐ ため必要
C=4000 '電源ON時にAC出力を中位レベルにする- 60-70V
Repeat1:
GPIO.0=0
GPIO.1=0
Pulsin GPIO.1, 1, InPulsW 'Read the width of coming-in pulse and store it in InPulsW
If 300 <InPulsW < 700 Then 'Restrict the width of pulse
Gosub DelayValue
Pauseus C 'C=Delay value in us
Else
Goto Repeat1
Endif
Pulsout GPIO.0, 20 'Output "H" pulse for 200 (10usx20=200us)
Goto Repeat1
DelayValue:
If GPIO.5=0 Then Countup 'Detect UP SW by picking up a falling edge
If GPIO.4=0 Then Countdown 'Detect DOWN SW by picking up a falling edge
Goto Jump1
Countup:
C=C+10
If C>8000 Then
C=8000
Goto Jump1
Else
Goto Jump1
Endif
Countdown:
C=C-10
If C<930 Then
C=930
Goto Jump1
Else
Goto Jump1
Endif
Jump1:
Return
End
'*************** プログラムの終わり ******************
'Note:
'AKI Programmer's configurations:
'FOSC – INTOSC (GP4:I/O); WDTE - Enable; PWRTE - Enable
'MCLR – MCLRpin, BODEN - Enable; CD - Disable; CDP – Disable
上記のプログラムのフローチャートは以下のように比較的簡単である。
結
結論・余談
1) 今回の改良で、白熱電球はフル点灯(AC99V弱)から完全消灯(AC2V以下)まで安定して点灯するようになった。
2) 交流の誘導モータは正弦波で回転するように設計されているため変形した正弦波では正常に回転させるのが難しくなる、という。
3) 小型扇風機(CF-420 Ac100V 50/60Hz 21/19W 泉精器製作所販売 \1500?):: 電源ONで回りだし、AC50−99Vでスムースに回り、99−100V超えると急に78V位に落ち回転が停止し、ブーンとゆう音が出る。したがってある程度実用的に制御ができる。
4)
機器換気用ファン(Maxi MA47B3S AC100-120V
0.32A 50/60Hz 日本サーボ製): AC10−100Vでスムースに回り、3V位で回転が完全に停止する。不安定な範囲ない。ほぼ完全にコントロールできる。中間域で多少異音がでる。
ちなみに、調光器は掃除機やミキサーに使われている整流子モータ(ユニバーサルモータ)の制御に限って使うことができるという話もある。
PIC Controlled Dimmer
developed by using PICBasic Pro (English version, 2008.10.16)
[Aim of this project:]
To control AC 100V (50Hz) using a triac and a PIC microcontroller (12F675)
1. A dimmer circuit was made and proven to function well.
2. A simple PBP program using no interrupt was made to control the dimmer.
[How it works]
In this system, when power is turned ON for the first time, AC output will be 60-70V. If DOWN SW (switch) is kept pressed, AC output voltage gradually decreases from 60-70V down to about 2V. If UP SW is kept pressed, AC output voltage gradually increases from 60-70V up to about 100V. That is, the controllable AC output voltage range is 2 to 100V.
[What were found]
This dimmer can smoothly control an incandescent lamp from 2V (light no longer visible) to 98-100V (full brightness). It can also control AC motors - some very well but the others not so well. For instance, a cheap electric fan (one I bought priced at \1500 years ago) rotated smoothly at a voltage range of 50 –99V but outside this range it didn't rotate properly while generating abnormal noise. An electric ventilation fan (diameter: 12 cm) that was perhaps designed for use in industrial electric equipment was found to rotate very smoothly over the entire range of 2 - 100 V. The appropriate range of Delay Value C that decides the trigger pulse position from each zero-cross point on the AC sine wave of 50 Hz was 930 to 8000.
[Conclusion]
The system seems to work all right No complicated interrupt function was necessary to introduce.
'****************** Memo ***************
'Name of program: DimmerIn2.bas
'AC output range observed: approximately 2 - 100V
'***************** Program ******************
TRISIO=%111010 'Set all pins except GPIO.0 & 2 as inputs
CMCON=7 'Turn off comparator function
ANSEL=%00000000 'All GPIOs=digital
InPulsW var Word 'Storage of Input Pulse Width
C var word 'C=Delay value in us (micro second)
Pause 500 '0.5-sec delay for system stabilization
C=4000 'Set AC output level to 60-70V when power is turned ON.
Repeat1:
GPIO.0=0
GPIO.1=0
Pulsin GPIO.1, 1, InPulsW 'Read the width of coming-in pulse and store it in InPulsW
If 300 <InPulsW < 700 Then 'Restrict the width of pulse
Gosub DelayValue 'Jump to subroutine DelayValue
Pauseus C 'C=Delay value in us
Else
Goto Repeat1
Endif
Pulsout GPIO.0, 20 'Send a 200-us H pulse from GP0 to Photo triac (10usx20=200us).
Goto Repeat1
DelayValue:
'UP/DOWN SWs checking routine to make a delay value C
If GPIO.5=0 Then Countup 'Detect UP SW by picking up a falling edge.
If GPIO.4=0 Then Countdown 'Detect DOWN SW by picking up a falling edge.
Goto Jump1
Countup 'Routine to gradually decrease AC output level down to Minimum voltage (about 2V).
C=C+10 '10 is an increment for changing AC output level. The smaller the value, the slower the changing rate will be.
If C>8000 Then
C=8000 '8000 gives the lowest AC output voltage (experimentally decided).
Goto Jump1
Else
Goto Jump1
Endif
Countdown 'Routine to gradually increase AC output level up to Maximum voltage (98-100V).
C=C-10
If C<930 Then
C=930 '930 gives the highest AC output voltage (experimentally decided).
Goto Jump1
Else
Goto Jump1
Endif
Jump1:
Return
End
'*************** End of program ******************
'Note:
'AKI Programmer's configurations: (AKI=Akitsuki Denshi – a local electronics shop)
'FOSC – INTOSC (GP4:I/O); WDTE - Enable; PWRTE - Enable
'MCLR – MCLRpin, BODEN - Enable; CD - Disable; CDP – Disable