SSブログ

SPRESENSE で DeepSleep から GPS をホットスタート! [SPRESENSE]

年明けはじめてのSPRESENSEネタです。SPRESENSEはいろいろ機能が多いので、一通り試すだけでもなかなか終わりません。今回は低消費電力の切り札”DeepSleep”を試してみました。

DSC_0875s.jpg


せっかくなら実用的なものをと思い、GPSとの組み合わせてスケッチを書いてみました。クロックも32MHzにして低消費電力にしています。


#include <GNSS.h>
#include <LowPower.h>
#include <RTC.h>

static SpGnss Gnss;

void setup()
{
  int resut;
  
  Serial.begin(115200);
  RTC.begin();

  LowPower.begin();
  LowPower.clockMode(CLOCK_MODE_32MHz);
  bootcause_e bc = LowPower.bootCause(); /* get boot cause */

  sleep(3);  
  Gnss.begin();
  Gnss.select(GPS); 
  Gnss.select(GLONASS); 
  Gnss.select(QZ_L1CA); 
  Gnss.select(QZ_L1S);
  
  if ((bc == POR_SUPPLY) || (bc == POR_NORMAL)) {
    Serial.println("Power on reset");
    Gnss.start(COLD_START);
  } else {
    Serial.println("Wakeup from deep sleep");
    RtcTime now = RTC.getTime();
    // Print the current clock
    printf("%04d/%02d/%02d %02d:%02d:%02d\n",
           now.year(), now.month(), now.day(),
           now.hour(), now.minute(), now.second());

    SpGnssTime gnss_time;
    gnss_time.year = now.year();
    gnss_time.month = now.month();
    gnss_time.day = now.day();
    gnss_time.hour = now.hour();
    gnss_time.minute = now.minute();
    gnss_time.sec = now.second();
    gnss_time.usec = now.nsec() / 1000;
    Gnss.setTime(&gnss_time);
    Gnss.start(HOT_START);
  }

}

void loop()
{
  if (!Gnss.waitUpdate(-1)) return;

  SpNavData NavData;
  Gnss.getNavData(&NavData);
  
  /* print satellites count */
  Serial.print("numSat: " + String(NavData.numSatellites) + " ");

  /* update RTC time */
  RtcTime gps_time(NavData.time.year
                 , NavData.time.month
                 , NavData.time.day
                 , NavData.time.hour
                 , NavData.time.minute
                 , NavData.time.sec
                 , NavData.time.usec * 1000 /* RtcTime requires nsec */);

  Serial.print(String(gps_time.year())   + "/" 
             + String(gps_time.month())  + "/" 
             + String(gps_time.day())    + " "
             + String(gps_time.hour())   + ":"
             + String(gps_time.minute()) + ":"
             + String(gps_time.second()) + " ");

  /* When time is different more than 1 sec, update RTC time */
  if (abs(RTC.getTime() - gps_time) >= 1) {
    RTC.setTime(gps_time);
    Serial.print(" * Updated RTC time * ");
  }
  
  /* print position data */
  if (NavData.posFixMode == FixInvalid && NavData.posDataExist == 0) {
    Serial.print("No Position");
  } else {
    static int g_loop = 0;
    Serial.print("Lat=" + String(NavData.latitude, 6));
    Serial.print(", Lon=" + String(NavData.longitude, 6));
    
    unsigned long passed_time;
    Serial.println("");
    passed_time = millis();
    Serial.println("POSITION FIXED TIME: " + String(passed_time));

    if (g_loop > 10) {
      // Go to deep sleep during about 60 seconds
      Gnss.saveEphemeris();
      Gnss.stop();
      Gnss.end();
      passed_time = millis();
      Serial.println("Go to deep sleep... " + String(passed_time));
      LowPower.deepSleep(60);
    }
    ++g_loop;
  }
  Serial.println("");
}




このスケッチの流れは次のようになっています。

setup 関数内
(1)LowPower.bootCause() で起動要因を取得
(2)電源投入直後の場合は、Gnss エンジンを COLD_START
(3)DeepSleepからの復帰の場合は、RTCから時間を取得、設定したら、
   Gnss エンジンを HOT_STARTします。
   Gnss エンジンは、保存されている衛星情報(Ephemeris)を読み込み、
   現在時刻を参照して、衛星位置を推測して素早く衛星を補足します。(恐らく)

