あけましておねでとうございます。
ラジオペンチさんの記事を参考にそのままESP32 DEV KITに書き込んで、オシロで賀正 2026を表示させました。
デジタルオシロでもXYモード表示できるんですね。
いま使っている、テクトロのTDS3014Bというオシロのマニュアルで確認しました。
ゲートXYZという機能をつかうとブランキング(表示を消す)もできるようです。

本年もよろしくお願いします。
完成したクリスマスツリーの動作です
前回の記事の続きです
今度は、120個のLEDストリップから6個のLEDを切り出した残り114個を光らせます。
ラジオペンチさんのこちらの記事、Arduino nanoのプログラムをSTM32F103C8に移植する作業になります。
今回はCDSを使って暗くなったら点灯して、タイマーで指定した時間デモを行った後、消灯する仕様を追加しました。
CDSの接続はコメントに書いている通りです。入力ポートはPA7を選びました。
// 回路構成:3.3V → CdS → 10kΩ → GND
// ADC入力:CdSと10kΩの分圧点
// ADC仕様:12bit(0~4095)
// AD値の意味:
// 大きい → 明るい(CdS低抵抗)
// 小さい → 暗い(CdS高抵抗)
#define CDS_PIN PA7 // CdS接続ピン(有効時のみ必要)
このように半田付けした後、熱収縮チューブでまとめます。

なお、信号線にはトグルスイッチをつけました。
トグルスイッチを切ると、PA7がオープンで入力レベルが上がって強制ONになります。
生活の知恵ですね。

