前回はESP8266でNTPサーバーから時刻を取得し、RTC-8564NBに現在時刻を書き込むとこまでやりました。
alasixosaka.hatenablog.com
今回は、RTC-8564のアラーム機能を使って、TWELITEからスリープ中のESP8266を起こしてみたいと思います。
何故そんな回りくどいことをするのかというと、前にも書いたようにRTC-8564のアラーム機能を使うと、INT端子がLOWになるのですが、LOWを維持したままになるのでESP8266のリセット端子に直接つないでもリセットがかけられないためです。
そこで、TWELITEでRTC-8564のINT端子を監視して、LOWになったら、TWELITEのデジタル出力を使ってESP8266をリセットしてやろうという試みです。
こんな感じで配線します。
かなり複雑になっていますが。ESP8266はRTC-8564にI2Cで接続します。また、RTC-8564のINT端子とTWELITEの13番ピンを接続し、ESP8266のRST端子とTWELITEの18番ピンを接続します。TWELITEのピン番号は少しややこしいのですが、TWELITEDIPの場合、基板にシルク印刷している番号です。13番ピンは通常のDIPの数え方だと16番ピンに相当します。また、18番ピンは通常のDIPの数え方だと5番ピンに相当します。
そしてTWELITEはFT232RLとシリアルで接続します。ESP8266とFT232RLをPCのUSB端子に接続します。
ESP8266側のプログラムは前々回のプログラムをそのまま使います。動作は、ESP8266が起動すると2022年11月5日10時0分0秒にRTCを設定。アラームはその1分後にかかるように設定しています。50秒間カウントするとESP8266はディープスリープします。
RTCは起動から1分後にアラームを出してINT端子をLowにします。
今回はTWELITE側のプログラムをいじってINT端子を監視して、LowになったらESP8266を再起動するシグナルを出します。RTCのINT端子はTWELITEのDIO13に接続しています。ESP8266のRST端子はTWELITEのDIO18に接続しています。
TWELITEのプログラムはBME280を動かしたときのプログラムをベースに書き換えました。
変更点だけを書きます。
まず、struct SHTC3{...の部分、つまりセンサーを制御するルーチンの一群ですが、今回はセンサーを繋いでいないので本当は全部不要なのですが、センサーにアクセスしに行く部分だけコメントアウトしています。
まず、bool setup(uint16_t &i15Temp, uint16_t &i15Humd) {...の所の下記の部分をコメントアウト。
/* if (auto&& wrt = Wire.get_writer(I2C_ADDR)) { wrt << 0xF4; // register address wrt << ctrl_meas_reg; // register data } else { return false; } //return true; if (auto&& wrt = Wire.get_writer(I2C_ADDR)) { wrt << 0xF5; // register address wrt << config_reg; // register data } else { return false; } delay(1000); //get compensation data if (auto&& wrt = Wire.get_writer(I2C_ADDR)) { wrt << 0x88; //register address } else { return false; } if (auto&& rdr = Wire.get_reader(I2C_ADDR, 6)) { rdr >> dig_T1tempL; rdr >> dig_T1tempH; rdr >> dig_T2tempL; rdr >> dig_T2tempH; rdr >> dig_T3tempL; rdr >> dig_T3tempH; } else { return false; } dig_T1 = uint16_t(dig_T1tempH<<8)|dig_T1tempL; dig_T2 = uint16_t(dig_T2tempH<<8)|dig_T2tempL; dig_T3 = uint16_t(dig_T3tempH<<8)|dig_T3tempL; i15Temp = dig_T1; i15Humd = dig_T2; ctrl_meas_reg = ctrl_meas_reg | 1; //set one shot mode */
続いて、セットアップの部分、void setup(){...以下の所に、ピンモードの設定を行う2行を追加。
/*** setup procedure (run once at cold boot) */ void setup() { /*** SETUP section */ pinMode(PIN_DIGITAL::DIO18, OUTPUT_INIT_HIGH); pinMode(PIN_DIGITAL::DIO13, INPUT_PULLUP);
18番ピンを出力にして、13番ピンを入力にしています。18番ピンの出力はESP8266のRST端子につながっていますので、デフォルトをHIGHにしています。また、13番ピンはRTC-8564のINT端子とつながっていますが、INT端子はオープンドレインのためTWELITE側でプルアップをしています。
ピン番号の指定ですが、ACT0のLチカのサンプルではピン番号の指定はpinMode(18, OUTPUT)のようにただの番号で指定していますが、これだとコンパイル時にエラーになるらしく、TweliteStageが落ちてしまうので、インタラクティブモードの判定に使っている部分の記述に倣って、PIN_DIGITAL::DIO18のようにしています。APIを読んでも数字で指定できるように読めるのですが、なぜだかよくわかりません。とりあえずこの記述で動いているのでまあ良しとしています。
それから、同じくvoid setup(){..中のセンサーのセットアップをする部分を下記のようにコメントアウト。
// setup sensor device /* sensor_device.setup(sensor.i15temp,sensor.i15humid); Serial << format(" : T1temp= %04x" ,sensor.i15temp) << mwx::crlf; Serial << format(" : T2temp=%04x" ,sensor.i15humid) << mwx::crlf; //Serial.flush(); */
そして、TWELITEがスリープから目覚めたときに実行されるvoid wakeup(){...の部分に、RTCのINT端子の状態を判定して、LOWなら、ESP8266をリセットする処理を入れています。if(digitalRead(... 以下がその部分です。一応シリアルにメッセージを出力する文も追加しています。
// wakeup procedure void wakeup() { Serial << mwx::crlf << "--- TEMP&HUMID:" << FOURCHARS << " wake up ---" << mwx::crlf << "..start sensor capture again." << mwx::crlf; if (digitalRead(PIN_DIGITAL::DIO13) == PIN_STATE::LOW) { digitalWrite(18, LOW); delay(100); digitalWrite(18, HIGH); Serial << mwx::crlf << "--- RTCC Alarm ---" << mwx::crlf; } }
続いて、ループ関数の中ですが、
case STATE::TX、つまり無線でデータを送信する部分は、初めの一行のstep.next(STATE::GO_SLEEP); を除いてすべてコメントアウトして、無線送信をキャンセルしてすぐにスリープするようにしています。
case STATE::TX: step.next(STATE::GO_SLEEP); // set default next state (for error handling.) /* // get new packet instance. if (auto&& pkt = the_twelite.network.use<NWK_SIMPLE>().prepare_tx_packet()) { // set tx packet behavior pkt << tx_addr(0x00) // 0..0xFF (LID 0:parent, FE:child w/ no id, FF:LID broad cast), 0x8XXXXXXX (long address) << tx_retry(0x1) // set retry (0x1 send two times in total) << tx_packet_delay(0, 0, 2); // send packet w/ delay // prepare packet payload pack_bytes(pkt.get_payload() // set payload data objects. , make_pair(FOURCHARS, 4) // just to see packet identification, you can design in any. , uint16_t(sensor.i16temp) //, uint16_t(sensor.i16humid) ); // do transmit MWX_APIRET ret = pkt.transmit(); Serial << "..transmit request by id = " << int(ret.get_value()) << '.' << mwx::crlf << mwx::flush; if (ret) { step.clear_flag(); // waiting for flag is set. step.set_timeout(100); // set timeout step.next(STATE::TX_WAIT_COMP); } } */
変更点は以上です。
これで、TWELITEがスリープから目覚めたときにINT端子がLOWになっていたらESP8266をリセットして再起動がかかります。