ソロでたのしむ

キャンプ、電子工作、DIY、乗り物などの趣味を紹介

無段変速フィニッシングモーターを自作しよう! 釣り竿のガイド交換用Arduino工作

こんにちは!

このところ魚釣りのトレーニングに集中していて、しばらく電子工作から遠ざかっていました~

電子工作も大好きなのですが、日常生活で使えるものを作りたい!ので、必要に迫られた時しか、はんだごてに手が伸びません。

そして魚釣りを楽しむ中で、釣り竿の糸を通す部分(ガイド)に錆が浮いてきたので、自分でガイドを新品に交換したいと思うようになりました。

交換作業の終盤で、エポキシ系の仕上げ塗装(フィニッシャー)をしないといけないのですが、これが半硬化するまでの約5時間ほど、竿をくるくると回転し続けないと、塗装が垂れてきて見苦しい仕上がりになってしまします。

・・・そこで・・・

久しぶりのArduino工作で、自動で釣り竿を回し続けてくれる装置を、自作してみます。

スピードコントロール フィニッシングモーターを自作します

 

スピードコントロール付きフィニッシングモーター

フィニッシングモーターって何なの?というご質問もあると思いますので、ご説明しておきます。

機能としては釣り竿を回転させ続けるだけ!というシンプルなもので、厚めの塗装を施す場合に、塗料のタレを発生しにくくするための道具です。

釣り竿を装着して作動させると、こんな感じです。

youtu.be

似たようなものとして、

  • 肉の丸焼き用のロティサリー
  • バームクーヘン製造機
  • ちくわ焼き機

がありますね!...食べ物系しか思いつきませんでしたけど。

要するに、長時間にわたって、ゆっくりと回転し続けてくれる、一部の界隈でのお役立ちアイテムです。

今回私が作りたいのは、硬化時間24時間のエポキシ塗料が釣り竿の表面に均一な被膜を形成するためのものになります。

それでは、回転方向と回転速度が調整できる、スピードコントロール フィニッシングモーターを自作しましょう!

用意するもの

フィニッシングモーターを自作するにあたり準備した主要な部品は、Arduino-Nanoと、ステッピングモーター28BYJ48です。

5Vで駆動するので、たいへん使いやすいステッピングモーターは、これまでも様々な自作品で活躍してくれました。

そのほかに必要なのは、モーター類を収納するプロジェクトボックスと可変抵抗(ボリューム)、そして配線に必要な電線やハンド付けキットなど、電子工作好きなご家庭には常備されていそうなものです。

配線

回路図をFritzingで作成してみました。

自作 フィニッシング モーター 回路図

はんだ付けが大変そうに見えますが、既製品のステップモーター駆動ボードを使えば、自分で配線するのは左半分だけになるので、ずいぶん楽ですよ~

無段変速フィニッシングモーターの回路

上の写真は、回路図とピン番号が少し違いますが、はんだ付け作業中のミステリーということで、ご理解とご容赦ください。

組み立て

電源は、5Vで数アンペア流せられれば大丈夫です。

私は家庭用コンセントを使いたいので、AC/DCコンバーターも収納するために、少し大きめのプロジェクトボックスを用意しました。

自作フィニッシングモーターの中身

Arduinoやコンバーターは、ホットメルトでボックスに固定しました。

ボックスの上面に、モーターと可変抵抗を取り付けて、本体が完成!

そして、釣り竿を固定する部分ですが、悩んだあげくに、

「その都度、マスキングテープで釣り竿を固定できれば良しとしよう~」

と決めました。

そこで、マスキングテープで固定しやすいように、ペットボトルのキャップとその付近をつけておきます。

ロッドのフィニッシングモーターを自作する

もっとスマートな方法が見つかったらバージョンアップするとして、当分はこれでいきます~

実使用

それでは、フニッシングモーターを動かしてみましょう~

実際に使っている途中で、エポキシ塗装をしている風景を撮影してみました。

youtu.be

可変抵抗で無段変速できて、正逆転も選べるようにしておいたので、なにかと便利です。

ちなみに、ボリューム調整は、

  • 中央で停止
  • 左右に動かすとその方向に回転しはじめて、徐々に速く

という仕様になっていきます。

硬化中は、最大速さよりも少し遅くした状態で、半硬化する5時間を目安に回転させ続けます。

使用したステッピングモーター28BYJ-48は、作動音が静かなので、長時間お部屋で動かしていても気になりません。

超有名メーカーの富士工業さんから美しい既製品を入手できますが、自作した無骨な物もいいじゃない!

<ご参考>

最後に、可変抵抗(ボリューム)1個で、回転方向とスピードをコントロールするスケッチ(プログラム)を紹介させていただきます。

なお、記事内の実物写真は、少し回路を変更しています。

このスケッチは、記事内の回路図どおりに配線した場合のスケッチとなります。

int motorPin1 = 4;    // Blue   - 28BYJ48 pin 1
int motorPin2 = 5;    // Pink   - 28BYJ48 pin 2
int motorPin3 = 6;    // Yellow - 28BYJ48 pin 3
int motorPin4 = 7;    // Orange - 28BYJ48 pin 4
int volumePin = 3;
long motorSpeed;
int motorSpeedtimes = 40;

int lookup[8] = {B01000, B01100, B00100, B00110, B00010, B00011, B00001, B01001};

void setup() {
  pinMode(motorPin1, OUTPUT);
  pinMode(motorPin2, OUTPUT);
  pinMode(motorPin3, OUTPUT);
  pinMode(motorPin4, OUTPUT);
  Serial.begin(9600);
}

void loop() {
   if( analogRead(volumePin) < 482 ) {
    motorSpeed  =  (512 - (482 - analogRead(volumePin))) * motorSpeedtimes ; // change into speed
    anticlockwise();
   }
   else if( analogRead(volumePin) > 542 ) {
    motorSpeed  =  (512 - (analogRead(volumePin) - 542)) * motorSpeedtimes ; // change into speed
    clockwise();
   }
   else {
    digitalWrite(motorPin1, LOW);
    digitalWrite(motorPin2, LOW);
    digitalWrite(motorPin3, LOW);
    digitalWrite(motorPin4, LOW);
   }
}

void anticlockwise()
{
  for (int i = 0; i < 8; i++)
  {
    setOutput(i);
      delayMicroseconds(motorSpeed) ;
}
}
void clockwise()
{
  for (int i = 7; i >= 0; i--)
  {
    setOutput(i);
      delayMicroseconds(motorSpeed);
}
}
void setOutput(int out)
{
  digitalWrite(motorPin1, bitRead(lookup[out], 0));
  digitalWrite(motorPin2, bitRead(lookup[out], 1));
  digitalWrite(motorPin3, bitRead(lookup[out], 2));
  digitalWrite(motorPin4, bitRead(lookup[out], 3));
}

DJI Action2とPocket2、じっくりスペック(仕様)比較します!

アウトドアを楽しむのに良い季節になりましたね〜

私もアウトドアを満喫しようと計画していますが、少し思うところがあります。

綺麗で見やすい動画にして、残しておきたい!

予想以上に長らく続いたインドア生活中に、「あの楽しかったアウトドア活動を動画で見返したい!」と思うことがあったのですが、もちろんそのような動画は残しておらず、断片的な思い出にふけるばかり...
ということで、気軽に使えるカメラを準備して、楽しい思い出をしっかりと残してみたいと思います。

DJI Action2とPocket2、じっくりスペック(仕様)比較

 

衝撃的に楽しいPocket2

さてさて、アクションカメラといえばGoProが有名ですが、他の人とは違ったものを使いたい〜という少しへそ曲がりな私。

1年ほど前に、歩きまわりながら綺麗な動画を撮りたいと思い、勢いでPocket 2を入手しました。

よくあるアクションカメラとは違ってジンバル付きのカメラなので、画像の安定性には疑いの余地がなく、またスムーズにカメラの向きを変えられるのも魅力的な機能でした。

私が入手した時は無かったのですが、最近になって白色も発売されていますね〜

目立たない黒色もいいですが、可愛さを感じられる白色も使っていて楽しそう!

私は黒色で、マイクや三脚などが付属しているコンボを選びました。

DJI Pocket2 (コンボ)付属品

初めて実物を見た時は、その小ささと軽さに驚きました。

片手でグリップしやすく、またジョイスティックなどの操作部が親指周辺にあって使いやすい!

録画モードもいろいろと準備されていて、動画撮影アマチュアの私には充分です。

そのうちの一つ、タイムラプスで撮影してみたのが、こちらになります。

youtu.be

ビーチでまったりと休日を過ごしていて、なんとなくサンセットを撮ってみたくなり、コンボに付属していた小型三脚を使って撮影してみました。

この時もそうですが、撮りたい時にさっと取り出して気楽に動画にできるので、旅行のお供には欠かせない相棒になっています。

Action2とPocket2を、スペック(仕様)で比較します!

旅行で使いやすいPocket 2ですが、メカニカルなジンバルのデメリットもあり、連続的な激しい動きに追従させるのは限界があります。

また、両手を自由に使いたい時には、三脚などで固定することになります。

ジンバル付きのカメラも楽しいですが、やはり両手をあけておきたいアウトドア活動には、アクションカメラが必要な気がする!

調べてみると、Pocket 2で慣れ親しんだDJIのラインナップにもアクションカメラはあり、小型でメカニカルな雰囲気のなかに可愛さも感じられるAction 2が気になります。

そのスペック(仕様)は、Pocket 2とどう違うのでしょうか?と興味が膨らんだので、一覧表にして比較してみることにしました。

DJI Action2とPocket2を比較してみます
DJI Action2とPocket2 スペック(仕様)比較

本体の一般スペック比較

まずは、一般スペックの一覧表です。

Action2 Pocket2 スペック比較 一覧表(一般)

光学式/ジンバル式の手振れ防止機能の違いが際立っています。

先述のとおり、ジンバル式のPocket 2は、カメラの向きを変える際にスムーズな方向変化の動画にしやすいです。

他の違いとしては、本体と追加モジュールの2個構成となっているAction 2は、カメラ本体側にメモリーが内蔵されているので、56gの軽い本体だけでも撮影が可能です。

長い時間の録画をする際には、SDカードスロットがついている別体型モジュールをカチッと連結させて使います。

カメラのスペック比較

次に、カメラのスペックを一覧表で比較してみます。

Action2 Pocket2 スペック比較 一覧表(カメラ)

Action 2のレンズ視野角が、Pocket 2と比べて格段に広いですね!

ギョロ目のサイコロのような愛くるしいデザインも納得です。

手で持ってカメラの向きを変えられるPocket 2と違い、衣服や帽子、ヘルメットなど何かに固定して撮影することが多いAction 2には嬉しいスペックで、被写体を画面外に逃してしまう可能性はずいぶん低くなるはずです。

録画品質は、Action 2の方が選択肢が多く、また高品質が選べるようになっていますが、解像度を上げた場合には水平維持など一部の機能は使えなくなります。

私としては、普通に綺麗な動画を撮るぶんには、Pocket 2が網羅している解像度で充分な気がしますし、Action 2を使うにしても機能優先としたいので、最高解像度で撮影することは無さそうです。

バッテリーのスペック比較

最後に、バッテリーの比較です。

Action2 Pocket2 スペック比較 一覧表(バッテリー)

Pocket2は、3.85VのLiPo電池を直列で2個使っています。

一方のAction 2は、

  • 本体;1個
  • 追加モジュール;直列で2個

となっており、本体と追加モジュールで電圧が異なりますが、連結するとスペック上はPocket 2よりも長時間の撮影が可能です。

ただし、選択した画質や撮影モードによって撮影時間は異なるので、ざっくりと同じくらいの時間にわたり撮影可能だと理解しておきます。

結論

共に直感的な操作ができて使いやすいAction 2とPocket 2、カメラとしてはどちらも充分なスペックを備えていることがわかりました。

一方で、もともとの用途が異なるので、今更言うまでもありませんが、

  • カメラを持って撮影するならAction 2
  • アクションカムとして何かに固定して使うならPocket 2

ということですね。

一例ですが、撮影中にズームイン/アウトをするような場合は、カメラを握った状態から、親指でジョイスティックで操作できるPocket 2の方が格段に楽です。

一方で、Action 2は画面上で指をスライドさせてズームしないといけないので、カメラの画面が見えるようにカメラか自分を移動してから、ズーム操作をすることになります。

DJI アクション2とポケット2を徹底比較

さて、私は歩きながらの風景撮影がしたくてPocket 2を入手しましたが、アウトドアでの利便性からAction 2も使ってみたい!という気持ちが膨らみます。

そこで、さらにAction 2について調べてみました。

Action2のモジュール2種類比較

シャツなどを磁石でサンドイッチする構造で固定できるので、さりげなく撮影することが可能なAction 2ですが、追加モジュールも磁石と機械式連結機構の組み合わせで、簡単に本体への付け外しができます。

その追加モジュールは

  • フロントタッチ画面モジュール
  • 電源モジュール

の2種類のタイプがあるので、こちらも比較してみましょう。

Action2 フロントタッチ画面モジュール と 電源モジュール スペック一覧表

自撮りなどで活躍するフロントタッチ画面モジュールは、電源モジュールと比べて奥行き方向で約3mmほど厚くなっています。

バッテリー容量はどちらのモジュールも同じ(1,300mAh)なので、フロントタッチ画面モジュールは、この約3mmのスペースに画面を追加しているということですね! すごい〜

とはいえ、自撮りをする予定がない私は、気持ち程度はバッテリー駆動時間が長くなる電源モジュールのセットを選択しました。

DJI Action2 開封の儀

ご参考;Action 2の試し撮り

スペックとしては充分なAction 2ですが、一番気になっていたのが、その手振れ補正性能です。

ということで、入手後すぐに揺れがある状況でお試し撮影をしてみます。

youtu.be

  • 海上の船の上(とはいえ凪に近い状況でした)
  • モジュールを装着したカメラを、片手の親指と人差し指でつまむように持っている状態
  • 手振れ補正レベルは一番弱い「STEADY」

で撮影しています。

いかがですか? 私としては充分な補正が効いていて、綺麗な画質でスムーズに手振れ補正してくれていると感じます。

多少プルプルしながら2本の指で保持していても大丈夫ということなので、私がやりたいTシャツへの磁石固定の場合は、カメラのブレはしっかり補正されますね。

さっそく次回のアウトドア活動から、自分の手元や景色を含めて、楽しい記録をしっかりと残していただきましょう!

DJI Action2をカスタマイズ

お部屋で焚き火!なフロアランプver.2

 

お部屋で焚き火!

皆さまキャンプ楽しまれていますか?

キャンプの醍醐味といえば焚火ですよね~

そんなキャンプの雰囲気をお部屋に持ち込んでみましょうシリーズのパート2として、丸いフロアアンプに焚火を閉じ込めてみました。

丸いフロアアンプに焚火を閉じ込めてみました

キャンプ場に瞬間移動

今回お部屋に追加した、自称「お部屋でキャンプファイヤー」は2作目です。

以前に作ったフロアランプの全貌は、こちらです。

ランダムな炎の雰囲気をLEDで表現したもので、暖炉がない部屋ですが、炎に見とれる至福の時間を与えてくれます。

スイッチをオン・オフするだけの手軽さも、めんどくさがりの私にピッタリ!

このフロアランプは、お部屋の片隅で夜のキャンプ場の雰囲気を演出してくれているのですが、使い続けているうちに、なんだか寂しさを感じるようになってきました。

ソロキャンプ好きの私といえども、焚火が一か所しかないのは物足りない...

そこで、もう一台の焚火台らしきものをお部屋にお迎えすることにします。

...と決意してしまうと、自作したい熱が盛り上がってきました!

炎の住処

炎のダンスをお部屋で表現することは決めましたが、悩ましいのが「何に炎を閉じ込めるか?」です。

以前に円筒形のものを作った時には、これだ!というフロアランプをIKEAで発見することができました。

そこで今回も、イメージに合致するものとの出会いを求めて、IKEAを散策してみました。

ショールームを抜けて、ランプコーナーに入ったところで、目に飛び込んできたのは...

IKEAのランプフード

フロアランプではなくランプフードですが、何かを訴えかけてきます。

これが床置きでも自立するなら、フロアランプにしてもいいのでは?

特に、右から2つ目の丸いフードは、そのシンプルな形に惹かれるだけでなく、以前に作った焚き火風フロアランプと材質感も同じです。

このランプフードに炎を入れて、フロアランプにしてしまいましょう!

炎を生み出す

