フォト
2018年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          
無料ブログはココログ

« 梅澤無線電機さんの「電子倶楽部60」を購入してみました | トップページ | CH340E搭載小型USB-シリアル変換モジュールの調査 »

2018年5月30日 (水)

NeoPixel(WS2812B)の制御 その3

前回行った、ArduinoによるNeoPixel(WS2812B)の制御の続きです。
今回は8x8ドットマトリックスタイプのNeoPixelを使って簡単なメッセージ表示を行いました。

Dscn8015

  接続
    Arduino:D11   -  NeoPixel:DIN
    Arduino:5V     -  NeoPixel:5V
    Arduino:GND  -  NeoPixel:GND

マトリックスタイプのNeoPixel、Aliexpressだと安価に入手できます。

01

amazonだと倍の金額。さすがにこの金額だと買う気がしないなぁ。02

動いている様子


以前作成した美咲フォントをつかったライブラリを利用して簡単な日本語メッセージを
表示しています。Neopixelの制御は前回作成した関数を利用しています。

   ライブラリ
    ・Arduino用 美咲フォントライブラリ 教育漢字・内部フラッシュメモリ乗せ版
     https://github.com/Tamakichi/Arduino-misakiUTF16
 

スケッチ

//
// Neopixel 8x8ドットマトリックス 制御 SPIバージョン by たま吉さん  2018/05/30
//

#include <SPI.h>
#include <misakiUTF16.h>

//***************
// 定数
//***************

#define PIXCELNUM   64           // Neopixel ピクセル数(LED数)
#define PIN         11           // Neopixel 制御用ピン番号
#define NEOSPI_0    0b11100000   // 1ビット 値0
#define NEOSPI_1    0b11111000   // 1ビット 値1
#define NEOSPI_RST  0b00000000   // REST

//***************
// グローバル変数
//***************
uint8_t buf[PIXCELNUM*3];     // Nexpixel用ピクセル色データ(ピクセル数 x 24ビット)

//***************
// 関数
//***************
// Neopixel初期化
void NeoInit() {
  memset(buf, 0, PIXCELNUM*3); // バッファの初期化

  // SPIの初期化
  SPI.setBitOrder(MSBFIRST);            // 最上位ビットから送信
  SPI.setClockDivider(SPI_CLOCK_DIV2);  // クロック 8MHz
  SPI.setDataMode(SPI_MODE1);           // アイドル時 LOW、立上りエッジ時送信
  SPI.begin();                          // 開始
}

// Neopixelへのデータ送信
void NeoUpdate() {
  // RESET送信
  SPDR = NEOSPI_RST;              // SPIデータ送信
  while(!(SPSR & (1 << SPIF))) ;  // 送信完了待ち
  delayMicroseconds(50);

  // ピクセル数x24ビット送信
  for (uint8_t i = 0; i < PIXCELNUM*3; i++) {
    for (uint8_t j = 0; j < 8; j++) {
      SPDR = buf[i] & (0x80>>j) ? NEOSPI_1:NEOSPI_0; // SPIデータ送信
      while(!(SPSR & (1 << SPIF))) ;                 // 送信完了待ち
    }
  }
}

// Neopixelの表示クリア
void NeoCLS(uint8_t flgUpdate=false) {
    memset(buf, 0, PIXCELNUM*3); // バッファの初期化
  if (flgUpdate)
    NeoUpdate();
}

// 指定したピクセルの色を設定
void NeoSetRGB(uint8_t no, uint8_t R, uint8_t G, uint8_t B, uint8_t flgUpdate=false) {
  if (no < PIXCELNUM) {
    buf[no*3+0] = G;
    buf[no*3+1] = R;
    buf[no*3+2] = B;    
  }
  if (flgUpdate)
    NeoUpdate();
}

