ArduinoとシリアルLED(WS2812B)

シリアルLEDの仕組みと使い方をArduinoで制御しながら解説
シリアルLEDの仕組みと使い方をArduinoで制御しながら解説

この記事では、ArduinoでシリアルLED(WS2812B)を動かす方法をくわしく解説いたします。

シリアルLEDは、電流の許す限りいくつもの同じシリアルLEDを数珠つなぎで増設できるLEDです。中でもテープ状になっているシリアルLEDがよく使われます。好きな長さにカットして使うことができるので、広告看板や室内の装飾、クリスマスや小規模なプロジェクトにもお使いいただけます。シリアルLEDのライブラリを使って、Arduinoから簡単に色や明るさを制御できます。

シリアルLEDの制御に必要なデータ通信線はたったの1本です。ひとつのArduinoで数百個のシリアルLEDを制御するなんてことも不可能ではありません。しかも、各シリアルLEDは独立してRGBフルカラーで点灯可能です。

シリアルLEDとは

シリアルLEDは、もともと中国のWorldSemi社が開発したもので「NeoPixel」と呼ばれてます。Neo PixelのシリアルLEDは、ひとつひとつの単品でも購入可能ですが、テープの形のものや、マトリックスになっているものが便利です。

とくに、テープ状になっているシリアルLEDは、ハサミで好きな長さにカットして使用できます。表面は柔らかい透明な樹脂でコーティングされており、裏面には両面テープが貼られてます。

▼ また、カットしたテープLEDをつなげるためには、次のようなコネクタケーブルがあると便利です。

本記事では紹介するのは「WS2812B」のシリアルLEDの制御方法となります。ご購入の際は、「WS2812B」という名前がついているものをお選びください。

開発環境

本記事でおこなった実験の開発環境は次の通りです。

項目バージョン
ArduinoデバイスSeeeduino XIAO
シリアルLEDBTF-LIGHTING WS2812B LEDテープライト 1m
Arduino IDE1.8.10
パソコンmacOS Big Sur 11.0.1

▼ 今回購入したBTF-LIGHTINGのLEDテープライトです。WS2812BのシリアルLEDが60個ついてます。

購入したWS2812BのLEDテープライト
購入したWS2812BのLEDテープライト

▼ Arduinoは「Seeeduino XIAO」を使いましたが、他のArduinoでももちろん構いません。

Seeeduino XIAOの使い方は Seeeduino XIAOでArduino開発をはじめよう に書きました。

▼ もちろん、ほかのArduinoをお使いになってもらっても構いません。

Arduino初心者の方で「どのArduinoを選べばよいか分からない」方は、 おすすめArduinoどれを選べばいい?Arduinoで電子工作をはじめる方へ をご覧ください。

シリアルLEDの仕組み

ここではシリアルLEDの仕組みを簡単に説明します。

シリアルLEDの構造

シリアルLED「WS2812B」を拡大した写真をご覧ください。

シリアルLEDの拡大写真
シリアルLEDの拡大写真

シリアルLEDをよく見ると、写真のようなICチップが埋め込まれてます。これによって、Arduinoなどから送られてきたデータを受け取り、赤・緑・青のRGBカラーを点灯できる仕組みです。

図中のDOUTには、次のシリアルLEDのDINへ接続されます。冒頭で述べたとおり、いくつものシリアルLEDを数珠つなぎのようして接続します。また、ひとつひとつのLEDは独立して色や明るさを変えられます。

シリアルLEDArduino
VDD5V
VSSGND
DINデジタルピン
DOUT次のシリアルLEDのDIN

シリアルLEDの制御信号の流れ

シリアルLEDの制御信号の流れを簡単に説明します。

シリアルLEDへ送る制御信号の流れ
シリアルLEDへ送る制御信号の流れ