IKEAから帰宅したら、さっそく今回のランプの肝となる「炎」を生み出す光源を作ります。

まずは、ゴソゴソと材料を準備しましょう。

Arduinoで、ランプを炎を入れる

紙の筒は、食材用ラップの芯です。

これをもう少し細く丸めなおすことで、ランプの中で直立する柱として再利用します。

テープ状のLEDと黒いボックスが、光源を作り出す部分になります。

ボックスの中には、直流5Vの電源回路と、マイコンが入っています。

Arduino プロジェクトボックス

これらの光源の作り方は、以前に作った円筒形のフロアランプと、LEDの高さを除いて一緒です。

回路図やプログラムについて、もっと詳しく知りたい!と思っていただけた方は、過去記事にて紹介しているので、ご参考にしてください~

www.solocamptouring.com

さてさて、今回のフロアランプ制作を続けます。

黒いボックスの中に、炎を作り出す制御部分を収納したら、次にラップの芯から作った柱に、LEDテープを貼り付けます。

テープをハサミで4分割して、柱に貼り付けました。

この4分割されているLEDテープを、電線を仲介してハンダ付けで繋ぎなおしたら、IKEAのランプフードの中に紐でぶら下げて、フロアランプの完成です。

入魂しましょう

それでは、ランプフードからフロアランプに生まれ変わった焚き火ランプを、点灯してみましょう!

youtu.be

どうですか?

炎っぽく見えません? 

先入観で他が考えられなくなるタイプの私には、焚き火の炎と同じに見えます!

炎パターン以外にも、いろいろな光り方のプログラムを入れておいたので、気分に合わせて変えられます。

予期せぬ発見ですが、丸いランプなので、惑星のような光り方も良い雰囲気になります。

お部屋での気分は、キャンプ場から宇宙へと旅立ちました〜

しばし丸い光を楽しんだのちに、せっかくなので筒状のフロアランプとならべてみました。

火みたいに光るフロアライト

この統一感、思惑通りです。

なんだか親子みたいですね〜

赤色の炎も良いのですが、青色の炎もお気に入りで、お部屋が深海のような雰囲気になります。

お部屋にいながら、キャンプ場から宇宙にも深海にも連れていってくれるランプって、凄い!

...と自画自賛。

ミニチュア キャンプ場

それでは! 完成したフロアランプを配置した、キャンプなお部屋を紹介してみます。

焚き火風でキャンプなお部屋

「アウトドアの雰囲気を、お部屋で再現」をコンセプトにしていますが、自分の中に「やりすぎは良くない」と訴えるものがあり、ほどほどにアウトドア感をだしています。

つまり、部屋でテントを張るようなことは、自主規制!

そのため、キャンプ用のチェアが常設されている他には、森の中にいるような感覚を誘うために、観葉植物とフェイクグリーンのスクリーンを置いているにとどめています。

それでも、炎のフロアランプのおかげで、夜にはジャングルな雰囲気に一変します。

わたしの部屋

光の視覚効果は大きいですね〜

キャンプでの焚き火時間のように、飲み物を片手に、リラックス姿勢で沈思黙考できる空間です。

あえて足りないものをあげるとしたら、大自然の中で感じる空気の流れ、つまり風の揺らぎです。

...と気付いてしまうと、もう風のことが頭から離れない...
焚き火の雰囲気を楽しみながら、部屋で自然風を再現する方法について、まったりと考えてみます。

良い案を思いついたら、次作「お部屋でキャンプの風」編に続けますね。

Arduinoな生活を、少し紹介してみます

こんにちは。

急に寒くなりましたが、皆様いかがお過ごしでしょうか?

暖かくしてご自愛くださいね。

...と、前置きと文末が同時に来たかのような挨拶になってしまいましたが、今回は、どうしても皆様にご報告とお礼を申し上げたくて、このブログ内としては少し異質な内容の記事を、いつもより少ない写真とともに紹介せていただきます。

Arduinoで楽しんでいて良かった!

「ソロで楽しむ」ブログ

本題に入る前に、少しだけこのブログについて紹介させてください。

この「ソロで楽しむ」は、私が人生で初めて開設したブログです。

大勢の人前で喋ることが不得意の私が、ブログを始めるにあたっては、自分には、皆様のお役にたてて頂けるような情報の質や量が、充分にあるのだろうか?という不安がありました。

一方で自分には、割と深く没頭している趣味が複数ある!というのも事実で、全部あわせれば、お役立ち情報も少しはあるのでは?とも思われます。

そこで、全ての趣味を楽しむ中で、

  • 調べたこと
  • 気付いたこと
  • 工夫したこと

について、余す事なく記事にしてみましょう!という方針を決めて、キャンプや乗り物、工作と幅広く紹介させていただくことにしました。

...となると、悩ましいのがブログタイトルです。

全ての趣味に共通していて、内容をイメージしていただけそうな言葉...

と考えていたら、

そういえば、お一人様でも楽しめる趣味ばかりですね!

ということに気付き、一人で苦笑いした結果、ひねりを入れることもなく、「ソロで楽しむ」というタイトルになりました。

電子工作も楽しむ

このブログで紹介させていただいている趣味のうちのひとつが、電子工作です。

売ってないものは、作りましょう!をモットーにしているので、電子工作自体も好きですが、どちらかというと、作ったものを日常生活で使っている時に、幸せを感じています。

そのため、ブログ内で紹介している工作物のほとんどが、別の趣味とリンクしています。

たとえば、キャンプで夜のテント周りを、アウトドアの雰囲気に調和して彩る照明なんてものも作りました。

テント周りのお洒落な照明が欲しい

お問い合わせやお声掛けをいただきました

趣味の範疇で、お役にたてる情報を!と思いながら、記事数を増やしてきましたが、電子工作については、いくつかお問合せお声かけをいただいています。

アメリカやフランスの方からも、

「Arduinoが動かない。助けて!」

というようなお問合せをいただき、メールのやりとりだけで、必死にトラブルシュートしたことがありました。

GPSモジュールを使った作品に関してのお問い合わせでは、私が使用したものとは違うメーカーのセンサーを使用するだけで、うまく動かないことがある!ということが、長い時間と多くのメール連絡の末に判明しました。

私自身も勉強になり、最終的に解決できた時には、お互いに

「やったね!ありがとう〜」

と盛り上がりました~

フランス語でのメールやりとりは大変でしたけど...

一方で、お声かけいただいた内容では、

「弊社のプリント基板を使ってみませんか?」

など、こちらも嬉しいものばかりでしたが、中には、

「うちのお店で使うものを作ってほしい!」

と仰っていただいたことがありました。

...しかし私が作っているのは、ブログタイトルどおり、あくまでソロで楽しむレベルのものです...

心惹かれるお声かけでしたが、お店で使える耐久性などの品質を保証する作品を、ご迷惑をおかけしない期間内で作れる自信はなく、泣く泣く辞退させていただきました。

皆様に御礼申し上げます

ご紹介してきた他にも、これまで色々とお問合せいただきました。

まだまだ情報量が少なかったり、わかりづらい記事内容ゆえにいただいているお問合せかもしれませんが、お問合せいただけるほどお役にたてているに違いない!と、「超」がつくほど前向きに捉えています。

特に情報が無くて困っている方のお役にたちたいのは、ブログを始める際の目標でもあったので、とても嬉しいことです。

同じ理由から、お問合せしていただいた方だけでなく、読んでいただいた全員の方に感謝しております。

そして、あらためて感謝とともにご報告したいことがあります。

工学社様の書籍に、掲載していただきました

はい! サブタイトルの通りです。

工学社様の書籍、

「Arduinoライブラリ」で作る電子工作

の一部に、ご掲載していただきました。

気軽にArduinoを始めませんか?

立派な本ですね! 私(の記事)のような分際だと、身分不相応になっていないか心配...

とにかく、このような形で、より多くの皆様にご参考にしていただけるチャンスをいただける日が来るとは、夢にも思っていませんでした。

これも全て、私のブログにご来訪いただき盛り上げてくださった皆様のおかげです。

ありがとうございます。

多趣味の雑記ブログなので、Arduinoを日常生活で使いたいプロジェクトを思いつき、また完成したものが皆様に報告してもよいレベルにあると自信が持てた時にしか記事数が増えませんが、今後ともよろしくお願いいたします。

面白い! 作ってみたい! 欲しい!などと感じていただける作品を紹介できるように努めつつ、まだまだ続けさせていただきますね!

Thank you! Arduino

それでは皆さま、

Have a Happy Arduino Life!

テント内で焚き火!っぽいランタンの炎を楽しむ

キャンプで、そろそろ寝ようかな〜という時に、大自然に囲まれていた雰囲気とテント内の雰囲気のギャップに、少しガッカリしたことがあります。

火器が使えないテント内では、LEDの灯りなどを使うことになりますが、目に刺さるような白色に、日常を感じてしまい、焚き火の炎に照らされて醸成されていたリラックスモードが、一気に無くなってしまったように気分に...

一方で、このところキャンプに行っていないどころか、買い物だけしか外出していませんが、このような時だからこそ!ということで、「外でもお家でもキャンプ」気分を盛り上げる小道具を増やそうと思います。

そこで今回は、テント内でも使える「焚き火の炎」を作って、どこでもキャンプファイヤーの光を、手軽に楽しめるようにしてみます!

テント内で焚き火!っぽいランタンを楽しむ

 

ランタンを見つめ続けた結果!

キャンプ用のLEDランタンは、停電などの非常時にも使えますよね!

私は、屋内ではいつも目につく場所に置いて、来たるべき次回のキャンプに備えて時々充電したり、来てほしくない非常時に備えたりしています。

キャンプや夜釣りで活躍していたLEDランタンですが、唯一の欠点が、明るすぎることです。

キャンプ用LEDランタンを改造します

焚火などの穏やかな明かるさに慣れた状態で、この光量を直視してしまうと、目が焼けるかのように感じます。

もっとキャンプで使いたくなるランタンにしたいと思いつつも、キャンプに行かない室内生活で、視野に入れるように置き続けていて、ふと思いつきました。

のように光らせたら、室内とキャンプのどちらでも、良い雰囲気作りができる!

少し前になりますが、フロアランプを焚き火風に光らせることができたので、それより少ないLEDを使えば良いランタンの改造は、難しくはない筈です。

早速、炎をランタンに封入してみましょう。

LEDランタンを改造

炎の光パターンを作るために、5Vで駆動するマイコンを使います。

2年ほど使い続けているランタンは、もともと白色LEDが使われており、またUSB(5V)で充電できるものなので、電源系はそのまま使えそうです。

炎のランタン作成に使うもの

まずは、WS2812Bが一定間隔で配置されているカラーLEDテープを準備しました。

WS2812Bで炎を作ります

写真には2種類のものが写っています。

今回は、少ないスペースにより多くのLEDを埋め込みたいので、外側でぐるぐるっとしているLEDの間隔が少ないものを使います。

材料として他に入手したのは、炎のパターンを作るために働いていただく、Arduinoだけです。

配線類などの副資材は、既にあるものや廃材を利用します。

LEDランタンの中身

自己責任!となるので、少しドキドキしながら、LEDランタンを開封します。

赤色の配線がプラス、青色の配線がマイナス...かと思いきや、一箇所だけ赤色のマイナス線がありますね。

(自己責任で)LEDランタンを分解
(自己責任で)LEDランタンを改造
  • 茶色の基盤;電源管理
  • 青色の円柱;リチウム電池
  • 緑色の基盤;スイッチ管理とLEDの定電流化

ということのようです。

回路の電圧を測ってみると、4V以上でている様子で、ギリギリですが思惑どおりArduinoも動かせそう!

本来であれば電圧変換すべきですが、とりあえず、オリジナルの回路をそのまま使って、様子をみましょう〜

ただし、もともとのLEDには定電流ダイオードを通して電源が供給されていましたが、ArduinoとWS2812Bには、定電流ダイオードを通さずに電源供給して、たくさん働いていただきます。

大まかな回路構成がわかったので、もともとのLEDWS2812Bに交換して、光り方を制御するArduinoを追加する作業に進みます。

ArduinoとWS2812Bを配線しましょう

LEDランタンには白色LEDが3本使われていたので、同じ長さになるように切断したWS2812Bテープ3本を、直列で配線します。

今回使うのは7個x3列の、合計21個ですね。

WS2812Bを3列に並べて使います
Arduinoをランタンに埋め込む!

ArduinoからWS2812Bへの信号線は、黄色の配線1本のみです。

他には、それぞれに電源線2本を接続するだけ!

作業の途中で、Arduinoのデジタルピンではなく、アナログピンに信号線をハンダ付けしてしまうというトラブルがあったものの、サクサクっとハンダ付けを終わらせて、準備しておいたプログラム(スケッチ)を書き込みます。

WS2812Bの炎パターン
ランタンのLEDをWS2812Bに改造

さて、電源を入れて試運転してみましょう。

...していたとおりに光っています!

いつも思うのですが、この瞬間の安堵感と嬉しさは、格別です〜

しっかり動くことがわかったので、後はランタンを組み立て直すだけですが、より炎っぽさを表現するために、シェード様のものを追加しておきます。

LEDの点光源感がバレてしまうと炎としては不自然なので、ボカシを入れるイメージです。

ランタンにキャンプファイヤーを封入

シェードには、よくある梱包材を廃材利用しました。

右の写真はシェード1枚での発光の様子ですが、まだ点光源感が残っていたので、左の写真のように二重のシェードを入れることにしました。

焚火風ランタンを自作

完成状態での点灯チェック!

本物の炎のようで、しばらく見入ってしまいました。

光り方は、動画でもご確認いただけます。

回路

今回つくる回路は、一か月ほど前に作った光ファイバーアートの時と、WS2812Bの個数を除いて全く同じです。

www.solocamptouring.com

回路図は、こちらで紹介しています。

WS2812Bは、配線数が少なくていいですね!

作業風景は、早送りですが動画でも紹介しています。

youtu.be

スケッチ

ご参考で、Arduinoのスケッチ(プログラム)です。

WS2812Bを使うため、GitHubのFastLEDライブラリを使用させていただきます。

炎の発光は、Fire2012WithPaletteのスケッチを応用しました。

#include "FastLED.h"
#define DATA_PIN    5
#define LED_TYPE    WS2812
#define COLOR_ORDER GRB
#define HEIGHT 7
#define WIDTH 3
#define NUM_LEDS HEIGHT*WIDTH
#define lighting_PER_SECOND 30 // Mainly for fire frame pattern

CRGB leds[NUM_LEDS];
CRGBPalette16 gPal;

int BRIGHTNESS = 20;
int scaleVol = 230; // Scale the heat value from 0-255
int SPARKING = 220; //50-200 out of 255
int COOLING = 50; // 20-100: Less = taller flames.  More = shorter flames. 

bool gReverseDirection = false;

void setup() {
  delay(1000); //delay for recovery
  FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
  FastLED.setBrightness(BRIGHTNESS);
}

void loop()
{
  gPal = CRGBPalette16( CRGB::Black, CRGB::Red, CRGB::Yellow, CRGB::White);
  static uint8_t heat[NUM_LEDS]; // Array of temperature readings

  // Cool down every cell a little
    for( int i = 0; i < NUM_LEDS; i++) {
      heat[i] = qsub8( heat[i],  random8(0, ((COOLING * 10) / HEIGHT) + 2)); //heat-randam8 with a floor of 0
    }
  
  // Heat from each cell drifts 'up' and diffuses a little
    for( int k= HEIGHT - 1; k >= 2; k--) {
      heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2] ) / 3;
      heat[2*HEIGHT-1-k] = (heat[2*HEIGHT-1-k + 1] + heat[2*HEIGHT-1-k + 2] + heat[2*HEIGHT-1-k + 2] ) / 3;
      heat[2*HEIGHT+k] = (heat[2*HEIGHT+k - 1] + heat[2*HEIGHT+k - 2] + heat[2*HEIGHT+k - 2] ) / 3;
    }
    
    //  Randomly ignite new 'sparks' of heat near the bottom
    if( random8() < SPARKING ) {
      int x = random8(6);
      int y ;
      if(x > 3){
        y = 2*HEIGHT-4+x;
      } else if(x > 1){
        y = 2*HEIGHT+1-x;
      } else {
        y = x;
      }
      heat[y] = qadd8( heat[y], random8(160,255) ); //heat+randam8
    }

    // Map from heat cells to LED colors
    for( int j = 0; j < NUM_LEDS; j++) {
      uint8_t colorindex = scale8( heat[j], scaleVol);
      CRGB color = ColorFromPalette( gPal, colorindex);
      int pixelnumber;
      if( gReverseDirection ) {
        if(j < HEIGHT){
          pixelnumber = (HEIGHT-1) - j;
          }else if(j < 2*HEIGHT){
          pixelnumber = HEIGHT+j;
          }else{
          pixelnumber = (3*HEIGHT-1) - j;
          }
      } else {
        pixelnumber = j;
      }
      leds[pixelnumber] = color;
    }

