メインページに戻る

参考:シリアルLED(WS2822S)をつかってみました。

(大前提)半田付けができなくても大丈夫です!あくまでのモノづくり体験の一環としてトライという程度で半田付できなくてもモノづくりは可能です!


0. 半田付けをしてみよう

講義中に実演しつつ説明します。以下は復習用に。

半田付け基本

デジタルマルチメータで短絡チェック

以下のようにブレッドボードへの接続部分を作成します。

1. LEDを光らせてみよう!

WS2822Sについて:https://trac.switch-science.com/wiki/WS2822S

1.1 材料

  • Arduino Nano
  • ブレッドボード
  • USBケーブル
  • フルカラーシリアルLEDテープ(WS2822S)
  • ジャンパーワイヤ
  • ヘッダピン
  • 導線

シリアル線1本でフルカラーを制御できるLEDテープ。

1.2 ブレッドボード図

それでは、以下のようにLEDテープとArduinoを繋げてみましょう。

LEDテープArduino
G (GND) GND
D (DAT)D12
5V 5V

実際の写真は以下の通り。

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

以下より、Code=> Download Zip でWS2822S-master.zipというZIPファイルをダウンロードします。

https://github.com/SWITCHSCIENCE/WS2822S

解凍したフォルダを[userdir]/Arduino/librariesに移動させます。

  • Mac
    • ユーザーディレクトリ下の「書類」フォルダの中にArduinoがあります。
    • /Users/yourname/Documents/Arduino/libraries 内にフォルダごとドラッグ&ドロップしてください。
  • Windows
    • ユーザーディレクトリ下の「\Documents\Arduino\libraries」内にフォルダごとドラッグ&ドロップしてください。

1.4 コード

1.4.1 基本編

コードは以下の通りです。Arduinoに書き込んでみましょう。

//*****************************************************************
// WS2822S
// 2015/01/29
//
// 色情報の設定 setColor(LEDの番号、赤、緑、青)
// 色情報の送信  send()
//
//******************************************************************

#include "Ws2822s.h" // WS2822Sライブラリをインクルード

#define NUM_PIXELS 7 // 使用するWS2822S LEDの数を定義
#define LED_PIN 12 // WS2822Sのデータ入力ピンに接続するArduinoのピン番号

Ws2822s LED(LED_PIN, NUM_PIXELS); // WS2822Sオブジェクトを作成

void setup()
{
  // setup関数は、Arduinoの初期設定を行うが、今回は特に何も必要ない
}

void loop()
{
  // 全てのLEDについてループ処理
  for (int i = 0; i < NUM_PIXELS; ++i) {
    // LEDを順番に色設定する。ここでは、赤色を設定
    LED.setColor(i, 0xFF, 0x00, 0x00); // i番目のLEDを赤色 (255, 0, 0) に設定
    // 次のLEDを黄色に設定(赤+緑)
    LED.setColor((i + 1) % NUM_PIXELS, 0xFF, 0xFF, 0x00); // 次のLEDを黄色 (255, 255, 0) に設定
    // その次を緑に設定
    LED.setColor((i + 2) % NUM_PIXELS, 0x00, 0xFF, 0x00); // 緑色 (0, 255, 0) に設定
    // 次をシアンに設定(緑+青)
    LED.setColor((i + 3) % NUM_PIXELS, 0x00, 0xFF, 0xFF); // シアン (0, 255, 255) に設定
    // 次を青に設定
    LED.setColor((i + 4) % NUM_PIXELS, 0x00, 0x00, 0xFF); // 青色 (0, 0, 255) に設定
    // 次をマゼンタに設定(赤+青)
    LED.setColor((i + 5) % NUM_PIXELS, 0xFF, 0x00, 0xFF); // マゼンタ (255, 0, 255) に設定
    // 残りのLEDを消灯(黒)に設定
    LED.setColor((i + 6) % NUM_PIXELS, 0x00, 0x00, 0x00); // 黒色 (0, 0, 0) に設定
    LED.setColor((i + 7) % NUM_PIXELS, 0x00, 0x00, 0x00); // 黒色 (0, 0, 0) に設定
    LED.setColor((i + 8) % NUM_PIXELS, 0x00, 0x00, 0x00); // 黒色 (0, 0, 0) に設定
    LED.setColor((i + 9) % NUM_PIXELS, 0x00, 0x00, 0x00); // 黒色 (0, 0, 0) に設定

    // LEDの色設定を送信
    LED.send();

    // 300ミリ秒待機してから次のLEDに移動
    delay(300);
  }
}