ひとつのシリアルLEDがDINから送られてきたデータを受信すると、先頭のデータだけ取り出し、残りのデータをDOUTから他のシリアルLEDへ渡す流れになってます。それぞれのデータの中には、赤・緑・青のLEDの明るさ情報が入れられており、それに基づいて各シリアルLEDは点灯されるのです。 データが空になれば、その先のシリアルLEDには届きません。よって予め、制御したいシリアルLEDの数分だけデータを作っておく必要があります。ただし今回はAdafruitの出しているNeo Pixcelライブラリを使用するので、難しいプログラミング作業はほとんどありませんのでご安心ください。

シリアルLEDとSeeeduino XIAOの配線

シリアルLEDとSeeeduino XIAOの配線はこちらの図のようになりました。

シリアルLEDとSeeeduino XIAOの配線図
シリアルLEDとSeeeduino XIAOの配線図

デジタルピン1番をシリアルLEDのDINへつないでいますが、もちろん他のピンでも構いません。シリアルLEDは5V電圧で動作しますが、Arduinoから電源供給するのではなく出来れば別電源を用意してお使いください。数十個のLEDを制御しようとするとArduinoからでは電流が足りなくなるからです。ただしGNDはArduinoと共通にしてください。

また、配線図ではシリアルLEDを数珠つなぎにしてますが、テープライトを使用する場合は予め数珠つなぎに配線されてますので、テープの末端のDIN端子にArduinoのデジタルピンを1つ繋げば済みます。

シリアルLEDテープライトの拡大写真
シリアルLEDテープライトの拡大写真

ライブラリのインストール

シリアルLED(WS2812B)をArduinoで簡単に制御できるように、AdafruitがリリースしているNeoPixelのライブラリをインストールします。 Arduino IDEのメニューで、SketchInclude LibraryManage LibraresLibrary Manager を開きます。 そこで「neopixel」で検索し、Adafruit NeoPixel/Arduino library for controlling single-wire-based LED pixels and strip.をインストールします。

ライブラリマネージャから「NeoPixel」で検索
ライブラリマネージャから「NeoPixel」で検索

シリアルLEDのプログラム例

ここからは、実際にArduinoでシリアルLEDを制御していきます。

シリアルLEDを1つだけ点灯させてみよう

シリアルLEDを1つだけ点灯させた画像
シリアルLEDを1つだけ点灯させた画像

まずは、シリアルLEDを1つだけ点灯させてみましょう。プログラムは次の通りです。

cpp
/*
  Created by Toshihiko Arai.
  https://101010.fun/iot/arduino-serial-led.html
*/

#include <Adafruit_NeoPixel.h>

const int DIN_PIN = 1; // D1
const int LED_COUNT = 60; // LEDの数

Adafruit_NeoPixel pixels(LED_COUNT, DIN_PIN, NEO_GRB + NEO_KHZ800);

void setup() {
  pixels.begin();
}

void loop() {
  pixels.clear();
  pixels.setPixelColor(0, pixels.Color(128, 0, 0)); // 0番目の色を変える
  pixels.show();
}

プログラムの解説

まず、pixels(LEDの数, DINに繋ぐArduinoのデジタルピン, NEO_GRB + NEO_KHZ800)で初期化します。制御するシリアルLEDの数を正しくセットしてください。他の型番のシリアルLEDではNEO_GRB + NEO_KHZ800を変える必要があるので注意しましょう。

pixels.clear()を呼び出すことで、すべてのシリアルLEDがリセットされ、点灯しているLEDが消灯します。シリアルLEDの色を変える場合はpixels.setPixelColor(LED番号, 色) のように制御したいシリアルLEDの番号と色を指定します。pixels.Color(128, 0, 0)では、赤・緑・青の順で0から255の範囲で明るさをセットします。数字が大きいほど明るくなりますが、シリアルLEDは非常に明るいので小さい値でも十分キレイです。

詳しくは、 AdafruitのNeoPixelライブラリー をご確認ください。

シリアルLEDの色を赤→緑→青の順に変える

シリアルLEDの色が赤緑青の順で変化する映像
シリアルLEDの色が赤緑青の順で変化する映像

今度は、先ほどのプログラムのloop関数の中を次のように変えてみましょう。シリアルLEDの色が、赤 → 緑 → 青の順番で変化します。