// Let's light them now
  random16_add_entropy( random());
  FastLED.show();  // send the 'leds' array out to the actual LED strip
  FastLED.delay(1000 / lighting_PER_SECOND);
// End of lighting
  
}

以前に作ったフロアランプは、WS2812Bを4列配置しましたが、今回のランタンは3列です。

また、今回は発光パターンを赤色の炎だけに限定したので、ランタンのスケッチは、フロアランプに比べて、たいへん短くなっています。

最後に、ランタンとフロアランプの炎を並べて、記念撮影

どちらも、なかなか良い雰囲気で、他の明かりを消して、室内で楽しんでいます!

夜に外から見たら、怪しいと思われているかもしれませんね。

WS2812Bで、炎パターンで光るライトを自作

光ファイバーの夜景アートが欲しい!

前回に引き続き、お部屋で楽しむノスタルジーシリーズです。

きらきらと、小さな光点が点滅したり色を変える夜景のアート、数十年前に流行りましたよね!

思い返せば、その頃から自作好きだったようで、夜のブルックリン橋のポスターを買ってきて、背景のビルの窓に、光ファイバーを一本づつ埋め込んだな〜と思い出します。

最近になって、この夜景アートが欲しくなり、ネットなどで調べているのですが、なかなか見つかりません。

薄型ディスプレイが出回っている昨今では、流行らないのでしょうか?

入手しづらいとわかると、あの幻想的にも感じた光が、どうしても欲しい!との思いが、なおさら増してきます。

またまた、無いものは作るしかない!ということで、お部屋で過ごす時間を使って、自作してみます。

Fiber optic picture DIY

夜景のポスター

今回の「光る夜景アート」のDIYにあたり、最初にベースとなる夜景のポスターを探してみました。

...しかし、私が探しているA3サイズの大きさで、感性を揺さぶるようなポスターは、なかなか見つかりません。

空が真っ赤に染まっているような夕焼けの景色はあるのですが、どちらかというと日が沈み切った後の景色が欲しい!

まあ、慌てずに探しましょう~と、1か月ほど構想を温めていた頃、普段から行くことがあるホームセンターの奥の方で、一枚の絵に目が止まりました。

タイで見つけたオーロラのアートフレーム

何、このオーロラの発色? 綺麗すぎます!

夕焼けに染まる街のアートフレームもありましたが、このグラデーションがかかったグリーンの空から、目が離せません。

10分ほど絵を眺めてつつ妄想にふけっていて、いい事を思いついてしまいました。

このオーロラをで光らせたら、おもしろそう!

お手頃価格で、DIYにちょうどいい大きさのこのアートフレーム、即購入しました。

ちなみに、このアートフレームは時計です。

オーロラのアートフレーム

オーロラが発生している夜空に、くっきりと時間が表示されていて、少し違和感がありますね。 

お家に帰ってきてアートフレームの中身を確認した時に、時計機能は撤去することにしました。

アートフレームの中のデジタル時計

時計を埋め込むのにちょうどいい入れ物が見つかったら、時計ユニットは再生いたします。

街の夜景とオーロラを同時に楽しむ

一目惚れしたアートフレームには、山の上空のオーロラに照らされて、海沿いの人里が描かれています。

漁師町といった雰囲気でしょうか? 私の勝手なイメージでは、カニ漁の漁船が係留されている筈です!

今回は、LEDから光ファイバーケーブルで導光して漁師町をライティングすると共に、オーロラはLEDの光を裏から当てます。

もうすっかり使い慣れたカラーLED、WS2812Bが25個直列で繋がったテープを使って、最初の3個は漁師町、残りの22個はオーロラ用とします。

ARDUINOで、ファイバー ライト ピクチャーを自作

山の影を作りましょう

アートフレーム全体は、キャンバス生地の裏側から光らせます。

夜空に、山の稜線が漆黒の姿を映すようにしたいので、山の輪郭に沿って、板を入れておきます。

この板は、光ファイバーケーブルの光源を取り付けるスペースとしても、活躍してもらいます。

街の夜景

街といっても、漁師町なので、派手すぎず、かといって寂しくは感じない程度の光りをつくります。

光源となるLED3個は、ランダムなタイミングで、それぞれの色を変えていきます

数えてはいませんが、たくさんの光ファイバーケーブルの端末を、町の光りとして埋め込んで、反対側の端末は、LED3個の光源近くに束ねました。

光ファイバーケーブルで光るアートを作りましょう

夜空に揺れるオーロラ

アートフレームの上方に22個のLEDを並べて、徐々に色を変えつつ、光量のゆらぎを作ります

個々のLEDごとに色と光量を制御できるWS2812Bのメリットをいかした表現で、実際のオーロラをイメージして、光量のゆらぎの大きさ発生頻度などをトライ&エラーで決めます。

瞬く星も、この光源を使って、数個つくっておきました。

WS2812B LEDでアートを光らせる

回路図

回路と言っても、ものすごく簡単なものです。

手動で光量や色を変更することも無いので、可変抵抗(ボリューム)も使いません。

回路図はFritzingで作成しました。

LED lighting circuit for Fiber light picture

回路の作成シーンや、アートフレームの改造風景は、動画でも紹介しています。

youtu.be

参考;夜景アートを光らせるArduinoこスケッチ(プログラム)

簡単な命令文で、綺麗な光を演出できるGitHubのFastLEDライブラリを使わせていただきます。

おかげさまで、随分と短いスケッチになりました。

#include "FastLED.h"
#define DATA_PIN    5
#define LED_TYPE    WS2812
#define COLOR_ORDER GRB
#define HEIGHT 25              //  aurora 22 + village 3
#define WIDTH 1
#define NUM_LEDS HEIGHT*WIDTH
#define lighting_PER_SECOND 10 // aurora pattern changr per sec.

CRGB currentleds[NUM_LEDS];
CRGB leds[NUM_LEDS];
int BRIGHTNESS = 160; //out of 255
int auroraSparkMax = 90; // aurora spark volume 0-100 out of 255 -BRIGHTNESS
int auroraSparkMin = 60; // aurora spark volume 0-100 out of 255 -BRIGHTNESS
static uint8_t heat[NUM_LEDS]; // Array of temperature readings
uint8_t gHue = 1; // starting color out of the patterns 0to255  


void setup() 
{
  delay(1000); //delay for recovery 
  FastLED.addLeds<LED_TYPE, DATA_PIN, GRB>(leds, NUM_LEDS);
}

void loop()
{
 unsigned long startMillis= millis();  // Start of sample window
 FastLED.setBrightness(BRIGHTNESS); 
 fadeToBlackBy( leds, NUM_LEDS, 200);
 
// make aurora and village light
  // aurora each cell heat slides
  EVERY_N_MILLISECONDS( 200 ) {
    for( int i = NUM_LEDS-1; i > 3; i--) {
     heat[i] = heat[i-1]  ; 
     }
     heat[3] = random8(auroraSparkMin, auroraSparkMax) ;
  }
     for( int j = 3; j < NUM_LEDS; j++) {
     leds[j] += CHSV( gHue + j, 255, heat[j]);
    }


  // village color

  EVERY_N_MILLISECONDS( 100 ) {
    for( int j = 0; j < 3; j++) {
    heat[j] = BRIGHTNESS  ;   
     int ColorChange = random8(250);
     if (ColorChange < 1){
     uint8_t gHueVillage = gHue + 127; 
     leds[j] += CHSV( gHueVillage, 255, heat[j]);
     currentleds[j] = leds[j] ;
     }else{
     leds[j] = currentleds[j] ;
     }
     uint8_t colorindex = scale8( heat[j], 255);
     }
  }
  
// Let's light them now
  FastLED.show();  // send the 'leds' array out to the LED strip
  FastLED.delay(1000 / lighting_PER_SECOND);
  
  EVERY_N_MILLISECONDS( 500 ) { 
    gHue++ ;
  }
  
// End of lighting

}

オーロラと街の光は、どちらも徐々に色を変えていきますが、意図的に違う色になるようにしています。

どちらかが緑色(に近い色)の時は、もう一方は紫色(に近い色)といったイメージです。

ファイバーライトピクチャーの自作

夜景アートというと、大都会の景色を連想しますが、偶然出会ったオーロラの景色に一目惚れしたことで、今回は一風変わった夜景アートを作ることになりました。

私としては、一本のLEDテープを光源に使い、オーロラと街の夜景を上手く表現できたと感じています。

このところ続いているお家で楽しむシリーズですが、今回は、懐かしさが漂うファイバー ライト ピクチャーを自作してみました。

スペースレールのモーター音を静かにしたい!

Light up the SPACERAIL

こんにちは。

皆様は、お家時間をいかがお過ごしでしょうか?

私は最近、お家に籠っている時間を使って、

スペースレールという知育おもちゃを、少しだけ改造して組み立てました!

「そういえば昔に持っていた!」と、懐かしく思い出される方も多いと思いますが、おそらくそれは、1983年くらいから5年ほど販売されていたスペースワープですね!

私も相当昔にスペースワープを組み立てたことがありますが、大人になった今回は、アップデートされて蘇ったスペースレールに、少し改造を織り込んで作成してみます。

お部屋のオブジェとして動かし続けるには、どうすれば良い?という観点で、小技も繰り出します!

SPACERAILのモーターの音を静かにしましょう!

スペースレール(SPACERAIL) 

スペースレールは、上の写真のようにレールを組み立てて、直径1/2インチ(1cmくらい)のボールを、上手く転がそう!という、パズル的な要素がある玩具です。

組み立てキットは14種類あり、難易度レベルが9段階で付与されています。

組み立て時間は、最も簡単なもので1時間、最高難易度のものだと60時間くらいかかるらしいとのこと!

スペースワープの時代には、レベル3に相当するものを組み立てたと記憶していますが、今回はレベル4.1に挑戦します。

大人の楽しみ方

さて、お部屋のオブジェにしましょう!というコンセプトで作るスペースレールは、スペースワープ時代の記憶を辿ると、2点ほど改良したくなります。

  1. エレベーターからボールが落ちることがある
  2. エレベーターを動かしているドライブユニットの音が大きい

f:id:solocamptouring:20210725161634j:plain

1 は、エレベーターの途中にあるボールが、他のボールがエレベーターに突入してくる時の衝撃で落ちることが多かったと思いますので、なんらかの落下防止ガードを付けたいと思います。

については、手の込んだ改善が必要だと思われます。

DCモーターと、その動力をエレベーターに伝えるギアの双方が、ウィ~ンという大きめな音を発生する原因となっている様子...

Inside the drive unit of Spacerail

静かな部屋で動かし続けるためには、少し耐えがたいドライブ音は消してしまって、ボールが転がる音と、エレベーターにボールが吸い込まれる瞬間の音だけにしたい!

静かに動かすのであれば、ステッピングモーター化がお手軽でしょう!ということで、モーターの種類を変えて、静音化してみます。

ステップモーター :  28BYJ-48 

ステッピングモーターは、速度(回転数)や位置を制御しやすいので、3Dプリンターにも使われていますね。

今回使うステッピングモーターは、ドライバーとセットで売られていることが多い28BYJ-48です。

ステップモーター 28BYJ-48をSpacerailに仕込む

上の写真で、右に写っているのが、そのステッピングモーターです。

スペースレールのドライブユニットのハウジングに収まりそうな、ちょうどいい大きさですね。

ドライバーとセットで安価に入手できる28BYJ-48は、マイコンボードで簡単に動かせます。

私がよく使うマイコンッボードは、Arduino Nanoという、小さいタイプのものです。

少しArduinoに興味がでてきた!という方は、使い方などを纏めている記事があるので、よろしければ参考にしてみてください。

www.solocamptouring.com

早速、必要な部品を入手して、ステッピングモーター化に取り組みます。

モーター交換のためのハンダ付け作業や、ハウジングの加工を終えて、静か~に動くドライブユニットが完成しました。

スペースレールを、ステップモータで動かす
Spacerailの、静かに動くドライブユニットが完成

作業の様子は、早送りですが、動画内で紹介しています。

ステッピングモータを動かす回路図

Fritzingで作成した回路図を紹介いたします。 

作るのが大変そうに見えるかもしれませんが、回路図の右半分は、ステッピングモータと、そのドライバなので、既製品です。

この回路では、USB接続の5V電源を使います。

ハンダ付け作業も少なく、配線をつなぐと、下の写真のような状態になります。

Arduinoとスッテプモーターで、スペースレールを動かす

スペースレールを組み立てましょう

ドライブユニットの試運転して、満足できるレベルの静音になっていることを確認したら、いよいよスペースレールを組み立てます。

説明書を見ながら、まずは支柱を立てていきます

スペースレールを組み立てます
Spacerail installation

1時間以上かけて、支柱の作業を終えました!

次に、レールを切ってから、取り付けていきます

説明書で指示されているレールの長さは少し余裕を持たせているようで、実際に装着した後で余った部分をさらに切断します。

ちなみに、同経路のレール左右でも、余る長さが違ってきます。

スペースレールのレール取付け
Install rails on the Spacerail

2時間以上かけて、レールも完成しました。

途中で、ボールを試走させながらレールを微調整しているので、予想以上に時間がかかります。

これらの作業と、静かに動くドライブユニットの様子は、動画でもご確認いただけます。

youtu.be

ほとんどの作業を早送り再生しているので、動画内では超高速で完成していますね。

エレベータータワーから落ちてしまうボールの対処方法

エレベータの中間地点を登っているボールが、他のボールがエレベータに突入してきた時の衝撃で落ちてしまうことがあります。

もう少ししっかりとボールを固定してくれる設計ならいいのに~」と言っていても仕方がないので、衝撃が加わってもボールが落ちないようにする手立てを考えます。

エレベータータワーから落ちてしまうボールの対処方法

これ、何かわかりますか?

はい! 食品を包んだりする時に使う、台所用ラップの芯です。

らせん状に切れ目を入れて、エレベータータワーの長さ(高さ)に合わせて切断したら、すぽっと入れるだけでボールの落下を防止できます。

ちょうどいい直径のアクリルパイプがあれば、もっと完成度が増すと思われますが、ラップの芯でも、それほど違和感はありません。

お家に在りそうな物での対策としては充分でしょう!

ボールの落下がなくなり、モーターもほぼ無音になったので、お部屋の置き物として、長時間動かし続けられるものになりました。

けっこう時間がかかりましたが、組み立て作業も楽しかった!

今日も、スペースレールの前に椅子を置いて、ボールの動きを目で追い続けています。

さて、次は何を作ってみようかな?

おまけ その1; ライトアップしてみました

テーマパークのジェットコースターを思い起こさせるスペースレールですが、さらに無事故(落下しない)かつ静音化して、オブシェとして動かし続けることに成功しました。

お部屋で眺めていて、もう少し幻想的にしたいと思い、ライトアップしてみました。

その様子を、約15分間にわたり録画してみます。

youtu.be

録音した音は、全く手を加えていないので、ボールの音だけが聞こえる様子をご確認いただけると思います。

おまけ その2;ステッピングモータを動かすスケッチ(プログラム)

ご参考で、スケッチを紹介いたします。

ステッピングモーターのドライバーに対して、コイルに順番に電気を流しなさい~と命令しているだけの、簡単なスケッチです。

int motorPin1 = 4;    // Blue   - 28BYJ48 pin 1
int motorPin2 = 5;    // Pink   - 28BYJ48 pin 2
int motorPin3 = 6;    // Yellow - 28BYJ48 pin 3
int motorPin4 = 7;    // Orange - 28BYJ48 pin 4
int volumePin = 5;
int motorSpeed;
int motorSpeedtimes = 2;

int lookup[8] = {B01000, B01100, B00100, B00110, B00010, B00011, B00001, B01001};

