公開日:2023/11/11
title.png

28th Season


#28-1 緯度を推定してみよう

 今回は、9軸加速度・ジャイロ・磁気センサ(MPU9250モジュール)を使って、現在地の緯度を推定してみよう、と言う挑戦的なテーマです。

地球は磁石

 ご存知の通り、地球🌏は北極をN極、南極をS極とする大きな磁石になっています。
 地球の磁気は一定では、ありません。経時変化があり、場所によっても変動があります。

磁力線

 磁力線を作図する時、一般にS極からN極へ向かう矢印を描きます。
 方位磁石は、この磁力線に沿って北の方角を指し示します。この、方位磁石が指す方向を磁北と呼びます。磁北の方向は、地図上の北から6°(※)程ずれているらしいです。

※地球の磁場には経時変化が有るので、執筆時点で確からしいとされていた値。

 磁力線は三次元ベクタであり、水平成分だけでなく垂直方向にも成分を持っています。

 南極にも北極にも行った事は無いし、一生の内で到達する事は無いでしょうから、確かめることはできませんが、理論上、方位磁石は、北極点では真下、南極点では真上を向き、赤道上では水平となるらしいです。間の北半球では下向き、南半球では上向きのベクタとなります。
 日本は北半球に位置しますので、日本で磁北の方向ベクタを観測すると、下向きのベクタとなります。

 方位磁石を使って磁北の方向ベクタを観測すると、少なくとも、その場所が南半球(上向き)なのか北半球(下向き)なのかを知ることができる、と言う事です。
 磁北ベクタを、もっと精密に測定出来たら、その方向から現在地の緯度を推定できるはず、これがスタートのアイディアです。

※そう言えば昔、オーストラリアに旅行した時、洗面台に溜めた水を流す時の渦の回転方向を見て、南半球を感じ、「おお〜っ」と思った経験があります。磁北を指すコンパスの傾きでも南半球を感じることができるという事については、当時は知らなかったので、試しませんでした。

緯度の推定

 前節で説明した通り、磁北ベクタには、水平方向の成分と、垂直方向の成分があります。
 水平成分の成す角度を偏角と呼び、地磁気のN極である磁北を指しています。
 垂直成分が水平面と成す角度を伏角(ふっかく、inclination)と呼び、今回観測したいのは、この伏角です。詳しく考察してみましょう。

水平面

 水平面を測定する方法は、「#26-10 水準器を作ってみよう」にて作成したアプリケーションの応用です。加速度センサを使って、重力加速度の方向を測定したら良いのです。
 重力加速度ベクタは鉛直方向を示すので、これに垂直な面を水平面と見なすことができます。

 加速度を計測可能なセンサがありましたね。
 手持ちでは、9軸加速度・ジャイロ・磁気センサ(MPU9250モジュール)があります。
 他には、M5StickC Plusに内蔵されたMPU6886でも加速度を計測することができます。

磁北

 伏角を知るためには、磁北ベクタを知る必要があります。
 手持ちでは、磁気センサAK8963を使って計測可能です。
 AK8963は、MPU9250チップと同一パッケージ内に集積されたセンサチップです。つまり、MPU9250モジュールに含まれていて、一緒に使用することができます。

伏角

 AK8963は、MPU9250チップに集積されているので、MPU9250モジュールを使うのが便利だと判りました。

a281_inclin.png

 上図は、日本付近を前提としているので、磁北ベクタは水平線より下向きに作図しています。南半球では上向きとなるのは、前の節で解説の通りです。また、演算子(・)は、ベクタの内積(スケイラ積)です。

緯度と伏角の関係

 伏角Iを測定出来たら、伏角と緯度の関係から逆算して、現在地の緯度を推定します。

  大雑把には、

 地球の磁力線モデル図なんかを眺めて見ると、さすがに、伏角I≒緯度、なんていう、単純なものでは無いですよね??その間の緯度ではどうなのでしょうか?

  緯度と伏角の関係を調べる(別ウインドウが開きます)

 国土地理院のHPが見つかると思います。今回は、日本付近に於ける近似式を使います。

 基準となっている東経37°、北緯138°は、新潟県の糸魚川市付近です。

 地磁気の状態は経時変化もあるし、場所によっても異なります。上に引用した式は、国土地理院が西暦2020年の実測データから近似した、場所(北緯-東経)から伏角を求めるための近似式です。
 2020年から長い時間が経過すると、誤差が大きくなる可能性があります。

