ESP8266 ArduinoとGPSモジュールで位置情報付きのデーターを取得し、Ambientに送信して地図上にプロットしました。
GPSモジュール
GPSモジュールは秋月電子さんの「GPS受信機キット 1PPS出力付き 『みちびき』対応」を使いました。このGPSモジュールは、受信したGPSデーターをシリアルで送出します。
マイコンはESP8266を搭載したスイッチサイエンスさんのESPr Developerを使いました。ESPr DeveloperとGPSモジュールとは次のように接続します。
ESPr Developer | GPSモジュール |
Vout | 5V |
GND | GND |
IO4 | TXD |
IO5 | RXD |
GPSの1PPSピンは使わないので何もつなぎません。
ESPr Developerでソフトシリアル通信
ESPr Developerのシリアル通信ポートは開発環境との通信に使われているので、GPSモジュールと通信するにはGPIOピン(今回はIO4とIO5)を使い、ソフトシリアルで通信します。
ソフトシリアルのライブラリーはEspSoftwareSerialを使いました。インストールは簡単で、Githubのページ右上の「Clone or download」から「Download ZIP」を選んでZIPファイルをダウンロードし、Arduino IDEを立ち上げて、「スケッチ」メニューの「ライブラリをインクルード」→「.ZIP形式のライブラリをインストール…」でダウンロードしたZIPファイルを選択すれば完了です。
ArduinoでGPSデーターを扱うライブラリー
GPSモジュールはGPS衛星からの信号を受信し、時刻、緯度、経度、海抜高度、測位に利用した衛星の数やID、それぞれの衛星の位置(方位角と仰角)などの情報をNMEA-0183フォーマットというフォーマットの文字列として送出します。この文字列データーをプログラムで扱いやすいデーターに変換するArduinoライブラリーがあります。
「Raspberry Pi3のPythonでGPSを扱う」というブログではPythonでGPSデーターを扱うmicropyGPSというライブラリーを紹介しました。このmicropyGPSがモデルにしているArduinoのライブラリーがTinyGPSで、今回はその後継にあたるTinyGPS++というライブラリーを使いました。
インストールはソフトシリアルと同様でTinyGPS++のサイトのダウンロードアイコンの先の最新のZIPファイルをダウンロードし、Arduino IDEで「.ZIP形式のライブラリをインストール…」でZIPファイルをインストールします。
シリアルから読んだGPSデーターを1文字づつライブラリーに渡すと、それを解析し、GPSオブジェクトに追加、更新します。
解析中はfalseが返り、1行処理して解析が成功するとtrueが返されます。シリアルからGPSデーターを読んでGPSオブジェクトにする部分は次のようなプログラムになります。
while (ss.available() > 0) { if (gps.encode(ss.read())) { break; } }
プログラム
Arduinoのプログラムを示します。
ESPr DeveloperのIO16にスイッチを付けて、スイッチが押されていたらその時の緯度経度と標高をAmbientに送信しています。while文でスイッチが押されている時間を見ているのはチャタリング(スイッチの機械的なバタつき)防止です。
Ambientには位置情報付きのデーターを受信し、地図上に表示する機能があります。通常のd1からd8のデーターに加えて、緯度をデーター9、経度をデーター10として送ると位置情報付きデーターになります。
#include <ESP8266WiFi.h> #include <SoftwareSerial.h> #include <TinyGPS++.h> #include "Ambient.h" extern "C" { #include "user_interface.h" } unsigned int channelId = 100; const char* writeKey = "ライトキー"; const char* ssid = "...ssid..."; const char* password = "...password..."; static const int RXPin = 4, TXPin = 5; SoftwareSerial ss(RXPin, TXPin, false, 256); TinyGPSPlus gps; void sendInfo2Ambient(); static const int sw = 16; static const unsigned long PUSH_SHORT = 100; WiFiClient client; Ambient ambient; void setup() { Serial.begin(115200); delay(20); Serial.println(F("Start")); wifi_set_sleep_type(LIGHT_SLEEP_T); WiFi.begin(ssid, password); // Wi-Fi APに接続 while (WiFi.status() != WL_CONNECTED) { // Wi-Fi AP接続待ち delay(100); } Serial.print("WiFi connected\r\nIP address: "); Serial.println(WiFi.localIP()); ss.begin(9600); pinMode(sw, INPUT); ambient.begin(channelId, writeKey, &client); } void loop() { unsigned long gauge = 0; while (digitalRead(sw) == 0) { gauge++; delay(0); } if (gauge > PUSH_SHORT) { if (gps.location.isValid()) { sendInfo2Ambient(); } } while (ss.available() > 0) { if (gps.encode(ss.read())) { break; } } } void sendInfo2Ambient() { char buf[16]; if (gps.location.isValid()) { dtostrf(gps.altitude.meters(), 4, 2, buf); Serial.println(buf); ambient.set(1, buf); dtostrf(gps.location.lat(), 12, 8, buf); Serial.println(buf); ambient.set(9, buf); dtostrf(gps.location.lng(), 12, 8, buf); Serial.println(buf); ambient.set(10, buf); ambient.send(); } }
Ambientでデーターを確認する
作ったGPSロガーを持ち、歩きながら所々でスイッチを押してデーターを取得し、スマホでテザリングしてAmbientにデーターを送信しました。
Ambientで位置情報付きのデーターを地図上に表示するには、チャート設定でグラフ種類として「地図」を選択します。
データーはこんな感じで地図上に表示されます。データーはGPSから取得した海抜高度です。緯度経度は非常に正確な値が取得できていますが、海抜高度は非常にばらつきが大きいようです。
位置情報付きデーターは車両の運行管理など実務的な応用もありますし、サイクルコンピューターのデーターなどを蓄積、可視化できたら面白いと思います。