0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

PICマイコンのCLCを使って超簡単にNeopixelLED(フルカラーシリアルLED)をコントロールする

0
Last updated at Posted at 2026-08-14

ナゾテックの名前で模型・ジオラマ用のLED電飾コントローラーや配線済みチップLEDの販売などを行っている者です。

Amazonストア

想定読者

MicrochipのPICマイコンを使ってNeopixelLED(フルカラーシリアルLED)をコントロールして見たいなと言う方。
Neopixelに付いてググるとarduinoを使った記事がたくさん出来てくるし、PICを使った場合の記事がほとんどないので読みたい、と言う方へ。
C言語に付いても有る程度はご存じの方向けです。

目次

経緯
機材
回路
電源に付いて
マイコンの設定
プログラミング
Neopixelが点かない
main.c全文

経緯

以前にいろいろググってきましたが、Neopixelの制御と言えばArduinoと言う感じで定番化しており、PICマイコンを使ったNeopixelの制御ではなかなかこれと言った記事が見つかりませんでした。その時見つけたのがPICマイコンメーカーであるMicrochip社が作っている動画と資料でした。
正直言うとここに書かれている内容を全部理解していませんが、少なくともPICマイコンでNeopixelを、それも簡単に制御できるようになりましたので、元ネタをある程度噛み砕いて解説いたします。
元記事を見たい方は下記を参照してください。

こちらは上記動画の日本語字幕付き

この記事をベースに実際にNeopixelを光らせている動画
https://youtu.be/5WT-D6lwKd0?si=jCuXBKcRiU5eyJMV

全部英語ですが、PDFはブラウザの翻訳機能で読みました。

機材

基本となるPCはとりあえずWindowsで説明しますが、MacでもMPLAB X IDEの使い方などはほぼ同じなので大丈夫だと思います。
プログラムの書き込みにSnapインサーキットデバッガを使います。他にもブレッドボードが有れば良いでしょう。下記の記事を参考にしてください。
またMPLAB X IDEでのプロジェクト新規作成などもこの記事で解説しています。

MPLAB X IDE+MCCでLチカやってみる

今回使用するNeopixelLEDはこちらの物です。おそらくNeopixel系の物なら同じように使用できると思います。

こちらはLEDの数が少ないですが安いので試験的に使う分には十分かと思います。

Neopixelの型番が違いますが、仕様的には同じものらしいので大丈夫かと思います(すみません後者はテストしていません)。
また今回使用するマイコンはPIC16F18346です。

上記の入門記事ではPIC16F1827を使っていますが、必要な機能が無かったので今回は18346を使います。
後述しますがNeopixelをコントロールするための機能が備わっていればいいので、他のマイコンでも使用可能なものが有ります。

回路

回路図とかちょっと面倒なんで、ブレッドボードの画像でご勘弁を願います。
Neopixelブレッド.png

ピン番号 用途
1 電源プラス
4 MLCR
12 Neopixelへの信号
18 PGC
19 PGD
20 電源マイナス

Snapの接続に付いてはMicrochipのPICマイコンとMPLAB Snap インサーキット デバッガを繋ぐをご参考にどうぞ。
この記事とはマイコン機種が違うので接続するピン番号に違いがありますから、上表を参考に接続してください。

Neopixelの端子に付いては、ブレッドボードに繋ぎ易い様に購入した「SK6812搭載シリアル制御フルカラーテープLED」のケーブルを外してピンを3本付けています。赤が電源プラス、黒が電源マイナス、白が信号になります。

電源に付いて

Neopixelの電源は5Vです。LEDの数が少なければ3Vでも動作する場合が有りますが安定しているかどうかは不明です。
この場合、Neopixelへ送り出す信号も5Vにする必要があります。つまりマイコンも5Vで動作させる必要が有ると言う事です。Snapの使い方で説明したようにSnapの基板から5V電源を得る事は可能ですので、そちらを検討してみてください。
なお、NeopixelのLED数が多いとそれだけ消費電力が大きくなるので、Snapからの電源だけでは容量が不足します。そうなるとマイコンの動作自体が不安定になり勝手にリセットされたりします。
ですので、Neopixelへの電源は別途用意してSnapからはマイコンへのみ電源供給するようにしましょう。

