で、そのディープスリープだが、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 100mSint timerCount;
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見限らずにしばらく使ってみるか。