So-net無料ブログ作成
前の5件 | -

SPRESENSE の Low Power ライブラリをバッテリー給電で試してみた! [SPRESENSE]

前回はUSB給電で試してみたので、今回はバッテリー給電を試してみました。USBの場合は、電圧変換が必要なので、そこで若干ロスが発生するためバッテリー給電なら、さらに消費電力が下がるのではないかと考えた次第です。

バッテリーには、だいぶ前にドローン検討用に購入した1セルのLiPoバッテリーを使ってみます。


DSC_0881.JPG


バッテリーを装着するにはバッテリー端子にピンをつけなければなりません。最初は給電できなくて焦りましたが、GNDのハンダがきちんとのっていなかったのが原因でした。

GNDはかなりしっかりしていて、熱が伝わりにくく、ハンダのノリが悪くて四苦八苦したのですが、なんとかつけることができました。


DSC_0875s.jpg


電流測定には、前回同様デジボルを電源ラインの間に入れて測定しました。安全のため配線の途中にスイッチをつけておきました。


DSC_0879.JPG


前回と同じスケッチで測定をしてみました。

#include <LowPower.h>

//#define LOWPOWER_32MHz
//#define LOWPOWER_8MHz


void setup()
{
  LowPower.begin();
#ifdef LOWPOWER_32MHz
  LowPower.clockMode(CLOCK_MODE_32MHz);
#elif defined(LOWPOWER_8MHz)
  LowPower.clockMode(CLOCK_MODE_8MHz);
#endif
}

void loop()
{
  /* do nothing */
}



測定結果です。156MHz は USB給電よりも消費電流が高い結果となりました。しかし、32MHz以下では、想定通りUSB給電のときよりも若干消費電力が低い結果が出てきました。


周波数消費電流
156MHz9.0 mA
32MHz3.7 mA
8MHz3.1 mA



次に、一秒のsleep を入れて消費電力がどう変化するか見てみました。シリアル出力は意味がないので省いています。


#include <LowPower.h>

//#define LOWPOWER_32MHz
//#define LOWPOWER_8MHz


void setup()
{
  LowPower.begin();
#ifdef LOWPOWER_32MHz
  LowPower.clockMode(CLOCK_MODE_32MHz);
#elif defined(LOWPOWER_8MHz)
  LowPower.clockMode(CLOCK_MODE_8MHz);
#endif
}

void loop()
{
  sleep(1);
}



こちらも 156MHz では若干高い値となっていますが、32MHz以下ではUSB給電よりもよい値が出ています。


周波数消費電流
156MHz7.6 mA
32MHz3.6 mA
8MHz3.0 mA



LED点滅も試してみました。


#include <LowPower.h>

//#define LOWPOWER_32MHz
//#define LOWPOWER_8MHz


void setup()
{
  LowPower.begin();
#ifdef LOWPOWER_32MHz
  LowPower.clockMode(CLOCK_MODE_32MHz);
#elif defined(LOWPOWER_8MHz)
  LowPower.clockMode(CLOCK_MODE_8MHz);
#endif
}

void loop()
{
  static int led_switch = HIGH;
  sleep(1);
  led_switch = (led_switch == HIGH) ? LOW : HIGH;
  digitalWrite(LED0, led_switch);
}



やはりLEDは2mA弱消費してしまいますねぇ。SPRESENSE本体が 十数 mA ~ 数 mA ということを考えると無視できないレベルです。


周波数消費電流(LED無灯)消費電流(LED点灯)
156MHz7.6 mA9.5 mA
32MHz3.6 mA5.6 mA
8MHz3.1 mA5.0 mA



最後に本命のGPS機能を試してみました。前回とは少しコードを変えて測定しやすいように、衛星探索中はLED点灯、捕捉をするとLED消灯するようにしました。


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

//#define LOWPOWER_32MHz
//#define LOWPOWER_8MHz

static SpGnss Gnss;

