// 跳ねるLED by KenKen // Arduino版 // https://github.com/KenKenMkIISR/Bouncing-LED // https://twitter.com/KenKenMkIISR/status/1286264718080917505 // https://note.com/bunkeidatte/n/na51f29995908 // 参考:LED_bouncing.ino // 2021-01-18 / JH3DBO // 01-25 GRAVITYの乱数発生毎ブロック落下ごとに変更 // 使ったLEDは「WS2812B」 1mで144LED // BRIGHTはPin11で明暗、Pin10で停止/点灯 ★1 // GRAVITYとBLOCKは乱数で変化するように ★2 // 先端から落ちるように ★3 (出窓での配線が床側だから) // 大きく跳ね返るように ★4 // GRAVITYと停止判定速度、跳ね返った時の速度をシリアル出力 #include #define PIN 12 //信号端子のピン番号 #define LED_NUM 130 //LEDの総数 (144個のから上端14個を切って130に) #define LED_R (LED_NUM -1) // ★3 Adafruit_NeoPixel LED = Adafruit_NeoPixel(LED_NUM, PIN, NEO_GRB + NEO_KHZ800); /***** ★1 明暗切り替え *****/ // Pin11を入力にして明るさ調整 // Hなら明るく Lなら暗く // Pin10を入力にして点灯/消灯 // Hなら点灯  Lなら消灯 uint16_t BRIGHT(void) { if(digitalRead(11) == HIGH) return 100; // 明るく else return 60; // 暗く } // LEDの個数やブロック長,跳ね返りの設定 // #define BLOCK 6 //LEDブロックの長さ uint8_t BLOCK = 6; //LEDブロックの長さ(変数にして乱数化) ★2 //#define BRIGHT 60 //明るさ (関数にしてPin11で明るさ変化) ★1 //#define GRAVITY 20 //重力加速度 int32_t GRAVITY = 20; //重力加速度(変数にして乱数化) ★2 //最下点での跳ね返り係数=R1/R2 #define R1 8 //跳ね返り係数1(3) ★4 大きい方が見ごたえがある #define R2 10 //跳ね返り係数2(5) //#define REFMINV -80 //跳ね返り最小速度 ★4 小さいと繰り返す #define REFV 35.0 // 停止判断定数 stop_vを計算 void set_block(uint16_t y,uint8_t c){ //LEDブロック表示 //y 表示するLEDブロックの先頭位置 //c 表示色 0(消灯), 1(赤)~8(緑)~16(青)~24(赤) uint32_t rgb; if(c==0) rgb=LED.Color(0,0,0); else if(c<=8) rgb=LED.Color((uint16_t)(8-c)*BRIGHT()>>3 ,(uint16_t)c*BRIGHT()>>3, 0); else if(c<=16) rgb=LED.Color(0, (uint16_t)(16-c)*BRIGHT()>>3 ,(uint16_t)(c-8)*BRIGHT()>>3); else if(c<=24) rgb=LED.Color((uint16_t)(c-16)*BRIGHT()>>3 ,0, (uint16_t)(24-c)*BRIGHT()>>3); else return; for(uint8_t i=0;i>8),col); //LEDブロック表示 LED.show(); delay(10); set_block((uint16_t)(y>>8),0); //LEDブロック消去 v=v+GRAVITY; //落下速度更新 y=y+v; //LEDブロック先頭位置更新 if(y>=h){ //最下点に衝突の場合 y=h-256; //衝突位置に戻す v=-v*R1/R2; //跳ね返り Serial.println(-v); // if(v>REFMINV){ //ある一定値より跳ね返り速度が小さい場合に停止 if(v > -stop_v){ // ★4 set_block((uint16_t)(h>>8)-1,col); //現在の最下点の上にLEDブロックを固定表示 h=h-(int32_t)(BLOCK*256); //最下点を1ブロック分上げる col=(col+18)%24+1; //次の色に変更 } } } while(y=256); //最下点が1未満になるまで繰り返す LED.show(); delay(500); //接続されたLED全体の落下 y=0; //接続されて落下するLEDの最後尾の位置 v=0; //全体の落下速度 do{ y=y+v; //最後尾位置更新 v=v+GRAVITY/2; //落下速度更新(摩擦を考慮) ★3 進行を逆に for(int16_t i=LED_NUM-1;i>=(int16_t)(y>>8);i--){ int32_t y1=((int32_t)i<<8)+(y&0xff)-v; //LED番号iの位置に次に落ちて来るLEDの現在位置 if(y1>=y){ LED.setPixelColor(LED_R-i,LED.getPixelColor(LED_R-((uint16_t)(y1>>8)))); //y1の位置のLEDの色をLED番号iにコピー } else{ LED.setPixelColor(LED_R-i,LED.Color(0,0,0)); //最後尾より上はLED消灯 } } LED.show(); delay(10); }while(y<(int32_t)LED_NUM<<8); //最後尾がLED総数を超えるまで繰り返し delay(500); }