mbed NUCLEO-F401REでWS2812BのフルカラーLEDストリップを使ってみた

2017年にAliexpressのこのお店から買って積んだままになっていたWS2812B搭載のフルカラーLEDストリップを動かしてみた。といっても、WS2812用の汎用ライブラリ(各ボードのクロックにあわせて、NOPの個数を調整することで、WS2812が要求するpulse width modulationの波形を出力するもの)を使っただけ。

いくつかの代表的なボードについては、WS2812_Exampleのページの方に、コンストラクタで指定すべきNOP数が掲載されています。Nucleo-F401RE用のものが運良く載っていたので(コンストラクタの引数の順番に、3, 12, 9, 12)、そのまま使わせてもらいました。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include "WS2812.h"
#include "mbed.h"

// Total number of LEDs in a strip
const int NUM_LEDS = 100;

// Wait duration between shift
const float WAIT_DURATION_SEC = 0.005;

// Instantiates WS2812 class.
// WS2812(PinName pin, int size,
//        int zeroHigh, int zeroLow, int oneHigh, int oneLow);
// The following values (3,12,9,12) are confirmed to work with Nucleo-F401RE.
// See https://os.mbed.com/users/bridadan/code/WS2812_Example/ for values known
// to work with other boards.
WS2812 ws(D8, NUM_LEDS, 3, 12, 9, 12);

DigitalOut led(LED1);

// Buffer that stores color data of each LED.
int buffer[NUM_LEDS];

// Color data of rainbow-like gradation
const size_t NUM_RAINBOW_COLORS = 21;
uint32_t RAINBOW_COLORS[NUM_RAINBOW_COLORS] = {  //
    0xff0000,                                    //
    0xff4000,                                    //
    0xff8000,                                    //
    0xffbf00,                                    //
    0xffff00,                                    //
    0xbfff00,                                    //
    0x80ff00,                                    //
    0x40ff00,                                    //
    0x00ff00,                                    //
    0x00ff40,                                    //
    0x00ff80,                                    //
    0x00ffbf,                                    //
    0x00ffff,                                    //
    0x00bfff,                                    //
    0x0080ff,                                    //
    0x0040ff,                                    //
    0x0000ff,                                    //
    0x4000ff,                                    //
    0x8000ff,                                    //
    0xbf00ff,                                    //
    0xff00ff};

// Lower brightness by reducing RGB values.
void dimmer(uint8_t numShiftedBits) {
  for (size_t i = 0; i < NUM_LEDS; i++) {
    const uint8_t red = ((buffer[i] & 0x00FF0000) >> 16) >> numShiftedBits;
    const uint8_t green = ((buffer[i] & 0x0000FF00) >> 8) >> numShiftedBits;
    const uint8_t blue = (buffer[i] & 0x000000FF) >> numShiftedBits;
    buffer[i] = (red << 16) + (green << 8) + blue;
  }
}

// Fills LED color buffer with rainbow data.
void fillBuffer(uint32_t startIndex) {
  uint32_t index = 0;
  startIndex = startIndex % NUM_LEDS;
  const uint32_t endIndex = startIndex + 10;
  for (size_t i = 0; i < NUM_LEDS; i++) {
    if (startIndex <= i && i < endIndex) {
      buffer[i] = RAINBOW_COLORS[index];
      index++;
      index %= NUM_RAINBOW_COLORS;
    } else {
      buffer[i] = 0;
    }
  }
  // Lower brightness
  dimmer(4);
}

int main() {
  uint32_t startIndex = 0;
  // Periodically shifts start position of the rainbow color.
  while (1) {
    wait(WAIT_DURATION_SEC);
    led = !led;
    fillBuffer(startIndex);
    startIndex++;
    ws.write(buffer);
  }
}

ボードのD8ピンと、LEDストリップのデータピン、GNDとGND、5Vと5Vを接続。上記コードをコンパイルして書き込んで実行すると、虹色が動いているように光ります。フルカラーLEDはじめて使ったんですが、すごいキレイ。いくらでも見てられます。