晴れたり沼ったり

へんなものに沼ることがあります。

seeed xiao に遊ばれる part3

で、そのディープスリープだが、geminiくんによれば、

LowPower.deepSleep(); 

で出来るとか行ってきたのだけど、使ってるボードではサポートしてない。

で、LPMモジュールを使えとか言ってコードを示してくるのでやってみたら、コンパイルエラー。

__WFI() 

を使えというので、また示してきたコードを試したら一応一瞬スリープするみたいなんだけどすぐに起きてきてしまう。

gemniくんはノイズだとかプルアップせよ(*1)とか言ってくるけど改善しない。んなあほな〜といいつつプルアップ抵抗いれても動作変わらず。

システムタイマーが悪いとかneopixel(多色のLED)が悪いとか、レジスタにシグナルが残ってるのが悪いとか、インタラプトを受け付けない設定が出来るからそれにしろとか、いってコード修正してくること、6,7回。結果変わらず。

xiao (少なくともRA4M1)ではディープスリープ使えないのかもね。

しょうが無いので、ライトスリープがあるなら書き換えてといったらサクっとそれは動いた。

やれやれ。

これが、一応 geminiくんと私の共作版のスケッチ。

(*1にあるようにプルアップが機能しないので、正しくないとこもあるし、ゴミコードも残ってるかもしれないけど一応動く)

#include <Adafruit_NeoPixel.h>

#define LED_PIN RGB_BUILTIN
#define NUM_PIXELS 1

volatile bool shouldSleep = false;
volatile bool shouldReset = false;
volatile bool timerFlag = true;
//Count = 5*60*10; // check every 100mS
int timerCount;

Adafruit_NeoPixel pixels(NUM_PIXELS, LED_PIN, NEO_GRB + NEO_KHZ800);

void setup() {
pinMode(LED_BUILTIN, OUTPUT);
pinMode(D1, INPUT_PULLUP);
pinMode(D2, INPUT_PULLUP);
pinMode(PIN_RGB_EN, OUTPUT);
digitalWrite(PIN_RGB_EN, HIGH);
pixels.begin();
// 割り込み設定
attachInterrupt(digitalPinToInterrupt(D2), triggerSleep, FALLING);
attachInterrupt(digitalPinToInterrupt(D1), triggerReset, FALLING);

// 起動時の青点灯
pixels.setPixelColor(0, pixels.Color(0, 0, 6));
pixels.show();
timerCount = 5*60*10;
timerFlag = true;
}

void triggerSleep() { shouldSleep = true; }
void triggerReset() { shouldReset = true; timerCount=0; }

void chk(){
// 1. D1が押されたら即リセット
if (digitalRead(D1) == LOW) {
__NVIC_SystemReset();
}
// 2. スリープ判定
if (shouldSleep) {
shouldSleep = false;
// LEDを消し、電源を落とす(これで電力はかなり下がります)
pixels.setPixelColor(0, pixels.Color(0, 0, 0));
pixels.show();
digitalWrite(PIN_RGB_EN, LOW);
digitalWrite(LED_BUILTIN, LOW);

// ボタンを離すのを待つ
while(digitalRead(D2) == LOW) { delay(10); }
delay(200);

// --- ライト・スリープ開始 ---
// 複雑なレジスタ操作をせず、単に「割り込み」を待つだけの状態にします
while (!shouldReset) {
// CPUを「割り込み待ち」の状態にする(最も軽いスリープ)
// 何らかの理由(タイマー等)で起きても、shouldResetがfalseなら即座にまた寝ます
__asm__ volatile ("wfi");

// D1(リセット用)が押されたかチェック
if (digitalRead(D1) == LOW) {
shouldReset = true;
}
}
// --- スリープ脱出 ---
// shouldResetがtrueになったらここに来るので、そのままリセット
__NVIC_SystemReset();
}

}
void loop() {
if(timerFlag == true){
// for文の条件に !shouldReset を追加することで、ボタンが押されたら即ループを抜ける
for(int i = timerCount; i > 0 && !shouldReset && !shouldSleep; i--){
delay(100);
chk();
}
// ループを抜けた原因が「時間切れ」の場合のみ、点滅フェーズへ
if (!shouldReset && !shouldSleep) {
timerFlag = false;
}
}

chk();


if (timerFlag == false) {
pixels.setPixelColor(0, pixels.Color(0, 23, 0));
pixels.show();
delay(120);
pixels.setPixelColor(0, pixels.Color(0, 0, 0));
pixels.show();
delay(300);
}
}
 

 

*1: あとで調べたら RA4M1は パラメータでプルダウン、プルアップが指定出来るけど、D1などのアナログ入力可能なポートでは不安定らしい。D6以降が比較的おすすめらしい。D1,D2でもgeminiくんによると、2度書き、100mSほど待ってから再度書き込みとかが比較的有効らしい。ライブラリとかで更新される可能性もあるらしい。RA4M1見限らずにしばらく使ってみるか。