Raspberry PiでC言語でNeopixel光らせる

2017-04-09

前回はPythonでライブラリ使ったけど、今回はC言語でやってみる。

WS2812のLEDテープを板に固定

前回までは紙にテープを貼ってただけなので、今回は板に固定して扱いやすくする。すずメッキ線でホッチキスのように板に留めて、さらにハンダ付けして固定。

Picture

配線も頑張って、簡単なコネクタを作って完了。

Picture
Picture
Picture

電源。5V 20A

Picture

Raspberry Pi をつなげる。信号線はGPIO18ピン。一応レベル変換基板を使って信号の3.3v - 5.0vの変換をする。

Picture

C言語でNeoPixel光らせる

ここからはRapsberry Piにssh接続して快適作業。まずライブラリをとってくる。 これのおかげでとっても楽ちん。


git clone https://github.com/jgarff/rpi_ws281x
cd rpi_ws281x

                              

当たり前だけど、使い方はREADMEにある。

  • ws2811_t 構造体を準備して
  • ws2811_init() でイニシャライズ
  • ws2811_render() でLEDに設定した色を反映
  • ws2811_fini() で終了。

色を24bitで表して、32bitの整数を使ってで設定する。今回はGBRの順なので

  • 右から0~7bitは赤
  • 右から8~15bitは青
  • 右から16~23bitは緑

赤、青、緑を、明るさ0から254(255がmax)まで光らせるコード。


#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <signal.h>
#include <stdarg.h>
#include <getopt.h>

#include "clk.h"
#include "gpio.h"
#include "dma.h"
#include "pwm.h"
#include "version.h"

#include "ws2811.h"

// defaults for cmdline options
#define TARGET_FREQ                              WS2811_TARGET_FREQ
#define GPIO_PIN                                 18
#define DMA                                      5

//#define STRIP_TYPE  WS2811_STRIP_RGB
// WS2812/SK6812RGB integrated chip+leds

#define STRIP_TYPE  WS2811_STRIP_GBR
// WS2812/SK6812RGB integrated chip+leds

//#define STRIP_TYPE     SK6812_STRIP_RGBW
// SK6812RGBW (NOT SK6812RGB)

#define WIDTH 24
#define HEIGHT 15
#define LED_COUNT   WIDTH * HEIGHT

ws2811_t ledstring =
{
     .freq = TARGET_FREQ,
     .dmanum = DMA,
     .channel =
     {
          [0] =
          {
               .gpionum = GPIO_PIN,
               .count = LED_COUNT,
               .invert = 0,
               .brightness = 255,
               .strip_type = STRIP_TYPE,
          },
          [1] =
          {
               .gpionum = 0,
               .count = 0,
               .invert = 0,
               .brightness = 0,
          },
     },
};

int main()
{

     ws2811_init(&ledstring);

     int col, pos; 
     uint8_t level;
     uint32_t gbrColor;

     // green, blue, red, brightness from 0-254
     for(col = 0; col < 3; col++)
     {
          for(level = 0; level < 255; level++)
          {
               gbrColor = level << (8 * col);

               for(pos = 0; pos < LED_COUNT; pos++)
               {
                    ledstring.channel[0].leds[pos] = gbrColor;
               }

               ws2811_render(&ledstring);
               usleep(1000000 / 60);
          }
     }

     ws2811_fini(&ledstring);

     return 0;
}

                              

コンパイルする。

レポジトリにあるSConscriptのソースファイル名と出力ファイル名を編集。今回はソースがcolortest.c、実行ファイルをcolortestとした。sconsなかったらapt-get install scons


srcs = Split('''
    colortest.c
''')

objs = []
for src in srcs:
   objs.append(tools_env.Object(src))

test = tools_env.Program('colortest', objs + tools_env['LIBS'])

                              

そしたらコンパイル。


sudo scons

                              

配線をよく確認して、実行。


sudo ./colortest

                              

1秒間に60回以上360個のLEDを更新できた。ただし、DMAがなんちゃらで、音関係とか周辺機器がRaspberry Pi上で扱いにくいので、複雑な使い方のときは(音楽をFFTとか)、LED制御はRaspberry Piにまかせて、各LEDの色情報は別PCで計算して、Raspberry PiにLAN経由で送信した方が良いはず。