ブロックでつくった obniz ライト Blobniz Light をゲーミング的に光らせたメモ

この記事は obniz Advent Calendar 2023 の 8 日目の記事です。ブロックでつくった obniz ライト Blobniz Light をゲーミング的に光らせたメモです。

登壇でよく使うライトをブロックに詰め込んでみた

わたしは登壇でライトを IoT 制御をするデモをするのですが、このたび外側を良い感じに仕上げたくブロックの中に詰め込めました。

image

このように 共立エレショップのピンヘッダ実装済 NeoPixel WS2812B フルカラー LED モジュール 4 素子・5 素子を obniz で動かしたメモ で、いい感じに光らせられるフルカラー LED を 2 つつけます。

image

ブロックで箱を作って詰めていきます。

image

うまくハマりました。

image

こんな光り方をします。

とりあえず七色に光らせる

正確には七色ではないのですが、決め打ちで、赤→黄→緑→水色→青→紫→(ループ)させて、それっぽく光らせるサンプルです。ただ、結構キビキビ変わります。

ソースコードは以下の通り。

<html>
<head>
  <title>LED Control</title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <script src="https://code.jquery.com/jquery-3.6.4.min.js" integrity="sha256-oP6HI9z1XaZNBrJURtCoUT5SUnxFr8s3BzRl+cbzUq8=" crossorigin="anonymous"></script>
  <script src="https://unpkg.com/obniz@3.26.0/obniz.js" crossorigin="anonymous"></script>
</head>
<body>

<div id="obniz-debug"></div>
<h1>obniz gaming light</h1>
<script>

const obniz = new Obniz("OBNIZ_ID_HERE");

let flagLoop = false;

let leds;
let leds2;

async function blinkLEDs(count, interval){
  obniz.display.clear();
  obniz.display.print("BLINK");
  obniz.display.print("count : " + count);
  obniz.display.print("interval : " + interval);

  for(let i = 0; i < count; i++){
    await onLEDs();
    await obniz.wait(interval * 500);
    await offLEDs();
    await obniz.wait(interval * 500);
  }
}

async function colorLEDs(r,g,b){
  leds.rgbs([
    [r, g, b],
    [r, g, b],
    [r, g, b],
    [r, g, b]
  ]);
  
  
  leds2.rgbs([
    [r, g, b],
    [r, g, b],
    [r, g, b],
    [r, g, b]
  ]);
}

obniz.onconnect = async function () {
  
  leds = obniz.wired("WS2812B", {gnd:0, vcc:2, din:1});
  leds2 = obniz.wired("WS2812B", {gnd:8, vcc:10, din:9});

  obniz.display.clear();
  obniz.display.print("[LED]");

  obniz.onloop = async function(){
    await colorLEDs( 255 , 0 , 0 );   // 赤
    await obniz.wait(300);          
    await colorLEDs( 128 , 128 , 0 ); // 黄
    await obniz.wait(300);
    await colorLEDs( 0 , 255 , 0 );   // 緑
    await obniz.wait(300);
    await colorLEDs( 0 , 128 , 128 ); // 水色
    await obniz.wait(300);
    await colorLEDs( 0 , 0 , 255 );   // 青
    await obniz.wait(300);
    await colorLEDs( 128 , 0 , 128 ); // 紫
    await obniz.wait(300);
  }

}

</script>
</body>
</html>

より滑らかに七色に変える

さっきのものでも結構いい雰囲気は出るのですが、上記の色進行をスムーズに補完する仕組み作ってみました。

image

こんな感じで、赤が 0 → 255 に行ききると緑が上昇をはじめて、赤が降下し緑要素が混ざりはじめて、また、緑が 0 → 255 に行ききると青が上昇をはじめて、緑が降下し青要素が混ざりはじめて・・・と繰り返し色が混ざっていく流れです。

ソースコードは以下の通り。

<html>
<head>
  <title>LED Control</title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <script src="https://code.jquery.com/jquery-3.6.4.min.js" integrity="sha256-oP6HI9z1XaZNBrJURtCoUT5SUnxFr8s3BzRl+cbzUq8=" crossorigin="anonymous"></script>
  <script src="https://unpkg.com/obniz@3.26.0/obniz.js" crossorigin="anonymous"></script>
</head>
<body>

<div id="obniz-debug"></div>
<h1>obniz gaming 2</h1>