void setup() {
  pinMode(motorPin1, OUTPUT);
  pinMode(motorPin2, OUTPUT);
  pinMode(motorPin3, OUTPUT);
  pinMode(motorPin4, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  motorSpeed  = 1024 * (motorSpeedtimes + 1) - (analogRead(volumePin) * motorSpeedtimes) ; //0to1023 change into speed
  clockwise();
}

void anticlockwise()
{
  for (int i = 0; i < 8; i++)
  {
    setOutput(i);
      delayMicroseconds(motorSpeed) ;
}
}
void clockwise()
{
  for (int i = 7; i >= 0; i--)
  {
    setOutput(i);
      delayMicroseconds(motorSpeed);
}
}
void setOutput(int out)
{
  digitalWrite(motorPin1, bitRead(lookup[out], 0));
  digitalWrite(motorPin2, bitRead(lookup[out], 1));
  digitalWrite(motorPin3, bitRead(lookup[out], 2));
  digitalWrite(motorPin4, bitRead(lookup[out], 3));
}

それでは、皆さま良いお家時間をお過ごしください!

お家でエレクトリカルパレード

いつでも正確な時計を自作。GPSからの情報を秒単位で表示します

いつでも正確な時計を自作。GPSからの情報を秒単位で表示しますこんにちは!

皆様お元気でおすごしですか?

私は、ここのところの天候不順でアウトドアで過ごす予定がたてられない日が続いています。

しかし、そんな時こそキャンプでも使えるガジェットを自作すべき!ということで、在宅時でもアウトドアでも使える、いつでも正確な時間を教えてくれる時計を作ってみます。

いつでも時間が正確な時計を作ってみる

 

マイコン「Arduino」は難しくない!

最初に、「デジタル時計なんて自作できるのか?」問題について、少しだけ私の所感を紹介させていただきます。

マイコンを使う工作なんて無理〜と思っていた私が、Arduinoに出会ったのは、数年前です。

その頃すでに、日本語でArduinoの使い方を紹介されているサイトなどがありましたが、専門用語が多くて少し難解だったり、応用しづらかったりして、やはり基礎知識がないと無理なのかな?と最初は思いました。

海外のサイトからも情報を得たりしながら、いろいろ作ることに成功した現在、結論を言うと、「基本的なエクセルの関数計算を使うことができるなら、難しくない!」です。

Arduinoの場合は、プログラムのことを「スケッチ」と呼びますが、スケッチを描くのと同じくらい簡単ですよ!ということのようです。

表計算ソフトのエクセルで「もし〇〇ならば、△△を計算(実行)」の関数を使ったことがあれば、Arduinoスケッチの8割くらいは理解できると思います。

実際に私は、if~else~式を乱用して、スケッチを作っています。残りは数字の種類(整数、桁数)などを少し勉強すれば、だいたい理解できました。

ひとつ作品を成功させると、可能性が無限に広がったような気持ちになって、何かを表示するだけでなく、動かしたり光らせたりする作品など、いろいろ作ってきました。

もし興味がおありでしたら、見てみてください。

www.solocamptouring.com

 

人工衛星の情報で、正確な時間を入手

さて、前置きが長くなりましたが、置き時計を作ります。

最近は、腕時計でも採用されているものがありますが、地球のまわりを飛んでいる人工衛星から、正確な時間情報をいただきます

使う部品はこれだけです。

GPS時計を自作します

あとは、試作用の汎用基盤などの小物ですね。

GPSモジュールとLCDモジュールは、電力消費がそれほど多くないので、この後で紹介する回路図とは少し違って、USB接続したArduinoからの5Vアウトプットで駆動しています。

GPS時計の回路図

いつもお世話になっているFritzingで回路図を作成しました。

LCDモジュールへの配線数が多いですが、GPSモジュールへの配線はわずか3本です!

これだけで正確な時間情報がいただけるなんて、嬉しいですね。

GPS clock 1604 LCD_回路図

組み立てましょう

はんだ付けって大変!なのですが、便利な道具があると、ずいぶん楽になります。

若かりし頃は、横着なやり方もしていましたが、分別ができる年頃になってから、便利な道具に助けてもらうことを覚えました。

電線どうしのはんだ付けなど、もう一本手が欲しい~と思いながら苦戦していましたが、クリップ付きのはんだこて台があると、本当に楽です。

ハンダ付けを含めた作成の様子は、タイムラプスの動画にしてみました。

youtu.be

完成したことろで、お部屋のテレビ台に置いてみると、こんな感じです。

USBで駆動するGPS置時計

きちんと、秒単位で正確に働いています!

青色の背景に白い文字が浮かび上がっていて、雰囲気も良いですね。

ちなみに、このGPS時計は、電源を入れた後、表示するまで少しだけ時間がかかりますが、一度電波を受信した後は、今のところ表示が止まったりすることはありません。

アウトドアなら問題なく、また置時計として使うにも、電波が受信できる場所であれば、大丈夫でしょう。

GPS時計のスケッチ(プログラム) 

これまで紹介させていただいた作品の中では、おそらく最もシンプルなスケッチです。

バンコク時間に合わせたスケッチになっているので、日本時間を表示する場合は、6行目の

#define time_offset 25200 // define a clock offset of 3600*7 seconds (7 hour) ==> TH = UTC + 7

の部分を、

#define time_offset 32400 // define a clock offset of 3600*9 seconds (9 hour) ==> JP = UTC + 9

にします。 

スケッチは、TinyGPS++と、Arduino Time Librariesのライブラリを、インストールしてから使います。

#include <TinyGPS++.h>    
#include <TimeLib.h>          
#include <SoftwareSerial.h>   
#include <LiquidCrystal.h>    
TinyGPSPlus gps;
#define time_offset   25200  // define a clock offset of 3600*7 seconds (7 hour) ==> TH = UTC + 7
#define S_RX    9
#define S_TX    8
SoftwareSerial SoftSerial(S_RX, S_TX);   
LiquidCrystal lcd(2, 3, 4, 5, 6, 7); // LCD connections (RS, E, D4, D5, D6, D7)
 
// variable definitions
char Time[]  = "00:00:00";
char Date[]  = "2000/00/00";
byte last_second, Second, Minute, Hour, Day, Month;
int Year;
 
void setup(void)
{
  SoftSerial.begin(9600); 
 
  lcd.begin(16, 2); 

// welcome display
  lcd.setCursor(0, 0); 
  lcd.print("   GPS  CLOCK   ");
  lcd.setCursor(0, 1); 
  lcd.print("ARDUINO  POWERED");

  delay(5000);
  lcd.clear()  ;
}
 
void loop()
{
  while (SoftSerial.available() > 0)
  {
    if (gps.encode(SoftSerial.read()))
    {
// get time from GPS
      if (gps.time.isValid())
      {
        Minute = gps.time.minute();
        Second = gps.time.second();
        Hour   = gps.time.hour();
      }
 
// get date from GPS
      if (gps.date.isValid())
      {
        Day   = gps.date.day();
        Month = gps.date.month();
        Year  = gps.date.year();
      }
 
      if(last_second != gps.time.second())  
      {
        last_second = gps.time.second();
        setTime(Hour, Minute, Second, Day, Month, Year);
        adjustTime(time_offset);
 
// update time
        Time[6] = second() / 10 + '0';
        Time[7] = second() % 10 + '0';
        Time[3]  = minute() / 10 + '0';
        Time[4] = minute() % 10 + '0';
        Time[0]  = hour()   / 10 + '0';
        Time[1]  = hour()   % 10 + '0';
 
// update date array
        Date[2] = (year()  / 10) % 10 + '0';
        Date[3] =  year()  % 10 + '0';
        Date[5]  =  month() / 10 + '0';
        Date[6] =  month() % 10 + '0';
        Date[8]  =  day()   / 10 + '0';
        Date[9]  =  day()   % 10 + '0';
 
// show time & date
        print_wday(weekday()); 
        lcd.setCursor(4, 0);    
        lcd.print(Time);         
        lcd.setCursor(0, 1);    
        lcd.print(Date);         
      }
    }
  }
}
 
// for displaying day of the week
void print_wday(byte wday)
{
  lcd.setCursor(11, 1);  // move cursor to column 5, row 1
  switch(wday)
  {
    case 1:  lcd.print("(SUN)");   break;
    case 2:  lcd.print("(MON)");   break;
    case 3:  lcd.print("(TUE)");   break;
    case 4:  lcd.print("(WED)");   break;
    case 5:  lcd.print("(THU)");   break;
    case 6:  lcd.print("(FRI)");   break;
    default: lcd.print("(SAT)");
  }
}

本当に短いスケッチですね~

今回は、簡単に自作できるGPS時計の紹介でした。

早くキャンプに持っていきたい!

電波が届かないキャンプでも正確な時間な時計

それでは最後に、皆様がお家時間もアウトドア時間も楽しまれるよう、祈念しております。

炎も躍るサウンド レベル メーター。IKEAのフロアランプをカラフルに改造

炎のフロアランプを自作しよう

今回は、お家でキャンプ気分シリーズの、スピンオフ編です。

焚き火を眺めてすごす、キャンプでの優雅な時間を、屋内でも楽しみたい!ということで、背が高いフロアランプを、カラーLEDを使って改造して、焚き火台風にしてみます。

 

炎が躍るサウンド レベル メーター。WS2812Bでファイヤーします

焚き火とサウンドレベルメーター

アウトドアを楽しめない週末が続くと、いろいろな思いがこみ上げてきます。

  • 殺風景な部屋に、フロアランプが欲しい!
  • キャンプに行けないのであれば、部屋で焚き火気分を楽しめないかな?
  • 外出できないのであれば、しばらく封印していたDIYでもやってみようか...

こんな妄想たちを、一気に実現するには、焚き火風のフロアランプを自作するしかない!と確信しました。

テーマパークの仕掛けで見かける、本物の炎のような、フェイクな焚き火です。

ファンの風によって布をチラつかせて、さらに光も当てることで、本物の焚き火と錯覚してしまう、あれですね。

購入した方が安くすみそうな気がしますが、自作もできそうな気がします。

 

しかし、構造を考えていて、音について悩みが生じます。

くつろぎの時間を過ごしたいところで、ファンの音に耐えられるだろうか?と。

テーマパークのような、他の音が存在する場所なら気にならないと思いますが、プライベートな部屋ではファンの音は雑音でしかありません。

ファンを使わずに炎のような光を実現するには、小さな光源がたくさん必要になりそう...と考えていて、それならLEDで表現してみましょう!と、コンセプトがみえてきました。

LEDの直接光では、炎のように見せるのは難しいと思われるので、日本の伝統的なフロアライト、行燈の中にLEDたちを閉じ込めてしまいます。

行燈の中に焚き火があっても、いいじゃない!

行燈をサウンド レベル メーターに!

不規則に揺らぐ焚き火の光は、見ていて飽きませんよね〜

あの揺らぎを人為的に表現するには、乱数発生プログラムを使ってLEDを不規則に光らせることが近道だと思いました。

...でも、それだけだと不規則すぎて面白くない気もします。

相変わらずの捻くれ者ぶりを発揮してしまったので、一週間ほど悩んでみました。

時間をかければ閃くこともあるようで、ふと音楽に合わせて光らせてみたら面白いのでは?と思いつきます。

行燈の中で、炎と、音楽に合わせて光が踊っているフロアーランプ!

これは欲しい!と納得できるアイデアが浮かんだので、さっそく制作に取り掛かります。

IKEAで行燈選び

アウトドアには行けない日が続いているものの、家具屋さんのIKEAが家の近くにあり、毎週末のように通って、気分転換をしています。

そんなIKEAには、今回の行燈サウンド レベル メーターの改造ベースにピッタリのフロアランプがあることを知っています。

IKEAのフロアランプに、カラフルなLEDを仕込もう!

フードの材質が紙なので、光の指向性があるLEDとの相性もバッチリです。

いつもIKEAでは散歩スピードでショールームを楽しんでいますが、今回は売り場に直行して、フロアランプを入手してきました。

Arduinoと接続するモジュール

フロアランプを、行燈風サウンド レベル メーターとして光らせるために、個別に制御できるRGB LEDのWS2812Bをを使います。

「〇〇番目のLEDさんは、△△色に光ってください〜」

という情報さえ流せば、その通りに光るので、多くのLEDを個別に光り方を変えるのに便利なものです。

1mあたりにWS2812Bが60m個並べられているカラーLEDテープを3mと、サウンドセンサーモジュール、そして可変抵抗(ボリューム)3個を入手しました。

以前に、可変抵抗1個を使ってナイトライダー風サウンド レベル メーターを作ったことがありますが、今回はフロアランプでもあるので、

  • 光量
  • 光らせ方

の3項目を可変抵抗で選択できるように進化させます。

表示イメージとパターン

もともとは、「焚火 in 行燈」コンセプトで始めたプロジェクトですが、純粋にサウンド レベル メーター風のパターンも含めて、合計7種類の光らせ方を準備します。

 行燈なので、まずは白色で光らせます。

写真は紫色のように写っていますが、実際には白色です。

WS2812Bで行燈を改造。(白色)

 サウンドレベルのバーが立ちます。色は炎のように、オレンジのグラデーションです。

WS2812Bで行燈を改造。(サウンド レベル メーター 赤色)

 サウンドレベルのバーが立ちます。色は可変抵抗で選択した単色です。

WS2812Bで行燈を改造。(サウンド レベル メーター 好きな色)

 サウンドレベルのバーが立ちます。色は徐々に変化します。

WS2812Bで行燈を改造。(サウンド レベル メーター 色は徐々に変化)

 焚き火風に光らせます。色は、「オレンジ白色」の3色です。

WS2812Bで行燈を改造。(ファイヤー 赤色)

 焚き火風に光らせます。色は、「水色白色」の3色です。

WS2812Bで行燈を改造。(ファイヤー 青色)

 焚き火風に光らせます。色は、「可変抵抗で選択した色白色」の2色です。

WS2812Bで行燈を改造。(ファイヤー 好きな色)

 焚き火風に光らせます。色は、「徐々に変化する白色」の2色です。

WS2812Bで行燈を改造。(ファイヤー 徐々に変化する色)

回路図

Arduinoで自作するサウンド レベル メーターの回路図

Fritzingで回路図を作成しました。

マイクモジュールは、MAX4466を搭載したものを使っています。

3個の可変抵抗(ボリューム)は、

  • R1;光量
  • R2;表示7パターンの切り替え
  • R3;色

の調節(選択)をするために使います。

Arduinoを使って、LEDを炎のパターンで光らせる

Arduinoのアナログ入力には、それぞれの可変抵抗から電圧で情報が送られます。

  • 電圧; 0〜5V
  • Arduinoの読み取り値; 0〜1023(整数)

0〜1023をArduinoのスケッチ(プログラム)で選択肢に置き換えれば、LEDの発光を調節できます。

今回は180個が繋がっているものを使うWS2812Bは、先程も簡単に紹介しましたが、それぞれのLEDが個別に信号処理して、色や光量を認識して発光するので、信号線1本と電源の、合計3本の電線を繋ぐだけで、自在に光を制御できる優れものです。

WS2812Bで、炎のランプを!

スケッチは、記事の最後に掲載しておきますね。

炎が踊るフロアーランプ

LEDの配置

LEDを、ランプ中心部の柱にどう配置するか?について、少し試行錯誤しました。

  • 螺旋状に巻く?
  • 縦の列状に配置する?

結論から言うと、縦に配置した方が、LEDの貼り付け作業も、炎やサウンドレベルメーターのスケッチ(プログラム)の作成も楽です。

私は4列で配置することにしました。

WS2812B ファイヤー

180個のWS2812Bテープなので、

「45行x4列 」

になる筈ですが、試行錯誤の段階でちょっとした事故があり、数セルが使えなくなってしまったので、やむなく43x 4の配置になりました。

ウエルカム点灯

電源投入時の動作は、3種類を仕込んでおきます。

  1. ランダム点滅(白色)

    f:id:solocamptouring:20210626123315j:plain

  2. 白色光を上下に一回走らせる

    f:id:solocamptouring:20210626123321j:plain

  3. レインボー色の光を上下に一回走らせる

    f:id:solocamptouring:20210626123435j:plain

静止画だと、どれだけ綺麗に光っているか?が伝わらないですが、光り方はメイキング動画でも、ご確認いただけます。

 

youtu.be

スケッチ(プログラム)

スケッチは、色々なパターンの光らせ方が準備されている、GitHubのFastLEDライブラリをベースにさせていただきます。

炎(fire)パターンは、派生バージョンも含めていくつか紹介されており、Fire2012WithPaletteの、炎を作成する部分のスケッチを使用させていただき、4列の炎専用に少し手を加えました。

もっと短いスケッチにできると思いますが、メモリー容量に余裕があるので良い!ということにして、同じ命令文が何度もでてきます。

#include "FastLED.h"
#define DATA_PIN    5
#define LED_TYPE    WS2812
#define COLOR_ORDER GRB
#define HEIGHT 43
#define WIDTH 4
#define NUM_LEDS HEIGHT*WIDTH
#define MAX_BRIGHTNESS 90      // Full is 164
#define MIN_BRIGHTNESS 5       // 25% is better
#define lighting_PER_SECOND 30 // Mainly for fire frame pattern

CRGB leds[NUM_LEDS];
CRGBPalette16 gPal;

const int sampleWindow = 50; // Sound sample window width in mS
unsigned int sample;
int SoundCenterAdjust = 0; // max 1024/2
int SoundLevelAdjust = 6; // defo and min 1 In case bar is small with the usual sound
int BRIGHTNESS = 50;
int scaleVol = 230; // Scale the heat value from 0-255
int SPARKING = 130; //50-200 out of 255
int COOLING = 70; // 20-100: Less = taller flames.  More = shorter flames. 
int colorSelect;
int micPin = 2;
int blightPin = 3;
int selectPin = 4;
int colorPin = 5;
int val = 0;
int numLedsToLight = 0;
long numLedsToLightCal = 0;
bool welcomeLight = true;
bool gReverseDirection = false;


void setup() {
  delay(3000); //delay for recovery
  FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
  FastLED.setBrightness(BRIGHTNESS);
}

// List of patterns to cycle through
typedef void (*SimplePatternList[])();

SimplePatternList gPatterns = { allwhite, soundBarFire, soundBarSelect, soundBarRotate, fireRed, fireBlue, fireSelect, fireRotate};

uint8_t gCurrentPatternNumber = 0;  // Index number of which pattern is current
uint8_t gHue = 96;                  // rotating "base color" used by many of the patterns 0to255
// End of the list of patterns to cycle through


void loop()
{
// Data collection
  // Choose the blightness
   if (analogRead(blightPin) < 50) {
    BRIGHTNESS = 0 ;
   } else {
    BRIGHTNESS = map(analogRead(blightPin), 50, 1024, MIN_BRIGHTNESS, MAX_BRIGHTNESS) ;
   } 
    FastLED.setBrightness(BRIGHTNESS); 

  // Choose the color
   if (analogRead(colorPin) < 50) {
    colorSelect = 0 ;
   } else if (analogRead(colorPin) < 950) {
    colorSelect = map(analogRead(colorPin), 50, 949, 0, 255) ;
   } else {
    colorSelect = 255;
   }

  // Choose the pattern
   val = analogRead(selectPin); //check the volume to choose the pattern
      if (val < 130) {
    gCurrentPatternNumber = 0;
       } else if (val < 260){
    gCurrentPatternNumber = 1;
       } else if (val < 390){
    gCurrentPatternNumber = 2;
       } else if (val < 520){
    gCurrentPatternNumber = 3;
       } else if (val < 650){
    gCurrentPatternNumber = 4;
       } else if (val < 780){
    gCurrentPatternNumber = 5;
       } else if (val < 910){
    gCurrentPatternNumber = 6;
       } else {
    gCurrentPatternNumber = 7;      
       }
    gPatterns[gCurrentPatternNumber](); // Call the current pattern function once, updating the 'leds' array

// End of data collection


// Welcome lighting
  if (welcomeLight == true) {
  // random speckles that blink in and fade smoothly
    for(int led = 0; led < 150; led++) { 
    fadeToBlackBy( leds, NUM_LEDS, 100);
    int pos = random16(NUM_LEDS);
    leds[pos] += CRGB::White;
    FastLED.show();  
    delay (100-led/2);
    }  
    
  // white up and down
    for(int led = 0; led < HEIGHT; led++) { 
    fadeToBlackBy( leds, NUM_LEDS, 100);
    leds[led] += CRGB::White ; 
    leds[HEIGHT*2-1-led] += CRGB::White ; 
    leds[HEIGHT*2+led] += CRGB::White ; 
    leds[HEIGHT*4-1-led] += CRGB::White ; 
    FastLED.show();    
    delay (80);
    }

    for(int led = 0; led < HEIGHT; led++) { 
    fadeToBlackBy( leds, NUM_LEDS, 100);
    leds[HEIGHT-1-led] += CRGB::White ; 
    leds[HEIGHT+led] += CRGB::White ; 
    leds[HEIGHT*3-1-led] += CRGB::White ; 
    leds[HEIGHT*3+led] += CRGB::White ; 
    FastLED.show();    
    delay (80);
    }
  
  // rainbow up and down
    for(int led = 0; led < HEIGHT; led++) { 
    fadeToBlackBy( leds, NUM_LEDS, 100);
    leds[led] = CHSV(255*led/HEIGHT, 255, 255) ; 
    leds[HEIGHT*2-1-led] = CHSV(255*led/HEIGHT, 255, 255) ; 
    leds[HEIGHT*2+led] = CHSV(255*led/HEIGHT, 255, 255) ; 
    leds[HEIGHT*4-1-led] = CHSV(255*led/HEIGHT, 255, 255) ; 
    FastLED.show();    
    delay (80);
     }
 
    for(int led = 0; led < HEIGHT; led++) { 
    fadeToBlackBy( leds, NUM_LEDS, 100);
    leds[HEIGHT-1-led] = CHSV(255*led/HEIGHT, 255, 255) ; 
    leds[HEIGHT+led] = CHSV(255*led/HEIGHT, 255, 255) ; 
    leds[HEIGHT*3-1-led] = CHSV(255*led/HEIGHT, 255, 255) ; 
    leds[HEIGHT*3+led] = CHSV(255*led/HEIGHT, 255, 255) ; 
    FastLED.show();    
    delay (80);
    }    
    welcomeLight = false;  //End welcome lighting
  }else{

// Let's light them now
  random16_add_entropy( random());
  gPatterns[gCurrentPatternNumber]();
  FastLED.show();  // send the 'leds' array out to the actual LED strip
  FastLED.delay(1000 / lighting_PER_SECOND);
  EVERY_N_MILLISECONDS( 300 ) { gHue++; } // slowly cycle the color through the rainbow
// End of lighting
    }  
}


void fireRed() 
{
  gPal = CRGBPalette16( CRGB::Black, CRGB::Red, CRGB::Yellow, CRGB::White);
  static uint8_t heat[NUM_LEDS]; // Array of temperature readings

  // Cool down every cell a little
    for( int i = 0; i < NUM_LEDS; i++) {
      heat[i] = qsub8( heat[i],  random8(0, ((COOLING * 10) / HEIGHT) + 2)); //heat-randam8 with a floor of 0
    }
  
  // Heat from each cell drifts 'up' and diffuses a little
    for( int k= HEIGHT - 1; k >= 2; k--) {
      heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2] ) / 3;
      heat[2*HEIGHT-1-k] = (heat[2*HEIGHT-1-k + 1] + heat[2*HEIGHT-1-k + 2] + heat[2*HEIGHT-1-k + 2] ) / 3;
      heat[2*HEIGHT+k] = (heat[2*HEIGHT+k - 1] + heat[2*HEIGHT+k - 2] + heat[2*HEIGHT+k - 2] ) / 3;
      heat[4*HEIGHT-1-k] = (heat[4*HEIGHT-1-k + 1] + heat[4*HEIGHT-1-k + 2] + heat[4*HEIGHT-1-k + 2] ) / 3;
    }
    
    //  Randomly ignite new 'sparks' of heat near the bottom
    if( random8() < SPARKING ) {
      int x = random8(19);
      int y ;
      if(x > 14){
        y = 4*HEIGHT+14-x;
      } else if(x > 9){
        y = 2*HEIGHT-10+x;
      } else if(x > 4){
        y = 2*HEIGHT+4-x;
      } else {
        y = x;
      }
      heat[y] = qadd8( heat[y], random8(160,255) ); //heat+randam8
    }

    // Map from heat cells to LED colors
    for( int j = 0; j < NUM_LEDS; j++) {
      uint8_t colorindex = scale8( heat[j], scaleVol);
      CRGB color = ColorFromPalette( gPal, colorindex);
      int pixelnumber;
      if( gReverseDirection ) {
        if(j < HEIGHT){
          pixelnumber = (HEIGHT-1) - j;
          }else if(j < 2*HEIGHT){
          pixelnumber = HEIGHT+j;
          }else if(j < 3*HEIGHT){
          pixelnumber = (3*HEIGHT-1) - j;
          }else{
          pixelnumber = 3*HEIGHT+j;
          }
      } else {
        pixelnumber = j;
      }
      leds[pixelnumber] = color;
    }
}

