米粒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領域を広く占有してしまいローカル変数エリアが不足する)