cpp
void loop() {
  pixels.clear();
  pixels.setPixelColor(0, pixels.Color(128, 0, 0)); // red
  pixels.show();
  delay(1000);

  pixels.clear();
  pixels.setPixelColor(0, pixels.Color(0, 128, 0)); // green
  pixels.show();
  delay(1000);

  pixels.clear();
  pixels.setPixelColor(0, pixels.Color(0, 0, 128)); // blue
  pixels.show();
  delay(1000);
}

60個のシリアルLEDを順番に点灯させる

60個シリアルLEDを高速で順番に点灯させている映像
60個シリアルLEDを高速で順番に点灯させている映像

今度は60個のシリアルLEDを順番に点灯させてみます。loop関数の中を次のように変えましょう。まるで光が生き物のように光が動いて面白いです。

cpp
void loop() {
  for(int i=0; i<LED_COUNT; i++) {
    pixels.clear();
    pixels.setPixelColor(i, pixels.Color(0, 0, 128)); // red
    pixels.show();
    delay(10);
  }
}

シリアルLEDで虹を走らせてみた

シリアルLEDテープライトで虹を走らせるている映像
シリアルLEDテープライトで虹を走らせるている映像

最後にシリアルLEDで虹を走らせてみます。C言語の配列を使っているので難しく感じますが、少しずつ慣れていけば大丈夫です。

cpp
/*
  Created by Toshihiko Arai.
  https://101010.fun/iot/arduino-serial-led.html
*/

#include <Adafruit_NeoPixel.h>

const int DIN_PIN = 1; // D1
const int LED_COUNT = 60; // LEDの数

Adafruit_NeoPixel pixels(LED_COUNT, DIN_PIN, NEO_GRB + NEO_KHZ800);

void setup() {
  pixels.begin();
}

uint32_t red = pixels.Color(128, 0, 0);
uint32_t orange = pixels.Color(128, 82, 0);
uint32_t yellow = pixels.Color(128, 128, 0);
uint32_t green = pixels.Color(0, 128, 0);
uint32_t cyan = pixels.Color(0, 128, 128);
uint32_t blue = pixels.Color(0, 0, 128);
uint32_t purple = pixels.Color(128, 0, 128);

uint32_t rainbow_color[] = {red, orange, yellow, green, cyan, blue, purple};
int rainbow_index[] = {6, 5, 4, 3, 2, 1, 0};

void loop() {
  
  for(int i = 0; i < LED_COUNT; i++) {    
    pixels.clear();    
    for(int j = 0; j < 7; j++) {
      rainbow_index[j] = i + 6 - j;
      if(rainbow_index[j] >= LED_COUNT) rainbow_index[j] -= LED_COUNT;
      
      pixels.setPixelColor(rainbow_index[j], rainbow_color[j]);
    }
    pixels.show();
    delay(20);
  }
}

以上でシリアルLED(WS2812B)の基本的な使い方の説明を終わります。シリアルLEDを購入する際はくれぐれも型番に注意しましょう。「WS2812B」であれば、この記事で紹介したライブラリが使えますし、書籍やネットにも情報が多くありますのでおすすめです。

さて、ここからはシリアルLEDを使った応用編のご紹介です。

【応用①】シリアルLEDでRGBライトを作ってみた

【応用①】シリアルLEDでRGBライトを作ってみた
【応用①】シリアルLEDでRGBライトを作ってみた
デジタル一眼レフを購入したので照明についていろいろと調べていましたら、「RGBライト」という製品を知ることになりました。シリアルLED(WS2812B)とArduinoで「RGBライト」を作れないだろうかと思い立ち、さっそくやってみました。

具体的には次のようなことをやっていきます。

  • ArduinoでシリアルLEDを制御する
  • 赤、緑、青のそれぞれの色を可変抵抗で調整可能にする
  • モバイルバッテリーを搭載させてケーブルレスにする