<script>

const obniz = new Obniz("OBNIZ_ID_HERE");

let leds;
let leds2;

async function colorLEDs(r,g,b){
  leds.rgbs([
    [r, g, b],
    [r, g, b],
    [r, g, b],
    [r, g, b]
  ]);
  
  
  leds2.rgbs([
    [r, g, b],
    [r, g, b],
    [r, g, b],
    [r, g, b]
  ]);
}

obniz.onconnect = async function () {
  
  leds = obniz.wired("WS2812B", {gnd:0, vcc:2, din:1});
  leds2 = obniz.wired("WS2812B", {gnd:8, vcc:10, din:9});

  obniz.display.clear();
  obniz.display.print("[LED]");

  let r_value = 256;
  let g_value = 0;
  let b_value = 0;

  let r_direction = -1;
  let g_direction = 1;
  let b_direction = 0;

  let change_step = 32;

  obniz.onloop = async function(){
    // r
    if(r_direction == -1){
      r_value = r_value - change_step;

      if(r_value <= 0 ){
        r_direction = 0;
        r_value = 0;
      }
    } else if(r_direction == 1){
      r_value = r_value + change_step;
      if(r_value >= 256 ){
        r_direction = -1;
        r_value = 255;
        // g start
        g_value = 0;
        g_direction = 1;
      }
    }
    // g
    if(g_direction == -1){
      g_value = g_value - change_step;

      if(g_value <= 0 ){
        g_direction = 0;
        g_value = 0;
      }
    } else if(g_direction == 1){
      g_value = g_value + change_step;
      if(g_value >= 256 ){
        g_direction = -1;
        g_value = 255;
        // b start
        b_value = 0;
        b_direction = 1;
      }
    }
    // b
    if(b_direction == -1){
      b_value = b_value - change_step;

      if(b_value <= 0 ){
        b_direction = 0;
        b_value = 0;
      }
    } else if(b_direction == 1){
      b_value = b_value + change_step;
      if(b_value >= 256 ){
        b_direction = -1;
        b_value = 255;
        // g start
        r_value = 0;
        r_direction = 1;
      }
    }

    await colorLEDs( r_value , g_value , b_value );
    await obniz.wait(50);
  }
}

</script>
</body>
</html>

HSVでよりやりやすく滑らかに七色に変える

さきほどは RGB 値だったんですが、交互に色が混ざっていくコードを if を駆使して書いてしまって、ちょっと冗長だなと思っていたら、そういえばフルカラー LED 制御で HSV 値を使ったほうが色味の変更はやりやすいことを思い出しました。

H 値は Hue 色相なのでこれを 0 から 360 で回すと求めていることができます。というかさっきの RGB のコードでやっていることって、この色相のループでした!

ということで、こちらのほうがシンプルに滑らかに七色に変わっていきます。

<html>
<head>
  <title>LED Control</title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <script src="https://code.jquery.com/jquery-3.6.4.min.js" integrity="sha256-oP6HI9z1XaZNBrJURtCoUT5SUnxFr8s3BzRl+cbzUq8=" crossorigin="anonymous"></script>
  <script src="https://unpkg.com/obniz@3.26.0/obniz.js" crossorigin="anonymous"></script>
</head>
<body>

<div id="obniz-debug"></div>
<h1>obniz gaming 3</h1>

<script>

const obniz = new Obniz("OBNIZ_ID_HERE");

let leds;
let leds2;

async function colorLEDs(h,s,v){
  leds.hsvs([
    [h,s,v],
    [h,s,v],
    [h,s,v],
    [h,s,v]
  ]);
  
  
  leds2.hsvs([
    [h,s,v],
    [h,s,v],
    [h,s,v],
    [h,s,v]
  ]);
}

obniz.onconnect = async function () {
  
  leds = obniz.wired("WS2812B", {gnd:0, vcc:2, din:1});
  leds2 = obniz.wired("WS2812B", {gnd:8, vcc:10, din:9});

  obniz.display.clear();
  obniz.display.print("[LED]");

  let h_value = 0;
  let change_step = 10;

  obniz.onloop = async function(){
    h_value += change_step;
    h_value %= 360;
    await colorLEDs( h_value , 1 , 1 );
    await obniz.wait(50);
  }
}

</script>
</body>
</html>