void setup()
{
  LowPower.begin();
#ifdef LOWPOWER_32MHz
  LowPower.clockMode(CLOCK_MODE_32MHz);
#elif defined(LOWPOWER_8MHz)
  LowPower.clockMode(CLOCK_MODE_8MHz);
#endif

  sleep(3);  
  Gnss.begin();
  Gnss.select(GPS); 
  Gnss.select(GLONASS); 
  Gnss.select(QZ_L1CA); 
  Gnss.select(QZ_L1S);
  Gnss.start(COLD_START);
}

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

  SpNavData NavData;
  Gnss.getNavData(&NavData);

  if (NavData.posFixMode == FixInvalid || NavData.posDataExist == 0) {
 digitalWrite(LED0, HIGH);
  } else {
    digitalWrite(LED0, LOW);
  }
  sleep(1);
}



前回と同じく、バッテリー給電でも 32MHz と 8MHz の大きな差は見られなかったので、GPSは 32MHz で使うのがよさそうですね。長い間の積算をとるとそこそこ差は出てくるのかもしれませんが。


周波数消費電流
156MHz13.0 - 14.5 mA
32MHz5.7 - 6.8 mA
8MHz5.6 - 6.3 mA



今回はがんばってバッテリー用のピンをSPRESENSEにつけてみました!( ー`дー´)キリッ
測定した結果、バッテリー駆動のほうが消費電力という面ではかなり有利という結果が出ました。空ループ時の値を電力値に換算してみました。


周波数USB給電(5.0V)バッテリ給電(3.7V)
156MHz44 mW33 mW
32MHz23 mW13 mW
8MHz20 mW11 mW



32MHz 以下だと消費電力は半減近いです。GPSトラッカーを作るならバッテリ給電が正解ですね!(^^)/~







nice!(16)  コメント(0) 

SPRESENSE の Low Power ライブラリをUSB給電で試してみた! [SPRESENSE]

GPSのトラッカーを作るなら省電力が良いに決まってるよね!ということで、SPRESENSEの Low Power ライブラリを試してみました。今回はUSB給電でメインボードのみで測定してみました。

最初、簡易USB測定器で測ってみたのですが、なんと0.00Aにしかならず測定不能!さすが低消費電力をウリにしているSPRESENSEというべきか。うーん、困った。


DSC_0885.jpg


で、手持ちのデジボルを見たら、精度はいかほどか不明ですが、μAレベルまで測れそう。


DSC_1000.jpg


ということで、USBケーブルをバラシて、USBの電源ラインの間にデジボルを挟んで電流を測定することにしました。こんな感じです。


DSC_0890.jpg


最初は基本性能から測定ということで、次のような単純なスケッチでを試してみました。

#include <LowPower.h>

//#define LOWPOWER_32MHz
//#define LOWPOWER_8MHz


void setup()
{
  LowPower.begin();
#ifdef LOWPOWER_32MHz
  LowPower.clockMode(CLOCK_MODE_32MHz);
#elif defined(LOWPOWER_8MHz)
  LowPower.clockMode(CLOCK_MODE_8MHz);
#endif
}

void loop()
{
  /* do nothing */
}


測定結果です。測定方法がかなりラフなので、誤差はかなりあると思いますが、周波数の設定を下げると消費電流も下がるので傾向を見ることはできそうです。

周波数消費電流
156MHz8.8 mA
32MHz4.6 mA
8MHz4.0 mA


次に、一秒ごとにシリアルを出力するスケッチを試してみました。sleep を入れて消費電力がどう変化するか、また、シリアル通信の消費電力を見るのが目的です。

#include <LowPower.h>

//#define LOWPOWER_32MHz
//#define LOWPOWER_8MHz


void setup()
{
  Serial.begin(115200);
  LowPower.begin();
#ifdef LOWPOWER_32MHz
  LowPower.clockMode(CLOCK_MODE_32MHz);
#elif defined(LOWPOWER_8MHz)
  LowPower.clockMode(CLOCK_MODE_8MHz);
#endif
}

void loop()
{
  sleep(1);
  Serial.print(".");
}


まずコンソールを開かない状態、つまりシリアル通信しない状態で電流値がどうなるか確認しました。

コンソールを開かない状態(シリアル通信なし)
周波数消費電流
156MHz7.3 mA
32MHz4.4 mA
8MHz4.0 mA


sleep も省電力に効くようですね!8MHz になるとほぼ誤差かな??

次に、シリアル通信の消費電力を見るために、PCのコンソール(Arduino IDE の Serial Monitor)を開いて測定した数値がこちら。

コンソールを開いた状態(シリアル通信あり)
周波数消費電流
156MHz16.2 mA
32MHz13.4 mA
8MHz12.9 mA


やなりシリアル通信をするとかなり電流を食いますね。+9 mA といったところです。GPSを使う場合、ATコマンドで他のホストマイコンと通信するのは消費電力面ではマイナスですね。

しかし、デバッグするには何か手段が必要ということで、LEDでどれだけ消費するか試してみました。次のスケッチで電流値がどうなるか見てみました。

#include <LowPower.h>

//#define LOWPOWER_32MHz
//#define LOWPOWER_8MHz


void setup()
{
  Serial.begin(115200);
  LowPower.begin();
#ifdef LOWPOWER_32MHz
  LowPower.clockMode(CLOCK_MODE_32MHz);
#elif defined(LOWPOWER_8MHz)
  LowPower.clockMode(CLOCK_MODE_8MHz);
#endif
}

void loop()
{
  static int led_switch = HIGH;
  sleep(1);
  led_switch = (led_switch == HIGH) ? LOW : HIGH;
  digitalWrite(LED0, led_switch);
}


LED点灯のテスト
周波数消費電流(LED無灯)消費電流(LED点灯)
156MHz7.3 mA9.2 mA
32MHz4.4 mA6.2 mA
8MHz4.0 mA5.9 mA


LED一つにだいたい 2mA 程度消費するようです。結構消費しますね…。

ということで、いよいよ GPS を動かしてみようと思います。次のスケッチを試してみました。シリアル通信なしで測定したいので、衛星を補足したことを知るためにLEDを点灯するようにしました。

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

//#define LOWPOWER_32MHz
//#define LOWPOWER_8MHz

static SpGnss Gnss;

void setup()
{
  Serial.begin(115200);

  LowPower.begin();
#ifdef LOWPOWER_32MHz
  LowPower.clockMode(CLOCK_MODE_32MHz);
#elif defined(LOWPOWER_8MHz)
  LowPower.clockMode(CLOCK_MODE_8MHz);
#endif

  sleep(3);  
  Gnss.begin();
  Gnss.select(GPS); 
  Gnss.select(GLONASS); 
  Gnss.select(QZ_L1CA); 
  Gnss.select(QZ_L1S);
  Gnss.start(COLD_START);
  Serial.println("GNSS is starting");
}

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

  SpNavData NavData;
  Gnss.getNavData(&NavData);

  if (NavData.posFixMode == FixInvalid || NavData.posDataExist == 0) {
    Serial.print("No Position");
  } else {
    static int led_switch = HIGH;
    sleep(1);
    led_switch = (led_switch == HIGH) ? LOW : HIGH;
    digitalWrite(LED0, led_switch);
    Serial.print("Lat=" + String(NavData.latitude, 6) + ", ");
    Serial.print("Lon=" + String(NavData.longitude, 6));
  }
  Serial.println("");
}


GNSS消費電力テスト(シリアル通信なし、LED無灯時、衛星補足時)
周波数消費電流(LED無灯時)
156MHz12.3 - 15.5 mA
32MHz6.9 - 9.0 mA
8MHz7.2 - 8.9 mA



GNSSを使っているときは、衛星の配置や受信環境に左右されるのか、電流値がかなりバラつきますが、8MHz と 32MHz については思ったほど差が出ませんでした。

GNSSを使うときは、32MHz がよさそうです。実験はしてみるものですね。
(^^)/~








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

SPRESENSE の RTC をGPS 時計に設定して時報アプリを作ってみた! [SPRESENSE]

SPRESENSEはGPSを受信できるので、正確な時間を取得できます。それならその時間をRTCに設定してみて、時報アプリを作れないかなと思い作ってみました。

DSC_0001_BURST20191019170915259.JPG


時報の音源は次のURLの「Sine波 予報音3回」のMP3ファイルを拝借させていただきました。

時報音の音源
https://ultra.zone/jihou.ja


スケッチは、メインループと "pthread" で構成されています。メインループはGPS時間を取得をしてRTCを更新し、"pthread" は RTCの時間を監視して1分毎に時報を鳴らすというものです。

もともとは、task_create でスレッドを生成していたのですが、なぜかPANICが起きるので pthread に置きかえました。^^;

#include <GNSS.h>
#include <RTC.h>
#include <SDHCI.h>
#include <Audio.h>
#include <pthread.h>

static SDClass theSD;
static SpGnss Gnss; 
AudioClass *theAudio = AudioClass::getInstance();

#define JST_IN_SECONDS  (9 * 60 * 60);

static File myFile;
static bool bTimeFixed = false;

static void time_signal_thread(void *arg) {

  while(true) {
    usleep(100000);
    if (bTimeFixed == false) continue;
  
    RtcTime now = RTC.getTime();
    if (now.second() != 56) continue;

    myFile = theSD.open("jihou.mp3");
    if (!myFile) {
      Serial.println("File open error");
      while(1);
    }

    theAudio->writeFrames(AudioClass::Player0, myFile);
    theAudio->setVolume(-60);
    theAudio->startPlayer(AudioClass::Player0);
    while (true) {
      sleep(1);  //  To ensure not re-entering the audio routine. 
      int err = theAudio->writeFrames(AudioClass::Player0, myFile);
      if (err == AUDIOLIB_ECODE_FILEEND) {
        theAudio->stopPlayer(AudioClass::Player0);
        myFile.close();
        break;
      }
    }
  }

  return 0;
}

void setup() {
  int result;

  Serial.begin(115200);
  theSD.begin();
  sleep(3);  /* Wait HW initialization done. */
  
  theAudio->begin();
  theAudio->setRenderingClockMode(AS_CLKMODE_NORMAL);
  theAudio->setPlayerMode(AS_SETPLAYER_OUTPUTDEVICE_SPHP, AS_SP_DRV_MODE_LINEOUT);
  theAudio->initPlayer(AudioClass::Player0, AS_CODECTYPE_MP3, "/mnt/sd0/BIN"
                     , AS_SAMPLINGRATE_AUTO, AS_CHANNEL_MONO);
  Serial.println("Audio initialized");
  
  Gnss.begin();
  Gnss.select(GPS);
  Gnss.start(COLD_START);
  Serial.println("Gnss start...");

  int policy;
  struct sched_param param;
  pthread_t m_pid = pthread_self();
  pthread_getschedparam(m_pid, &policy, &param);
  Serial.println("Main Priority is : " + String(param.sched_priority));

  pthread_t t_pid;
  pthread_create(&t_pid, NULL, time_signal_thread, NULL);
  param.sched_priority = 130;
  pthread_setschedparam(t_pid, policy, &param);
  Serial.println("time_signal_thread start: " + String(param.sched_priority));
}


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

  SpNavData NavData;
  Gnss.getNavData(&NavData);
  
  Serial.println("numSat: " + String(NavData.numSatellites));

  if (NavData.time.year == 1980) return;
  bTimeFixed = true;
  
  /* Create RTC time */
  RtcTime gtime(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 */);

  gtime += JST_IN_SECONDS; /* convert UTC to JST */

  printf("%04d/%02d/%02d %02d:%02d:%02d\n"
          , gtime.year(), gtime.month(), gtime.day()
          , gtime.hour(), gtime.minute(), gtime.second());
  
  /* When time is different more than 1 sec, update RTC time */
  if (abs(RTC.getTime() - gtime) >= 1) {
    RTC.setTime(gtime);
    Serial.println(" * Updated RTC time * ");
  }
}




わざわざスレッドにしなくてもいいんじゃないかというコードではありますが、スレッドにすることでRTC の効用を少し分かりやすくしてみたつもりです。^^;

SPRESENSEはGPS時刻を取得できるので、複数のカメラ付きSPRESENSEを時刻同期で撮影すれば全球カメラができそうですね。ヘルメットにつけたりしたら面白いかも。
(^^)





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

SPRESENSE のNMEA 出力をNMEAモニターで確認してみた! [徒然日記]

SPRESENSEのNMEA出力が Arduino のスケッチできるようになったので、その出力を解析できるツールを探してみました。せっかくなら”みちびき”も見れたほうがいいなと思って探し出したのがこちら。


NMEA Monitor for windows
http://4river.a.la9.jp/gps/indexj.htm#001


次の記事のスケッチをSPRESENSEのメインボードに書き込み、上記アプリでコンソールを指定すれば、リアルタイムで衛星信号の受信状態を見ることができます。


DSC_0713.JPG
SPRESENSEでArduinoのスケッチでNMEAをシリアル出力してみた!
https://makers-with-myson.blog.ss-blog.jp/2019-11-10


すごく簡単です。実際に受信している状態の画面です。


NMEA_Monitor.png


一番右の「QZGSV」が”みちびき”の信号ですね。このアプリで静止状態での精度を見ることができます。


NMEA_Monitor2.png


まぁ、部屋の中から窓に向けて受信したので、精度はイマイチですねぇ。でも、これでSPRESENSEの衛星受信状態を確認できるようになりました。

GPSの受信状態は刻一刻と変わっていくので、見ているだけでも楽しいですね。
(^^)






タグ:GPS nmea Spresense
nice!(30)  コメント(0) 
共通テーマ:趣味・カルチャー

SPRESENSEでArduinoのスケッチでNMEAをシリアル出力してみた! [SPRESENSE]

SPRESENSEには、実はあまり使ってないのですけどGPSの機能があったります。しかも「みちびき」対応です。最近、Twitterで”みちびき”の災害危険情報を皆さんがデコードをするを見て、私も流行りに乗ってGPSを使ってみることにしました。


DSC_0713.JPG


話は変わりますが、みちびき打上げ用ロゴって、エバンゲリオンの制作スタッフが作ったものなんですね。ブログに貼り付けたいなと思ったのですが、使用についてうるさいことが書いてあったのでやめておきました。


SPRESENSE の Arduino用のライブラリは、便利なAPIは用意しているのですが、GPSの解析アプリ等と連携しようとするとNMEA出力のほうが便利そうです。

そこで、SPRESENSEのGPSの出力を、Arduino を使ってNMEAで出力する方法を探してみました。参考にしたのは、Spresense公式サポートページと、SDKサンプルアプリの「gnss_atcmd」と、Arduino 用のGNSSライブラリの実装です。

いろいろ試行錯誤した結果、以下のスケッチでNMEAをコンソールに出力することができました!最初の情報取得でこけているのは謎ですが、出力ログもマスクを変更することで変更可能です。


#include <GNSS.h>
#include <GNSSPositionData.h>
#include <gpsutils/cxd56_gnss_nmea.h>

static SpGnss Gnss;
static GnssPositionData posdat;
static char nmea_buf[NMEA_SENTENCE_MAX_LEN];

/* output NMEA */
FAR static char *reqbuf(uint16_t size) {
  return size > sizeof(nmea_buf) ? NULL : nmea_buf;
}

static void freebuf(FAR char *buf) {
  // do nothing...
}

static int outnmea(FAR char *buf){
  return Serial.println(buf);
}

static int outbin(FAR char *buf, uint32_t len) {
  return len; // do nothing...
}


void setup() { 

  Serial.begin(115200);

  Gnss.begin();
  Gnss.select(GPS); Gnss.select(QZ_L1CA); Gnss.select(QZ_L1S);
  
  /**
   * Set NMEA sentence 32bit mask
   * - Default value 0x000000ef.
   * |bit |sentence|
   * |:----:|:---:|
   * |bit0|GGA|
   * |bit1|GLL|
   * |bit2|GSA|
   * |bit3|GSV|
   * |bit4|GNS|
   * |bit5|RMC|
   * |bit6|VTG|
   * |bit7|ZDA|
   * |bit14|QZQSM|
   */
  uint32_t mask = 0x000040ff; // set the full mask
  NMEA_OUTPUT_CB funcs;
  
  NMEA_InitMask();
  NMEA_SetMask(mask);
  funcs.bufReq  = reqbuf;
  funcs.out     = outnmea;
  funcs.outBin  = outbin;
  funcs.bufFree = freebuf;
  NMEA_RegistOutputFunc(&funcs);
  
  Serial.println("NMEA initialized");
  
  int ret = Gnss.start(COLD_START);
  if (ret != 0) {
    Serial.println("Gnss start error!");
    while(1);
  }
}

void loop() {
  memset(&posdat, 0, sizeof(posdat));
  Gnss.getPositionData((char*)&posdat);
  NMEA_Output((struct cxd56_gnss_positiondata_s*)&(posdat.Data));
  sleep(1);
}



出力はこんな感じです。詳しい緯度・経度は秘密です!( ー`дー´)