void fireRotate() 
{
  gPal = CRGBPalette16( CRGB::Black, CHSV( gHue, 255, 192), CRGB::White);
  static uint8_t heat[NUM_LEDS]; // Array of temperature readings

  // Cool down every cell a little
    for( int i = 0; i < NUM_LEDS; i++) {
      heat[i] = qsub8( heat[i],  random8(0, ((COOLING * 10) / HEIGHT) + 2)); //heat-randam8 with a floor of 0
    }
  
  // Heat from each cell drifts 'up' and diffuses a little
    for( int k= HEIGHT - 1; k >= 2; k--) {
      heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2] ) / 3;
      heat[2*HEIGHT-1-k] = (heat[2*HEIGHT-1-k + 1] + heat[2*HEIGHT-1-k + 2] + heat[2*HEIGHT-1-k + 2] ) / 3;
      heat[2*HEIGHT+k] = (heat[2*HEIGHT+k - 1] + heat[2*HEIGHT+k - 2] + heat[2*HEIGHT+k - 2] ) / 3;
      heat[4*HEIGHT-1-k] = (heat[4*HEIGHT-1-k + 1] + heat[4*HEIGHT-1-k + 2] + heat[4*HEIGHT-1-k + 2] ) / 3;
    }
    
    //  Randomly ignite new 'sparks' of heat near the bottom
    if( random8() < SPARKING ) {
      int x = random8(19);
      int y ;
      if(x > 14){
        y = 4*HEIGHT+14-x;
      } else if(x > 9){
        y = 2*HEIGHT-10+x;
      } else if(x > 4){
        y = 2*HEIGHT+4-x;
      } else {
        y = x;
      }
      heat[y] = qadd8( heat[y], random8(160,255) ); //heat+randam8
    }

    // Map from heat cells to LED colors
    for( int j = 0; j < NUM_LEDS; j++) {
      uint8_t colorindex = scale8( heat[j], scaleVol);
      CRGB color = ColorFromPalette( gPal, colorindex);
      int pixelnumber;
      if( gReverseDirection ) {
        if(j < HEIGHT){
          pixelnumber = (HEIGHT-1) - j;
          }else if(j < 2*HEIGHT){
          pixelnumber = HEIGHT+j;
          }else if(j < 3*HEIGHT){
          pixelnumber = (3*HEIGHT-1) - j;
          }else{
          pixelnumber = 3*HEIGHT+j;
          }
      } else {
        pixelnumber = j;
      }
      leds[pixelnumber] = color;
    }
}

void fireBlue() 
{
  gPal = CRGBPalette16( CRGB::Black, CRGB::Blue, CRGB::Aqua,  CRGB::White);
  static uint8_t heat[NUM_LEDS]; // Array of temperature readings

  // Cool down every cell a little
    for( int i = 0; i < NUM_LEDS; i++) {
      heat[i] = qsub8( heat[i],  random8(0, ((COOLING * 10) / HEIGHT) + 2)); //heat-randam8 with a floor of 0
    }
  
  // Heat from each cell drifts 'up' and diffuses a little
    for( int k= HEIGHT - 1; k >= 2; k--) {
      heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2] ) / 3;
      heat[2*HEIGHT-1-k] = (heat[2*HEIGHT-1-k + 1] + heat[2*HEIGHT-1-k + 2] + heat[2*HEIGHT-1-k + 2] ) / 3;
      heat[2*HEIGHT+k] = (heat[2*HEIGHT+k - 1] + heat[2*HEIGHT+k - 2] + heat[2*HEIGHT+k - 2] ) / 3;
      heat[4*HEIGHT-1-k] = (heat[4*HEIGHT-1-k + 1] + heat[4*HEIGHT-1-k + 2] + heat[4*HEIGHT-1-k + 2] ) / 3;
    }
    
    //  Randomly ignite new 'sparks' of heat near the bottom
    if( random8() < SPARKING ) {
      int x = random8(19);
      int y ;
      if(x > 14){
        y = 4*HEIGHT+14-x;
      } else if(x > 9){
        y = 2*HEIGHT-10+x;
      } else if(x > 4){
        y = 2*HEIGHT+4-x;
      } else {
        y = x;
      }
      heat[y] = qadd8( heat[y], random8(160,255) ); //heat+randam8
    }

    // Map from heat cells to LED colors
    for( int j = 0; j < NUM_LEDS; j++) {
      uint8_t colorindex = scale8( heat[j], scaleVol);
      CRGB color = ColorFromPalette( gPal, colorindex);
      int pixelnumber;
      if( gReverseDirection ) {
        if(j < HEIGHT){
          pixelnumber = (HEIGHT-1) - j;
          }else if(j < 2*HEIGHT){
          pixelnumber = HEIGHT+j;
          }else if(j < 3*HEIGHT){
          pixelnumber = (3*HEIGHT-1) - j;
          }else{
          pixelnumber = 3*HEIGHT+j;
          }
      } else {
        pixelnumber = j;
      }
      leds[pixelnumber] = color;
    }
}

void fireSelect() 
{
  gPal = CRGBPalette16( CRGB::Black, CHSV( colorSelect, 255, 192), CRGB::White);
  static uint8_t heat[NUM_LEDS]; // Array of temperature readings

  // Cool down every cell a little
    for( int i = 0; i < NUM_LEDS; i++) {
      heat[i] = qsub8( heat[i],  random8(0, ((COOLING * 10) / HEIGHT) + 2)); //heat-randam8 with a floor of 0
    }
  
  // Heat from each cell drifts 'up' and diffuses a little
    for( int k= HEIGHT - 1; k >= 2; k--) {
      heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2] ) / 3;
      heat[2*HEIGHT-1-k] = (heat[2*HEIGHT-1-k + 1] + heat[2*HEIGHT-1-k + 2] + heat[2*HEIGHT-1-k + 2] ) / 3;
      heat[2*HEIGHT+k] = (heat[2*HEIGHT+k - 1] + heat[2*HEIGHT+k - 2] + heat[2*HEIGHT+k - 2] ) / 3;
      heat[4*HEIGHT-1-k] = (heat[4*HEIGHT-1-k + 1] + heat[4*HEIGHT-1-k + 2] + heat[4*HEIGHT-1-k + 2] ) / 3;
    }
    
    //  Randomly ignite new 'sparks' of heat near the bottom
    if( random8() < SPARKING ) {
      int x = random8(19);
      int y ;
      if(x > 14){
        y = 4*HEIGHT+14-x;
      } else if(x > 9){
        y = 2*HEIGHT-10+x;
      } else if(x > 4){
        y = 2*HEIGHT+4-x;
      } else {
        y = x;
      }
      heat[y] = qadd8( heat[y], random8(160,255) ); //heat+randam8
    }

    // Map from heat cells to LED colors
    for( int j = 0; j < NUM_LEDS; j++) {
      uint8_t colorindex = scale8( heat[j], scaleVol);
      CRGB color = ColorFromPalette( gPal, colorindex);
      int pixelnumber;
       if( gReverseDirection ) {
        if(j < HEIGHT){
          pixelnumber = (HEIGHT-1) - j;
          }else if(j < 2*HEIGHT){
          pixelnumber = HEIGHT+j;
          }else if(j < 3*HEIGHT){
          pixelnumber = (3*HEIGHT-1) - j;
          }else{
          pixelnumber = 3*HEIGHT+j;
          }
      } else {
        pixelnumber = j;
      }
      leds[pixelnumber] = color;
    }
}