回路図と接続は前回書いた通りですね。
NEOPIXEL WS2813は、下記のようにつながっていますから、まず電源としてBLUEPILLの5V(VBUS)、
GNDを接続し、信号線はPA8から330Ωを介してDIに接続します。
多重化のBIはGNDに接続する様になっています。(私は間違って、DI同様 330ΩでPA8につなぎました)
CDSは秋月で買った500kΩくらいのものを使います。
3.3V電源につなぐと10kΩと直列にしているので、明るい時に3V近く、暗い時に0.2V程度になります。
STM32F103のADCは12bitなので、AD値で明るい時 3000以上、暗い時 250位になるわけです。
この辺は実験して決める必要があります。
最終のプログラムはここに置いておきます。
STM32_110Led_XmassTreeV230_add_three_effect5_20251227g.ino
実際のNEOPIXELのファンクション動作は、ラジオペンチさんのブログを参照してくださいね。
いつものように、移植はAIのChatGPTとGROK先生に手伝ってもらいました。
ChatGPTのコードレビューと修正提案
https://chatgpt.com/c/694d0c6e-4528-8320-bb08-acdb5aa8e484
GROKのSTM32F103 BLUE PILLプログラム TickerからHardwareTimerへ変更
https://x.com/i/grok/share/cxtIkN7zs8QsJXVA8aeNKCj1y
プログラムの最初の部分を説明しますね。
// STM32用 NeoPixel 110LEDクリスマスツリー // ラジオペンチさんのプログラムをChatGPTで改造 // MsTimer2 を Ticker に置き換え、PROGMEM削除 // 2025/12/21 Todopapa 改造版 // 251222_add three effects // 251223_180分で止まらないバグ修正(TickerからHardwareTimerに変更)→ 300分に変更 // 251223_CDSを使って、暗くなったら起動するように仕様変更 PA7に入力 3.3V → CDS → 10k → GND // 251224_ PA7に入力にトグルスイッチを入れて、明るくても動作するモードを追加 // 251224_ 110個 → 114個に変更 // 251224_ CDSで起動して240分動作し停止後、明るくなっても再起動しないバグを修正 // 251225_ CDSで起動して240分動作し停止後、暗かったら再起動するバグを修正 // 251227_ GROK先生のアドバイスでプログラムのリファクタリング実施 #include <Arduino.h> #include <Adafruit_NeoPixel.h> // #include <Ticker.h> // tickerはSTM32で安定して動かないので timerを使う方式に変更 #define LED_PIN PA8 // LED制御用のシリアル出力ピン #define LED_COUNT 114 // LEDカウント数 #define STD_BRIGHTNESS 50 // 標準明るさ #define OFF_TIMER_VAL 300 // 自動OFFタイマー(分単位)180→300(5時間) //#define OFF_TIMER_VAL 3 // 自動OFFタイマー(分単位)3分でテスト(1ループ終わらないと止まらない) // ===== CdS(光センサ)設定 ===== // CdSを使いたいときは以下の行のコメントを外す #define USE_CDS // CdS機能有効(コメントアウトするとCdS無効=常にデモ実行) // 回路構成:3.3V → CdS → 10kΩ → GND // ADC入力:CdSと10kΩの分圧点 // ADC仕様:12bit(0~4095) // // AD値の意味: // 大きい → 明るい(CdS低抵抗) // 小さい → 暗い(CdS高抵抗) #define CDS_PIN PA7 // CdS接続ピン(有効時のみ必要) #define CDS_DARK_TH 400 // これ以下で「暗い」暗いと判断する閾値(0-4095、実測で調整。例: 明るい時3000、暗い時500) #define CDS_BRIGHT_TH 800 // 550 → 800に変更 これ以上で「明るい」(ヒステリシス十分) volatile bool demoRunning = false; // デモ実行中フラグ #define RAND_COL7 col[random(7) + 1] // 7色からランダムに色を選択 #define RAND_COL8 col[random(8)] // 黒を含む8色からランダムに色を選択 #define RAND_COL7H colH[random(7) + 1] // 7色からランダムに色を選択 #define RAND_COL8H colH[random(8)] // 黒を含む8色からランダムに色を選択 Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800); //timer 1秒周期 HardwareTimer timer(TIM2); // TIM2を使用
Arduno NanoのArduino IDEに、STM32F103はSTM32dunoという基板ライブラリを使います。
そのため、MSTIMER2ライブラリは使えないので、HardwareTimerというライブラリを使います。
詳しい使い方はこちらにありますので、興味のあるかたは見てくださいね。
実際のタイマーの設定に関してはこちらになります。 前にPZEM-004Tを使った電力計を作った時と同じですね。
// -----------------------
// 割り込み1秒ごと
// -----------------------
void timer2IRQ() { //割り込みハンドラ
static bool led = false;
led = !led;
digitalWrite(PC13, led); // PC13トグル(常に動作)
if (demoRunning) { // デモ実行中だけ時間を進める
sec++;
if (sec >= 60) {
sec = 0;
mmm++;
}
}
t2Flag = true; // フラグを立てる(loopで待つ用)
}
// -----------------------
void setup() {
Serial.begin(115200);
pinMode(PC13, OUTPUT); //割り込みモニタ用
strip.begin();
strip.show();
strip.setBrightness(STD_BRIGHTNESS);
// ===== 1秒タイマーの設定 =====
timer.pause(); // 一旦停止
timer.setPrescaleFactor(7200); // プリスケーラ:72MHz / 7200 = 10kHz
timer.setOverflow(10000); // オーバーフロー:10kHzで10000カウント = 1秒
timer.refresh(); // リセット
timer.attachInterrupt(timer2IRQ);// 割り込み関数設定
timer.resume(); //タイマー開始!
-------
void timer2IRQ() の割り込みハンドラは、demorunning中は sec,mmm という時間カウンタを1秒ずつ進める
ことと、モニタのためにPC13の緑LEDを点滅させます。
また、loop()での1秒待ちのために、 t2Flag = true; というフラグを立てます。
loop()内では demoRunningが有効な間は下記Functionのデモを実施します。(1ループ 5分ほど)
if (demoRunning) {
demo1;
demo2;
-------
}
デモを抜けると、タイマーUPの検出に続いて1秒待ちでCDSの状態を検知するルーチンに入ります。
/* ===== OFFタイマー経過で停止処理 =====
※ demoRunning の外に置くのが重要 */
if (mmm >= OFF_TIMER_VAL) {
if (demoRunning) {
demoRunning = false;
todayDone = true; // 今日の点灯は完了
}
strip.clear();
strip.show();
// 停止表示(PC13 ゆっくり点滅)
digitalWrite(PC13, HIGH);
delay(30);
digitalWrite(PC13, LOW);
delay(2000);
}
#ifdef USE_CDS
/* ===== CdS 読み取り ===== */
int cdsValue = analogRead(CDS_PIN);
/* ===== ヒステリシス付き明暗判定 ===== */
// 暗くなった判定(AD値が小さくなる)
if (!isDark && cdsValue < CDS_DARK_TH) {
isDark = true;
}
// 明るくなった判定(AD値が大きくなる)
else if (isDark && cdsValue > CDS_BRIGHT_TH) {
isDark = false;
todayDone = false; // 翌日の点灯を許可
}
/* ===== 暗くなったら起動(1日1回) ===== */
if (isDark) {
if (!demoRunning && !todayDone) {
demoRunning = true;
mmm = 0;
sec = 0;
}
}
else {
// 明るい間は必ず停止
demoRunning = false;
}
#endif
/* ===== 1秒同期(必ず最後) ===== */
while (!t2Flag) {
// 割り込み待ち(実質ビジーループ)
}
t2Flag = false;
} // loop() 終了
// -----------------------
これでCDSで暗くなったのを検出してデモ動作を開始して、時間が来たら消灯するようになります。
暗い間に再度起動しないように、 todayDone = false; というフラグが明るくならないとクリア
されないように制御します。
これで、毎日 暗くなると一定時間デモを行い、次の日も暗くなると同様にデモを行うことができるようになりました。
(クリスマス終わったんですが(笑))
ラジオペンチさんのクリスマスツリーは、アクリル板をカットして10段で n x (n+1)=110個のLEDを制御します。
トドお父さんは、そのような加工技術も根気もないので、そのまま小型のクリスマスツリーに巻きつけました。