ただし、Amazonを見るとRGBライトは三千円ほどで販売されてます。安い!、と思いました。正直、自作してもそんなに安くありません^^; そんなわけで、自作がメンドーな方は素直に製品を選びましょう。

どうしても自作したい方は、この先をお読みください。自作ですとバッテリー容量を大きくできたり、ライトの数を増やしたり、プログラムを組んでオリジナルの演出効果を作り出したりできるメリットがあるんじゃないかと思ってます。

Arduinoには互換機の「Seeeduino XIAO」を使用しましたが他のArduinoでも同じように動きます。「Seeeduino XIAO」には、WiFiやBluetooth機能などの無線はありませんが、今回のようなモバイル型のスタンドアローンなモノには小さくて便利です。

Arduino初心者の方で「どのArduinoを選べばよいか分からない」方は おすすめArduinoどれを選べばいい?Arduinoで電子工作をはじめる方へ をご覧ください。

RGBライトのに使うシリアルLED

シリアルLED「WS2812B」 が60個付いているテープライトを、百均で購入したケースに貼り付けました。横幅が収まるようにカットし、数珠つなぎになるように導線をはんだ付けしました。ライトはすべて直列につないでいます。

60個のシリアルLEDを貼り付け配線
60個のシリアルLEDを貼り付け配線

このはんだ付け作業はかなり大変でした。もしこれから制作しようとなさるなら、最初からマトリックス状に並べられているものをおすすめします。

ArduinoとシリアルLEDの配線

最初に説明したとおり、今回は赤(R)緑(G)青(B)のそれぞれの色を可変抵抗で調節できるようにします。また、電源スイッチを取り付けたいです。よって、配線は次の図のようになりました。

RGBライトの配線
RGBライトの配線

USBコネクタの部分は、モバイルバッテリーへ接続します。USBコネクタの+5VとGNDの位置を間違えないように注意してください。不安な方は一度テスターで確認すると良いでしょう。

ところで、モバイルバッテリーは2A以上の出力でないと、シリアルLEDを点灯した際に電力不足によってXIAOが落ちてしまいます。本来ならば、XIAOとシリアルLEDの電源は別々に供給したいところですが、手軽さを考えてコレで行きます。

WS2812Bをフルに光らせようとすると50mAほど必要になるので、50mA x 60個だと3A以上欲しいところです。

RGBライトのプログラム

先ほどの配線をブレッドボードで組んで、次のようなプログラムでRGBライトを実現しました。

cpp
/*
  Created by Toshihiko Arai.
  https://101010.fun/arduino-serial-led.html
*/

#include <Adafruit_NeoPixel.h>

const int POT_R = 3; // A3
const int POT_G = 2; // A2
const int POT_B = 1; // A1
const int DIN_PIN = 0; // D0
const int LED_COUNT = 60; // LEDの数

Adafruit_NeoPixel pixels(LED_COUNT, DIN_PIN, NEO_GRB + NEO_KHZ800);

void setup() {
  pinMode(POT_R, INPUT);
  pinMode(POT_G, INPUT);
  pinMode(POT_B, INPUT);
  pixels.begin();
  pixels.clear();
  Serial.begin(9600);
}

void loop() {

  int R = int(analogRead(POT_R) / 1023.0 * 255.0);
  int G = int(analogRead(POT_G) / 1023.0 * 255.0);
  int B = int(analogRead(POT_B) / 1023.0 * 255.0);
  Serial.printf("R:%d G:%d B:%d\n", R, G, B);
  for(int i=0; i<LED_COUNT; i++) {
    pixels.setPixelColor(i, pixels.Color(R, G, B)); // red
    pixels.show();
  }
  delay(100);
}

可変抵抗を回せば、写真のように色合いや明るさを自由に変えることができます。

RGBライトの色を変える
RGBライトの色を変える

loop内のdelayをもっと短くすると、可変抵抗を回した時の色の変化の追従が滑らかになります。ただし、なんとなく消費電力も多くなりそうなので100ms程度に設定しました。

最終的には、銅基板をエッチングして基板をつくり、はんだ付けして下の写真のようにケース内に回路を収めました。

