電子工作が趣味の奴はアクアリウムを始めてもすぐ機材を改造しはじめるのでダメ

6月にメダカを飼い始めたところ完全にハマり感が出てきてしまい、最近アクアリウムのサイトばかり見ています。家の小さな水槽も、いまでは魚3種と貝とエビ、水草3種の豪華メンバーになってしまいました。

f:id:slideglide:20191116010919j:plain

水草抜けて浮いてるなこれ。
ところで今回は魚の話ではなくて、電子工作の話です。

水槽に照明をつけるんですよ。その方が魚がきれいに見えるし、水草を健康に保つには光が必要です。

f:id:slideglide:20191103192553j:plain

写真の照明が拙宅の水槽ライトです。

自動ON/OFFのタイマー付きで2000円。かなりコストパフォーマンスのよい品で、全体的には大変満足しております。しかしながら微妙に不満点もある。

まずその形状です。水槽だけを照らしたいので、できるだけ水面に近づけたいんですよ。しかしこれは水槽のふちにクランプで止めるタイプ。アームがあるので、どうしてもちょっと離れて上から照らす形になってしまう。それが一個目の不満です。まあこれは製品の不備というか自分がクランプ式を選んだのが悪いのですが。

次に、タイマー付きで24時間周期のうち何時間ONにするかを設定できるのですが、その設定がなぜか

f:id:slideglide:20191103192615j:plain

3時間、5時間、12時間の3種類。アクアリウムのサイトを見ていると、一般的な照明時間としては約8時間と言われています。ちょうどいい時間がないんですよ。これが2個目の不満。

あと最後に、タイマーで消灯設定の時間帯の挙動です。真っ暗になると思うじゃないですか。この照明におけるOFFの定義は「照明が暗くなる」なんですよ。おかしくない??

f:id:slideglide:20191103211442j:plain

これが証明OFF時の明るさです。けっこう明るい!薄明りってどうもコケ(アクアリウム用語でいうところのコケは藻類のことです。金魚の水槽放っておくと緑色になるアレ)が好むらしく、放っておくとコケだらけになります。コケ抑止のためにも真っ暗にしたい。それが3つめの不満。

そんなわけでぎりぎりかゆいところに手が届かないこのライトですが、ところで我々DIY派が商品に不満を持った時、やるべきことはAmazonにネガティブレビューを書き込むことではありません。改造することです。というわけでモリモリやっていきます。

まず修理

とそのまえに、実はこのライト、初期不良だったんですよ。買って10日くらいですぐ点かなくなってしまって、問い合わせたら新しいのを送ってくれました。
古いのは返さなくていいっていうので、新しいのはそのまま取っておいて、古い方を修理&改造したいと思います。

f:id:slideglide:20191114221029j:plain

リモコンの中身です。どうせ基板周りの接触不良だと思って開けたんですけど、原因がよくわからないんですよね。うーん、と思っていろんなところにテスターを当てていたその時…

f:id:slideglide:20191118190106j:plain

パチン!という音とともに、急に目の前が真っ白になりました。やべ、爆発した!!!!!!

俺は死んだのか…?と一瞬思ったのですが、どうも電源抜き忘れてたみたいで、急に直ってライトがついただけでした。びっくりした…。
結局、何が壊れていたのかわからずじまいですが、直ったし人生も終わらずに済んだので良かったです。
電子回路いじるときは忘れずに電源抜こうな。

アームをなくす

気を取り直して改造です。いじりやすいところで、まずは形状を変えていきます。クランプ+アームの形状から、水槽の上にかぶせるタイプに変えます。

f:id:slideglide:20191114210415j:plain

作業としては、リモコン→クランプ→アーム→ライト、となっている現構成から、まんなかのクランプとアームを切除して、リモコン→ライトにするだけです。

f:id:slideglide:20191114210656j:plain

クランプ部分を開いてこの線を切る