void soundBarFire() 
{

  // Sound level to lighting LED amount
   unsigned long startMillis= millis();  // Start of sample window
   unsigned int peakToPeak = 0;   // peak-to-peak level
   unsigned int signalMax = 0;
   unsigned int signalMin = 1024;
   while (millis() - startMillis < sampleWindow)
   {
      sample = analogRead(micPin);
      if (sample < 1024)
      {
         if (sample > signalMax)
         {
            signalMax = sample;  // save the max levels
         }
         else if (sample < signalMin)
         {
            signalMin = sample;  // save the min levels
         }
      }       
   }
   peakToPeak = signalMax - signalMin ;  // max - min = peak-peak amplitude
   numLedsToLightCal = ((peakToPeak-SoundCenterAdjust)*HEIGHT*SoundLevelAdjust)/1024 ;
   if(numLedsToLightCal >= HEIGHT){
    numLedsToLight = HEIGHT;
   }else {
   numLedsToLight = numLedsToLightCal; // adjusting to the output of the mic 
   }
    fadeToBlackBy( leds, NUM_LEDS, 200);

  for(int led = 0; led < numLedsToLight; led++) { 
  leds[led] += CHSV( 2*(numLedsToLight-1-led), 255, 192);
  }
  for(int led = HEIGHT*2-numLedsToLight; led < HEIGHT*2; led++) { 
  leds[led] += CHSV( 2*(led-(HEIGHT*2-numLedsToLight)), 255, 192);
  }
  for(int led = HEIGHT*2; led < HEIGHT*2+numLedsToLight; led++) { 
  leds[led] += CHSV( 2*(HEIGHT*2+numLedsToLight-1-led), 255, 192);
  }
  for(int led = HEIGHT*4-numLedsToLight; led < HEIGHT*4; led++) { 
  leds[led] += CHSV( 2*(led-(HEIGHT*4-numLedsToLight)), 255, 192);
  }
}

void soundBarSelect() 
{

  // Sound level to lighting LED amount
   unsigned long startMillis= millis();  // Start of sample window
   unsigned int peakToPeak = 0;   // peak-to-peak level
   unsigned int signalMax = 0;
   unsigned int signalMin = 1024;
   while (millis() - startMillis < sampleWindow)
   {
      sample = analogRead(micPin);
      if (sample < 1024)
      {
         if (sample > signalMax)
         {
            signalMax = sample;  // save the max levels
         }
         else if (sample < signalMin)
         {
            signalMin = sample;  // save the min levels
         }
      }       
   }
   peakToPeak = signalMax - signalMin ;  // max - min = peak-peak amplitude
   numLedsToLightCal = ((peakToPeak-SoundCenterAdjust)*HEIGHT*SoundLevelAdjust)/1024 ;
   if(numLedsToLightCal >= HEIGHT){
    numLedsToLight = HEIGHT;
   }else {
   numLedsToLight = numLedsToLightCal; // adjusting to the output of the mic 
   }
    fadeToBlackBy( leds, NUM_LEDS, 200);


  for(int led = 0; led < numLedsToLight; led++) { 
  leds[led] += CHSV( colorSelect, 255, 192);
  }
  for(int led = HEIGHT*2-numLedsToLight; led < HEIGHT*2; led++) { 
  leds[led] += CHSV( colorSelect, 255, 192);
  }
  for(int led = HEIGHT*2; led < HEIGHT*2+numLedsToLight; led++) { 
  leds[led] += CHSV( colorSelect, 255, 192);
  }
  for(int led = HEIGHT*4-numLedsToLight; led < HEIGHT*4; led++) { 
  leds[led] += CHSV( colorSelect, 255, 192);
  }
}

void soundBarRotate() 
{

  // Sound level to lighting LED amount
   unsigned long startMillis= millis();  // Start of sample window
   unsigned int peakToPeak = 0;   // peak-to-peak level
   unsigned int signalMax = 0;
   unsigned int signalMin = 1024;
   while (millis() - startMillis < sampleWindow)
   {
      sample = analogRead(micPin);
      if (sample < 1024)
      {
         if (sample > signalMax)
         {
            signalMax = sample;  // save the max levels
         }
         else if (sample < signalMin)
         {
            signalMin = sample;  // save the min levels
         }
      }       
   }
   peakToPeak = signalMax - signalMin ;  // max - min = peak-peak amplitude
   numLedsToLightCal = ((peakToPeak-SoundCenterAdjust)*HEIGHT*SoundLevelAdjust)/1024 ;
   if(numLedsToLightCal >= HEIGHT){
    numLedsToLight = HEIGHT;
   }else {
   numLedsToLight = numLedsToLightCal; // adjusting to the output of the mic 
   }
    fadeToBlackBy( leds, NUM_LEDS, 200);

   for(int led = 0; led < numLedsToLight; led++) { 
   leds[led] += CHSV( gHue, 255, 192); 
   }
  for(int led = HEIGHT*2-numLedsToLight; led < HEIGHT*2; led++)  { 
   leds[led] += CHSV( gHue, 255, 192); 
  }
  for(int led = HEIGHT*2; led < HEIGHT*2+numLedsToLight; led++) { 
   leds[led] += CHSV( gHue, 255, 192); 
  }
  for(int led = HEIGHT*4-numLedsToLight; led < HEIGHT*4; led++) { 
   leds[led] += CHSV( gHue, 255, 192); 
  } 
}

void allwhite() 
{
  // all led white color
  fill_solid(leds, NUM_LEDS, CRGB::White); 
}

 

今回は、フロアランプに焚火を仕込みましょう!というコンセプトで、お家ですごす時間を楽しくしてみました。

毎週末を使って、製作期間は一か月ほどかかりましたが、初めて見る人には「フロアランプが燃えている!」と思わせそうな完成度で、満足しています。

WS2812Bでファイヤーパターンのフロアライト

室内で焚火はできないアパート暮らしですが、お部屋に焚き火風の光があると、本当にキャンプしているような気分になって、うっとりと見入っています。

ソロキャンプに似合うタクティカルなバッグは、MOLLE(モール)システムでカスタマイズしよう!

ソロキャンプに似合うバッグ

静かな雰囲気を楽しむようなソロキャンプスタイルでは、リュックサックに全てのキャンプ道具を積み込んで、身軽に出かけたくなります。

そんなキャンプの時に似合うのが、タクティカル系のリュックですね!

 

このような、ウェビング(ストラップ)がたくさん縫いこまれているリュックサックは、ポーチ類が簡単に脱着できるので、その時々のキャンプ条件に合わせて、持っていくものをポーチごと付け替えできるのも嬉しい機能です。

見るからにタクティカル(戦術的)で機能的な、このリュックサック、遅ればせながら私も欲しくなってきたのですが、ふとウェビングがあれば、いつも使っているバッグ類も、簡単に変身させられるのでは?と思いつきました。

周りにあるバッグを改めて確認してみると、同じくらいの幅のウェビングが、だいたい一か所は使われています。

ノースフェイスの防水リュックにもMOLLEシステムのウェビングが

これはカスタマイズして楽しめそう!だと思い、早速ウェビングに取り付けるアタッチメント類のセットを、入手してみました。

MOLLEアクセサリーでキャンプ用バッグにカスタマイズ

このアタッチメント類を活用し、普段使っているバッグにポーチや小物を追加して、個性的で機能的なソロキャンプ用のバッグに変身するかを試してみます!

ソロキャンプに似合うタクティカルなバッグは、MOLLE(モール)システムでカスタマイズしよう!

OLLE(モール)システムでソロキャンプに似合うバッグにしよう!タクティカルにカスタマイズ

MOLLE、モール、モーリーシステム?

ポーチをバッグに連結するアタッチメント類を入手するにあたり、そのシステムや規格について調べてみました。

1インチ幅のウェビングを使うMOLLEシステムは、アメリカで軍をはじめ警察や消防でも採用しているシステムです。

MOLLEは、Modular Lightweight Load-carrying Equipment(モジュラー ライトウェイト ロードキャリーイング イクイップメント)の省略名称です。

このMOLLEシステムを採用しているベストやベルト、バッグなどは、PALS(Pouch Attachment Ladder System;ポーチ アタッチメント ラダーシステム)と呼ばれる、

  • ハシゴ状に配置されたウェビングがついているか、
  • もしくはそのウェビングに取り付けられる構造

になっています。

PALSウェビングの規格は

  • 幅1インチ(約2.5cm)で、
  • 縦方向の間隔1インチでハシゴ状に配置し、
  • 1.5インチ(約3.8cm)間隔でベースの生地に縫いこまれて

います。

少し説明が長くなってしまいましたが、まとめると、MOLLEシステムを使ったポーチ類などは、PALSに簡単に付け外しができる仕組みになっています。

ちなみに、日本ではMOLLEを「モール」と発音することが多いですが、本場アメリカでは「モーリー」に近い発音のようです。

MOLLEアタッチメント類の使い方

入手したアタッチメント類について、それぞれの使い方を写真で簡単に紹介いたします。

ウェビング グリムロック(Dリング)

 普通のカラビナと、形も使い方も似ていますが、MOLLEシステム用のウェビンググリムロックは、頂上部のロックボタンを押してはずすと、外側に開きます。

MOLLEウェビング グリムロック(Dリング)
MOLLEウェビング グリムロックでキャンプ用バッグ

開いた状態でのみ、ウェビングに取り付けられるようになっているので、閉じて使っている通常時には、意図せず紛失する可能性は低いですね!

逆に、装着していたものを取り外すときに、普通のカラビナの感覚で操作すると開きっぱなしになり、何かに引っかかりやすくなってしまいます。

かっこ良さと引き換えに、開けたら閉じる!をクセ付けしようと思います。

ウェビング クリップ(コネクティング バックル)

ウェビングやストラップを2本束ねて挟む、MOLLE用のクリップです。

MOLLEウェビング クリップでキャンプ用のバッグをつくる
MOLLEコネクティング バックルでキャンプ用のバッグをつくる

上の写真では、ポーチに縫製されているPALSウェビングと、MOLLE規格のベルトを止めてみました。

ウェビングクリップがあれば、幅1インチ以下のウェビングがついているバッグ類に、MOLLE対応ポーチを取り付け可能です。

ウェブドミネーター

 名前を初めて聞いた時は、インターネット上の凄そうなもの(人)を連想しましたが、「ウェブ」は「ウェビング」の省略形だとわかって、納得しました!

MOLLEウェブドミネーターでキャンプ用のバッグをつくる

ウェブドミネーターには、ゴムコードと、それを引っかけられる溝がついていて、余分なストラップを束ねて保管できるようになっています。

せっかくのゴムコードなので、何か他の使い方がないかと思い、とりあえず、クルクルと丸めたタオルを留めてみました。

キャンプ用ポーチに、MOLLEウェブドミネーターでタオルを留める

予想外に良い感じでタオルがついています!

キャンプでの使い方としては、野営地に到着して最初に広げることになるグランドシートを、丸めて留めておくと便利そうです。

キーリング(キーホルダー)

「タクティカル」という言葉が似合う雰囲気の、ベルト付きキーホルダーです。

ポーチのPALSウェビングに、キーリングべルトのマジックファスナーで付けてみました。

MOLLEキーリング(キーホルダー)でキャンプ用のバッグにする

コレと決めたモノをつけるだけではなく、キャンプ中に使う細々としたグッズを、使わない時に一時的にぶらさげておくのにも便利そうです。

ポーチ類だけではなく、ベルトやベストに付けておいても便利そうですね。

そのための、MOLLEシステムのベストなんてものもあるようです!

回転Dリング

ウェビング上の好きな位置につけられる、Dリングです。

Dリングの向き(角度)は、45度ごとに調整できるので、ナナメ方向にも取り付けできます。

MOLLE 回転Dリング

このアタッチメントだけは、ベースを90度回転させる形で、1インチよりも細い幅のウェビングにも対応できるようになっています。

ベルトループ

 最後に、いろいろと使えそうな、マジックファスナー付きのベルトループです。

MOLLE ベルトループ

PALSウェビングがついているポーチ類の結合に使う他にも、いろいろな物をぶら下げる時のループとしても使えます。

キャンプでは数本持っておくと、何かと便利なアタッチメントです。

いつものバッグを変身させます! 

それでは実際に、普段使っているバッグ類をカスタマイズしてみます。

ノースフェイスのBCフューズボックス2に、こっそりDリングをつける

手始めに、家族が使っているノースフェイスのリュック(BC Fuse Box2)に、持ち主にはナイショでDリングを付けてみました。

ノースフェイスのリュックにMOLLEのDリングを付けてみた

あまりのシンデレラフィットに、毎日使っている持ち主には、まだ気づかれていません!

ちなみに、このリュックのストラップ部はデイジーチェーンとして設定されており、ウェビングの幅はPALS規格とほぼ同じですが、リュック本体への縫い目は斜めになっています。

通勤用のボディーバッグを、タクティカル風にしてみたら?

ブロック遊びのようにに組み立てられるMOLLEシステムが楽しすぎるので、勢いで、通勤で使っているNEOPROのボディーバッグのイメージチェンジを狙います。

バッグ背面のウェビングと、肩掛け用ストラップのそれぞれに、MOLLEポーチを装着してみました。

MOLLEシステムで、通勤用のボディーバッグもキャンプが似合うタクティカル風に

ブラックで色を統一しているのが幸いして、アウトドア用途化!という本来の目的を忘れて、このまま通勤で使ってもいいかも?と思わせる一体感です。

ウェブドミネーターを2か所つけたら、折り畳み傘の持ち運びも便利になりそうです。

ボディーバッグ本体を背中側にして肩掛けした時に、お腹側のちょうどいい位置にくるMOLLEポーチも使いやすく、正背面ともにバッグになっているボディーバッグが普及しないのが不思議なくらいです。

ハイキングやデイキャンプ程度であれば、このボディーバッグが活躍してくれそうです。

リュックサックを、キャンプが似合うタクティカル風にします!

 最後に、大本命のリュックサックを、イメージチェンジさせてみます。

バイク用品ブランド「FOX」のリュックで、少し古いものですが、気に入って今でも使い続けています。

もとから容量はそこそこあるリュックなので、背面ではなく前面の肩ストラップにポーチを追加してみます。

既に写真で何度も登場しているMOLLEポーチは、このために入手しました!

MOLLEシステムを使ってリュックサックをキャンプが似合うタクティカル風にかえる

キャンプで使うにしては少しオシャレ感がある、透かし模様の生地を使ったリュックですが、MOLLE ポーチを付けたことで、タクティカルな雰囲気に一変します!

MOLLEシステムに対応したポーチは、この写真の2種類の他にも、スマホホルダーやドリンクボトルホルダー、サングラスケースなど様々な種類があり、キャンプスタイルや持っていくものに合わせて選択できます。

ダッフルバッグ形状も、キャンプには便利!

MOLLEシステムで自由に組み合わせられる楽しさが病みつきになり、さらにキャンプに似合う、自分だけの荷物入れを作りたくなり、他のポーチやアタッチメント類も物色しはじめました。

どうせなら便利に活用したいので、少し長尺のキャンプ用品に対応できるものにしたい!と思います。

トライポッドやランタンスタンドで使うような、太めのポール類をキャンプに持っていく場合がありますが、長さがあるものが多いと持ち運びが大変だったりしますよね。

そこで、ポール類を余裕を持って入れられる長さの、MOLLEシステム対応のライフルケースを入手してみました。

MOLLE(モール)システムのバッグでキャンプに行く

ポールの他にも、軽量テントやハンモックなどを同時に入れられる容積のものにしたので、このバッグだけでソロキャンプに行けます。

大開口で開けられるようなジッパー配置になっているので、キャンプ地での設営や撤収作業も楽ですね。

テントやハンモックなどを入れられるMOLLE(モール)システムバッグ

そして最大の便利ポイントですが、荷物が収まりきらなかったり長さが足りないといった時に、ポール類はウェブドミネーターでバッグの外側にも取り付けることができます。

意外にもキャンプ道具がちょうどよく収まるMOLLE対応ライフルケースですが、さっそくポーチやアタッチメント類でカスタマイズして、上の写真の状態で楽しく便利に使っています!

色と明るさを変えられる集魚灯。ArduinoとLEDボードで自作したら爆釣!

先日、初めての夜釣りで小さい根魚を釣り上げました。

f:id:solocamptouring:20190427081000j:plain

手のひらに収まる、あまりにも可愛いサイズだったので、海に元気にお帰りになりました。

次回は、なんとしてでも大きな根魚に出会いたいので、魚が集まりやすい集魚灯を自作して、夜釣りに導入したいと思います。

f:id:solocamptouring:20190427134321j:plain

 

魚が集まる集魚灯の色

集魚灯に魚が集まってくる理由を調べてみました。

陸地からのチョイ投げタイプの海釣りで使う集魚灯は、発光性プランクトンや夜光虫を模したものです。

集魚灯の光に、プランクトンや夜光虫を食べる虫や小魚が寄ってきて、さらにそれらを捕食する魚も寄ってくるようです。食物連鎖でなんでも釣れそうですね!

発光性プランクトンといえば青色緑色のイメージです。

しかし、疑似餌(ルアー)が、実際にはありえない配色のものがよく釣れたりするので、集魚灯に最適な色も、実際に試してみないとわかりません。

そこで、自由に色を変えられる集魚灯を作って、その時々の最適な色を探ってみたいと思います。

