マイコン内臓LED(WS2822S)を使ってみる

フルカラーLEDはリアルタイムに色々表現できるのでとても楽しいLEDです。しかしここ数年、マイコンが搭載されてさらに楽しいLEDが出回ってきました。その一つがWE2822で、舞台向けなどの照明機器で使用されているDMX512という規格に似たフルカラーLEDのライブラリを作ったので紹介します。

使用機器

使用機器は下記のとおり。他、パソコンや電源、PICKIT2も当然ながら必要です。電源は写真の様に5Vラインに直接5Vを供給して下さい。レギュレータを通すと電力不足で動きがおかしくなります。

  • マイコンボード(PIC16F1947搭載)…ZEATEC co.,ltd. ZT-PIC16F194701(5V仕様)
  • スイッチサイエンス WS2822SシリアルLEDスティックモジュール2本
    又はWS2822Sを20個接続したもの

WS2822Sについて

このLEDは上でも説明したとおりDMX512という規格に基づいて制御します。しかし、通常DMXの機器は機器のディップスイッチなどによってアドレス設定しますが、この場合アドレス設定もシリアル信号によって行います。
先にアドレス設定の信号を送信して再起動後、カラーデータを送信します。ちなみにアドレスの設定は何度も書き換えできるようです。下のライブラリでは起動後、USARTポートから「mode,1」と入力してアドレス設定モードにし、1秒程度接続します。後に「mode,2」と入力するかマイコンを再起動すればカラーデータが送信されます。

アドレス設定信号プロトコル

アドレス信号はADRIに入力します。そしてADROから出てきた信号を次のLEDのADRIに接続します。その時DAIは何でも良いようですが、念のためライブラリではHIとしています。プロトコル内容については下記資料で何とか理解できそうですが、アドレスの割り当て順については少々理解しにくかったので注意が必要です。
1個のLEDには3つのアドレスが必要?なため、一つ目を1と設定すると次は4となります。順に3を足した数値となり、1、4、7,10、13という感じになります。

カラーデータ信号プロトコル

カラーデータはDAIから入力し、それぞれのLEDにも並列に接続します。各色のデータ(3バイト)を並べて送るだけで制御できます。

接続

接続は下記のとおりです。アドレスの設定が出来れば3本でも出来ますが、トラブルが起きた際の事を考えるとアドレスも配線しておいたほうが無難です。
電源は通常のピンから供給するとレギュレータの許容値を超えるようですので、PORT1もしくはPORT2の5Vラインに入力して下さい。

 

WS2822S用ライブラリ WS2822S.zip

 
  WS2822Sデータシート WS2822S.pdf  
  プロジェクトファイルも含めたサンプル ZT-PIC16F194701_WS2822S.zip  
            ウィンカーも作ってみました 16f1947_ws2822_turnsignal.zip  
  開発環境:MPLAB_IDE_8_92 + CCS-C PCMコンパイラVer.4.132
/*****************************************************************************************
マイコン内臓RGB LED(WS2822S)用ライブラリ 2015/11/04作成

□提供元
ZEATEC co.,ltd. 

□ご利用について
転載・無断使用可です。このライブラリを使用した上での不具合等に関しては、いかなる内容におい
ても一切の責任を追わないものとします。

□使用方法
#include "ws2822.c"をヘッダ部分に追加して起動と同時にライブラリを読み込むようにしてください。

ws2822_set_color();

ws2822_set_address(1,20);

*****************************************************************************************/
//DMX通信LED関係
#define PIN_ADDRESS     PIN_A1
#define PIN_COLORDATA     PIN_A3
int ws2822_led_value = 20;
int Color_R[20];
int Color_G[20];
int Color_B[20];

void ws2822_set_address(int start_add);
void ws2822_set_color();
void ws2822_send_one_packet(int mode,int set_data);
void ws2822_send_one_bit(int mode,int set_data);

//アドレスの書込み
void ws2822_set_address(int start_add){

    int tmp1 = 0;
    int tmp_data = 0;
    int tmp_start_add = start_add-1;
    int tmp_use_num = ws2822_led_value * 3;
    int tmp_set_address = 0;

    //カラーデータ送信ポートをHi
    output_bit(PIN_COLORDATA,1);

    //MTBP
    ws2822_send_one_bit(1,1);
    delay_us(88);

    //BREAK
    ws2822_send_one_bit(1,0);
    delay_ms(5);

    //MAB 12uS
    ws2822_send_one_bit(1,1);
    delay_us(8);

    //SC
    ws2822_send_one_packet(1,0x00);

    for(tmp1=tmp_start_add;tmp1<tmp_use_num;tmp1++){

        //セットするアドレスを用意 32uS
        tmp1++;
        tmp_data = tmp1;
        ws2822_send_one_packet(1,tmp_data);

        //セットするアドレスによってブロック番号を変える
        tmp1++;
        tmp_data = 0xf0;//0~255
        ws2822_send_one_packet(1,tmp_data);

        //アドレス書込み時の定数
        tmp1++;
        tmp_data = 0xd2;
        ws2822_send_one_packet(1,tmp_data);
        tmp1--;
    }
}

