Spresenseに実装されているGPSで準天頂衛星システム「みちびき」(QZSS(Quasi-Zenith Satellite System))を捕捉します。「GPSチュートリアル」に従って、Arduino IDEを用いてコードを作成します。
準天頂衛星システム「みちびき」
みちびきの準天頂軌道は、南北非対称の「8の字軌道」になり、北半球に約13時間、南半球に約11時間留まり、日本付近に長く留まります。( 技術情報|みちびき(準天頂衛星システム:QZSS)公式サイト – 内閣府から引用)
準天頂衛星システム「みちびき」の衛星運用状況を次に示します。
コードの「satType 」には
- PNTサービス:QZSS_L1CA
- SLASサービス:QZSS_L1S
と設定します。
Spresenseに実装されているGPS
SPRESENSEのGNSS Domainは、GPS/GLONASS/QZSSに対応し、専用のGNSS受信回路から得た人工衛星の情報を取得、到達する時刻情報を活用し人工衛生のズレを推測、最後に緯度経度情報と時刻情報を推定します。
- 衛星測位サービス L1C/A
- サブメータ級測位補強サービス L1S
一般の信号を、みちびきも出力しています。信号の元が増えるので、精度が良くなります。誤差10m程度
L1C/Aと同じ信号らしいので、機器の対応はしやすい様です。誤差1m以下。
サンプルコード「gnss 」でのGPSデータ取得
Arduino IDE のスケッチ例から次の手順でコードを取得してGPSデータを取得します。
メニュー「ファイル」から→ 「スケッチ例」 →「 GNSS」 → 「gnss」と選択してスケッチを開きます。
取得したスケッチを次のように変更します。
- 24行目でsatType を eSatGpsQz1cQz1S へ変更して、準天頂衛星システム「みちびき」からのデータを取得します。
- 10-20行目にParamSatで設定できるパラメータとその意味を示します。
- 36-65行目にシリアルモニタに表示される衛星タイプを示します。
gnss.ino
・・・ static SpGnss Gnss; /**< SpGnss object */ /** * @enum ParamSat * @brief Satellite system */ enum ParamSat { eSatGps, /**< GPS World wide coverage */ eSatGlonass, /**< GLONASS World wide coverage */ eSatGpsSbas, /**< GPS+SBAS North America */ eSatGpsGlonass, /**< GPS+Glonass World wide coverage */ eSatGpsBeidou, /**< GPS+BeiDou World wide coverage */ eSatGpsGalileo, /**< GPS+Galileo World wide coverage */ eSatGpsQz1c, /**< GPS+QZSS_L1CA East Asia & Oceania */ eSatGpsGlonassQz1c, /**< GPS+Glonass+QZSS_L1CA East Asia & Oceania */ eSatGpsBeidouQz1c, /**< GPS+BeiDou+QZSS_L1CA East Asia & Oceania */ eSatGpsGalileoQz1c, /**< GPS+Galileo+QZSS_L1CA East Asia & Oceania */ eSatGpsQz1cQz1S, /**< GPS+QZSS_L1CA+QZSS_L1S Japan */ }; /* Set this parameter depending on your current region. */ static enum ParamSat satType = eSatGpsQz1cQz1S ; /** * @brief Turn on / off the LED0 for CPU active notification. */ ・・・ /* Get satellite type. */ /* Keep it to three letters. */ switch (sattype) { case GPS: pType = "GPS"; break; case GLONASS: pType = "GLN"; break; case QZ_L1CA: pType = "QCA"; break; case SBAS: pType = "SBA"; break; case QZ_L1S: pType = "Q1S"; break; case BEIDOU: pType = "BDS"; break; case GALILEO: pType = "GAL"; break; default: pType = "UKN"; break; } /* Get print conditions. */ ・・・
作成したコードをSPRESENSEに書き込み、実行します。次のようにGPSデータがシリアルモニタ表示されます。
・・・ 17:47:00.797 -> numSatellites: 7 17:47:00.797 -> [ 0] Type:GPS, Id:10, Elv:52, Azm:298, CN0:40.119999 17:47:00.797 -> [ 1] Type:GPS, Id:15, Elv: 0, Azm: 0, CN0:20.160000 17:47:00.797 -> [ 2] Type:GPS, Id:25, Elv:36, Azm:182, CN0:15.969999 17:47:00.797 -> [ 3] Type:GPS, Id:32, Elv:23, Azm:304, CN0:33.779999 17:47:00.797 -> [ 4] Type:Q1S, Id:186, Elv:68, Azm:207, CN0:43.090000 17:47:00.844 -> [ 5] Type:QCA, Id:194, Elv:53, Azm:164, CN0:32.360001 17:47:00.844 -> [ 6] Type:QCA, Id:196, Elv:68, Azm:207, CN0:40.489998 17:47:00.844 -> 2022/09/10 08:47:00.000684, numSat: 7, Fix, Lat=xx, Lon=xx 17:47:01.778 -> 2022/09/10 08:47:01.000675, numSat: 7, Fix, Lat=xx, Lon=xxx 17:47:02.808 -> 2022/09/10 08:47:02.000698, numSat: 7, Fix, Lat=xx, Lon=xx 17:47:03.792 -> 2022/09/10 08:47:03.000687, numSat: 7, Fix, Lat=xx, Lon=xx 17:47:04.820 -> 2022/09/10 08:47:04.000673, numSat: 7, Fix, Lat=xx, Lon=xx ・・・
次のみちびきの衛星が表示されています。
- Type:Q1S, Id:186
- Type:QCA, Id:194
- Type:QCA, Id:196
SpresenseのGPSでNMEA センテンスの出力
GPS受信機で一般的に使用される NMEA0183 形式に従った データをシリアルモニタに出力します。「2.5. NMEA センテンスを出力する」を参考にして次のようにコードを作成します。
- 文字列に変換されたNMEA センテンスはシリアルモニタに表示するために9行目の「outnmea」関数を呼び出します。従って、パラメータで渡された文字列を解析すれば、物理的なフォーマットでシリアルモニタに表示できます。
- 22-26行目で使用する衛星システムを選択します。
- 39行目でシリアルモニタに表示するNMEA センテンスします。GGA+GSA+GSVを選択します。詳細については、「 NMEA マスク値について」に示します。
SpresenseNMEA.ino
・・・ static int outbin(char *buf, uint32_t len) { return len; } static int outnmea(char *buf) { //buf = "$GPGGA,234356.00,3525.9459,N,13938.7785,E,2,09,1.1,36.1,M,39.2,M,,*52"; //GPS_datareceiveNMEA(buf,NMEA_SENTENCE_MAX_LEN); return printf("%s", buf); } void setup() { ・・・ /* select satellite system */ Gnss.select(GPS); //Gnss.select(GLONASS); //Gnss.select(SBAS); Gnss.select(QZ_L1CA); // Michibiki complement Gnss.select(QZ_L1S); // Michibiki augmentation(Valid only in Japan) ・・・ /* set interval */ Gnss.setInterval(1); if (Gnss.start(COLD_START)) { Serial.println("start error!"); } /* use NMEA library */ NMEA_InitMask(); NMEA_SetMask(0x0d); // only GGA+GSA+GSV //NMEA_SetMask(0x5); // only GGA+GSA //NMEA_SetMask(0x4000); // only QZQSM NMEA_OUTPUT_CB funcs; funcs.bufReq = reqbuf; funcs.out = outnmea; funcs.outBin = outbin; funcs.bufFree = freebuf; NMEA_RegistOutputFunc(&funcs); } void loop() { /* Check update. */ if (Gnss.waitUpdate(1000)) { /* Output NMEA */ Gnss.getPositionData(PositionData); NMEA_Output(&(((GnssPositionData*)PositionData)->Data)); } }
作成したコードをSPRESENSEに書き込み、実行します。次のようにデータがシリアルモニタ表示されます。
・・・ 17:41:30.828 -> $GNGSA,A,3,10,15,,,,,,,,,,,12.0,4.6,11.0,1*35 17:41:30.828 -> $GNGSA,A,3,02,04,,,,,,,,,,,12.0,4.6,11.0,5*32 17:41:30.828 -> $GPGSV,2,1,06,10,50,301,35,13,04,098,,15,35,102,25,18,06,212,,0*6F 17:41:30.828 -> $GPGSV,2,2,06,22,00,291,,23,68,239,,,,,,,,,,0*6E 17:41:30.828 -> $GQGSV,1,1,03,58,69,208,42,02,52,164,35,04,69,208,40,,,,,0*5C 17:41:31.810 -> $GPGGA,084131.00,3525.9498,N,13938.7724,E,2,04,4.7,26.8,M,39.2,M,,*58 ・・・
次のNMEA「$GQGSV」は、??です。みちびき衛星「02」,「04」は、PRNでなくSVNで示しているように思います。それ以前のデータ群のフォーマットが「xxGSV」と異なっています。
$GQGSV,1,1,03,58,69,208,42, 02,52,164,35, 04,69,208,40,,,,,0*5C
NMEA マスク値について
NMEA 0183 (ver 4.00) 規格で定義されている NMEA センテンスのうち、 出力する NMEA センテンスをビットマスク値を NMEA_SetMask() 関数の引数に指定します。 初期状態では NMEA マスクには 0xef が設定されています。
NMEA | Bit | Description | |
---|---|---|---|
$xxGGA | 0 | 時刻、緯度経度、標高、測位状態、DGPS基地局番号などの基本情報 | |
$xxGLL | 1 | 時刻、緯度経度、測位状態などGGAの簡易版 | |
$xxGSA | 2 | 衛星毎の使用不使用、DOP値 | |
$xxGSV | 3 | 可視衛星の衛星番号、仰角、方位角、信号強度 | |
$xxGNS | 4 | 時刻、緯度経度、測位状態 | |
$xxRMC | 5 | 時刻、緯度経度、速度、時期偏差 | |
$xxVTG | 6 | 移動速度に関する詳細情報 | |
$xxZDA | 7 | 年月日を含む時刻情報 | |
$QZQSM | 14 | 災害危機管理通報サービスメッセージ(QZSS独自センテンス) |
xx は、以下を表します。
GP:GPS衛星で測位している場合
GL:GLONASS衛星で測位している場合
GZ:QZS衛星で測位している場合
BD:BeiDou衛星で測位している場合
GA:Galileo衛星で測位している場合
GN:複数の衛星システムを利用して測位している場合