集魚灯の自作

なるべく簡単に、そして安く集魚灯を作ってみます。

魚を集める機能を追い求めるので、見栄えは二の次です!

集魚灯の部品を準備します

Arduino

マイコンは、コンパクトな大きさで使いやすいArduino Nanoを使います。

写真は、今回使ったDC5Vの外部電源入力用の部品も写っています。

f:id:solocamptouring:20190427091835j:plain
f:id:solocamptouring:20190427104755j:plain

Arduinoのスケッチ(プログラム)は、記事の最後に掲載しています。

WS2812Bボード

集魚灯の発光部は、WS2812B を7個 配置した円形ボードを使います。

直径23mmと小型なので、堤防で根魚を狙う時などの集魚灯には、ちょうどいい性能と大きさです。

自作した集魚灯に使うWS2812B

ミサイルスイッチ

スイッチはなくても集魚灯は動かせるのですが、実際に使う時の雰囲気づくりのために、他の作品でもミサイルスイッチを使っています。

プロジェクトボックスのスペースをとってしまいますが、ミサイルスイッチで電源を入れる儀式をしてから使うと、何かが起きそうで気分が盛り上がります。

今回は、青色のミサイルスイッチで、釣れるスイッチのおまじないをします。

集魚灯の電源はミサイルスイッチで
集魚灯のプロジェクトボックス

可変抵抗(ボリューム)

集魚灯をコントロールするために、可変抵抗を使います

  • 光の色
  • 光の強さ

をそれぞれ選択できるように、2個の10KΩ可変抵抗を準備します。

コネクターとコード

海中に入れる発光部は5mのコードでコントローラに繋ぎます。

持ち運びやすくしたいので、AWG28の細い電線が3本入っているコードを準備しました。

コントロールボックスと発光部をつなぐコードは、コネクターで接続します。

Arduinoの自作作品に似合うコネクター

通販サイトでは、航空コネクタで検索するとみつかる、この少し仰々しいコネクターも、雰囲気づくりのために愛用しています。

集魚灯の回路をつくる

 WS2812Bボードは、電源線2本と信号線1本の合計の3本の電線をつなぐだけで、様々な光らせ方ができる優れものです。回路も単純な構成になるので、自作品には便利に使えます。

回路図は、Fritzingで作成しました。

f:id:solocamptouring:20190427101733j:plain

スペースの都合で、回路図にWS2812Bは5個だけ表現されていますが、実際には7個が直列につながっています。

発光部を除いて、配線をはんだ付けしてみました。

自作集魚灯の回路

今回は配線が少ないので、Arduinoには直接はんだ付けしています。

はんだごての熱でArduino上の部品を壊さないように、注意しながら作業を進めました。

プロジェクトボックスに回路を入れる

コントローラを仕上げるために、プロジェクトボックスに各部品の取付穴をあけます。

コネクターだけは、ボックスに外側から固定する形なので、配線をはんだ付けする前にボックスにねじ止めします。

続いて、スイッチと可変抵抗も、ボックスの上面に内側から取り付けます。

Arduino Nanoは、ボックス内に両面テープで貼り付けておきました。

自作集魚灯のコントローラ
自作集魚灯のコントローラの中

蓋を閉じたら、コントロールボックスの完成です。

試しに光らせてみましょう

5mの3芯コードの両端に、WS2812Bボードとコネクタをつけて、実際に光らせてみました。

自作集魚灯がほぼ完成

集魚灯として本命案の青色や緑色は、一種類だけでなく、可変抵抗のツマミをまわすことで多彩な色をつくりだすことができます。

集魚灯としての効果は無いかもしれませんが、 ツマミをまわして赤色や黄色などの色も作れます。

記事の最後で紹介しているスケッチでは、色を調整する可変抵抗のツマミを右にいっぱいまで回すと、ゆっくりと全ての色に変わっていくようにしています。

発光部の防水化

WS2812Bボードは、水深5mの水圧でも耐えられるように、透明樹脂で覆って防水化します。 

透明樹脂を流し込むケースに何を使おうか考えていたら、卓球の玉に目がとまりました。

大きさが発光部にちょうどよく、乳白色なので周囲に光を拡散してくれそうです。

さっそく玉の上部を切開します。

錘をつける針金を発光部の穴に通して玉の中にいれた後に、クリスタルレジン を流し込みました。

そのまま動かさないようにして樹脂が固まったら完成ですが、待ちきれないなので再度光らせてみます。

玉の下部に無造作に貼られているマスキングテープは、クリスタルレジンが流れ出ないように塞いでいるもので、樹脂が固まったら取り除きます。

自作集魚灯の発光部

狙いどおり、乳白色の卓球の玉全体で、いい感じで光っています。

自作集魚灯のシェイクダウン

後日、ためしに使ってみました。

釣りには不向きな強風の日に、漁港の堤防の風裏になる場所で、昼過ぎから釣り竿をたらしつつ、夜を待ちます。

明るいうちは何も釣れないままで時間が過ぎていき、あたりが暗くなったところで集魚灯の電源を入れて、釣りをしている場所から2mほど離れた海中に投入してみました。

すると、魚が活発に動く時間になったのもあると思いますが、種類は同じで前回よりも(成長したので!?)大きめの魚が、ほぼ入れ食いとなりました!

自作集魚灯に群がる根魚
色を変えて海中で淡く光る自作集魚灯

キャッチ&リリースを繰り返しましたが、あまりにも簡単に釣れるので、何匹釣ったか数えるのは途中でやめてしまいました。これは、もう夜釣りでは手放せません!

効果的な光の色は、少し青色が入った緑色が良さそうですが、これはもう少し継続して試してみて、確信を得たいと思います。

集魚灯のスケッチ(プログラム)

ご参考で、スケッチの紹介です。

GitHubのFastLEDライブラリを使って、簡単な命令文で光らせているので、短いスケッチになっています。

#include "FastLED.h"
#define DATA_PIN    4
#define LED_TYPE    WS2812
#define COLOR_ORDER GRB
#define HEIGHT 1
#define WIDTH 7
#define NUM_LEDS HEIGHT*WIDTH

CRGB leds[NUM_LEDS];

const int sampleWindow = 20; // Sample window width in mS
unsigned int sample;
int colorSelect;
int colorPin = 2;
int selectPin = 5;
int val = 0;
int numLedsToLight = 0;
int numLedsSide = 0;
int volumeLight = 0;

void setup() {

  delay(3000); //delay for recovery

  FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
}

uint8_t gHue = 96; // rotating "base color" used by many of the patterns

void loop()
{
  colorSelect = analogRead(colorPin); //check the volume to choose the color

  if (analogRead(colorPin) < 50) {
    colorSelect = 0 ;
  } else if (analogRead(colorPin) < 950) {
    colorSelect = map(analogRead(colorPin), 50, 949, 0, 255) ;
  } else {
    colorSelect = gHue;
  }

  val = analogRead(selectPin); //check the volume to choose the volume

  if (val < 205) {
    volumeLight = 3;
  } else if (val < 1000) {
    volumeLight = map(analogRead(selectPin), 205, 1000, 3, 50);
  } else {
    volumeLight = 50;
  }

  FastLED.setBrightness(volumeLight);

  fill_solid(leds, NUM_LEDS, CHSV( colorSelect, 255, 192));

  FastLED.show();  // send the 'leds' array out to the actual LED strip

  EVERY_N_MILLISECONDS( 300 ) {
    gHue++;  // slowly cycle the "base color" through the rainbow
  }
}

カヤックを載せやすいルーフキャリア。タフレックのアルミキャリアをカスタマイズ

カヤックをルーフキャリアにする。タフレックのアルミキャリア


ルーフキャリアに、長さ3m以上で重さ30Kgほどの荷物(カヤック)を、頻繁に載せたくなりました。

今すでに使っているルーフキャリアを改造して、すこしでも楽に積載できるようにしたいと思います。

私が使っているルーフキャリア

最初に、ジムニーに使っているキャリアについて、簡単に紹介いたします。

横から見たデザインに力強さがある、タフレックのルーフキャリア を選んで、不満なく使っています。

天板部が鉄のものとアルミのものがありますが、写真はアルミ天板のものです。

私の使い方での剛性は充分にありつつ、軽いのでキャリア自体を車から脱着する時の持ち運びも一人でできます。

そして、これから紹介するプチ改造では、「このための構造では?」と思ってしまうほど重要なポイントですが、サイドバーが丸パイプなのも、このキャリアの特徴です。

ルーフキャリアに積みたい長尺物

タフレックのアルミルーフキャリアを入手した時には、載せるものを特に決めていませんでした。

キャンプ道具をルーフに積むことがあるかもしれない!くらいにしか考えてなく、実際には雨で濡れたタープを運んだりと、半年に一度活躍する程度です。

しかし、ここにきてカヤックを始めたくなり、このキャリアに長さ3.15m、重さ約30Kgのカヤックを、おそらく頻繁に載せることになりました。

これだけの重さがある長尺物だと、一人で載せたり降ろしたりするために、ルーフキャリアを上手に活用したくなり、そのために少し改造したくもなります。

とりあえずやりたいのが、横から積み込む時の支点となるサイドバーのローラー構造化です。

長尺物を載せやすいルーフキャリアに工夫する。タフレックのアルミキャリア

横側のパイプが回転してくれれば、カヤックを車の横に立てかけた後に、ルーフ上に持ち上げる時に、楽になること間違いありません。

そしてもう一点、手を加えておきたいのが、長尺物を積んだ時には不要になる、前後ガードパイプの取り外しです。

f:id:solocamptouring:20190210163611j:plain

このパイプは、もともと格納式ですが、格納状態がキャリアの天板の高さより、少しだけ飛び出します。

カヤックのような平らなものを載せた時には、このパイプに重量がかかってしまうので、積載物を一部だけで支持することを避けるためにも、取り去ってしまおうと考えました。

それでは、ルーフキャリアにこれらの改造をしていきます!

タフレックのアルミルーフキャリアを改造します

ルーフキャリアは、車から降ろした後に、ある程度バラバラにしておきます。

10mmおよび8mmのソケットツールと、プラスドライバーがあれば作業できます。

長尺物の積み込み用ローラーをつける

ホームセンターで、外形32mmのアルミパイプと、それに合うパイプクッションを入手してきました。

f:id:solocamptouring:20190210164427j:plain

アルミパイプは55mmの長さに切断して、切断面のバリをとるために、やすりをかけておきます。

切断したアルミパイプにパイプクッションを被せて、パイプの長さにあわせてハサミでクッションを切ります。

f:id:solocamptouring:20190210165223j:plain

このパイプを、タフレックのサイドパイプに被せるかたちで組み付ければ完成です。

私の場合は片側だけローラー化できればいいので、運転席側だけを改造しました。

なお、追加したアルミパイプの走行時ガタつき防止のために、結束バンドを使っています。

この部分については、もっといい方法を思いついたらバージョンアップしていきます。

前後のガードパイプの取り外し

サイドバーをローラー化するためにルーフキャリアをバラバラにした際に、前後のガードパイプも取り外しておきました。

すっきりとしたので、長尺物を載せてタイダウンベルトで固定する時にも、作業がしやすくなっています。

思いのほか簡単にできました

今回、カヤックという長尺物をルーフキャリアに載せたいという想いから、ルーフキャリアを改造してみました。

構想に数週間かけてしまいましたが、実際の作業は半日もかからずに終わる、簡単な改造でした。

アルミパイプが追加されましたが、もともとついていたガードパイプを取り外したので、どちらかというと軽くなり、キャリア自体の車への付け外しも楽になっています。

f:id:solocamptouring:20190301045134j:plain

サイドバーが丸パイプのタフレックのキャリアだからこそできた、少し重量がある長尺物を搭載しやすくするプチ改造ですが、一年以上使ってみて、その積みやすさに毎回助けられています!

冬のテント内でも安全な暖房器具。酸欠にならないファンヒーターを自作します

f:id:solocamptouring:20181217045809j:plain

ポリエステルやナイロンなど、火に弱くて気密性の高い素材で作られているドーム型テントでは、中で火器を使うことができません。

そのようなテントの中で安全に使える暖房器具は、電気で発熱するもの以外には、なかなか見当たりません。

100ボルトの交流電源がないキャンプ場でも暖かくすごしたいので、バッテリー電源を使って省電力で駆動しつつも、テント内を安全に暖かくしてくれる暖房器具を、自作してみます。

テント内で安全に使えるファンヒーター

 

軽量ドーム型テント内での暖房器具に求められること

f:id:solocamptouring:20181217050337j:plain

ポリエステルやナイロン素材のテント内での暖房には、事故を起こさないという観点から、

  • 火(燃焼)は使わない
  • 高温にならない

ことが求めらます。

燃焼を伴う、ガスや灯油などを使う化石燃料ストーブや、薪や炭も使えません。

安全な暖房器具として思いつくのが電気で発熱するものですが、暖まるためには数十ワットが必要なため、コンセント電源がないキャンプ場ではバッテリーや発電機が必要になり、荷物が増えてしまいます。

そこで、発熱はテントの外の火力で行い、テント内に50℃以下の熱を送る方法を考えてみました。

f:id:solocamptouring:20181217050222j:plain

テント内を温める熱循環システム

テントの外でつくった熱をテント内に持ってくるための装置について、各機能ごとに考えてみました。

テント外での発熱部

電気を使わないテント外での熱源として、真っ先に思いつくのが焚き火やBBQです。

焚き火は、こまめな火の管理が必要なので、火に目が届きにくいテント内で、長時間過ごすことは不可能です。

火力が長持ちする炭を使う場合、酸素の流入をうまく制限できれは、数時間は放置できそうです。

火災がおきにくい周りが囲まれたもので、空気流入を制限して長時間にわたり炭を燃焼させやすい燃焼器具としては、ウッドストーブが使いやすそうです。

ウッドストーブを七輪がわりにして炭が使えることは、別に記事でも紹介しています。

www.solocamptouring.com

自作する暖房器具も、ウッドストーブで炭を使って、熱源とします。

火災予防としては、上から可燃物が落ちてきた時などのガード用で、小型のアルミテーブルの下で使うようにします。

f:id:solocamptouring:20181217051221j:plain

熱をテント内に運ぶ

テントの耐熱性から、テント内に送る熱は50℃以下をねらいます。

熱を運ぶ液体としては、水がもっとも簡単に取り扱うことができそうです。

ここまでで、ウッドストーブと湯たんぽの間を、温水が行き来するイメージが浮かんできました。

テント内での放熱

ウッドストーブで温めた水を、テント内まで循環して放熱するとなると、放熱器としてラジエーターのようなものが必要になります。

ふと、夏場にパソコンが相当熱くなって対応策を調べた時に、水冷式のパソコンの存在を知ったのを思い出しました。

水冷式パソコンの部品を調べてみると、多くの小型のラジエーターがあり、今回のテント暖房用にちょうどいい大きさのものもあります。

テント内で使うラジエーターとポンプは、水冷式パソコン用の部品を使うことにします。

テントで使う暖房システムの全体像

ウッドストーブの熱で水を温める方法については、最後まで悩みました。

外径9mm程度の銅管をコイル状にしてウッドストーブに置く方法にこだわったのですが、ちょうどいい形や大きさの完成品は見つけられませんでした。

また加工が楽なナマシ銅管は、少し予算オーバーなうえに、折れることなくコイル状に加工できるか心配です。

最終的に、放熱部同様に水冷式パソコンの部品を使って温水を作ることにしました。

高温になるCPUなどの熱を吸収するために使われる、アルミの水冷ブロックプレートです。

水冷PCのヒートシンクをキャンプの暖房に使う

このブロックプレートを、ウッドストーブの上に置いて循環水を温めます。

主な準備品をまとめてみます。

水冷PC用部品の流用

  • 水冷ブロックプレート
  • ラジエーター
  • ポンプ
  • リザーバータンク
f:id:solocamptouring:20181217052532j:plain
f:id:solocamptouring:20181217052540j:plain
f:id:solocamptouring:20181217052548j:plain

