QZQSMのデコード
Spresense

概要

みちびき(準天頂衛星システム)が送信する災害・危機管理通報サービス「災危通報」を受信して、内容を表示します。

最近災害が多いので、みちびきが送信している、災危通報を受信してみたいと思い、災危通報を受信できるデバイスを探したところ、SONYが発売しているSpresenseの名前があったので、Spresenseを入手して試してみました。

準備

Spresense Arduino Libraryのインストール

今回は、Spresense Arduino Libraryを利用しました。このため、Spresense Arduino スタートガイドに従い、環境を準備しました。詳細に説明されているので、問題なくインストールすることができました。また、インストール後は、VSCodeからも問題なく利用することができました。

GNSSサンプルプログラムの実行

災危通報を受信する前に、GPSチュートリアルに従い、GNSSのサンプルプログラム(スケッチ例⇒GNSS⇒gnss)を動作させてみました。チュートリアルに記載されていますが、みちびきを利用するため、60行目を、eSatGpsからeSatGpsQz1cQz1Sに変更しました。

60
static enum ParamSat satType =  eSatGpsQz1cQz1S;

プログラムを動かすと、受信している衛星の数などが1秒ごとに表示されます。また、毎分0秒には、各衛星の情報が表示されます。以下は、8個の衛星から情報を取得している状態ですが、災危通報の受信に必要なL1S信号は受信できていません。受信しているときは、「Type:Q1S」と表示されます。

1
2
3
4
5
6
7
8
9
numSatellites: 8
[ 0] Type:GPS, Id: 4, Elv:22, Azm: 44, CN0:17.730000
[ 1] Type:GPS, Id: 5, Elv:27, Azm:  5, CN0:17.309999
[ 2] Type:GPS, Id: 6, Elv:70, Azm: 29, CN0:26.019999
[ 3] Type:GPS, Id: 9, Elv:54, Azm: 70, CN0:29.160000
[ 4] Type:GPS, Id:12, Elv:11, Azm: 26, CN0:5.210000
[ 5] Type:GPS, Id:17, Elv:37, Azm:171, CN0:30.849998
[ 6] Type:GPS, Id:19, Elv:55, Azm:182, CN0:16.410000
[ 7] Type:QCA, Id:195, Elv:67, Azm:197, CN0:20.059999

次は、12個の衛星から情報を取得している状態で、災危通報の受信に必要なL1S信号も受信できています。Elv(仰角)とAzm(方位角)の両方が0なのが気になりますが。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
numSatellites:12
[ 0] Type:GPS, Id: 2, Elv:49, Azm: 63, CN0:20.059999
[ 1] Type:GPS, Id: 4, Elv:19, Azm: 42, CN0:21.859999
[ 2] Type:GPS, Id: 5, Elv:30, Azm:  8, CN0:24.260000
[ 3] Type:GPS, Id: 6, Elv:70, Azm: 42, CN0:25.990000
[ 4] Type:GPS, Id: 7, Elv:12, Azm:119, CN0:25.160000
[ 5] Type:GPS, Id: 9, Elv:52, Azm: 63, CN0:27.939999
[ 6] Type:GPS, Id:12, Elv:10, Azm: 22, CN0:0.000000
[ 7] Type:GPS, Id:17, Elv:32, Azm:171, CN0:16.410000
[ 8] Type:GPS, Id:19, Elv:50, Azm:181, CN0:22.559999
[ 9] Type:GPS, Id:25, Elv: 2, Azm: 50, CN0:0.000000
[10] Type:Q1S, Id:183, Elv: 0, Azm:  0, CN0:22.680000
[11] Type:QCA, Id:195, Elv:65, Azm:197, CN0:0.000000

しばらく眺めていましたが、L1S信号を受信できないことも結構多いようです。室内で受信しているからかもしれません。

実験

災危通報の受信