緯度の推定

 前節の近似式を使って緯度を推定する手順は、

と、式の変形としては正しいけれど、これでは未知数λ(経度)が残ってしまいます。

 現在地の経度λを指定しなくてはならない、と言う事でしょうか?でも、「経度が判る環境なら、緯度だって判るでしょ?」って事です。……意味ないじゃん(1^^;)。

 さて、後ほど実験して確かめるのですが、所詮、そんなに高い精度で推定することはできません。
 なので、経度λについては、日本の東西方向の中央付近であるλ=138°を使って逆算しても、大きな偏差は無いと思われます。
 尚、東経138°は、新潟県糸魚川市付近です。沖縄県那覇市が東経127°、北海道根室市が東経145°なので、現在地の大体の経度が判っているなら、その値を設定すると精度は上がります。

M5StickC Plus+UIFlow

 今回のアプリケーションでは、複雑な制御は必要ないですし、M5StickC PlusUIFlowを使って作成して見ようと思います。

a236_m5flow.png


 M5StickC Plusにも加速度センサが内蔵されていますが、磁気センサがありませんので、今回のアプリケーションには不足です。外部にMPU9250モジュール(下図)を接続して使います。

ar9a_mpu9250.jpg

 MPU9250には、磁気センサが集積(内蔵)されているので、MPU9250モジュール自体の置き場所や傾きが変わっても、加速度センサと磁気センサの位置関係が変化することが有りません。今回のアプリケーションには最適です。
 加速度センサと、磁気センサが別々になったチップやモジュールを使うのは、互いの位置関係や傾きが誤差となってしまうので、お勧めしません。

 以上より、M5StickC Plusは、ただのセンサ制御と、表示(U/I)だけに使用するので、他のArduinoを使っても良いと思います。

UIFlowのI2C通信

 MPU9250モジュールは、I2C接続のセンサモジュールです。M5StickC Plus+UIFlow開発環境で、I2C通信を実行した時の解説は、以下の記事をご参照ください。

  「#26-1 温度・湿度リモート監視」から、こちらを参照

 M5StickC Plusの拡張I/Oポートに外付けしたI2C機器と通信した時の記事です。

※UIFlowは、ブロックを組み立てていく形式のプログラミングで、使っていて楽しいのですが、コピー&ペーストができないため、「以前作ったプログラムから部分的にコピーして使いたい」と思っても、出来ないのが残念。

重力加速度ベクタ

 重力加速度は、物体が地球の重力に引っ張られることで下向きに働く加速度です。従って本来は下向きのベクタなのですが、普通、加速度センサを使って測定すると、上向きのベクタとして観測されます。

 アプリケーションによっては、測定値を地球の重力加速度g≒9.8m/s2との相対値に調整して使う場合もありますが、今回は方向(ベクタ)だけが重要なので、測定した三次元ベクタを正規化して使います。

※ベクタの正規化とは、ベクタの大きさ(絶対値)が1となる様に、ベクタの方向を変えずに各成分値を調整する事を指します。

磁北ベクタ

 磁気センサによって観測される磁北ベクタは、補正値などを使って、テスラと言う単位などに換算できるようになっています。今回のアプリケーションでは方向(ベクタ)だけが必要なので、こちらも正規化して使います。

 ただし、センサによって出荷時の補正値が用意されている場合、それが絶対値だけではなく、方向に影響を与える様な補正値であるならば、補正して使う必要があります。
 AK8963では、ASAレジスタから補正値を読み出して補正する必要があります。

  Hadj=H×((ASA−128)×0.5÷128+1)
  ※AK8963データシートより引用。

 ASAレジスタは三次元ベクタの成分毎に3個あるので、補正しておかないとベクタ(方向)がずれてしまいます。

移動平均

 加速度センサも、磁気センサも、非常に精密で繊細なセンサなので、測定する度に値が変動します。緯度を推定するためには、2つのセンサ値を使うため、更に変動幅が大きくなります。

 今回は、加速度センサと磁気センサの測定値を使って、近似値を求める式から逆算した緯度φの移動平均を取り、少しでも安定した平均値を求めて表示しようと思います。