車用品の流用

  • 内径8mmの耐熱ホース (長さ2m

その他の部品

  • 小型ファン(PC空冷用のもの)
  • システム固定用の小物類
  • 12Vバッテリー

発熱に電力は使わないので、消費電流は

  • ポンプ: 0.5アンペア
  • ファン: 0.2アンペア

で合計1アンペア以下となり、モバイルバッテリーでも動かせそうです。

今回は小型の12Vバッテリーを使って、出力制限が無い状態で動かしてみます。

暖房システムの組み立て

全ての部品が内径8mmのホースでつながるので、ホースを必要な長さで切断する以外には、特に部品の加工はしないで組み立てていきます。

放熱用ラジエーターは、裏面に金網を、表面には電動ファンを取り付けます。

f:id:solocamptouring:20181217052839j:plain
f:id:solocamptouring:20181217052847j:plain

ラジエーターモジュールは、暖房として時用する時に、ちょうどいい位置に固定することが重要です。

全てのパーツが収納できるプロテクションボックス内に、蝶番で取り付けました。

f:id:solocamptouring:20181217053552j:plain

そのプロテクションボックスですが、他の部品も入れて持ち運びができる大きさで、頑丈なものがキャンプに似合いそうです。

他の用途で使っていた、TRUSCOのプロテクターツールケースを転用することにしました。

暖房性能を確認してみました

ウッドストーブ内の炭に火をつけます。

実際にキャンプで使う時には、上側をアルミのテーブルでガードする予定です。

プロテクションボックス内の暖房器具を組み立てて、リザーバータンクから循環水を注入します。

ウッドストーブはテントから少し離れた場所に置いて使いたいので、ホースの長さは往復各1mで、合計2mです。

約1リットル強の水で、循環システムが満たされました。

テント内で安全に使える暖房機器。ソロキャンプ用のヒーターを自作します。

ヒートシンクをウッドストーブ上に置いて、電動ファンとポンプの電源を入れてみます。

5分もたたずに循環水の温度が上がり、ラジエーターを通したファンの風が、暖かくなってきました。

youtu.be

温風は、おそらく30~40℃くらいです。実際にキャンプで使う時には、正確に計測する予定です。

ウッドストーブ上のヒートシンクは、ラジエーターで温度が下がった水が常に流れ込むため、手でも触れる温度を保っています。

思惑どおりの暖房効果を得られたので、次の冬季キャンプで使ってみます。

スマホを見ながらパソコン作業したい!ノートPCスタンドのプチ改造

持ち運びや移動が楽なタブレットパソコンを、家の中でさらに使いやすくするために、スタンドを導入してカスタマイズしました。

ノートPCスタンドをカスタマイズして、モバイルパソコンでの作業が快適に

私のタブレットパソコンの使い方紹介

参考で、私のタブレットパソコンは、LenovoのYOGA BOOKです。

軽くてコンパクトなので、外出時の携帯に便利なだけでなく家の中でも、机、テーブル、ソファー、ベッドなど、どこでもパソコン作業ができる点が気に入っています。

家の中でタブレットパソコンを使って作業する時には、数時間ごとに気分と姿勢を変えて、ソファーに深く腰掛けたり、床に座り込むようなことがあります。

そのような姿勢の時に、膝の上にパソコンを置いて作業すると、位置が低いために首などに負担がかかります。

この苦しい体勢から脱却できるように、ノートパソコンスタンドを導入することにしました。

どこでも使えるノートパソコンスタンドを選択

ノートパソコンスタンドを選ぶにあたり、重要視したのは、

  • 収納時にコンパクトになる
  • 軽い
  • いろんなパターンに応用できる

ことです。

いろいろなスタンドを比較した結果、このタイプを選びました。

 

選択時に重要視したポイントについて、実際に使ってみて気づいた事などを紹介いたします。

収納性

折り畳みや角度調整は、脚の関節部の中心にあるボタンを軽い力で押しながら角度を変えます。

角度の目盛りは、左右の関節を同じ角度にするのに便利です。

f:id:solocamptouring:20180918051141j:plain

関節を全て折り畳めば、天板とほぼ同じ厚さまで薄くなるので、家具と壁の隙間スペースなど、部屋の広さを阻害しない場合に収納できます。

軽さ

大部分の部品はアルミでできており、総重量は約1Kgです。

片手で難なく持ち運ぶことができます。

多くの使用パターン

脚の関節3ヶ所で、角度だけでなく、高さも自由に変えられます。

天板に軽く手を置いてキーボードやマウスを使っていますが、関節の剛性は充分で、作業時に天板が揺れる事はありません。

多関節の角度を変えて脚を伸ばせば、高さ約50cmのPCテーブル風になります。

f:id:solocamptouring:20180918202942j:plain

一番低い状態では、卓上でキーボードの角度を傾けて使いたい時にも応用できます。

f:id:solocamptouring:20180918202106j:plain

 

選択の決め手は価格

紹介してきたように、多くのパターンに融通が効くにもかかわらず、角度だけ変えられる卓上用スタンドと大差ないお値段だったので、迷わずこれを選びました。

なお、私が入手したPCスタンドには、脚の穴にネジでつける、マウス用のプラスチックのボードが付属しています。

便利そうですが、スタンドを収納する時など、脚を折り畳むときには取り外さないといけません。

f:id:solocamptouring:20180918051227j:plain

 スタンドを頻繁に収納する私は、付属のマウスボードは使用しないことにしました。

タブレットパソコンが10.1インチと小さいので、天板の余ったスペースでも、余裕をもってマウスを使えます。

ノートパソコンスタンドをカスタマイズします

これまで紹介している写真で既にお気づきだと思いますが、もっと便利に使えるようにカスタマイズしました。

PCの滑り防止

入手したノートPCスタンドは、天板を斜めにして使う時のパソコン滑り落ち防止用として、プラスチックのストッパーが2個が付属しています。

f:id:solocamptouring:20180918051426j:plain

厚みがあるパソコンを使うことを考慮したのだと思いますが、このストッパーは薄いパソコンで使うと、高さ方向の飛び出し量が多くなり、キーボードをうつ時に邪魔だったり、手首に当たってしまったりします。

そこで、このストッパーは使わずに、両面テープ付きのスポンジを貼って、パソコンが落ちるのを防止するとともに、傷付きも防ぐことにしました。

f:id:solocamptouring:20180918051524j:plain

パソコンの上や横の外形に合わせた位置にもスポンジを貼って、四方への滑りを防止しています。

スマホを見ながら、パソコン作業できるようにします

通常のパソコンで作業する際は、モニターが複数あると便利です。

タブレットパソコンで作業するときでも、似たような環境を作りたいと思います。

スマホの画面を見ながら作業できるように、スタンドの右上でマウス用スペースの奥の方に、スマホホルダーを取り付けます。

f:id:solocamptouring:20180918051649j:plain

使わずに余っていた、おそらく車のアクセサリー用のユニバーサルステーに、クリップタイプの100均スマホホルダーをボルト締めして、天板に貼り付けました。

f:id:solocamptouring:20180918051703j:plain

スマホやiPodタッチで、調べものをしたり動画を見たりしながら、PC作業ができるようになりました。

ちょっとしたカスタマイズですが、小さな画面が増えただけで、作業中の充実感が増したように感じます。

ノートパソコンスタンドは、とっても便利だと実感

ノートPCスタンドがあると、タブレットパソコンを家中どこでも快適便利に使えます。

一番ありがたみを感じているのはソファーに深く座ってパソコン作業する時で、前かがみになる事がなくなったので、たいへん楽な姿勢で作業を続けられます。

私のように、いろんな場所で高さや姿勢を変えながらパソコン作業する場合には、おすすめしたいスタンドです。

人の動きに同調する1/fゆらぎのつくりかた。USB扇風機を改造してみます(動画あり)

USB扇風機を癒しの1/fゆらぎ風に改造して、パソコン前スペースを快適化

空調の効いた屋内でも、いつも風を感じていたい!ので、パソコンのUSB端子を電源とする小型扇風機を使ってみる事にしました。

せっかくなので、自然風のような1/fゆらぎの風を感じられるように改造してみます。

1/fゆらぎについて

1/fゆらぎとは、振幅が周波数 f に反比例する波の集合波形です。

ゆらぎは平均値からの変動幅なので、周波数が小さい、ゆっくりとした波の成分ほど大きく変動するという意味になります。

人体も1/fゆらぎをしていて、周りの1/fゆらぎ を感じると、共鳴して精神安定などの効果があると考えられています。

USB電源のミニ扇風機

改造ベースとなる扇風機は、しっかり風を感じられて静かなものを選びます。

飛行機でSBも採用例がある二重反転プロペラ(コントラペラ)で、効率よく空気を押し出すものが良いようです。

たまたま、実際に使っている人のパソコン前を、静かなので扇風機に気付かずに通った時に、予想外の風量に驚かされたこともあり、写真の二重反転プロペラを持つ扇風機を選びました。

f:id:solocamptouring:20180719045658j:plain

リズム時計製のコントラペラ扇風機で、他にも「くまのプーさん」や「ミッキー」をデザインモチーフとしたバージョンもあります。

私は、一番安かったオーソドックスな形の薄紫色をチョイスしました。

この扇風機は、風量をハイ/ローの二段階に切り替えられます。

ローはそのまま使えるようにして、ハイに切り替えると1/fゆらぎの風になるように改造します。

Arduino と赤外線センサーで1/fゆらぎをつくる

1/fゆらぎの風は、扇風機と人との距離に応じて変動するようにします。

基本は、距離が

  • 近いと弱風
  • 遠いと強風
  • さらに遠いと停止(OFF)

にします。

赤外線センサーは、正面の平面体に対しては安定して距離を測れますが、服などの凹凸物に対しては少しばらつきがある測定結果になります。

これを逆手にとって、ばらつきが

  • 大きい時は、ゆっくり風量を変える
  • 小さい時は、早く風量を変える

ことで、1/fゆらぎの風をつくります。

これをモーターの回転数を変化させて実現するために、Arduinoを使って赤外線センサーで計測した扇風機前のもの(人)との距離から、モーターの目標スピードと、目標スピードに変わるまでの時間を決めて、PWM制御のパルスで出力します。

PWM(Pulse width modulation、パルス幅変調)は、電圧一定で、周期も一定のパルス波形です。このパルスを電源に使いつつ、ONパルスの幅を変える(=デューティ比を変える)と電圧の平均値が変わるため、結果として電圧を変えた時と同じ効果があります。

Arduino を使う回路

回路図は、Fritzingで作成しました。

f:id:solocamptouring:20180722133259j:plain

赤外線センサーGP2Y0E02Aの接続

シャープの、赤外線式の測距モジュールGP2Y0E02Aには、4本の端子があります。

  1. VDD(3.3V電源)
  2. GND
  3. Vout(出力)
  4. GPIO1

1番はArduinoの3.3Vに、2番はGNDに接続します。

3番のVoutは、電圧で距離情報を返してくるので、Arduinoのアナログピン(回路図ではA3ピン)に接続します。

4番のGPIO1は、電圧がVDD付近であれば計測、GND付近であればスタンバイ(計測しない)モードとなります。Arduinoのデジタルピン(回路図ではD5ピン)からの5V信号を、抵抗3個とダイオードで約3.3Vに減圧して接続します。

赤外線センサーGP2Y0E02Aの接続(USB扇風機の癒し改造)

モーターの接続

PWMで速度を変えるため、Arduinoのデジタルピン7からパルス信号を出力します。

パルス信号はトランジスタのベースに送ってスイッチングして、モーターに電流供給します。

パルスがLOW(0V)の時に、モーターの逆起電力からトランジスタを守るために、ダイオード(D1)を、モーターと並列に使用します。 

トランジスタとベース抵抗値の計算

トランジスタ2SD882を使う回路設計

使用するUSB扇風機は、商品説明によると定格電流210mAです。

トランジスタは、余裕を持って作動させられる2SD882を使います。

  • Ic=210mA
  • hFE=100倍
  • VBE=0.8V

の値を使って、ベースに接続する抵抗値を求めます。

RB=(5-0.8)/(0.21/100)=2000Ω

2000Ωの抵抗RBを使用して、トランジスタのベースとArduinoのデジタルピン(D7)を接続します。 

作動を安定させるため、抵抗RBと平行にコンデンサを、またトランジスタのBE間に抵抗を入れておきます。

扇風機から、そのまま使う電子部品

f:id:solocamptouring:20180719050203j:plain

使用するUSB扇風機の、ハイ/ロー切り替えの元回路は、

  • ハイ側: 電源は、2個の直列配置モーターに直接供給
  • ロー側: 2個の定電流ダイオード(直列)を通して、2個の直列配置モーターに電源供給

となっていました。

ロー側の定電流ダイオードは、電源のプラス側からマイナス側に移設して、そのまま使います(回路図では、2個をまとめてD4と記載)。

スイッチをハイ側に切り替えると、Arduinoの電源が入り、トランジスタを通してPWMでモーターを駆動するように、回路を作ります。

USB扇風機にArduinoを搭載して、癒しの1/fゆらぎ風に改造

1/fゆらぎ扇風機のスケッチ(プログラム)

1/fゆらぎのつくりかた

赤外線測距センサーで計測した距離は、100回測定した平均値を使います。

得られた距離に応じて、

  • 5〜60cm: PWMのデューティ比を50%〜100%に変化
  • それ以外: 停止

として、目標速度と、そこに到達するまでの時間を設定します。

また、目標速度に到達するまでの間も距離を測定して、その時点におけるデューティー比のゆらぎ(計算値と、距離測定値から置き換えた数値の差を1/3したもの)を変化量として瞬時に加えます。

デューティー比のゆらぎが負(マイナス)の場合は、数値に応じて短い間、電源を遮断して即答させます。

距離が60cmより遠い場合は、人(私)が扇風機前から席を外したと判断して停止し、以後1秒毎に距離測定して、人が戻ってきたら再開します。

USB扇風機をArduinoで改造

スケッチの紹介

int trigPin = 5;
int pwmOutput = 7;
int distResult = 0;
long distA = 0 ;
int i = 0 ;
int j = 0 ;
int frequencyWindChange = 0 ;
int speedOutput = 0 ;
int speedCurrent = 50 ;
int speedNowTarget = 50 ;
int speedOldGoal = 50 ;
int speedGoal = 50 ;
int speedAdjust = 0 ;
int speedAdjustParameter = 3 ;

void setup() {
pinMode(trigPin, OUTPUT); 
pinMode(pwmOutput, OUTPUT); 
delay (100);
digitalWrite(trigPin, HIGH);
}

void loop() {
  
     long voltAns ;
     voltAns = IDMread(3)  ;           // アナログピン3番のセンサーの値を読込む
     long distAns1 = map(voltAns,0,1023,0,500) ; // 電圧値に変換する(0から5V)
     long distAns2 = map(distAns1,55,220,50,4) ;  // 電圧値から距離に変換する(0.55から2.2Vを50から4cm)
     int distResult = distAns2; 

  if(distResult > 60){
  analogWrite(pwmOutput, 0) ;
  speedOldGoal = 50 ;  
  delay(1000) ;
  }else{
  speedGoal = map(distResult,0,65,50,100) ;
  frequencyWindChange = abs(speedGoal - speedOldGoal) ;

    for (j=0 ; j < frequencyWindChange; j++) {
   speedNowTarget = speedOldGoal + (speedGoal - speedOldGoal)/frequencyWindChange*j ;

      
    long voltAns ;
     voltAns = IDMread(3)  ; 
     long distAns1 = map(voltAns,0,1023,0,500) ; 
     long distAns2 = map(distAns1,55,220,50,4) ; 
     int distResult = distAns2; 
     
     speedAdjust = (map(distResult,0,65,50,70) -  speedNowTarget)/speedAdjustParameter ;
     speedOutput = 255*(speedNowTarget + speedAdjust)/100 ;
     if(speedAdjust < 0){
      analogWrite(pwmOutput,0);
      delay(70*abs(speedAdjust));
     }
     analogWrite(pwmOutput,speedOutput);
     delay(200);
     } 
     
   speedOldGoal = speedGoal ;  
  }
}

// 赤外線測距モジュールから読み込む処理
int IDMread(int PinNo) {
     distA = 0 ;
     for (i=0 ; i < 100; i++) {
          distA  = distA + analogRead(PinNo) ;   // アナログピンから読取る
     } 
     return distA/100 ;                        // 100回の平均値を返す
}

癒しの風を感じてみます

扇風機のプロペラ回転数は細かく変動しています。時々、自然に風のような、ゆっくりとした大きな変動もあり、1/fゆらぎらしくなっています。

回転数に応じてプロペラの残像が刻々と変化するので、ぼ~っと見ていても飽きません。

また、席をはずして戻ってきた時には、停止状態から自動で動き始めるので、「おかえり!」と言われたようで、少し幸せな気持ちになります。

youtu.be

ちょっとした改造ですが、Arduinoと測距センサーを使うことで、オフィスなどの密閉された屋内空間でも、自然のような風のそよぎを感じる事ができて、眠気を誘うほど快適になります。