RGBライトの背面
RGBライトの背面
また、カメラの1/4インチネジで取り付けられるように、百均のスマホホルダーを利用してケースに接着してみました。カメラネジにこちらのホットシューを取り付けてありますので、RGBライトをカメラへマウントできます。

フロントはこんな感じです。半透明なケースがほどよくディフューザーになりました。

RGBライトの前面
RGBライトの前面

三脚、雲台、スマホホルダーそしてホットシューを介してRGBライトを取り付けてみました。部屋を暗くすると怪しい感じの撮影ができますね(笑)

カメラの上にRGBライトを取り付ける
カメラの上にRGBライトを取り付ける

ちなみに、こちらは私が使用している三脚とスマホホルダーです。スマホホルダーはホットシューをマウントできるので、RGBライトをマウントするには便利ですね。

【応用②】HSV色空間でグラデーション表現 3Dプリンタの照明を作ってみた

【応用②】HSV色空間でグラデーション表現 3Dプリンタの照明を作ってみた
【応用②】HSV色空間でグラデーション表現 3Dプリンタの照明を作ってみた

NeoPixelとPro Microで、3Dプリンタエンクロージャー内の照明を作ってみました。ロータリーエンコーダーで色をコントロール可能なRGBライトになってます。

ゴール

この記事で制作するRGBライトはYouTubeの アイデアノート channel で公開中です。ぜひこちらの動画をご覧ください。

NeoPixel(シリアルLED WS2812B)とPro Microを組み合わせてRGBライトを制作します。今回はローターリースイッチを使ってHSV色空間のHueを変更することで色を調整できるようにします。ですからインターフェースはロータリーエンコーダひとつのみでさまざまな色の表現が可能です。

NeoPixelを連結させる
NeoPixelを連結させる

制作したRGBライトは3Dプリンタエンクロージャー内の照明に使います。

3Dプリンタのエンクロージャー内
3Dプリンタのエンクロージャー内
3Dプリンタのエンクロージャー内
3Dプリンタのエンクロージャー内
3Dプリンタのエンクロージャー内
3Dプリンタのエンクロージャー内

下の写真のようにエンクロージャーの支柱に結束バンドで輪っかを作り、制作したRGBライトを通して固定してます。

結束バンドで固定
結束バンドで固定

つかうもの

この記事でつかうものをご紹介いたします。

NeoPixel(シリアルLED WS2812B)

NeoPixelというシリアルLEDを使います。型番WS2812BのシリアルLEDが60個ついてます。

Pro Micro

KEYESTUDIOさんから販売されているこちらのPro Microを使用しました。

ロータリーエンコーダ

RGBの色相をコントロールするためにロータリーエンコーダを使います。秋月電子通商さんで販売されている ロータリーエンコーダ を使いました。Amazonでも入手可能です。

3Dプリンタ

3DプリンタはEnder3 V2を使ってます。温度管理の難しいABSフィラメントを印刷したくて、3Dプリンタが丸ごと収まるエンクロージャーも購入しました。おかげでABSフィラメントで印刷しても反りがなく、失敗せずに印刷できるようになりました。

▼ ABS樹脂での印刷の関連記事

3Dプリンタ印刷物

廃物のテープライトを利用しましたので、そのままだと細切れで強度的にも不安でした。そこで、3Dプリンタでテープライトのレールガイドを作って強度を上げました。配線のはんだ付け部分は、写真の通り接着剤で補強してます。また、ロータリーエンコーダとPro Microを収納するためのケースも作成しました。NeoPixelとPro Microの電源供給はUSBコード二つを使ってそれぞれ別々にしました。

テープライトのレールガイド
テープライトのレールガイド
ロータリーエンコーダとPro Micro
ロータリーエンコーダとPro Micro
コントローラーのケース
コントローラーのケース

これらの印刷物(STLファイル)は、Thingiverseで公開中です。

NeoPixelとPro Microの配線図

