米粒AVR–ATtiny10でシリアル信号制御フルカラーLED「WS2812」をドライブしてみました。
![]() |
使用部品等
|
開発環境作り
かつて,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クローンにする方法を再度実験し製作記事をまとめることにしました。
成果
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( )でプログラムを書いています。
Arduino IDEはスケッチにmain( )関数があればsetup(),loop()が無くともコンパイルしhexを吐いてavrチップに書き込むことができます→「Arduinoでmain関数」
結果
- 生成コードは500バイト以下
- 制御できた最大LED数 8個 (9個目以降はRAM不足でダメ)
- グローバル変数を使うと挙動不審 or 動かない。(グローバル変数がRAM領域を広く占有してしまいローカル変数エリアが不足する)