f:id:slideglide:20191114211022j:plain

ライト側のこっちの線も切る

f:id:slideglide:20191114212354j:plain

アームと一体化している黒い部分はライト本体のカバーの一部なのですが、これがなかなか外せなくて手間取りました。

f:id:slideglide:20191114213137j:plain

試行錯誤の末、アームの金属部にはんだごてを当てて加熱し、樹脂を少し溶かしながら回すと…

f:id:slideglide:20191114213515j:plain

抜けました。この工程に写真3枚もいる??って感じですけど、苦労したので…。

f:id:slideglide:20191114221723j:plain

あとは切った線をそれぞれ繋げます。

f:id:slideglide:20191114222204j:plain

あと、アームを抜いた部分が大穴になっていたので、

f:id:slideglide:20191114223312j:plain

別件でたまたま家にあったコーキング材で埋めました。水回りで使うものなので一応。
これで完成です!

f:id:slideglide:20191116010920j:plain
こっちは改造前のライト。アーム付き。

f:id:slideglide:20191116010839j:plain
改造後。アームの方も残してあるのでわかりにくいですが、光ってるのは水槽の上に直接乗せてるライトです。

若干ですが水槽内が明るくなった気がしないでしょうか。
あと光が漏れにくくなり、周囲が散らかっているのが少しカモフラージュできていますね。最高から二番目!(散らかっていない状態が最高なので)

タイマーの改造

さてここまでは線切って繋いだだけなので、電子工作的にはここからが本番です。タイマーの方をやっていきます。

  • 時間の設定を3、5、12時間以外も設定できるようにしたい
  • OFFの時に薄暗くするのではなく消灯したい

この2点の実装です。

搭載されているマイコンのプログラムを書き換えられれば簡単そうですが、到底無理なので、ハード的に解決します。
「ハード的に解決する」とはつまり、ライトのタイマー機能を使わずに、別のタイマー機器を使ってライトの電源供給自体をストップして消灯してしまう方法です。つまり擬似的に、コンセントを抜き差ししている状態を作りだすわけです。

実はそれをやるんだったら

コンセントにつけるタイマーが世の中にはすでにあります。でもかさばりますし、せっかくタイマー付きのライトを買ったのにまた買い足すのは癪じゃないですか。という謎のこだわりにより、自作していきます。

リレー&Digispark編

電子工作で、電源のON/OFFといえばこれです。

f:id:slideglide:20191117005937j:plain


リレーです。電気回路の接続/遮断を行う部品です。LEDライトの電源ラインにこれを挟めば、ライトのON/OFFができます。Arduinoとかから簡単に制御できます。

今回はコントローラーとしてArduinoではなくて、これを使います。

f:id:slideglide:20191117005849j:plain

Digisparkっていう、コインサイズの小さいArduino的なやつです。Arduinoでもいいのですが、できるだけ小さく仕上げたかったので。
Digisparkの内部クロックで時間経過を測ってリレーを制御、ONの時間だけ電源ラインを接続し、ライトに給電するという作戦です。

f:id:slideglide:20191104000429j:plain

試作。何となく動いてるっぽいのでそのまま基板実装します。

f:id:slideglide:20191117005732j:plain

できました!これをライトとACアダプタの間に挟めば、期待通りの動作をするはずです。

余談ですが、追加の機能として、タイマーをリセットするスイッチと、ライトの一時点灯スイッチもつけました。ここでハマったのですが、DigisparkはpinMode関数のINPUT_PULLUPが使えない(コンパイルは通るけど動作しないという激ヤバ仕様…というかこれ不具合では)ので注意してください。スイッチを使うにはプルアップ抵抗が必要。あとpin5はresetピンなので、入力のつもりで電圧かけると再起動します。この2つで3時間くらい悩みました…。

では、実際に水槽に設置してみましょう。テスト用に24時間周期ではなく5秒おきに点滅する設定にしています。