上記が光ればOK!
※LEDは間近で直視しないことを推奨。明滅を確認したらUSB抜いてしまってください。

16進数(0xFFなど)とは

16進数(16進法)は、数字を表す方法の一つで、0から9までの数字とAからFまでの6つのアルファベットを使って数を表します。これは、私たちが普段使っている10進数と似ていますが、10進数では0から9までの10種類の数字しか使わないのに対して、16進数では16種類の記号を使います。

例えば、10進数では「10」という数字は「10」を意味しますが、16進数では「10」は「16」を意味します。10進数の16は、16進数では「10」になるのです。

具体的には:

  • 16進数の「0x0」は10進数の「0」
  • 16進数の「0x1」は10進数の「1」
  • 16進数の「0xA」は10進数の「10」
  • 16進数の「0xF」は10進数の「15」

次に、16進数の「0x10」は10進数の「16」、そして「0xFF」は10進数の「255」です。数字の前に「0x」が付くと、それは16進数を意味します。

どうして16進数を使うのか?

コンピュータは情報を扱うとき、基本的には2進数(0と1だけの数)を使います。しかし、2進数は桁数が多くて読みづらいので、それをまとめた形で表すために16進数が使われます。16進数だと、1つの桁で4つのビット(2進数の単位)をまとめて表すことができるため、コンピュータの情報を扱うのに便利です。

例えば、コンピュータで色を指定するとき、赤、緑、青の各色の明るさを0から255の範囲で表します。これは10進数でいうと「255」ですが、16進数で表すと「0xFF」になります。このため、赤色を「255, 0, 0」と指定する代わりに、16進数で「0xFF, 0x00, 0x00」と書くことが多いです。

1.4.2 発展編

以下は発展編です!

#include "Ws2822s.h" // Ws2822sライブラリをインクルード

#define NUM_PIXELS 7 // 使用するLEDの数を定義
#define LED_PIN 12 // WS2822Sのデータ入力ピンに接続するArduinoのピン番号

Ws2822s LED(LED_PIN, NUM_PIXELS); // WS2822Sオブジェクトを作成

void setup() {
  LED.send(); // 全てのLEDを消灯して初期化
}

void loop() {
  // 各エフェクト関数を呼び出してLEDを制御
  colorWipe(0xFF, 0, 0, 50); // 赤色のエフェクトを実行
  colorWipe(0, 0xFF, 0, 50); // 緑色のエフェクトを実行
  colorWipe(0, 0, 0xFF, 50); // 青色のエフェクトを実行
  theaterChase(0x7F, 0x7F, 0x7F, 50); // 白色のシアターエフェクトを実行
  theaterChase(0x7F, 0, 0, 50); // 赤色のシアターエフェクトを実行
  theaterChase(0, 0, 0x7F, 50); // 青色のシアターエフェクトを実行

  rainbow(20); // レインボーエフェクトを実行
  rainbowCycle(20); // レインボーサイクルエフェクトを実行
  theaterChaseRainbow(10); // レインボーシアターエフェクトを実行
}

// 各LEDを順番に指定した色に変えていくエフェクト
void colorWipe(uint8_t r, uint8_t g, uint8_t b, uint8_t wait) {
  for(uint16_t i = 0; i < NUM_PIXELS; i++) {
    LED.setColor(i, r, g, b); // i番目のLEDを指定した色に設定
    LED.send(); // LEDにデータを送信して色を更新
    delay(wait); // 次のLEDに進む前に少し待つ
  }
}