次に、チュートリアルのQZSS 災危通報を出力するに従い、災危通報を出力させてみました。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
$QZQSM,56,9AADF3D10F0002C3F2587F8B101962082C41A58898B1F4165E1000128E99B90*0A
$QZQSM,56,C6ADF3D1118002D3885A7ECB5002880751022A271000000000000012DAF2FF4*7A
$QZQSM,56,53ADF3D10F0002CBCC5984CB30C1661D2CC445A01CB40616811000130F016E0*79
$QZQSM,56,9AADF3D10F0002C3F2587F8B101962082C41A58898B1F4165E10001369467CC*07
$QZQSM,56,C6ADF3D1118002D3885A7ECB5002880751022A271000000000000011D66B094*07
$QZQSM,56,53ADF3D10F0002CBCC5984CB30C1661D2CC445A01CB40616811000122BF8D64*04
$QZQSM,56,C6ADF3D1118002D3885A7ECB5002880751022A271000000000000012BB61C18*72
$QZQSM,56,53ADF3D10F0002CBCC5984CB30C1661D2CC445A01CB4061681100012E8DEABC*70
$QZQSM,56,9AADF3D10F0002C3F2587F8B101962082C41A58898B1F4165E10001308D5420*72
$QZQSM,56,C6ADF3D1118002D3885A7ECB5002880751022A2710000000000000135CBE044*7F
$QZQSM,56,53ADF3D10F0002CBCC5984CB30C1661D2CC445A01CB4061681100013ADB42D4*7C

仕様書(IS-QZSS-DCR-007)によると、上記の出力は以下の通りです。

Field(フィールド) Value(値) Number of character(文字数)
Message Header(メッセージヘッダ) $QZQSM 6
Field delimiter(区切り文字) , 1
Satellite ID(衛星番号) 55,56,57,61(PRN183,184,185,189) 2
区切り文字 , 1
DC Report Message(災危通報) 63
Field delimiter(区切り文字) * 1
Checksum(チェックサム) 2

上記の出力の場合は、衛星番号が56番となっているので、各国の測位衛星によると、PRN184に対応した、みちびき2号機の電波を受信しているということになります。

災危通報の解析

サンプルプログラムの出力だけでは何のことかわからないので、出力を解析するプログラムを作成しました。

サンプルプログラムでは、災危通報の取得と表示は以下のようになっています。

1
2
3
4
    /* Output QZQSM */
    void *handle;
    if (handle = Gnss.getDCReport()) {
      NMEA_DcReport_Output(handle);

Gnssは、SpGnssクラスの変数です。このクラスは、GNSS.hで定義されています。getDCReport()は、void* SpGnss::getDCReport(void)となっていて、void *を返す関数です。これだけでは何もわからないので、NMEA_DcReport_Output()の方を見てみると、こちらは、gpsutils/cxd56_gnss_nmea.hで、以下のように定義されていました。

1
uint16_t NMEA_DcReport_Output(const struct cxd56_gnss_dcreport_data_s* dcrdat);

struct cxd56_gnss_dcreport_data_sは、gnss_type.hで、以下のように定義されていました。

1
2
3
4
5
6
struct cxd56_gnss_dcreport_data_s
{
  uint8_t sf[CXD56_GNSS_QSM_MSG_BIT_NUM /
              CXD56_GNSS_QSM_NUM_BITS_IN_BYTE + 1]; /* [out] Message body */
  uint8_t svid;                                     /* [out] Satellite id */
};

struct cxd56_gnss_dcreport_data_sのsfメンバーがメッセージの本体のようです。

仕様書を見ながらこの値を解析して表示させた様子が以下です。少し眺めた範囲では、防災気象情報(海上)が多く出てきました。

解析プログラム自身は、とても単純ですが、解析結果に対応する文字列が膨大なものになりました。Spresenseなので問題なく動作しましたが、Arduino Unoだと工夫がいると思います。

2020年9月4日追記

2020年9月の、台風10号に関する情報を受信したところです。被害が出ませんように。

2022年1月16日追記

2022年1月の、トンガの海底火山の噴火に伴う津波警報を受信したところです。被害が出ませんように。

バージョン

Hardware:Spresense
Software:Arduino 1.8.19/Spresense Arduino Library 2.4.0

最終更新日

January 16, 2022

inserted by FC2 system