今回は、お家でキャンプ気分シリーズの、スピンオフ編です。
焚き火を眺めてすごす、キャンプでの優雅な時間を、屋内でも楽しみたい! ということで、背が高いフロアランプを、カラーLEDを使って改造して、焚き火台風にしてみます。
焚き火とサウンドレベルメーター
アウトドアを楽しめない週末が続くと、いろいろな思いがこみ上げてきます。
殺風景な部屋に、フロアランプが欲しい!
キャンプに行けないのであれば、部屋で焚き火気分を楽しめないかな?
外出できないのであれば、しばらく封印していたDIYでもやってみようか...
こんな妄想たちを、一気に実現するには、焚き火風のフロアランプを自作 するしかない!と確信しました。
テーマパークの仕掛けで見かける、本物の炎のような、フェイクな焚き火です。
ファンの風によって布をチラつかせて、さらに光も当てることで、本物の焚き火と錯覚してしまう、あれですね。
購入した方が安くすみそうな気がしますが、自作もできそうな気がします。
しかし、構造を考えていて、音について悩みが生じます。
くつろぎの時間を過ごしたいところで、ファンの音に耐えられるだろうか? と。
テーマパークのような、他の音が存在する場所なら気にならないと思いますが、プライベートな部屋ではファンの音は雑音でしかありません。
ファンを使わずに炎のような光を実現するには、小さな光源がたくさん必要になりそう...と考えていて、それならLEDで表現 してみましょう!と、コンセプトがみえてきました。
LEDの直接光では、炎のように見せるのは難しいと思われるので、日本の伝統的なフロアライト、行燈の中にLEDたちを閉じ込めてしまいます。
行燈の中に焚き火があっても、いいじゃない!
行燈をサウンド レベル メーターに!
不規則に揺らぐ焚き火の光は、見ていて飽きませんよね〜
あの揺らぎを人為的に表現するには、乱数発生プログラムを使ってLEDを不規則に光らせることが近道だと思いました。
...でも、それだけだと不規則すぎて面白くない気もします。
相変わらずの捻くれ者ぶりを発揮してしまったので、一週間ほど悩んでみました。
時間をかければ閃くこともあるようで、ふと音楽に合わせて光らせてみたら面白いのでは? と思いつきます。
行燈の中で、炎と、音楽に合わせて光が踊っているフロアーランプ!
これは欲しい!と納得できるアイデアが浮かんだので、さっそく制作に取り掛かります。
IKEAで行燈選び
アウトドアには行けない日が続いているものの、家具屋さんのIKEAが家の近くにあり、毎週末のように通って、気分転換をしています。
そんなIKEAには、今回の行燈サウンド レベル メーターの改造ベースにピッタリのフロアランプ があることを知っています。
フードの材質が紙なので、光の指向性があるLEDとの相性もバッチリです。
いつもIKEAでは散歩スピードでショールームを楽しんでいますが、今回は売り場に直行して、フロアランプを入手してきました。
Arduinoと接続するモジュール
フロアランプを、行燈風サウンド レベル メーターとして光らせるために、個別に制御できるRGB LEDのWS2812Bをを使います。
「〇〇番目のLEDさんは、△△色に光ってください〜」
という情報さえ流せば、その通りに光るので、多くのLEDを個別に光り方を変えるのに便利なものです。
1mあたりにWS2812Bが60m個並べられているカラーLEDテープ を3mと、サウンドセンサーモジュール、そして可変抵抗(ボリューム)3個を入手しました。
以前に、可変抵抗1個を使ってナイトライダー風サウンド レベル メーターを作ったことがありますが、今回はフロアランプでもあるので、
の3項目を可変抵抗で選択できるように進化させます。
表示イメージとパターン
もともとは、「焚火 in 行燈」 コンセプトで始めたプロジェクトですが、純粋にサウンド レベル メーター風のパターンも含めて、合計7種類の光らせ方を準備します。
① 行燈なので、まずは白色 で光らせます。
写真は紫色のように写っていますが、実際には白色です。
② サウンドレベルのバーが立ちます。色は炎のように、赤 とオレンジ のグラデーションです。
③ サウンドレベルのバーが立ちます。色は可変抵抗で選択した単色 です。
④ サウンドレベルのバーが立ちます。色は徐々に変化 します。
⑤ 焚き火風 に光らせます。色は、「赤 、オレンジ 、白色 」の3色です。
⑥ 焚き火風 に光らせます。色は、「青 、水色 、白色 」の3色です。
⑦ 焚き火風 に光らせます。色は、「可変抵抗で選択した色 、白色 」の2色です。
⑧ 焚き火風 に光らせます。色は、「徐々に変化する 色 、白色 」の2色です。
回路図
Fritzing で回路図を作成しました。
マイクモジュールは、MAX4466 を搭載したものを使っています。
3個の可変抵抗(ボリューム)は、
R1;光量
R2;表示7パターンの切り替え
R3;色
の調節(選択)をするために使います。
Arduinoのアナログ入力には、それぞれの可変抵抗から電圧で情報が送られます。
電圧; 0〜5V
Arduinoの読み取り値; 0〜1023(整数)
0〜1023をArduinoのスケッチ(プログラム)で選択肢に置き換えれば、LEDの発光を調節できます。
今回は180個が繋がっているものを使うWS2812B は、先程も簡単に紹介しましたが、それぞれのLEDが個別に信号処理して、色や光量を認識して発光するので、信号線1本と電源の、合計3本の電線を繋ぐだけで、自在に光を制御できる優れものです。
スケッチは、記事の最後に掲載しておきますね。
炎が踊るフロアーランプ
LEDの配置
LEDを、ランプ中心部の柱にどう配置するか?について、少し試行錯誤しました。
結論から言うと、縦に配置した方が、LEDの貼り付け作業も、炎やサウンドレベルメーターのスケッチ(プログラム)の作成も楽です。
私は4列で配置することにしました。
180個のWS2812Bテープなので、
「45行x4列 」
になる筈ですが、試行錯誤の段階でちょっとした事故があり、数セルが使えなくなってしまったので、やむなく43x 4の配置になりました。
ウエルカム点灯
電源投入時の動作は、3種類を仕込んでおきます。
ランダム点滅(白色)
白色光を上下に一回走らせる
レインボー色の光を上下に一回走らせる
静止画だと、どれだけ綺麗に光っているか?が伝わらないですが、光り方はメイキング動画でも、ご確認いただけます。
VIDEO 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
#define MIN_BRIGHTNESS 5
#define lighting_PER_SECOND 30
CRGB leds[NUM_LEDS];
CRGBPalette16 gPal;
const int sampleWindow = 50 ;
unsigned int sample;
int SoundCenterAdjust = 0 ;
int SoundLevelAdjust = 6 ;
int BRIGHTNESS = 50 ;
int scaleVol = 230 ;
int SPARKING = 130 ;
int COOLING = 70 ;
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 );
FastLED.addLeds<LED_TYPE, DATA_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
FastLED.setBrightness(BRIGHTNESS);
}
typedef void (*SimplePatternList[])();
SimplePatternList gPatterns = { allwhite, soundBarFire, soundBarSelect, soundBarRotate, fireRed, fireBlue, fireSelect, fireRotate};
uint8_t gCurrentPatternNumber = 0 ;
uint8_t gHue = 96 ;
void loop()
{
if (analogRead(blightPin) < 50 ) {
BRIGHTNESS = 0 ;
} else {
BRIGHTNESS = map(analogRead(blightPin), 50 , 1024 , MIN_BRIGHTNESS, MAX_BRIGHTNESS) ;
}
FastLED.setBrightness(BRIGHTNESS);
if (analogRead(colorPin) < 50 ) {
colorSelect = 0 ;
} else if (analogRead(colorPin) < 950 ) {
colorSelect = map(analogRead(colorPin), 50 , 949 , 0 , 255 ) ;
} else {
colorSelect = 255 ;
}
val = analogRead(selectPin);
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]();
if (welcomeLight == true ) {
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 );
}
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 );
}
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 ;
}else {
random16_add_entropy( random());
gPatterns[gCurrentPatternNumber]();
FastLED.show();
FastLED.delay(1000 / lighting_PER_SECOND);
EVERY_N_MILLISECONDS( 300 ) { gHue++; }
}
}
void fireRed()
{
gPal = CRGBPalette16( CRGB::Black, CRGB::Red, CRGB::Yellow, CRGB::White);
static uint8_t heat[NUM_LEDS];
for ( int i = 0 ; i < NUM_LEDS; i++) {
heat[i] = qsub8( heat[i], random8(0 , ((COOLING * 10 ) / HEIGHT) + 2 ));
}
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 ;
}
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 ) );
}
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];
for ( int i = 0 ; i < NUM_LEDS; i++) {
heat[i] = qsub8( heat[i], random8(0 , ((COOLING * 10 ) / HEIGHT) + 2 ));
}
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 ;
}
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 ) );
}
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];
for ( int i = 0 ; i < NUM_LEDS; i++) {
heat[i] = qsub8( heat[i], random8(0 , ((COOLING * 10 ) / HEIGHT) + 2 ));
}
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 ;
}
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 ) );
}
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];
for ( int i = 0 ; i < NUM_LEDS; i++) {
heat[i] = qsub8( heat[i], random8(0 , ((COOLING * 10 ) / HEIGHT) + 2 ));
}
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 ;
}
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 ) );
}
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()
{
unsigned long startMillis= millis();
unsigned int peakToPeak = 0 ;
unsigned int signalMax = 0 ;
unsigned int signalMin = 1024 ;
while (millis() - startMillis < sampleWindow)
{
sample = analogRead(micPin);
if (sample < 1024 )
{
if (sample > signalMax)
{
signalMax = sample;
}
else if (sample < signalMin)
{
signalMin = sample;
}
}
}
peakToPeak = signalMax - signalMin ;
numLedsToLightCal = ((peakToPeak-SoundCenterAdjust)*HEIGHT*SoundLevelAdjust)/1024 ;
if (numLedsToLightCal >= HEIGHT){
numLedsToLight = HEIGHT;
}else {
numLedsToLight = numLedsToLightCal;
}
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()
{
unsigned long startMillis= millis();
unsigned int peakToPeak = 0 ;
unsigned int signalMax = 0 ;
unsigned int signalMin = 1024 ;
while (millis() - startMillis < sampleWindow)
{
sample = analogRead(micPin);
if (sample < 1024 )
{
if (sample > signalMax)
{
signalMax = sample;
}
else if (sample < signalMin)
{
signalMin = sample;
}
}
}
peakToPeak = signalMax - signalMin ;
numLedsToLightCal = ((peakToPeak-SoundCenterAdjust)*HEIGHT*SoundLevelAdjust)/1024 ;
if (numLedsToLightCal >= HEIGHT){
numLedsToLight = HEIGHT;
}else {
numLedsToLight = numLedsToLightCal;
}
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()
{
unsigned long startMillis= millis();
unsigned int peakToPeak = 0 ;
unsigned int signalMax = 0 ;
unsigned int signalMin = 1024 ;
while (millis() - startMillis < sampleWindow)
{
sample = analogRead(micPin);
if (sample < 1024 )
{
if (sample > signalMax)
{
signalMax = sample;
}
else if (sample < signalMin)
{
signalMin = sample;
}
}
}
peakToPeak = signalMax - signalMin ;
numLedsToLightCal = ((peakToPeak-SoundCenterAdjust)*HEIGHT*SoundLevelAdjust)/1024 ;
if (numLedsToLightCal >= HEIGHT){
numLedsToLight = HEIGHT;
}else {
numLedsToLight = numLedsToLightCal;
}
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()
{
fill_solid(leds, NUM_LEDS, CRGB::White);
}
今回は、フロアランプに焚火を仕込みましょう! というコンセプトで、お家ですごす時間を楽しくしてみました。
毎週末を使って、製作期間は一か月ほどかかりましたが、初めて見る人には「フロアランプが燃えている!」と思わせそうな完成度で、満足しています。
室内で焚火はできないアパート暮らしですが、お部屋に焚き火 風の光があると、本当にキャンプしているような気分になって、うっとりと見入っています。