公開日:2022/02/26
title.png

19th Season


#19-10 何回目?LEDキャンドル

 何回目なのやら覚えていませんけど、今回もLEDキャンドルを作って見ました。

  「#4-6 LEDキャンドル

  「#11-6 LED暖炉

  「#14-6 暗くなったら蝋燭を灯して

  「#15-10 汎用16ビットタイマユニット
    ※オリジナル16ビットCPUコアMoscoviumのデモとして、LEDキャンドルを作成。

 ろうそくの炎とかもそうだけど、風等も含め、自然界の現象には1/fゆらぎになっているものが多いそうです。
 そこで、1/fゆらぎ乱数列を使ってLEDの明るさを制御、明るさの変化がまるで炎が揺らめいているかのように見せるのが、LEDキャンドルです。
 基本的には、「#4-6 LEDキャンドル」で作成した1/fゆらぎ乱数列が肝となっています。1/fゆらぎ乱数列を作る(生成する)のは少し大変でしたが、一度乱数列を作成してしまえば、それをデータ(定数)としてプログラムに埋め込んで使うだけなので、色々な場面で作ってきました。

 今回もLEDキャンドルを作るのですが、今回使うのは、RGB LEDパネル(下図)です。

a191_rgbpnl.jpg

 このRGB LEDパネルを縦に使って、8個あるピクセルを下から順番に光らせます。光らせるピクセルの数で炎の大きさを表現すると共に、フルカラーRGB LEDを活用して炎の色も表現しようと思います。

プログラム設計

 今回使用するRGB LEDパネルには、8個のWS2812B(RGB LEDチップ)が並んでいます。
 WS2812Bの制御方法については、「#11-2 円形配置RGB LED(WS2812B)を使う」に解説がありますので、参照して見てください。
 WS2812BはR,G,B各0〜255の256段階で設定可能なので、一応、フルカラーRGB(2563≒1,677万色)と言うふれ込みになっています。ところが、WS2812Bはとても明るくて、4〜8段目(/255段階)で光らせても、既にロウソクとしては明るすぎるくらいの明度なのです。

 そこで、「#19-1 デジタルPWM」で解説したデジタルPWMを使って暗く光らせると共に、1/fゆらぎ乱数に従った明度調整を組み合わせて、見た目もろうそくの炎に近づけてみようと思います。

 8ピクセルが縦に並んでいるので、光らせるピクセルの数で炎🔥の大きさを表現します(下図)。

a19a_npix.png

 炎の大きさは、1/fゆらぎ乱数列を使って変動させます。
 フルカラーRGB LEDなので、色合いも、ロウソクの炎っぽい色に調整しています。炎の色合いは、予めそれらしく見えるような値を配列変数(cdl_patn[ ])に保持しておきました。

  // fire pattern: (R,G,B)
  PROGMEM const uint8 cdl_patn[3*cdl_SIZ_PATN]=
  {
    187,34,0,  // bottom
    255,51,0,
    255,68,0,
    255,85,0,
    255,102,17,
    255,102,17,
    255,119,17,
    255,119,17,
    255,102,17,
    255,102,17,
    255,102,17,
    255,85,0,
    255,68,0,
    255,51,0,
    204,34,0,
    119,17,0  // top
  };


 RGB LEDパネルのピクセル数8個に対して、cdl_patn[ ]のパタン数16個と多めなのは、1/fゆらぎ乱数列で決定した光らせるピクセル数Nから16パタンにマッピングした時、パタン間の補間効果を適応するためです。


 見た目の発光ピクセル数と、全体の明るさ(ロウソクの瞬き)には、同じ1/fゆらぎ乱数値R1Fを使っています。

 シリアルモニタ無しで自立する様、電源投入・リセット解除後、デフォルトでLEDキャンドルモードを有効にしてあります。以下に完成したプログラムをリンクしておきます。

  完成プログラム:led_candle_ws2812b.ino

 コンパイルしてArduino UNOに書き込むと、シリアルモニタから以下のコマンドを受け付けています。

  シリアルモニタコマンド仕様:

 基本的にすべてデバッグ用のコマンドなので、シリアルモニタ無しで自立します。

回路設計

 と言っても、繋ぐだけです(1^^;)。電源とノイズ設計には注意が必要です。

 WS2812Bは明るく光る分、電流を大量に消費します。デジタルPWMで明るさを抑えているので、平均電流はそれなりに小さいはずです。
 デジタルPWMは、時分割で明るく光らせる時間と消灯している時間のデューティを制御して、平均的な明るさを調整する技術です(「#19-1 デジタルPWM」)。

 WS2812B自体は、光る時は明るく光っているので、その瞬間の電流値はとても大きいです。また、短時間でON/OFFを繰り返すため、ノイズ(EMI、EMS共)も大きくなります。

 UNOの5VピンソケットからRGB LEDパネルに給電してしまうと、瞬間的に電流が足りなくなって誤動作したり、UNOのリセットがかかってしまったりする場合があります。
 どうしてもUNOの5Vピンソケット(等、電流容量の小さい電源)から電源供給したい場合は、最大輝度値(プログラム内のrgb_MAX_LUM定数値等)を小さく抑えるなど、対策を講じてください。

 実際、当方の実験中でも、UNOがハングアップしてしまうことがありました。おそらく、RGB LEDパネルからのノイズ回り込みによる誤動作だと考えられます。どういう状態なのか、再起動することもなく、シリアルモニタの反応が無くなってしまいました。当方の実験では、リセットスイッチを押したら回復しました。

※USB⇔UART変換チップATmega16U2の方がスタックしてしまったのかな?

 恐らく、電源・ノイズ設計の問題なので、UNOがハングアップする確率が高い場合には、電流を抑える、ノイズ対策を強化する、などの対策を実施してください。


 可能ならば、フォトカプラなどを使って、RGB LEDパネルとUNOの電源線を分離しておくと、ノイズ(EMS)の影響を受け難くすることができます。ですが、WS2812Bとの通信信号はとても高速なので、この信号が通過できる高速なフォトカプラが存在するかどうか?不明です。

周囲を暗くして、実験

 UNOにプログラム(led_candle_ws2812b.ino)を書き込んだら、以下の様に接続して、電源を供給してください。

Arduino UNO 接続 RGB LEDパネル 接続 電源モジュール
  4-7VDC 5V
GND GND GND
D3(OC2B) DI  


 以下、実験中の様子です。

a19a_expr.jpg

 電源を投入すると、既にLEDキャンドルとして、RGB LEDパネルが発光しているはずです。

 以下、LEDキャンドルを表示している様子です。



 撮影スペースの関係でドアップですが、もう少し遠目で観た方が、それらしく見えるかも?


 今までLEDの明るさだけで表現していたLEDキャンドルですが、今回の物は光らせるピクセル数で炎の大きさも制御してみました。少し引いて遠目に見たらそれっぽく見えると思いますよ。


btn_arduino.png

btn_prev.png btn_next.png

home