これでも、十分きれいに光りますすね。さすが、ラジオペンチさん。
これで、今回のNIOPIXEL114個でのクリスマスツリー作成の話は終わりです。
クリスマスには何とか間に合ってよかったです!
それでは、皆さんおやすみなさい。
おもちゃ病院で必要な部品をAliExpressで購入しようと思いました。
Choice という仕組みがあって、1500円以上なら送料無料になるんですよ。
そういえばラジオペンチさんのブログで、NEOPIXELというRGB LEDをテープに多段接続
したテープLEDが安く売っていることを思い出しました。
ラジオペンチさんのホームページに載っていた元記事はこれです。
まずは、120個のLEDストリップから6個のLEDを切り出します。
これをSTM32F103 BLUEPILLでテストしましょう。
下記はWS2813のテストプログラムです。
/*
WS2813B LED テストプログラム(ビットバン方式)
MCU : STM32F103 (BluePill想定)
IDE : Arduino IDE (STM32duino)
書き込み : ST-LINK
LED : WS2813B × 6個
出力ピン : PA8
ライブラリ : Adafruit NeoPixel
※ WS2813B は WS2812B 互換のため、
NEO_KHZ800 を指定する
*/
#include <Adafruit_NeoPixel.h>
// ===== 設定 =====
#define LED_PIN PA8 // LEDデータ出力ピン
#define LED_COUNT 6 // 接続しているLEDの数
// NeoPixel オブジェクト生成
// NEO_GRB : 色データ順
// NEO_KHZ800 : 800kHz(WS2812/WS2813共通)
Adafruit_NeoPixel strip(
LED_COUNT,
LED_PIN,
NEO_GRB + NEO_KHZ800
);
void setup() {
// NeoPixel 初期化
strip.begin();
// 念のため全LED消灯
strip.clear();
strip.show();
}
void loop() {
// 赤 → 緑 → 青 を順番に表示
colorAll(255, 0, 0); // 赤
delay(500);
colorAll(0, 255, 0); // 緑
delay(500);
colorAll(0, 0, 255); // 青
delay(500);
}
/*
全LEDを同じ色で点灯させる関数
r, g, b : 0~255
*/
void colorAll(uint8_t r, uint8_t g, uint8_t b) {
for (int i = 0; i < LED_COUNT; i++) {
strip.setPixelColor(i, strip.Color(r, g, b));
}
strip.show(); // ここで実際にLEDへデータ送信
}
これで、6個のLEDにr=g=b=255のデータを流し込みましたから、6個が白に光ったら接続確認はOKです。
接続は下記のデータシートに示すように、先頭のLEDにUSB 5VとGND、それから信号線のDIに330Ωを介してSTM32F103 BLUEPILLのPA8を接続します。
データシート接続図
このとおりにブレッドボードで組んで、STLINKでスケッチをダウンロードすると
あっけなく動作しました。 USB経由の書き込みは何度かトライしましたが地雷があってうまくいきませんでした。
あっさり光りました!
次に光がダイナミックに動いて動作するデモプログラムを作りました。
この時はNEOPIXELの動作を理解してなかったので、GROK先生に相談しました。
https://x.com/i/grok/share/raiTG4ZqQ6bDDPPBPhTkunrzJ
ChatGPT先生にも、プログラムの添削とエフェクトの追加をお願いしました。
https://x.com/i/grok/share/raiTG4ZqQ6bDDPPBPhTkunrzJ
* - WS2813BのDIとBIは両方接続推奨 は間違いで、
実際は、DIを330Ωを介してPA8に接続し、BIはGNDに落とします。
エフェクトを追加した、最終のテストプログラムは下記です。
NeoPixel_xmas_demo2_25dec21c.ino
容量が大きいので、頭の部分だけ貼り付けますね。
/*********************************************
******
* NeoPixel クリスマスエフェクト サンプルプログラム (WS2813B 6個用)
*
* 対象ボード : STM32F103 (Blue Pill) + Arduino IDE
* 使用ライブラリ: Adafruit NeoPixel (STM32対応版 ANDnXORフォーク)
* LED種類 : WS2813B (6個直列接続)
* データピン : PA8 (動作確認済み!)
*
* 主な機能:
* - colorWipe : 順番に単色で塗りつぶし(赤→緑→青)
* - theaterChase : シアター風追いかけ点灯
* - rainbow : 全体でゆっくり虹色サイクル
* - candyCane : 赤白キャンディケイン風ストライプ(回転)
* - christmasTwinkle : ランダムきらきら点滅(白/金)
* - christmasAlternate : 赤緑交互点灯(クラシッククリスマス)
*
* 注意事項:
* - WS2813BのDIとBIは両方接続推奨
* - データ線に330-470Ω抵抗 + レベルシフタ推奨
* - 明るさ50でUSB電源でも安全
*
* 作成日: 2025/12/21
* 動作確認環境: Blue Pill + WS2813B 6個 (PA8)
***************************************************/
#include <Adafruit_NeoPixel.h>
#define NUM_LEDS 6
#define DATA_PIN PA8
#define LED_TYPE NEO_GRB + NEO_KHZ800
Adafruit_NeoPixel pixels(NUM_LEDS, DATA_PIN, LED_TYPE);
void setup() {
pixels.begin();
pixels.setBrightness(50); // 明るさ調整(クリスマスは少し明るめにしてもOK)
pixels.clear();
pixels.show();
}
void loop() {
// 既存のエフェクト
colorWipe(pixels.Color(255, 0, 0), 200); // 赤
colorWipe(pixels.Color(0, 255, 0), 200); // 緑
colorWipe(pixels.Color(0, 0, 255), 200); // 青
theaterChase(pixels.Color(127, 127, 127), 100); // 白追跡
rainbow(10);
}
https://x.com/powpher/status/2002751267123470633
X(旧Twitter)の投稿も参考まで
ラジオペンチさんの記事を参考に、
— トドお父さん@水曜日はヤクルトファン (@powpher) December 21, 2025
NEOPIXELをSTM32F103 BLUEPILLで動かしました!
まだたった6個です。
https://t.co/bNKt6sHb2g
それでは、次は前にも紹介したSTM32F103C8T6を搭載したBluePill基板の紹介です。
AliExpressで200円前後で買えるので、やすいですね。
自分はおもちゃ修理にSTM32を使うアイデアがあるので、勉強用に3枚買いました。
その場合は、開発環境はSTM32CubeIDEかKEILというものを使う必要があるのですが、
今回はArduinoベースなので、Arduino STM32Coreというものを使います。
これだと、STM32でArduinoのライブラリが使えるので、非常にラクですね。
ArduinoのボードマネージャでSTM32Coreというものを組み込むのですが、この辺の情報は
巷にあふれていますので、割愛します。ただし、Arduinoは最新のVerを使ってくださいね。
もうひとつ、BluePillを使うためには、Amazonで中華製のST-LINK/V2というプログラマを
買うことをお勧めします。 自分の場合は、500円くらいで十分使えました。
ST-LINKが必要なのは、中華製の廉価BluePillはプログラムが書き込まれてないまっさらの状態のためです。 例えばArduinoに接続する場合、BootLoader(USBのCDC)が書き込まれていれば、BOOT1のJumperを”1”に切り替えてUSB経由で書き込みができますが、まっさらではお手上げです。
そこでSTLINKで接続すれば、BootLoaderの書き込みをを行うことができるので、Arduinoから書き込み
ができるようになります。
ここでも、細かい話はネットの情報で確認下さい。
ST-LINKで接続すると細かい話はおいといて、プログラムの書き込みができるようになりました。
さて、ラジオペンチさんのシリアルテープLEDを使った110LEDクリスマスツリーのプログラムをArduino Nanoから、STM32F103C8T6 BluePillに移植したプログラムですが、こちらにおいています。
説明が長くなってきたので、移植したプログラムでNEOPIXELを6個→ 114個に拡張し、クリスマスツリーに巻き付けてNEOPIXELのデモをした話は次回にしますね~。
こうご期待 !
それでは、皆さんおやすみなさい。