//カラーセット
void ws2822_set_color(){

    int tmp1 = 0;
    int tmp_data = 0;
    int tmp_set_address = 0;
    int tmp_end_num = ws2822_led_value;

    //MTBP
    output_bit(PIN_COLORDATA,1);
    delay_ms(5);

    //BREAK 88uS
    output_bit(PIN_COLORDATA,0);
    delay_us(88);

    //MAB 8uS
    output_bit(PIN_COLORDATA,1);
    delay_us(5);

    //SC
    ws2822_send_one_packet(2,0x00);

    //各データ
    for(tmp1=0;tmp1<tmp_end_num;tmp1++){
        //青色を設定
        ws2822_send_one_packet(2,Color_B[tmp1]);
        //緑色を設定
        ws2822_send_one_packet(2,Color_G[tmp1]);
        //赤色を設定
        ws2822_send_one_packet(2,Color_R[tmp1]);
    }
}


//1パケット分送信
void ws2822_send_one_packet(int mode,int set_data){

    int tmp_data = set_data;

    if(mode == 1){
        //アドレス設定送信

        //StartBit 4uS
        output_bit(PIN_ADDRESS,0);
        delay_us(3);delay_cycles(1);

        //アドレス送信
        output_bit(PIN_ADDRESS,bit_test(tmp_data,7));
        delay_us(3);//delay_cycles(1);
        output_bit(PIN_ADDRESS,bit_test(tmp_data,6));
        delay_us(3);//delay_cycles(1);
        output_bit(PIN_ADDRESS,bit_test(tmp_data,5));
        delay_us(3);//delay_cycles(1);
        output_bit(PIN_ADDRESS,bit_test(tmp_data,4));
        delay_us(3);//delay_cycles(1);
        output_bit(PIN_ADDRESS,bit_test(tmp_data,3));
        delay_us(3);//delay_cycles(1);
        output_bit(PIN_ADDRESS,bit_test(tmp_data,2));
        delay_us(3);//delay_cycles(1);
        output_bit(PIN_ADDRESS,bit_test(tmp_data,1));
        delay_us(3);//delay_cycles(1);
        output_bit(PIN_ADDRESS,bit_test(tmp_data,0));
        delay_us(3);//delay_cycles(1);
        
        //StopBit 8uS
        delay_cycles(3);
        output_bit(PIN_ADDRESS,1);
        delay_us(3);delay_cycles(8);
    }else if(mode == 2){
        //カラーデータ送信

        //アドレス送信ポートをHi
        output_bit(PIN_ADDRESS,1);

        //StartBit 4uS
        output_bit(PIN_COLORDATA,0);
        delay_us(3);delay_cycles(3);

        //アドレス送信
        output_bit(PIN_COLORDATA,bit_test(tmp_data,7));
        delay_us(3);delay_cycles(1);
        output_bit(PIN_COLORDATA,bit_test(tmp_data,6));
        delay_us(3);delay_cycles(1);
        output_bit(PIN_COLORDATA,bit_test(tmp_data,5));
        delay_us(3);delay_cycles(1);
        output_bit(PIN_COLORDATA,bit_test(tmp_data,4));
        delay_us(3);delay_cycles(1);
        output_bit(PIN_COLORDATA,bit_test(tmp_data,3));
        delay_us(3);delay_cycles(1);
        output_bit(PIN_COLORDATA,bit_test(tmp_data,2));
        delay_us(3);delay_cycles(1);
        output_bit(PIN_COLORDATA,bit_test(tmp_data,1));
        delay_us(3);delay_cycles(1);
        output_bit(PIN_COLORDATA,bit_test(tmp_data,0));
        delay_us(3);delay_cycles(1);
        
        //StopBit 8uS
        delay_cycles(3);
        output_bit(PIN_COLORDATA,1);
        delay_us(3);
    }
}

//1ビット分送信
void ws2822_send_one_bit(int mode,int set_data){
    if(mode == 1){
        //アドレスデータを送信
        output_bit(PIN_ADDRESS,set_data);
        delay_cycles(7);
    }else if(mode == 2){
        //色データを送信
        output_bit(PIN_COLORDATA,set_data);
        delay_cycles(7);
    }
}