宴会芸用の電子工作
皆さんは、飲み会で「一発芸をしろ」といわれた経験はあるでしょうか?このような悩みを電子工作で解決したいと思う。目指すは装着するだけでバイブスぶちあがりな装置である!!
なお、実行結果のGIF画像は激しい光の点滅を伴うので、ご視聴の際はご注意ください。
要件的なもの
バイブスぶちあがりな装置として、今回はワイシャツのように前開きの服を開いたときに〇首を光らせる装置を作成しようと思う。こんなことをすると電子工作への冒涜だとか言われそうなのでまともな使用例を挙げておくと、部屋の消灯を確認して足元を照らすなどにも使える。
簡単なフローチャートを以下の図に示す。
![](https://assets.st-note.com/img/1715486397497-mpTtKE0SIj.jpg?width=1200)
今回は、シャツが開いている時のみLEDを点灯させる。(シャツを閉じている時に光らせるとネタバレしてしまうため)
シャツの開閉検出とLEDの点灯は以下のように行う。
ワイシャツの開閉を検出:Cds光可変抵抗器によって検出
光らせる:できるだけまぶしくしたいので、フルカラーLEDを採用
Cds光可変抵抗
今回使用するCdsを図で示す。
![](https://assets.st-note.com/img/1715494638549-Ze8kng5KZs.jpg?width=1200)
Cds光可変抵抗はセンサ部に照射される光の明るさに応じて抵抗値が変化する部品である。
光の明るさに応じて抵抗値が変化していることを実験で確認してみる。Cdsに光があたる状態と当たらない状態の抵抗値を計測してみる。
試しにLEDとCdsをつなげてLEDの明るさの変化を調べてみる。回路図を以下の図に示す。ここでは、抵抗値が低くなりすぎることを防ぐため、330Ωの抵抗をかませている。
![](https://assets.st-note.com/img/1715486853751-MME5uysyTW.png?width=1200)
光の明るさの変化を以下の図に示す。
![](https://assets.st-note.com/img/1715494949460-sVec3e3Mmi.jpg?width=1200)
写真では少しわかりにくいが、暗いときの方がLEDが暗くなっていることが確認できる。また、テスターでCdsの抵抗値を測った結果9倍程度、抵抗値に変化が見られた。
言うまでもないかもしれないが、LEDと抵抗値の関係は以下の式の通りである。
$$
I = \frac{V_{in} - E_{LED}}{R}
$$
ここで、Vinは電源電圧、E_LEDはLEDによる電圧降下、Rは抵抗値を示す。電流値Iの値によってLEDの明るさが変化する。
Iが大きい(Rが小さい):LEDは明るく光る
Iが小さい(Rが大きい):LEDは暗く光る
以上のことから、Cdsは光が明るいほど抵抗値が低くなり、光が暗くなるほど抵抗値が高くなることが確認できる。
Arduinoを使った明るさの検出
今回も例によって、制御用マイコンとしてArduinoを使用する。ArduinoとCdsは可変抵抗と同じ要領で接続すればよい。今回は分圧回路の要領で、Cdsに流れる電圧を計測する。Cdsから明るさを検出するための回路図を以下に示す。
![](https://assets.st-note.com/img/1715487170467-xLjVmGu5Ht.png)
この時ArduinoのA5ピンが検出する電圧は以下の式に基づいて検出される。
$$
V_{out} = \frac{R_{Cds}}{R + R{Cds}}V_{in} = \frac{R_{Cds}}{330 + R{Cds}}5[V]
$$
この式のRCdsはCdsの抵抗値を示し、うえで述べたように抵抗値が変化する。よって、RCdsとAruinoが検出する値の関係は以下の通りになるはずだ。
RCdsが小さい(明るいとき):Arduinoは0に近い値を検出
RCdsが多きい(暗いとき):Arduinoは5[V](1025)に近い値を検出する。
明るさを取得するArduinoプログラム
それでは、実際にArduinoからデータを取得して、シリアルモニターに出力してみる。Arduinoに書き込むコードを以下に示す。といっても至って普通のanalogReadプログラムだが…
void setup() {
Serial.begin(115200);
}
void loop() {
Serial.println(analogRead(A5));
delay(10);
}
実行結果
プログラムの実行結果を以下に示す。実行結果から「明るいとき」と「暗いとき」で取得値に差があることが分かる。
![](https://assets.st-note.com/img/1715495514170-cgl7fCdjAU.jpg)
これらの結果から、シャツが開いていることを閾値的に検出する。今回は閾値を適当に850としておく(実際に装着したり、物理的な実行環境によってどうせ値が変わっちゃうからて適当で)。
フルカラーLED
フルカラーLEDの性質
フルカラーLEDはRGBすべての色で光らせることのできるLEDである。
![](https://assets.st-note.com/img/1716046231956-sKqG6sflEZ.jpg?width=1200)
特徴として、通常のLEDと異なり、複数のアノード線がある。このアノードに与えるパターンを変えることでLEDの色を制御することができる。
フルカラーLEDの制御回路
![](https://assets.st-note.com/img/1715488944478-69bEj927WU.png)
Arduinoのコードの作成
コードは以下のように作成した。今回はできるだけ(視覚的に)騒がしくLEDを光らせるため、LEDの色を100[ms](10[ms]だと早すぎて、色の変化が分からなかった)ごとに変更している。
2つのLEDを簡単に制御するため、C++のクラスを使ってプログラムを作成している(要望があればコードの詳解をします)。LEDを光らせるためアルゴリズムはこのページを参照してください(宣伝)。
//main.ino
#include "LED_Control.h"
LED_Control Right(2, 3, 4);
LED_Control Left(5, 6, 7);
void setup() {
Serial.begin(115200);
Right.set_up_LED();
Left.set_up_LED();
Left.keep_right_num = B0010;
}
void loop() {
int right_pow = analogRead(A5);
if (right_pow < 850){
Right.LED_ON(B000);
Left.LED_ON(B000);
}
else{
Right.LED_off();
Left.LED_off();
}
delay(100);
}
// LED_Control.cpp
#include "LED_Control.h"
#include "Arduino.h"
bool LED_Control::access_digit(int num, int digit){
return (((num % (1 << digit+1)))-(num % (1 << digit)))/(1 << digit); //powを使うとintに変換したときに誤差が大きいので、シフト演算子を使う
}
void LED_Control::LED_off(){
digitalWrite(LED_pin_A, LOW);
digitalWrite(LED_pin_B, LOW);
digitalWrite(LED_pin_C, LOW);
}
void LED_Control::set_up_LED(){
pinMode(LED_pin_A, OUTPUT);
pinMode(LED_pin_B, OUTPUT);
pinMode(LED_pin_C, OUTPUT);
}
void LED_Control::LED_ON(int pattern){
digitalWrite(LED_pin_A, access_digit(pattern, 0));
digitalWrite(LED_pin_B, access_digit(pattern, 1));
digitalWrite(LED_pin_C, access_digit(pattern, 2));
}
void LED_Control::LED_ON(){
digitalWrite(LED_pin_A, access_digit(keep_right_num % 7, 0));
digitalWrite(LED_pin_B, access_digit(keep_right_num % 7, 1));
digitalWrite(LED_pin_C, access_digit(keep_right_num % 7, 2));
keep_right_num++;
}
// LED_Control.hpp
class LED_Control{
public:
int LED_pin_A;
int LED_pin_B;
int LED_pin_C;
int keep_right_num;
public:
LED_Control(int a, int b, int c){
LED_pin_A = a;
LED_pin_B = b;
LED_pin_C = c;
keep_right_num = 0b0000;
}
void set_up_LED();
void LED_off();
void LED_ON(int pattern);
void LED_ON();
bool access_digit(int num, int digit);
};
実行結果 激しい点滅に注意!!
実行結果の一例をGIF画像で示す。非常にうっとうしい。動画にはフィルターを掛けているのでわかりにくいが、LEDの色が変化していることが確認できる。また、Cdsを覆うと、LEDが消えていることも確認できる。
![](https://assets.st-note.com/production/uploads/images/141067906/picture_pc_d3dde0c6c643a40a1865367c5a420963.gif)
ちなみに、動画ではCdsの閾値を950としている(スマホをセンサ上にかざすとセンサが反応してしまった)。
さいごに
今回はCdsの値に基づくフルカラーLEDの制御を行った。今後の課題として以下のようなことが挙げられる。
基板にはんだ付けし、実際に装着して使用できるようにする。
小型化:今回はマイコンにArduino UNOを使用したが、小型化のため、最低でもArduino nanoシリーズを使用する。
LEDの点灯周波数とCdsの計測周波数が同じなので別々にする。
Cdsの検出は閾値以外のものを使う など
この記事が気に入ったらサポートをしてみませんか?