![]() |
iPhone6s plus、カメラの性能すげええ |
前回はとりあえず20khzで発振して、ボリュームに応じてデューティー比を変えるだけで32bit CPU Cotrtex-M0をまったく活かしておりませんでした。
今回は、少し仕事をしてもらっています…とはいえ、8bitどころか4bitで十分なレベルなのですが。
■仕様■
出力電圧をボリュームで設定できるように。■実装■
メインループでは設定電圧と現在の電圧を測定し、その差でパルス幅を設定します。設定電圧以上なら出力をオフにし、設定電圧より低ければその差に応じてパルス幅を決めます。差が大きければ大きいほどパルス幅を広くしてインダクタンスに貯める電力を増やします。その他、100m秒ごとに電圧設定のためのボリュームを読みに行きます。
■ハード■
前回はMOSFETとSBDの耐圧が限界となって電圧を上げられませんでした。今回は、耐圧500vのMOSFETと1000vのダイオード、それに400vの電解コンデンサを使います。ただ、一つ問題があって、高耐圧のMOSFETはゲートがオンになる電圧も高く、今回使った2SK3234の場合は約5v以上必要です。そのため3.3vのLPC1114では直接ドライブできないので、小さなMOSFETを一段追加しそれでゲートを駆動します。電源電圧も5v以上必要です。何かすごーい遠回りをしているような気もしますが、気にしないで作ります。
あとどのぐらいの出力かを示すLEDと、出力電圧を測定するための分圧抵抗などを追加しました。
なおMOSFETが1個余計に入ったので、出力の論理が反転しています。つまり、mbedから「1」を出力するとパワーMOSFETがoffになります。そのためにPWMへの出力では 1.0 - width としてデューティー比を反転させています。
■mbedのPWM■
当初はボリュームでPWM周波数を変更できるようにしていました。インダクタンスを使っているので、どのぐらいの周波数でパルスを出力するのが一番効率が良いのかをさぐるためです。で、100m秒ごとにボリュームからanalog inで読み取った値をもとにpwm.periodの値をセットしたのですが…これを行うとPwmOutの値を0にしていても100mSごとに出力がon / offする、つまり約5hzの太いパルスが出てしまいます。
設定電圧を0にしていても約40vの電圧が出てMOSFETがヤケに熱いので、何だろうと思ったのですが…ともかく回路が壊れなくて何よりです。
もう一つ、LEDをPWMで駆動しているのですが、当初まったく点灯しませんでした。これは、PWMの周波数がデフォルトのまま(約20m秒=50hz)なのにそれよりも早い周期でPWMへの書き込みを実行していたためです。ledに書き込みをしているループは1m秒で1回回りますので、それより十分早い10khzを出力するよう変更したところ、無事点灯しました。
いやはや…。
■動かしてみて■
設定電圧を急速に上げるとLEDが明るく点灯し、電圧が上昇して設定電圧に近づくとすーっと暗くなっていきます。逆に急に下げてやるとLEDはしばらく消灯した後、設定電圧に近づくとすっと点灯します。だいたい狙い通りです。強烈なノイズ発生源の近くにあるのでanalog inの値はそうとうバラついているはずで、安定しなければ移動平均処理を加えようかと思っていたのですが、なしでも安定してます。時間積分効果とでも言いましょうかw
なお、こういう制御(PD)の場合、設定電圧よりも少し低いところで安定します。今回はボリュームを使っているので気にならないですが、電圧を数値で設定する場合にはそのための補正が必要です。
昔、Skycamという製品のためにモーターぶんまわし系の制御をしていた時にはずいぶん苦労したものです…(遠い目
なお、現在、出力値と電圧差の関係は単純な比例ですが、より安定かつスムーズな制御を行うためには二次関数式で比例させることもできます。つまり電圧差が少ないときには少しだけパルスを出して、差が大きい時はドカッと出すわけです(何その小学生なみの表現)。その先にはPID制御などが…ってキリがないw
電源電圧5vと9vで試しましたが、どちらも200vまできっちり上がりました。一応設定限度を200vにしているんですが、波形を見る限りもうちょっと上げられそうです。消費電流は多いですねぇ…9v電源から100vまで上げた時で70mA前後です。冬の太陽だと手持ちの0.5w太陽電池では無理で、2-5wぐらいのセルでないと安定して動かすのは難しいでしょうねぇ。大きいと風の影響なども考えないといけないし…ああどんどん違う方向へ(笑)。
■ソース■
特に珍しいことはしていません。このソースはフリーで公開します。つまり、何にどう使ってもいいですが、責任は問いませんよライセンスです。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "mbed.h" | |
#include "rtos.h" | |
AnalogIn vol(dp4); | |
AnalogIn mea(dp11); | |
AnalogIn fre(dp13); | |
PwmOut pwm(dp18); | |
PwmOut led(dp1); | |
float prevPwm = 0.0; | |
void WritePWM(float inWidth) { | |
led = inWidth * 0.5; | |
if (prevPwm != inWidth) | |
pwm = 1.0 - inWidth; | |
prevPwm = inWidth; | |
} | |
float TargetVoltage = 0.0; | |
void CheckVolumes(void const *val) { | |
TargetVoltage = vol * 200; // max 200v | |
} | |
int main() { | |
pwm.period(1.0 / 25000); // 周波数25khz | |
WritePWM(0.0); | |
led.period(1.0 / 10000); // LED10khz | |
RtosTimer checkTimer(CheckVolumes, osTimerPeriodic, NULL); | |
checkTimer.start(100); | |
while(1) { | |
float voltage = mea * 330; // 分圧比1/100、3.3vフルスケール | |
if (voltage > TargetVoltage) { | |
WritePWM(0.0); | |
} else { | |
float d = (TargetVoltage - voltage) * 0.005; | |
if (d < 0.0) { | |
d = 0.0; | |
} else { | |
if ( d > 0.8) { | |
d = 0.8; | |
} | |
} | |
WritePWM(d); | |
} | |
Thread::wait(1); | |
} | |
} |
0 件のコメント:
コメントを投稿
注: コメントを投稿できるのは、このブログのメンバーだけです。