$GPGGA,143132.00,35xx.xxxx,N,139xx.xxxx,E,1,09,1.1,70.6,M,39.1,M,,*53

$GNGLL,35xx.xxxx,N,139xx.xxxx,E,143132.00,A,A*7B

$GNGSA,A,3,08,09,16,21,23,26,27,31,194,,,,1.8,1.1,1.5*1A

$GPGSV,3,1,11,04,15,305,,07,01,318,,08,34,239,31,09,18,293,25*7B

$GPGSV,3,2,11,16,62,015,26,21,32,058,26,23,25,263,28,26,51,067,28*70

$GPGSV,3,3,11,27,70,260,32,31,26,145,32,194,88,077,30,,,,*76

$QZGSV,1,1,01,02,88,077,30,,,,,,,,,,,,*55

$GNGNS,143132.00,35xx.xxxx,N,139xx.xxxx,E,AN,09,1.1,70.6,M,39.1,M,,*68

$GNRMC,143132.00,A,35xx.xxxx,N,139xx.xxxx,E,0.0,14.4,101119,,,A*74

$GNVTG,14.4,T,,M,0.0,N,0.0,K,A*22

$GNZDA,143132.00,10,11,2019,,*75





NMEAの出力の詳細は、次のページで確認できます。

GPSのNMEAフォーマット
https://www.hiramine.com/physicalcomputing/general/gps_nmeaformat.html


”みちびき”の情報はどうしたらええねん?と思っていたら、すでに”みちびき”の災危情報をデコードするためのライブラリを作られている猛者がいました。もちろんSPRESENSE用です。

みちびき災危通報をデコードしてみる
https://qiita.com/baggio/items/497b654cd4ec1bfd74fc


ただ私のコンソール出力に、$QZQSVって、みちびきっぽい出力は出ているけど、でもこれ災危情報の出力じゃないような。$QZQSMって出るときと出ないときがあるのか、そもそも設定出きていないのか?…悩む…。GPSの世界はまだまだ奥が深く難しいなぁ。
σ( ̄ε ̄ )







タグ:GPS nmea Spresense
nice!(27)  コメント(2) 
共通テーマ:趣味・カルチャー
前の5件 | -