マイコンの設定

まずはプロジェクトを新規に作成してください。MPLAB X IDE+MCCでLチカやってみるを参考にされながら、マイコン機種は"PIC16F18346"を選択してください。必要な機能をご理解された上で他の機種をお使いの場合はその機種を選択してください。
スクリーンショット 2026-08-13 082244.png
プロジェクト名は何でも良いですが、ここでは"NeopixelSample_18346"としています。"Encoding"は”Shift_JIS"にしています。
スクリーンショット 2026-08-13 082343.png
MCCを起動しましょう。下記記事を参考にしてください。
MCC Classicの操作方法
まずは"System Module"でMCUの設定を行います。
最速設定を行ってください。"HF Internal Clock"は"32MHz"、"Clock Divider"は"1"にします。
スクリーンショット 2026-08-13 082920.png
次に"Peripherals"から"TMR2"を追加して下記の様に設定します。
重要な点は"TImer Period"で"625 ns"に設定することです。
スクリーンショット 2026-08-21 085547.png
次に"Peripherals"から"PWM5"を追加し、下記の様に設定します。
スクリーンショット 2026-08-21 085708.png
初期値で問題有りませんが”Select a Timer"が"Timer2"になっていることを確認してください。
今度は"Peripherals"から"MSSP1"を追加し、下記の様に設定します。
スクリーンショット 2026-08-14 105716.png
"Clock Source Selection"を"TMR2"にする以外は初期状態のままで問題ないはずですが、内容を確認しておいてください。
また"Easy Setup"タブの設定だけでは不足なので"Registers"タブに切り替えてください。
申し訳ありませんがこの辺りの設定も良く分かっていないので、解説は出来ません。下記の様に設定してください。
"SSP1ADD"を"0x0"に。
スクリーンショット 2026-08-14 110753.png
"SSP1STAT"の"CKE"を"Idle to Active"に。
スクリーンショット 2026-08-14 110805.png
最後に"Peripherals"から"CLC1"を追加します。下図のような画面が表示されます。
CLC設定1.png
こちらのモジュールは複数の信号を指定された"ロジック"に従って合成して一つの信号にするための物です。
こちらはマイコン内部のハードウエア機能として備わっていますので、プログラムを書く必要がなくしかもMPUを使わずに高速に処理できるという利点があり、Neopixelへの信号送信には最適です。
表示されているちょっと変わった記号は「論理回路記号」でそれぞれの形に意味が有ります。詳しくはググッてください。CLCに付いての解説はMicrochipの解説記事を参考にしてください。
まず赤枠の4つの部分を上から下記の様に選択します。
PWM5 output
SCL1
SDA1
FOSC
スクリーンショット 2026-08-14 111730.png
次にその右側に有る"Gate"への入力信号を選択します。ここは✖マークは入力しないことを表し、〇マークは信号を反転(0なら1に1なら0に)して入力、記号無しはそのまま入力することを表します。
設定の変更は下記の部分をクリックします。1回クリックする毎に変化します。入力側、出力側の設定が可能です。
スクリーンショット 2026-08-14 111730.png
下記の様に設定します。赤丸は反転、青丸はそのまま入力です。
スクリーンショット 2026-08-14 114822.png
次にCLCの最終出力信号を出力するピンを割り当てます。回路のところで12番ピンにNeopixelの信号線をつないだので、"Pin Manger Grid"で12番ピン("RB5")に"CLC1->CLC1OUT"を割り当てます。実際には出力ピンは他と被ってなければどれでも構いません。変更した時は回路もそれに合わせてください。
スクリーンショット 2026-08-14 115405.png
リソースとして"Libraries"の"DELAY"も追加しておきましょう。
スクリーンショット 2026-08-14 122254.png
これでMCCの設定は終わったので、忘れずに"Generate"をクリックしてソースコードを生成しましょう。

