フルカラーLEDを使おうとSeeeduino-XIAOのポートコントロールを再確認した
フルカラーLEDのなかでWS2812BなどNeoPixelとも呼ばれるLEDはリングやマトリックスパネルとしても良く使われています。電源と1本の通信線で動くので小さなMCUでも使いやすいのですが,信号パルスにナノ秒領域のコントロールが必要です。噴水のコントロールに光を追加しようと,Seeeduino-XIAO( MCU:SAMD21 )のポートコントロールを再確認しました。チェックプログラムでNeoPixelの小さなリングが光りました(^^)。別電源なのでXIAOからは信号線とグランドの2本だけつながっています。以前のSeeeduino-XIAOのプログラムでポートコントロール部を見てみると2つの様式で書いていました(^^;;;;;;。・Seeeduino-XIAOのポートコントロールでフルカラーLEDテープを動かしてみた・NeoPixel系の8x32フルカラーLEDパネルで中間色と表計算ソフトでのデザインを試してみたここはPin番号を引数としてOUTSETレジスタとOUTCLRレジスタのポートやビットをセットするマクロが提供されているので,これを使った方が分かりやすいですね。digitalPinToPort(LED_Pin) -> OUTSET.reg = digitalPinToBitMask(LED_Pin); digitalPinToPort(LED_Pin) -> OUTCLR.reg = digitalPinToBitMask(LED_Pin);このペアを使うとdigitalWriteFastの無い元祖XIAO(SAMD21 )でも100ns単位のパルスが発生できます。OUTSETを8回連続すると約700〜800ns,4回続けると約300〜400nsの長さのHIGHパルスが作れOUTCLRで下げられるので,約800KHzのNeoPixelのHigh/LOW信号が送れるわけです(^^)。以前の古〜いプログラムの流用ですが,上記画像のチェックプログラムをメモしておきます。/** XIAO NeoPixel test **/// LED_Pin:0, GRB_LED(WS2812B) number: 8#define LED_Pin 0#define lednumber_max 8byte aData[lednumber_max][3]; // number of LED * GRB(3) bytebyte lednumber = lednumber_max ; // Init. lednumbervoid setup() { pinMode(LED_Pin, OUTPUT); // set the pin as output digitalWrite (LED_Pin,0); byte r,g,b; // LED All Clear r=0;g=0;b=0; allset(r,g,b); sendData(); delay(500);} // setup endvoid loop() { // color test byte r,g,b; int waitms=2000; lednumber=lednumber_max; r=0x3F;g=0x00;b=0x00; allset(r,g,b); sendData(); delay(waitms); // R r=0x00;g=0x3F;b=0x00; allset(r,g,b); sendData(); delay(waitms); // G r=0x00;g=0x00;b=0x3F; allset(r,g,b); sendData(); delay(waitms); // B r=0x3F;g=0x3F;b=0x00; allset(r,g,b); sendData(); delay(waitms); // R+G r=0x3F;g=0x00;b=0x3F; allset(r,g,b); sendData(); delay(waitms); // R+B r=0x00;g=0x3F;b=0x3F; allset(r,g,b); sendData(); delay(waitms); // G+B r=0x3F;g=0x3F;b=0x3F; allset(r,g,b); sendData(); delay(waitms); // R+G+B lednumber=lednumber_max; for (byte i=0;i<=lednumber;i++){ // R,G,B,R+G,R+B,G+B,R+G+B byte j=i%7; if (j==0){r=0x3F;g=0x00;b=0x00;} //R else if (j==1){r=0x00;g=0x3F;b=0x00;} //G else if (j==2){r=0x00;g=0x00;b=0x3F;} //B else if (j==3){r=0x3F;g=0x3F;b=0x00;} //R+G else if (j==4){r=0x3F;g=0x00;b=0x3F;} //R+B else if (j==5){r=0x00;g=0x3F;b=0x3F;} //G+B else if (j==6){r=0x3F;g=0x3F;b=0x3F;} //R+G+B aData[i][0]=g; aData[i][1]=r; aData[i][2]=b; } sendData(); delay(waitms);} // loop endvoid allset (byte r,byte g,byte b){ for (byte i=0;i<lednumber_max;i++){ // Make all LEDs the same color aData[i][0]=g; aData[i][1]=r; aData[i][2]=b; }}void sendData(){ noInterrupts(); for (byte numLed=0; numLed<lednumber; numLed++){ // LED for (byte rgbLed=0; rgbLed <3; rgbLed++){ // 3byte:G,R,B byte a=aData[numLed][rgbLed]; for (byte i=0; i<8; i++){ // set 1byte byte hbit=a & 0x80; if (hbit>0){ // if bit=1 for (byte j=0; j<8; j++){ digitalPinToPort(LED_Pin) -> OUTSET.reg = digitalPinToBitMask(LED_Pin); } for (byte j=0; j<4; j++){ digitalPinToPort(LED_Pin) -> OUTCLR.reg = digitalPinToBitMask(LED_Pin); } }else{ // if bit=0 for (byte j=0; j<4; j++){ digitalPinToPort(LED_Pin) -> OUTSET.reg = digitalPinToBitMask(LED_Pin); } for (byte j=0; j<8; j++){ digitalPinToPort(LED_Pin) -> OUTCLR.reg = digitalPinToBitMask(LED_Pin); } } a=a*2; // next bit } } } interrupts();}