こちらがNeoPixelとPro Microの配線図になります。NeoPixelはデータ線がひとつだけで済み、数珠つなぎのように複数つなげることが可能で、しかもそれぞれのLEDの色を独立して制御できます。

NeoPixelとPro Microの配線
NeoPixelとPro Microの配線

ライブラリのインストール

シリアルLEDを動かすために、 adafruit/Adafruit_NeoPixel 1.10.7 のライブラリを使用しました。また、ロータリーエンコーダを扱いやすくするために、 mathertel/RotaryEncoder 1.5.3 ライブラリを使用しました。私は普段PlatformIOを使ってArduino開発しているため、ライブラリのソースファイルをダウンロードして直接配置してます。次のようなディレクトリ構造になりましたので、ご参考までに。

.
├── lib
│   ├── RotaryEncoder
│   │   ├── RotaryEncoder.cpp
│   │   └── RotaryEncoder.h
│   └── WS2812B
│       ├── Adafruit_NeoPixel.cpp
│       ├── Adafruit_NeoPixel.h
│       ├── esp.c
│       ├── esp8266.c
│       ├── kendyte_k210.c
│       └── rp2040_pio.h
├── platformio.ini
└── src
    └── main.cpp

NeoPixelとPro Microのプログラミング

次は、NeoPixelとPro Microのプログラミング例です。起動後数秒間、虹色のグラデーションのデモンストレーションを行います。その後、ローターリーエンコーダを回すと、RGBライトになって色を変更可能となります。

cpp
/**
 * @file main.cpp
 * @author Toshihiko Arai
 * @brief Neopixel(WS2812B)とPro Microを使ったRGBライト
 * @version 1.0
 * @date 2023-01-02
 *
 * @copyright Copyright (c) 101010.fun 2023
 *
 */
#include <Adafruit_NeoPixel.h>
#include <Arduino.h>
#include <RotaryEncoder.h>

#define NEO_PIN 5
#define NUMPIXELS 60
Adafruit_NeoPixel pixels(NUMPIXELS, NEO_PIN, NEO_GRB + NEO_KHZ800);

/**
 * @brief  ロータリーエンコーダ
 * A相、B相
 */
#define RE_A A2
#define RE_B A1
#define ROTARY_STEPS 4       // 色相Hueのステップ数
#define ROTARY_MIN 0         // 色相Hueの最小
#define ROTARY_MAX 360       // 色相Hueの最大
#define ROTARY_START_POS 90  // 色相Hueの初期値

RotaryEncoder encoder(RE_A, RE_B, RotaryEncoder::LatchMode::TWO03);
int lastPos = ROTARY_START_POS - 2;
int rgb[3];

/**
 * @brief 参考: https://www.codespeedy.com/hsv-to-rgb-in-cpp/
 * 
 * @param H 色相(Hue)
 * @param S 彩度(Saturation)
 * @param V 明度(Value)
 * @param rgb 
 */
void HSVtoRGB(float H, float S, float V, int* rgb) {
    if (H > 360 || H < 0 || S > 100 || S < 0 || V > 100 || V < 0) {
        Serial.println("The givem HSV values are not in valid range");
        return;
    }
    float s = S / 100;
    float v = V / 100;
    float C = s * v;
    float X = C * (1 - abs(fmod(H / 60.0, 2) - 1));
    float m = v - C;
    float r, g, b;
    if (H >= 0 && H < 60) {
        r = C, g = X, b = 0;
    } else if (H >= 60 && H < 120) {
        r = X, g = C, b = 0;
    } else if (H >= 120 && H < 180) {
        r = 0, g = C, b = X;
    } else if (H >= 180 && H < 240) {
        r = 0, g = X, b = C;
    } else if (H >= 240 && H < 300) {
        r = X, g = 0, b = C;
    } else {
        r = C, g = 0, b = X;
    }
    rgb[0] = int((r + m) * 255);
    rgb[1] = int((g + m) * 255);
    rgb[2] = int((b + m) * 255);
}