プログラミング

プログラムコード全体は最後に記載します。
Neopixelへ信号を送る時はRGB(赤緑青)の順で1バイト×3を一つのLED分として、接続されているLEDの数分送信します。そのためにまずRGBを表す構造体を定義します(main関数の手前に記述)。

typedef struct {
    uint8_t r;
    uint8_t g;
    uint8_t b;
}RGB;

uint8_tはPICマイコンで使える1バイト符号なしのデータ型です。
たとえばLEDを赤にしたい場合は"r"メンバーに255を、gとbに0をセットします。緑ならgだけ255の様にします。
後の処理がやり易い様に点灯したいLEDの数分の配列を用意しましょう。

#define LEDNUM 5
RGB ledTable[LEDNUM];

LEDの数を5としていますがいくつでも構いません。
ただし、LEDの数が多いと消費電力も大きくなり、Snapでの書き込み時にエラーが出る場合も有ります。またマイコンを起動する場合もSnapからの電力だけでは不足して正しく起動できないことも有るので、最初は5個くらいにして実行しましょう。LEDの数を増やす場合は、プログラムの書き込み時はNeopixelの接続を外して書き込み、実行する場合はSnap以外の電源から電源を送るようにしましょう。
もしくは、Neopixelへの電源をマイコンとは別に用意してそちらから供給するのも良いでしょう。なおその場合でも電源マイナスだけは互いに接続しておいてください。
この配列データをNeopixelへ送信するコードは下記になります。

void sendRGBData(){
    //INTERRUPT_GlobalInterruptDisable();  //割込みを許可しない
    for(int i=0;i<LEDNUM;i++){
        SSP1BUF = ledTable[i].g; //Green
        while (!SSP1STATbits.BF);
        SSP1BUF = ledTable[i].r; //Red
        while (!SSP1STATbits.BF);
        SSP1BUF = ledTable[i].b; //Blue 
        while (!SSP1STATbits.BF);
    }
    //INTERRUPT_GlobalInterruptEnable(); //割込みを許可する
}

配列データをループしながらSPIの書き込みバッファに1バイトずつ値をセットします。送信自体はこれで自動で行われるのでwhile (!SSP1STATbits.BF);で送信完了を待ち、その後次の1バイトを書き込みます。
注意しないといけないのは、送信順がG->R->Bだと言う事です。
また、データ送信中に中断が発生すると正しくLEDが光らないので、割込みを一旦停止します。送信完了後に割込みを再度許可してください。なお、今回は割込みを使ってないのでそれぞれのコードはコメント化しています。
ここまでは全てmain関数の手前に記述してください。
プログラム起動時に、MCCで定義したMSSP1のSPIモジュールに付いて使用可能とするために下記のコードをmain関数のwhileループの前に記述します。

    SPI1_Open(SPI1_DEFAULT);    

では、ちょっとダサいコードですが全てのLEDを赤・青・緑と1秒おきに光らせるコードです。

    while (1)
    {
        for(int i=0;i<LEDNUM;i++){
            ledTable[i].r = 255;  //赤で光らせる
            ledTable[i].g = 0;
            ledTable[i].b = 0;            
        }
        sendRGBData();
        DELAY_milliseconds(1000);
        for(int i=0;i<LEDNUM;i++){
            ledTable[i].r = 0;
            ledTable[i].g = 255; //緑で光らせる
            ledTable[i].b = 0;            
        }
        sendRGBData();
        DELAY_milliseconds(1000);
        for(int i=0;i<LEDNUM;i++){
            ledTable[i].r = 0;
            ledTable[i].g = 0;
            ledTable[i].b = 255;  //青く光らせる
        }
        sendRGBData();
        DELAY_milliseconds(1000);
    }