f:id:slideglide:20191117004723g:plain

いい感じですね!これで水槽のライトが、理想の動作をするようになりました…!


……と思ったのですが、1時間ほどの連続稼働の後にDigisparkに触ってみると、見事にアッツアツになっていました。燃えそう。近くにはエサやフィルタ材などの可燃物があるので引火すると怖いですね。これはダメだ。

再検討

なぜDigisparkがアッツアツになってしまうのか。いろいろ調べた結果、だいたいこんな感じだろうと思います。

これはリレーが電磁石で動いていることに起因します。いま使っているリレーは、デフォルトでOFF(というか遮断)になるタイプなんですね。そこにDigisparkから電流を流すと、電磁石がリレーの中の金属端子を引き寄せて、ONになります。
電磁石というのはけっこう電気を使うので、つまりONになっているあいだ、Digisparkはリレーにそこそこの電流を流し続けてるんです。

加えて電圧の問題もあって、Digisparkの電源はLEDライトの12VのACアダプタから取ってまして、しかしdigisparkに載っているマイコンは5V動作のため、Digispark内の部品が12V→5Vの電圧変換を行っているわけです。電磁石のために大電流を流すと、そこの変換に負荷がかかるのでアッツアツになる、ということです。(変換の有無にかかわらず、大電流流してる時点でマイコン自体がアツアツになりそうな気もしますが)

リレーをDigisparkに直結しないでコンデンサ噛ませば解決しそうな気もしないでもないですが、あとヒートシンク付ければ即解決な気もしないでもないですが、いずれにせよ毎日8時間もマイコンがアツアツになるほどのエネルギーを使い続けるのは省エネ的にイマイチなので、別案を考えることにします。

Arduino Nano & フォトカプラ編

みなさん、いいですか。聞いてください。ひらめきました。

これまでは、リレーを使ってACアダプタからライトへの給電自体を遮断していました。でもちょっとそれって野蛮じゃないですか?だってライト消すときいちいちコンセント抜かないじゃないですか。電源ボタンを押すのが文明人です。
そういうわけで、切り替え時には電源ボタンを押すことにしました。

といってもサーボモータで物理的に押すわけではなくて、回路的に押します。スイッチって、遮断されてる回路を、ボタンを押すことでつなげてるわけですよね。回路を接続したり遮断したりしている。それってつまり、リレーと同じじゃないですか。スイッチをリレーに置き換えれば、マイコンからLEDライトの電源ボタンを押せるわけです。

前回はLEDがONになっているあいだずっとリレーをONにしておく必要があり、過熱してしまいました。今回は、「ボタンを押す」という一瞬の動作にリレーを使うだけなので、ONにするのも一瞬です。なのでマイコンがアッツアツになるのも防げるというわけです。

さらに今回は、リレーをこの部品に差し替えます。

f:id:slideglide:20191115120407j:plain

これはフォトカプラという部品です。フォトリレーと呼ばれることもあるくらいでリレーとだいたい同じように使えるので、今回はこれを使うことにしました。

フォトカプラは、電磁石を使わないので少ない電力で動きます。そのかわりデメリットもあり、制御される方の回路に大きな電流を流せません。だからさっきリレーでやったような用途、つまりLEDライトの電源をフォトカプラ経由で取るようなことはできないんです。

でもボタン代わりにする程度なら問題なし。今回の用途にはうってつけです!

また、コントローラーもDigisparkからArduino Nanoに変えました。前回スイッチ周りのハマりで懲りたのに加えて、前者はマイコンの内部クロックで時間を測っており、後者は外部水晶がついています。こっちの方がタイマーの精度が高いはず。

Arduino Nano

Arduino Nano

f:id:slideglide:20191115120210j:plain

電源スイッチの両端から線を引き出しまして…

f:id:slideglide:20191117011329g:plain

試作。これはいける!!

さて、タイマーでのライトのON/OFFまでできましたが、実はこれ、まだひとつ問題が残っています。