U/I設計

 今回のアプリケーションでは、操作系のU/Iは必要ありません。画面表示系のU/Iは、以下の様に決定しました。

a281_latest.png

 上から順に定数、測定値、計算値と続き、一番下に推定した経度(latitude)が表示される設計です。さて、うまく推定できるでしょうか?

プログラム

 完成したUIFlowのプログラムを以下にリンクしておきます。

  完成プログラム:latitude_est.m5f

 ダウンロードしたら、UIFlowで読み込んで、ご使用ください。

 UIFlow開発環境の立ち上げ方法や使い方に関しては、以下記事をご参照ください。

  「#23-6 UIFlowを使って見る

 逆引き索引からも、UIFlow関連記事にアクセスできます。

推定実験

 実験して動作を確かめてみましょう。M5StickC PlusとMPU9250モジュールを以下表の様に接続してください。

M5StickC Plus 接続 MPU9250モジュール
3V3 VCC
GND GND
G36/G25(SCL) SCL
G26(SDA) SDA
  × EDA
  × ECL
GND ADO
  × INT
3V3 NCS
GND FSYNC

 いずれも、M5StickC Plusの上部にあるピンソケットから接続します(下図)。

a237_ioport.jpg

 以下図に実験中の様子を示します。

a281_expr.jpg

※3V3,GNDへ固定する端子(ADO,NCS,FSYNC)は、MPU9250を実装したブレッドボード上で結線しておくと、M5StickC Plusとの結線は4本(VCC,GND,SCL,SDA)だけで済みます。

 実験を進めましょう。
 MPU9250モジュールを動かさない様に、机の上などに静かに置いて、暫く観察して見てください。
 PCやスピーカ、TVなど、電磁気を発する機器から離して置いてください。
 現在の設定では、500ms間隔で推定した緯度を、20区間の移動平均を取って表示しているので、安定するまでに10秒(≒500ms×20区間)程の時間がかかります。

 当方の実験地は東京近郊でしたので、北緯35°、東経139°(伏角50°)辺りなのですが、推定結果は北緯20°〜50°辺りで大きくばらつきが有りました。
 センサを設置する位置や角度、傾きを変えると、推定値も数10°のオーダで変動してしまう始末です。
 上に示した実験中の写真では、それらしい値が表示されているようなシーンを撮影したのですが、推定値に大きなばらつきがあるので、「それらしき値」を表示する場合もある、と言うだけの話です。
 実際に実験してみると、まともに推定できていないことは明らかです。

 だめだめ。本当に、南半球/北半球くらいの精度しか無いかも?日本国内に限定して控えめに見ても、北日本/本州/沖縄諸島部くらいの大雑把な判定しかできない程度の精度しかないかな?と言う感じです。

失敗原因の考察

 まず、理解を深めるため、伏角と経度-緯度の近似式(I2020.0)をグラフ化してみました(下図)。

a281_i2020_0.png

 近似式の定義域(λ=東経120°〜154°)では、同じ緯度(φ)に対して、伏角I2020.0で約5°(4.3°〜5.6°)程の偏差がありました。伏角で5°変動すると、緯度でも、約5°ほどの変動幅が有ります。

 東京から北へ2.5°移動すると新潟県、南へ2.5°移動すると八丈島を越えて鳥島くらいまで変動してしまう(南北へ5°の範囲)ので、経度λ=138°へ固定した推定では最初から、その程度の精度しかないことが判りました。

 そこへもってきて、加速度センサも磁気センサも、微小な物理量を数値化して計測する繊細なセンサなので、十分な精度が得られなかったと推測しています。
 特に、磁気センサは、周囲状況の影響を受け易いセンサです。磁気を帯びたスピーカの近く、電磁波を発生するPCなど電子機器の近く、などでは、そういった磁場の影響を受けてしまいます。


 アイディアは良かったと思うんだ、アイディアは。でも、センサの測定精度が着いて来なかった、残念な結果となりました。「失敗は成功のもと」でしたか、懲りずに挑戦を続けたいと思います。


btn_arduino.png

btn_prev.png btn_next.png

home