// ピクセルのシフト
void ShiftPixel(uint8_t flgUpdate=false) {
  uint8_t tmpbuf[3];
  memmove(tmpbuf,buf,3);
  memmove(buf, buf+3, (PIXCELNUM-1)*3);
  memmove(buf+(PIXCELNUM-1)*3,tmpbuf,3);
  if (flgUpdate)
    NeoUpdate();
}

// 8x8ドットマトリックス 指定座標ピクセル番号変換
inline uint8_t XYtoNo(uint8_t x, uint8_t y) {
  return y&1 ? 8*y + x : 8*y + 7 -x;
}

// ドットマトリックス 左スクロール
void NeoScroll(uint8_t flgUpdate=false) {
  for (uint8_t i=0; i < 8; i++) {
    if ( i&1 ) {
      memmove(&buf[i*8*3], &buf[(i*8+1)*3],7*3);
      memset(&buf[(i*8+7)*3], 0, 3);
    } else {
      memmove(&buf[(i*8+1)*3], &buf[i*8*3],7*3);
      memset(&buf[i*8*3], 0, 3);
    }
  }
  if (flgUpdate)
    NeoUpdate();
}

// 1文字左スクロール挿入
void NeoScrollInChar(uint8_t *fnt, uint8_t R, uint8_t G, uint8_t B, uint16_t tm) {
  for (uint8_t i = 0; i < 8; i++) {
    // 左1ドットスクロール
    NeoScroll(false);

    // フォントパターン1列分のセット
    for (uint8_t j = 0; j < 8; j++) {
      if (fnt[j] & (0x80 >> i)) {
         NeoSetRGB(XYtoNo(7,j), R,G,B, false);
      } else {
         NeoSetRGB(XYtoNo(7,j), 0,0,0, false);        
      }
    }
    NeoUpdate();
    delay(tm);
  }
}

// メッセージの表示
void NeoMsg(char* msg, uint8_t R, uint8_t G, uint8_t B, uint16_t tm) {
  uint8_t  fnt[8];
  int8_t   len;
  
  // テスト用文字列
  //char msg_str[] = "あいうえお、今日は5月30日です。かんたんなかんじの表示ができます。";

  char *str = msg;
  NeoCLS();
  while(*str) {
    if (! (str = getFontData(fnt, str)) )  {
         Serial.println("Error"); 
         break;
    }
    NeoScrollInChar(fnt, R, G, B, tm);         
  }
}

void setup() {
  NeoInit();  // Neopixcelの初期化
  NeoCLS();   // Neopixcelの表示クリア
}

void loop() {
   NeoMsg("あいうえお、",0, 16, 0, 100);
   NeoMsg("今日は5月30日です。",0, 8, 8, 100);
   NeoMsg("かんたんなかんじの表示ができます。",16, 4, 4, 100);      
   delay(1000); 
}

意外とお手軽に実装出来ました。表示についてもチラつきや遅延もなく、スクロール表示
出来ています。

8x8だと流石に日本語表示は辛いですね。
16x16ドットくらいだともうちょっと面白い表示が出来るかもしれません。
機会があればチャレンジしてみます。

関連記事
 NeoPixel(WS2812B)の制御 その3(2018.05.30)  ・・・ 8x8マトリックスの制御(この記事です)
 NeoPixel(WS2812B)の制御 その2(2018.05.22)   ・・・ SPIを使った制御
 NeoPixel(WS2812B)の制御(2018.05.20)            ・・・ GPIOを使った制御

« 梅澤無線電機さんの「電子倶楽部60」を購入してみました | トップページ | CH340E搭載小型USB-シリアル変換モジュールの調査 »

arduino」カテゴリの記事

表示器制御関連」カテゴリの記事

コメント

コメントを書く

(ウェブ上には掲載しません)

トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/571408/66776618

この記事へのトラックバック一覧です: NeoPixel(WS2812B)の制御 その3:

« 梅澤無線電機さんの「電子倶楽部60」を購入してみました | トップページ | CH340E搭載小型USB-シリアル変換モジュールの調査 »