前回の電源遮断方式では、リレーに電流を流せばライトはON、流さなければライトはOFFでした。マイコン視点だと自分が電流を流しているかどうかです。つまりソフトウェア側から、いまライトがついてるかどうかが簡単にわかるんですね。
しかし今回は、リレーに電流を流すたびにON/OFFが切り変わるしくみです。これってソフトウェア側からいまどっちかがわからないんです。ボタンを奇数回押したか偶数回押したかで推定はできますけど、あくまで推定なので、何らかの理由で途中でずれることもある。(例えば、途中で誰かが手でボタンを押したら?)

なのでいまLEDライトがONになっているかOFFになっているか、調べる手段を別途確保する必要があります。さてどうしよう…。

f:id:slideglide:20191116002329j:plain

OFF時はこの青いLEDが点くので、ここの電圧調べたら点灯状態わからないかな、とかいろいろテスターで調べていたのですが…

f:id:slideglide:20191116004720j:plain

どうもこのマイコンの足に、電源ON時だけ5Vが来ているようでした。表面実装の脇に無理やり銅線をはんだづけしました。いちばん端のピンでよかった…。
5Vなのは好都合です。直接Arduinoのピンにそのまま入れてデジタル入力で読み取ることができます。

f:id:slideglide:20191116005256j:plain

というわけで試作完成です!!

さて、実際に水槽に置いてみます。
実はこの記事の序盤、ライトのアームをなくした時に貼った、Afterの写真がその時の写真です。

f:id:slideglide:20191116010839j:plain

よく見ると左側にマステで留めたタッパーが写っていますね。この中にブレッドボードがそのまま入っています。
前回、先に基板実装したら結局ダメで苦労が無に帰してしまったので、今度はこのまま仮運用に移ります。

よいです

数日間運用してみたのですが、大変良いです。この実装であればArduinoがアツアツになることはありません。またタイマーも思いのほか正確で、秒単位で調べたわけではないですが、分単位ではだいたいあってそう。
申しぶんない感じですので、いよいよ基板実装して仕上げます。

f:id:slideglide:20191118131405j:plain

しました。

f:id:slideglide:20191118131341j:plain

フリスクのケースがちょうどいいサイズだったので収納しました。ケースの高さが足りずいろんなものがはみ出していますが…。また、コンパクトにまとめるために、もともとのリモコンと裏表で接着。

ついでにライト本体にもマジックテープで金具をつけて、水槽の上で安定するようにしました。
これで本当の本当に完成です。

f:id:slideglide:20191118212427j:plain

いい…。

作業時間捻出のためまるっと1週間寝不足が続きましたが、寿命と代償に水槽周りはかなりすっきりしました。

一回改造してしまうと、今後ほしい機能ができたときにまた拡張できそうなのもいいですね。「買ったデバイスが自分のものになった」という感じがします。

以下に技術情報を載せておくので、アクアリウムをやっていて腕に覚えがあり、かつ物好きな方はぜひチャレンジしてみてください。

技術解説

ここからはもうちょっと詳しい技術よりの話です。フォトカプラを使ってみたい場合など、参考にしてください。

f:id:slideglide:20191118013008j:plain

これがブレッドボード上での配線図です。フォトカプラはTLP222AFを使っています(ちなみに上に貼ったAmazonリンクは別の型番ですが、少なくともピン配置は同じでした)。4本足で、切り欠きがない方の2本には繋いだり遮断したりしたい回路を、切り欠きがある方はGNDとArduinoのOUTPUTピンにつなぎます。Arduinoとの間には抵抗を入れる必要がありますが、計算方法はYahoo知恵袋(!)に書いてありました。

f:id:slideglide:20191118013010j:plain
基板の配線図です。基本的には上のブレッドボードの接続図と同じですが、インジケータLEDを一個追加しました。