// レインボーエフェクトを実行
void rainbow(uint8_t wait) {
  uint16_t i, j;

  for(j = 0; j < 256; j++) { // 256色を全て表示
    for(i = 0; i < NUM_PIXELS; i++) {
      uint8_t r, g, b;
      Wheel((i + j) & 255, r, g, b); // Wheel関数でRGB値を取得
      LED.setColor(i, r, g, b); // RGB値を使ってLEDを設定
    }
    LED.send(); // LEDにデータを送信して色を更新
    delay(wait); // 少し待つ
  }
}

// レインボーエフェクトを5サイクル実行
void rainbowCycle(uint8_t wait) {
  uint16_t i, j;

  for(j = 0; j < 256 * 5; j++) { // 5サイクル全色表示
    for(i = 0; i < NUM_PIXELS; i++) {
      uint8_t r, g, b;
      Wheel(((i * 256 / NUM_PIXELS) + j) & 255, r, g, b); // Wheel関数でRGB値を取得
      LED.setColor(i, r, g, b); // RGB値を使ってLEDを設定
    }
    LED.send(); // LEDにデータを送信して色を更新
    delay(wait); // 少し待つ
  }
}

// シアターチェイスエフェクトを実行
void theaterChase(uint8_t r, uint8_t g, uint8_t b, uint8_t wait) {
  for(int j = 0; j < 10; j++) { // 10サイクル実行
    for(int q = 0; q < 3; q++) {
      for(uint16_t i = 0; i < NUM_PIXELS; i = i + 3) {
        LED.setColor(i + q, r, g, b); // 3つごとにLEDを点灯
      }
      LED.send(); // LEDにデータを送信して色を更新
      delay(wait); // 少し待つ

      for(uint16_t i = 0; i < NUM_PIXELS; i = i + 3) {
        LED.setColor(i + q, 0, 0, 0); // 点灯したLEDを消灯
      }
    }
  }
}

// レインボーカラーのシアターチェイスエフェクトを実行
void theaterChaseRainbow(uint8_t wait) {
  for(int j = 0; j < 256; j++) { // 256色全てを使用
    for(int q = 0; q < 3; q++) {
      for(uint16_t i = 0; i < NUM_PIXELS; i = i + 3) {
        uint8_t r, g, b;
        Wheel((i + j) % 255, r, g, b); // Wheel関数でRGB値を取得
        LED.setColor(i + q, r, g, b); // RGB値を使ってLEDを設定
      }
      LED.send(); // LEDにデータを送信して色を更新
      delay(wait); // 少し待つ

      for(uint16_t i = 0; i < NUM_PIXELS; i = i + 3) {
        LED.setColor(i + q, 0, 0, 0); // 点灯したLEDを消灯
      }
    }
  }
}

// 0から255の値を入力すると、対応するRGBカラーを取得する関数
void Wheel(byte WheelPos, uint8_t &r, uint8_t &g, uint8_t &b) {
  WheelPos = 255 - WheelPos; // WheelPosを逆転させる
  if(WheelPos < 85) {
    r = 255 - WheelPos * 3;
    g = WheelPos * 3;
    b = 0;
  } else if(WheelPos < 170) {
    WheelPos -= 85;
    r = 0;
    g = 255 - WheelPos * 3;
    b = WheelPos * 3;
  } else {
    WheelPos -= 170;
    r = WheelPos * 3;
    g = 0;
    b = 255 - WheelPos * 3;
  }
}

※LEDは間近で直視しないことを推奨。明滅を一通り確認したらUSB抜いてしまってください。

2. 課題

以下をアップロードしてください。

  • 制作物の写真 1枚
    • Arduinoと自身で作成したLED全体が入るように写真を撮ってアップロードしてください(上記のGIF画像のイメージ)。LEDは光っている状態にしてください。
    • GIF画像でアップロードできる方は加点(ヒント:
       ffmpeg -i test.mp4 -vf scale=320:-1 -r 10 test.gif)。
  • LEDの半田付け部分の拡大写真 1枚
    • 半田付けのクオリティが確認できるように近くで撮影してください。
  • リアクションペーパーに回答してください。
    • 「なぜソフトウェアのみのアプリケーション開発と比べて、ハードウェアを含めたアプリケーション開発のデバッグ(エラーや不具合を見つけて修正すること)は難しいか?」に対する考えを書いてください。簡単な感想やもしわかりにくかった点・改善点などあれば教えてください。