如何だったでしょうか。プログラム自体は非常に簡単なコードでNeopixelを光らせる事が出来ました。

Neopixelが点かない

もしNeopixelが点かない、変な光かたをするなどの場合はプログラムの問題も有ると思いますが、場合によってはNeopixelの型番による違いも有るかも知れません。
Neopixelを光らせるためのデータ送信のタイミングが型によって多少違う場合があるので、これを変更して見てどうなるか試してみるのも良いかも知れません。
変更するには"TMR2"の”Timer Period"の値を変更してみてください。たとえば"500ns"とか"700ns"などもっと低くまたは高く設定してやって見てください。"Timer Period"を変更した時は"Generate"を必ず行ってください。

main.c全文

/**
  Generated Main Source File

  Company:
    Microchip Technology Inc.

  File Name:
    main.c

  Summary:
    This is the main file generated using PIC10 / PIC12 / PIC16 / PIC18 MCUs

  Description:
    This header file provides implementations for driver APIs for all modules selected in the GUI.
    Generation Information :
        Product Revision  :  PIC10 / PIC12 / PIC16 / PIC18 MCUs - 1.81.8
        Device            :  PIC16F18346
        Driver Version    :  2.00
*/

/*
    (c) 2018 Microchip Technology Inc. and its subsidiaries. 
    
    Subject to your compliance with these terms, you may use Microchip software and any 
    derivatives exclusively with Microchip products. It is your responsibility to comply with third party 
    license terms applicable to your use of third party software (including open source software) that 
    may accompany Microchip software.
    
    THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER 
    EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY 
    IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS 
    FOR A PARTICULAR PURPOSE.
    
    IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, 
    INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND 
    WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP 
    HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO 
    THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL 
    CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT 
    OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS 
    SOFTWARE.
*/

#include "mcc_generated_files/mcc.h"

typedef struct {
    uint8_t r;
    uint8_t g;
    uint8_t b;
}RGB;

#define LEDNUM 5
RGB ledTable[LEDNUM];

void sendRGBData(){
    //INTERRUPT_GlobalInterruptDisable();
    for(int i=0;i<LEDNUM;i++){
        SSP1BUF = ledTable[i].g; //Green
        while (!SSP1STATbits.BF);
        SSP1BUF = ledTable[i].r; //Red
        while (!SSP1STATbits.BF);
        SSP1BUF = ledTable[i].b; //Blue 
        while (!SSP1STATbits.BF);
    }
    //INTERRUPT_GlobalInterruptEnable();
}

/*
                         Main application
 */
void main(void)
{
    // initialize the device
    SYSTEM_Initialize();

    // When using interrupts, you need to set the Global and Peripheral Interrupt Enable bits
    // Use the following macros to:

    // Enable the Global Interrupts
    //INTERRUPT_GlobalInterruptEnable();

    // Enable the Peripheral Interrupts
    //INTERRUPT_PeripheralInterruptEnable();

    // Disable the Global Interrupts
    //INTERRUPT_GlobalInterruptDisable();

    // Disable the Peripheral Interrupts
    //INTERRUPT_PeripheralInterruptDisable();

    SPI1_Open(SPI1_DEFAULT);
    
    while (1)
    {
        for(int i=0;i<LEDNUM;i++){
            ledTable[i].r = 255;
            ledTable[i].g = 0;
            ledTable[i].b = 0;            
        }
        sendRGBData();
        DELAY_milliseconds(1000);
        for(int i=0;i<LEDNUM;i++){
            ledTable[i].r = 0;
            ledTable[i].g = 255;
            ledTable[i].b = 0;            
        }
        sendRGBData();
        DELAY_milliseconds(1000);
        for(int i=0;i<LEDNUM;i++){
            ledTable[i].r = 0;
            ledTable[i].g = 0;
            ledTable[i].b = 255;            
        }
        sendRGBData();
        DELAY_milliseconds(1000);
    }
}
/**
 End of File
*/
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?