で、以前、赤外線リモコンのボタンを押すとLEDが点滅して誰かが呼んでいることを知らせてくれるデバイスを作りました。結構便利でした。
でもね、所詮はLED、仕事に夢中になっていると気づかないことも。
ということで、作りました。少し大きなリモコン付きのLチカを。
ビデオでは最大1wぐらいにおさえていますが、フル点灯30wの状態を直接見ると目が痛いです。
■材料■
プラットフォームはmbed、LPC1114FN28とLEDドライバと電源、それに赤外線受光器です。以前、「普通の基板に表面実装パワーLEDを並べて何ワットぐらい点灯できるか?」を調べようとElecrowで起こした基板を引っ張りだしてきました。うーん、まだホームリフロー試行錯誤中だったので表面実装のハンダが汚いorz せっかく基板を作るのだからとファン駆動回路やPIR接続ピンなどインタフェースがてんこ盛りになっており、その1つとして「赤外線受光器インタフェース」も付いてます(実は基板見るまですっかり忘れてた)。よくある5v電源3ピンの赤外線受光器を挿すだけで使えます。なお、私が買ったものは5v電源を与えてもVoutが3vまでしか上がらないものだったので直結していますが製品や電源電圧によって異なります。買ってきたら出力電圧を確かめてもし3.3vを越えるようならば電源を3.3vにするか出力を抵抗で分圧してください。
手前の黒い直方体はDC/DCです。24vから3.3vまで落とすとさすがに通常の三端子レギュレータはかなり熱くなります。
LEDドライバはCL6807を3セット、電流検出用のシャント抵抗は0.1ΩなのでLED 7個ずつの各ストリングには1Aまで流せます。電源24vではVfの7倍にはちょっと足りないのですが、そこはマージン見越して動かしてます。なお、CL6807は秋月の「1000mA 可変定電流パワーLEDドライバーキット」にも使われています。このキット、我が家の洗面台の自動点灯LEDにも使っていますが、安定していて使いやすいです。ただし、マイコンから制御するためには多少の改造が必要です。CL6807はバラでも売ってますし、プリント基板を起こさなくてもSOT89-5用基板とSBD、シャント抵抗(0.1 - 1.0Ω)、4.7μFの積層セラミックコンデンサ、ユニバーサル基板があれば自作も可能です。なおメーカーの応用回路例には書いてないのですが、LEDへの出力の両端にパスコン(1μF)をつけると点灯が安定します。
なお基板の裏には放熱器を高品質グリースで貼り付けてありますが、これぞ焼け石に水。フルパワーにすると室温20度でも基板温度は50度を越えていきます。我ながら何をしたかったのかわからない基板です(笑)。
■ソフト■
AQ0802、IR Receiverなどのライブラリを使って、組み立てました。ループは1秒間に10回まわっていて、Lチカの基本周期となっています。リモコンの信号を受けると、「あと何回点滅させるか」という変数に値を代入します。その変数が偶数なら点灯、奇数なら消灯、という決まりにすることで、0.1秒ごとにペカペカ点滅します。これだと複数のLEDを逆相や追いかけるように点滅させるのがラクです。
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
// Bright board | |
// ver 0.0 ボードのテスト用。ボリューム輝度調整、温度による出力制限など | |
// | |
// ver 0.1 2016-01-08 IR Receiverを追加してリモコン通知機能として実装 | |
// | |
#include "mbed.h" | |
#include "AQM0802.h" | |
#include "ReceiverIR.h" | |
// PWM Outputs | |
PwmOut white(dp18); | |
PwmOut warm(dp1); | |
PwmOut yobi(dp24); | |
PwmOut fan(dp2); | |
// LCD | |
I2C i2c(dp5, dp27); | |
AQM0802 lcd(i2c); | |
// IR Receiver | |
ReceiverIR irReceiver(dp4); | |
// Analog input | |
AnalogIn vol(dp9); | |
AnalogIn sensor(dp13); | |
// | |
// temperature calc | |
// | |
const float ReferenceVoltage = 3.3; | |
float readTmpSensor() { | |
return (sensor*ReferenceVoltage - 1.951) * -121.95121951219512 - 30.0; | |
} | |
// | |
// main | |
// | |
int main() { | |
uint8_t buf[32]; // string convesion buffer | |
uint8_t hex[20]; // hex convertion buffer | |
white.period_ms(1.0); // set all pwm freq. 1khz | |
warm.period_ms(1.0); | |
yobi.period_ms(1.0); | |
fan.period_ms(1.0); | |
white = 1.0; // turn off all pwm ports | |
warm = 1.0; | |
yobi = 1.0; | |
fan = 1.0; | |
RemoteIR::Format format; // received format identity | |
int bitcount; // number of bits | |
lcd.cls(); | |
int countWhite = 0; // led blinking flag / counter | |
int countWarm = 0; | |
while(1) { | |
if (irReceiver.getState() == ReceiverIR::Received) { // check ir receiver | |
// got signal | |
bitcount = irReceiver.getData(&format, buf, sizeof(buf) * 8); | |
// convert to hex string | |
int len = bitcount > 8 ? 8 : bitcount; | |
int p = 0; | |
hex[0] = 0; | |
for (int i = 0; i < len; i++) { | |
char temp[4]; | |
sprintf(temp, "%02x", buf[i]); | |
hex[p++] = temp[0]; | |
hex[p++] = temp[1]; | |
} | |
hex[p] = 0; // end of c string | |
hex[8] = 0; // 念のため | |
lcd.locate(0,1); | |
// turn on if defined signal | |
hex[8] = 0; | |
if (strcmp((char *)hex, "10eff807") == 0) { | |
countWarm = 8; // button 'A' | |
} else if (strcmp((char *)hex, "10ef7887") == 0) { | |
countWhite = 16; // button 'B' | |
} else if (strcmp((char *)hex, "10ef58a7") == 0) { | |
countWhite = 19; // button 'C' | |
countWarm = 20; | |
} else { | |
lcd.print((char *)hex); | |
} | |
} | |
// | |
// volume | |
// | |
float a = vol; | |
int i = a * 1000; | |
char buf[32]; | |
// display volume value | |
// lcd.locate(0, 0); | |
// sprintf(buf, "vol%5d", i); | |
// lcd.print(buf); | |
// | |
// temperature sensor | |
// | |
float tmp = readTmpSensor(); | |
i = tmp; | |
lcd.locate(0, 1); | |
sprintf(buf, "tmp%5d", i); | |
lcd.print(buf); | |
// | |
// fan's control : turn of if temperature over 30.0 degree | |
// | |
fan = (tmp >= 30.0) ? 1.0 : 0; | |
// | |
// if temperature is over 35.0, limit the output power | |
// | |
if (tmp >= 35.0) { | |
float hosei = (40.0 - tmp) / 5.0; | |
if (hosei > 1.0) hosei = 1.0; | |
if (hosei < 0) hosei = 0.0; | |
a = a * hosei; | |
} | |
// reverse pwm duty | |
a = 1.0 - a; | |
// | |
// check led | |
// if counter is even, turn on. and decrement the counter for next loop | |
if (countWhite > 0) { | |
white = (countWhite % 2) == 0 ? a : 1.0; | |
countWhite --; | |
} | |
if (countWarm > 0) { | |
warm = (countWarm % 2) == 0 ? a : 1.0; | |
countWarm --; | |
} | |
// loop period is 0.1 sec | |
wait_ms(100); | |
} | |
} |
0 件のコメント:
コメントを投稿
注: コメントを投稿できるのは、このブログのメンバーだけです。