loop 関数内
(1)位置情報を取得します
(2)RTCの時刻と衛星の時刻が1秒以上違いがあったら、RTC時刻を更新します
(3)10回(10秒間)位置情報を取得したら、
   衛星情報(Ephemeris)を保存して、Gnssエンジンを停止します。
   そのあと、60秒間の DeepSleep をセットします。


動作させた際のログは次のようになりました。

Power on reset
numSat: 0 1980/1/6 0:0:1  * Updated RTC time * No Position
numSat: 4 1980/1/6 0:0:2 No Position
... snip ...
numSat: 5 2020/1/26 9:58:1  * Updated RTC time * Lat=3x.xxxxxx, Lon=13x.xxxxxx
POSITION FIXED TIME: 36045

numSat: 5 2020/1/26 9:58:2 Lat=3x.xxxxxx, Lon=13x.xxxxxx
POSITION FIXED TIME: 36059

numSat: 5 2020/1/26 9:58:3 Lat=3x.xxxxxx, Lon=13x.xxxxxx

... snip ...

numSat: 5 2020/1/26 9:58:12 Lat=3x.xxxxxx, Lon=13x.xxxxxx
POSITION FIXED TIME: 46058
Go to deep sleep... 46526
Wakeup from deep sleep
2020/01/26 09:59:18
numSat: 5 2020/1/26 9:59:21 Lat=3x.xxxxxx, Lon=13x.xxxxxx
POSITION FIXED TIME: 8062

numSat: 5 2020/1/26 9:59:22 Lat=3x.xxxxxx, Lon=13x.xxxxxx
POSITION FIXED TIME: 9062

numSat: 5 2020/1/26 9:59:23 Lat=3x.xxxxxx, Lon=13x.xxxxxx
POSITION FIXED TIME: 10062

... snip ...

numSat: 5 2020/1/26 9:59:32 Lat=3x.xxxxxx, Lon=13x.xxxxxx
POSITION FIXED TIME: 19439
Go to deep sleep... 19958
Wakeup from deep sleep
2020/01/26 10:00:39
numSat: 5 2020/1/26 10:0:42 Lat=3x.xxxxxx, Lon=13x.xxxxxx
POSITION FIXED TIME: 8063

numSat: 5 2020/1/26 10:0:43 Lat=3x.xxxxxx, Lon=13x.xxxxxx
POSITION FIXED TIME: 9063

... snip ...

numSat: 6 2020/1/26 10:0:53 Lat=3x.xxxxxx, Lon=13x.xxxxxx
POSITION FIXED TIME: 19063
Go to deep sleep... 19577
Wakeup from deep sleep
2020/01/26 10:02:00
numSat: 5 2020/1/26 10:2:3 Lat=3x.xxxxxx, Lon=13x.xxxxxx
POSITION FIXED TIME: 8062



測定するまでの時間にばらつきはありますが、きちんとディープスリープが動いているようです。これで電力は大幅に削減できそうです。肝心のディープスリープの電力はスタックオーバーフローで次のような議論がありました。


Sony Spresense Deep Sleepでの電力
https://ja.stackoverflow.com/questions/55366/sony-spresense-deep-sleep%e3%81%a7%e3%81%ae%e9%9b%bb%e5%8a%9b


μAレベルまで落とせるようですが、工作必要ですね。さて、5000円をおじゃんにする覚悟で試してみるか。悩む…
(´-ω-`)


関連記事
SPRESENSE の Low Power ライブラリをバッテリー給電で試してみた!
https://makers-with-myson.blog.ss-blog.jp/2019-12-08

SPRESENSE の Low Power ライブラリをUSB給電で試してみた!
https://makers-with-myson.blog.ss-blog.jp/2019-12-01

SPRESENSE の RTC をGPS 時計に設定して時報アプリを作ってみた!
https://makers-with-myson.blog.ss-blog.jp/2019-11-24

SPRESENSE のNMEA 出力をNMEAモニターで確認してみた!
https://makers-with-myson.blog.ss-blog.jp/2019-11-17









nice!(26)  コメント(0) 
共通テーマ:趣味・カルチャー

nice! 26

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。