米粒AVR–ATtiny10でシリアル信号制御フルカラーLED「WS2812」をLチカしてみました。

使用部品等
  1. Attiny10
  2. NeoPixel Ring
    16連フルカラーシリアルLED
  3. AVRISPmk2化したArduino UNO R3
  4. Arduino IDE ATtiny他開発環境

 

開発環境作り

かつて,ATtiny10の開発をArduino IDE 1.0.6で行っていたのですが,IDE 1.6.x を併用していて1.0.6のATtiny他の開発環境を破壊してしまい,開発環境の再構築が必要となりました。

いまさら,IDE 1.0.6用に再構築しても意味がないので1.6.x,1.8.x向けにAttiny〜ATmega開発環境一式を整えることにしました。また,これを機会に2013〜4年頃に実験してうまく動いたArduino UNO R3等をAVRISPmk2クローンにする方法を再度実験し製作記事をまとめることにしました。

成果
  1. Arduino IDEでATtiny他の開発
  2. Arduino UNO Rev.3 でAVRISPクローンを作る
  3. Arduino Leonardo Rev.3 / Micro でAVRISPクローンを作る
  4. Da Vinci 32U でAVRISPクローンを作る
WS2812でLチカ

1週間くらいかけてATtiny10他の開発環境が整いましたので,目的の”WS2812でのLチカ”に取り組みました。ATtiny10はプログラムメモリ:1Kバイト,RAM:32バイト,クロック8MHzとと非力ですのでAdafruitのNeoPixelシリーズのArduino用ライブラリはオブジェクトコードサイズが1Kバイトを遥かに超えるため使えません。自前でライブラリを作ろうかとも考えましたが「参考事例があるハズ」とWeb探索すると。ありました。

light_ws2812ライブラリ

https://github.com/cpldcpu/light_ws2812 にコンパクトなライブラリがありました。各種プラットホーム向けのライブラリが用意されています。このリポジトリをフォークして試して見ました。

まず,light_ws2812_Arduinoライブラリを試してみましたがオブジェクトサイズが2Kバイトを超えるのでATtiny10には使えません。
次にlight_ws2812_AVRライブラリを試してみました。生成されるオブジェクトサイズが余裕で1Kバイトに収まります。

これを使って,Lチカ というより Lフワ・レインボー・イルミネーション(8個のLEDの色がフワフワと遷移する)をやって見ました。

ソースコード

main( )抜粋。全ソースコード+ライブラリ(include file)はこちら–> Tiny-Rainbow.zip

#include <util/delay.h>
#include <avr/io.h>
#include <avr/interrupt.h>

#include "ws2812_config.h" //configure output_port etc.
#include "light_ws2812.h"
#include "light_ws2812.c"

#define LEDS 8         //number of LEDs 1-8
#define BRIGHTNESS 255 //brightness 0-255
#define CD 32          //color step devision 1-255
#define DLY 100        //scroll delay [ms]

struct cRGB led[LEDS];

//Show and Shift LED Color
void shift_led(){ 
  ws2812_setleds(led,LEDS); 
  for(int m=LEDS-1;m>=0;m--){ 
    led[m+1].r=led[m].r; led[m+1].g=led[m].g;led[m+1].b=led[m].b; 
  }
}

int main(void)
{
 init();
 #ifdef __AVR_ATtiny10__
 CCP=0xD8; // configuration change protection, write signature
 CLKPSR=0; // set cpu clock prescaler =1 (8Mhz) (attiny 4/5/9/10)
 #endif
 int r,g,b;
 while(1)
 {
   // Red vs Green
   b=0;
   for(int n=0;n<BRIGHTNESS+2;n+=CD){
     if(n>BRIGHTNESS) n=BRIGHTNESS;
     g=n;
     r=BRIGHTNESS-g;
     shift_led();                          //call Show and Shift LED Color func.
     led[0].r=r; led[0].g=g;led[0].b=b; 
     _delay_ms(DLY); 
   }
   // Green vs Blue
   r=0;
   for(int n=0;n<BRIGHTNESS+2;n+=CD){
     if(n>BRIGHTNESS) n=BRIGHTNESS;

ー以下略ー

Arduinoスタイルのsetup( ),loop( )は使っていません。代わりに,一般的なmain( )でプログラムを書いています。

結果
  • 生成コードは500バイト以下
  • 制御できた最大LED数 8個 (9個目以降はRAM不足でダメ)
  • グローバル変数を使うと挙動不審 or 動かない。(グローバル変数がRAM領域を広く占有してしまいローカル変数エリアが不足する)