コネクタの配線です。カッコ内は上のブレッドボードの図での色。
0:ACアダプタの+(赤)
1:リモコンのマイコンにはんだづけした線(黄色)
2:ACアダプタのー(黒)
3,4:リモコンのボタンからひっぱってきた線(緑)
です。

さいごにArduinoのコード。

unsigned long startTime;
unsigned long offTime;
unsigned long nowTime;
int relayPin = 3;
int resetPin = 7;
int tempOnPin = 12;
int tempLedPin = 10;
int readLedPin = 2;

//オンにしておく時間を設定
int onHours = 9;


void setup() {
  pinMode(relayPin, OUTPUT); //フォトカプラ
  pinMode(resetPin, INPUT_PULLUP); //リセットスイッチ
  pinMode(tempOnPin, INPUT_PULLUP); //一時ONスイッチ
  pinMode(tempLedPin, OUTPUT); //一時ONスイッチのインジケータLED
  pinMode(readLedPin, INPUT); //ライトがONかどうか調べるためのピン

  offTime = 1000UL * 60UL * 60UL * onHours;
//  offTime = 1000UL * 1UL;
  
  delay(200);
  startTime = millis();

}

void turnOnLed(){ //ライトを点ける
  if (digitalRead(readLedPin) == LOW){
    digitalWrite(relayPin, HIGH);
    delay(20);
    digitalWrite(relayPin, LOW);
    delay(1000);
  }
}

void turnOffLed(){ //ライトを消す
  if (digitalRead(readLedPin) == HIGH){
    digitalWrite(relayPin, HIGH);
    delay(20);
    digitalWrite(relayPin, LOW);
    delay(1000);
  }
}

void loop() {
  nowTime = millis();
 
  //リセットスイッチが押されたらタイマーリセット
  if (digitalRead(resetPin) == LOW){
    digitalWrite(tempLedPin, HIGH);
    delay(500);
    digitalWrite(tempLedPin, !digitalRead(tempOnPin));
    startTime = nowTime;
  }
 

  //一時ONスイッチが入ってたら電源ON、そうでなければ経過時間による電源ON/OFF
  if ((nowTime - startTime) < offTime || digitalRead(tempOnPin) == LOW){
    turnOnLed(); 
  } else {
    turnOffLed();  
  }

  //一時ONスイッチのインジケータLED
  digitalWrite(tempLedPin, !digitalRead(tempOnPin));

  //24時間経ってたらタイマーをリセットして電源ON
  if ((nowTime - startTime) > 1000UL * 60UL * 60UL * 24UL){
//  if ((nowTime - startTime) > 1000UL * 2UL){
    startTime = nowTime;
    turnOnLed();
  }

  delay(100);
}


ポイントとしてはタイマーにmillis()を使っているところでしょうか。Arduino(というかそこに載っているAVR)は起動時点からの時間経過を内部でカウントしており、それをミリ秒単位で取得するのがmillis関数です。

今回のプログラムでは、ライトをONにしたタイミングでmillis()の結果をstartTimeに代入しておき、随時最新の結果と比較、設定した時間が経過していたらライトをOFFにしています。その後24時間まで経ったらstartTimeを現在のミリ秒で上書きし、再びライトをONにします。

注意点としてはこのカウンタはunsigned longなので、だいたい50日くらいでオーバーフローします。が、幸運にも今回のような前回時刻からの経過時間を求めるような処理では、特段配慮する必要はないようです。なんでこうなるのかもっと詳しいことがここに書いてあって、英語ですが読んでみると面白いです。

以上です。みなさまも良い水槽およびDIYライフを。

近況

f:id:slideglide:20191103193722j:plain

最近飼いはじめた貝です。これ。

2匹いると爆発的に増えるらしいので1匹だけにしました。

f:id:slideglide:20191103192740j:plain

ピンボケですみませんがグッピーの子供も生まれました。生まれたてと、ちょっと大きくなったやつ。