void demo(float beginHue) {
    for (int i = 0; i < NUMPIXELS; i++) {
        float hue = 360.0 * (float(i) / float(NUMPIXELS)) + beginHue;
        if (hue >= 360.0) {
            hue -= 360.0;
        }

        // Serial.println(hue);
        HSVtoRGB(hue, 100.0, 100.0, rgb);

        int red = rgb[0];
        int green = rgb[1];
        int blue = rgb[2];

        pixels.setPixelColor(i, pixels.Color(red, green, blue));
    }
    pixels.show();

    if (beginHue >= 360.0) {
        Serial.println("Done demo.");
        return;
    } else {
        beginHue += 3.6;
        // Serial.println(beginHue);
        demo(beginHue);
    }
}

void setup(void) {
    Serial.begin(115200);
    pixels.begin();
    encoder.setPosition(ROTARY_START_POS / ROTARY_STEPS);
    pixels.clear();
    demo(0.0);
    demo(0.0);
    demo(0.0);
    demo(0.0);
    demo(0.0);
    demo(0.0);
}

void loop() {
    encoder.tick();  // just call tick() to check the state.

    int newPos = encoder.getPosition() * ROTARY_STEPS;

    if (newPos < ROTARY_MIN) {
        encoder.setPosition(ROTARY_MAX / ROTARY_STEPS);
        newPos = ROTARY_MAX;

    } else if (newPos > ROTARY_MAX) {
        encoder.setPosition(ROTARY_MIN / ROTARY_STEPS);
        newPos = ROTARY_MIN;
    }

    if (lastPos != newPos) {
        Serial.println(lastPos);
        Serial.println(newPos);
        
        lastPos = newPos;
        float hue = float(lastPos);
        HSVtoRGB(hue, 100.0, 100.0, rgb);

        // Serial.println(lastPos);
        // Serial.println(hue);
        //  Serial.println(rgb[0]);
        int red = rgb[0];
        int green = rgb[1];
        int blue = rgb[2];
        // Serial.println(red);
        for (int i = 0; i < NUMPIXELS; i++) {
            pixels.setPixelColor(i, pixels.Color(red, green, blue));
        }
        pixels.show();
        delay(50);
    }
}

プログラムの解説

ロータリーエンコーダでHSV色空間のHue(色相)を変更後、その値をRGBに変換してシリアルLEDの色を変更させてます。

ロータリーエンコーダは割り込み処理を使わずに、ポーリングで回転を検知してます。ポーリングで処理する方が変数管理に悩まなくて済みますし、トラブルも少ないです。と言いますか、私には割り込み処理で上手くやるスキルと自信がありません^^; ロータリーエンコーダの詳しい使い方はこちらの記事をご覧ください。

HSVからRGBに変換するプログラムはネットでいくつも見つかります。 こちらの記事 のソースコードを参考に、少し修正して使わせていただきました。

HSV色空間はRGBと違って色相(Hue)、彩度(Saturation)、明度(Value)の三要素で色を表現する仕組みです。画像編集ソフトのカラーピッカーでよく使われます。また、OpenCVを使った画像処理では、HSV処理をうまく使うことで特定の色のみ変更したり、特徴点を取得してくり抜いたりできます。以前にOpenCVで遊んだ経験が、本プロジェクトを進める上でも役立ちました。

関連記事

 
最後までご覧いただきありがとうございます!

▼ 記事に関するご質問やお仕事のご相談は以下よりお願いいたします。
お問い合わせフォーム

この記事で紹介した商品

人気のArduino互換機
Arduinoで人気の周辺パーツ
あると便利な道具
Arduinoのオススメ参考書

▼ Arduino初心者向きの内容です。ほかのArduino書籍と比べて図や説明がとてもていねいで読みやすいです。Arduinoで一通りのセンサーが扱えるようになります。

▼ 外国人が書いた本を翻訳したものです。この手の書籍は、目からうろこな発見をすることが多いです。

▼ Arduinoの入門書を既に読んでいる方で、次のステップを目指したい人向きの本です。C言語のプログラミングの内容が中心です。ESP32だけでなく、ふつうのArduinoにも役立つ内容でした。

関連記事