技術情報

WiFiモジュール(ESP8266)で作るワンコイントラッカー(2)

2018.08.04

WiFiモジュール(ESP8266)で作るワンコイントラッカー(1)に続いて、ここでは、ESP8266で取得したWiFiアクセスポイント情報を、Sigfoxネットワークで送信するところまでを試します。

用意するもの

品名数量参考
ESP-WROOM-02開発ボード(ESP8266を搭載した開発ボード) 1 ESPr® Developer
Sigfoxシールド(Sigfox通信モジュールを搭載したArduinoシールド) 1 UnaShield
ブレッドボード 1
ジャンパーケーブル 数本

すでに、ご予算的には、オーバーしていますが、ちゃんと基板をおこせる方は、ESP8266とSigfoxモジュールで作ってもらうと安価に作れます。

ESP-WROOM-02をArduino化する

前回は、ESP8266をPCからATコマンドを使って動作確認しましたが、今回は、ESP8266をArduinoとして動かし、WiFiアクセスポイント情報を取得したうえで、Sigfoxシールドに対してシリアルATコマンドを使ってデータ送信します。

Arduino IDEにESP8266ボードをインストール

ESP8266ボードのインストール

Arduino IDEを起動し、環境設定を開き、「追加のボードマネージャのURL」に下記URLを入力します。
http://arduino.esp8266.com/stable/package_esp8266com_index.json

img-20180804-technical-01.png

この設定を入れておくと、ボードマネジャにesp8266が追加されますので、最新版をインストールします。

img-20180804-technical-02.png

ESP8266ボードの設定

ESP-WROOM-02をPCと接続しておき、ボードの一覧から"Generic ESP8266 Module"を選択し、ボードの設定をします。

img-20180804-technical-03.png

これで、スケッチをマイコンボードに書き込むことが可能になりました。

ESP8266とSigfoxシールドの接続

今回は、ESP8266をArduino化し、Sigfoxシールドと接続します。

img-20180804-technical-04.png

Sigfoxシールド(UnaShield)は、Arduinoボードとの複数のPIN接続がありますが、内蔵Sigfoxモジュールを動かすためだけであれば、下図の通り、3V3*,5V,GND,RXD*(D5),TXD*(D4)の5つのPINだけでも動作可能です。

img-20180804-technical-05.png
img-20180804-technical-06.png

ESP8266 Sigfoxトラッカースケッチ

このサンプルスケッチでは、ESP8266で、WiFi.scanNetworksを行い、アクセスポイント一覧を取得し、String Atlas-WiFiのガイドラインに従い、上位2局のMACアドレスをSigfoxメッセージ送信コマンドAT$SF=[payload]で送信する例となっています。
EEPROMは、デザリング端末などのWiFiアクセスポイントを除外するために、そのSSID一覧を操作するために使用しています。RAMのサイズが十分にあるマイコンを使う場合は、EEPROMを使用する必要はありませんが、Arduino UnoはRAMが1024バイトしかないため、EEPROMを使用する必要があります。

#include  #include  #include  int _wifiscan_ssidfilerlen = 12; struct AP { String ssid = ""; int rssi = -999; String mac = ""; }; SoftwareSerial SerialSig(14, 12, false, 256); void setup() { Serial.begin(115200); writeIgnoreSSID(); setupWifi(); setupSigfox(); } void setupWifi() { WiFi.mode(WIFI_STA); WiFi.disconnect(); delay(100); Serial.println("[Wifi] Setup done."); } void setupSigfox() { SerialSig.begin(9600); SerialSig.write("AT"); SerialSig.write(10); SerialSig.write("ATS410=0"); SerialSig.write(10); SerialSig.write("AT$IF=923200000"); SerialSig.write(10); } void loop() { AP ap[2]; //RSSI上位2局のWiFi AP情報 Serial.println("[WiFi] scan start"); int n = WiFi.scanNetworks(); Serial.println("[Wifi] scan done"); if (n == 0) { Serial.println("no networks found"); } else { Serial.print(n); Serial.println(" networks found"); for (int i = 0; i < n; i++) { // Print SSID and RSSI for each network found Serial.print(i + 1); Serial.print(": "); Serial.print(WiFi.SSID(i)); Serial.print(" ("); Serial.print(WiFi.RSSI(i)); Serial.print(")"); String mac = WiFi.BSSIDstr(i); Serial.println(mac); mac.replace(":", ""); filterAP(ap, WiFi.SSID(i), WiFi.RSSI(i), mac); } } Serial.println(""); String msg = "AT$SF=" + ap[0].mac + ap[1].mac; //Sigfoxメッセージ Serial.println(msg); SerialSig.write(msg.c_str()); SerialSig.write(10); delay(600000); } void filterAP(AP* ap, String ssid, int rssi, String mac) { if (filterMac(ssid, mac)) { if (ap[0].rssi < rssi) { ap[1] = ap[0]; ap[0].ssid = ssid; ap[0].rssi = rssi; ap[0].mac = mac; } else if (ap[1].rssi < rssi) { ap[1].ssid = ssid; ap[1].rssi = rssi; ap[1].mac = mac; } } } bool filterMac(String ssid, String mac) { bool pass = true; pass = filterMacBySsid(ssid); if (pass) { pass = filterMacByMac(mac); } return pass; } bool filterMacBySsid(String ssid) { bool pass = true; for (int i = 0; i < _wifiscan_ssidfilerlen; i++) { String filteredSsid = read_data_from_rom(i); if (ssid.indexOf(filteredSsid) >= 0) { pass = false; break; } } return pass; } bool filterMacByMac(String mac) { bool pass = true; if (mac.length() != 12) pass = false; //リザーブMACアドレスならフィルタリング if (pass) { if (mac.equalsIgnoreCase("000000000000") || mac.equalsIgnoreCase("FFFFFFFFFFFF")) { pass = false; } } //マルチキャストMACアドレスならフィルタリング if (pass) { long LSBbit_1stOct = strtol(mac.substring(0,2).c_str(), NULL, 16); if (LSBbit_1stOct % 2 == 1) { pass = false; } } return pass; } //EEPROMに文字列(6byte)を書き込む //注意:EEPROMのサイズはEEPROM.beginで設定したサイズ void write_data_to_rom(int address, String String_data) { const int MAX_LEN = 6; byte Byte_data[MAX_LEN+1]; String_data.getBytes(Byte_data, MAX_LEN+1); int k; int start = address * (MAX_LEN+1); for (k = 0; k < MAX_LEN && Byte_data[k] != '\0'; k++) { EEPROM.write(start + k, Byte_data[k]); } EEPROM.write(start + k, '\0'); } //EEPROMから文字列(6byte)を読み込む String read_data_from_rom(int address) { const int MAX_LEN = 6; String data_from_rom; int start = address * (MAX_LEN+1); for (int i = 0; i < MAX_LEN && EEPROM.read(start + i) != '\0'; i++) { char c = EEPROM.read(start + i); data_from_rom = data_from_rom + String(c); } return data_from_rom; } void writeIgnoreSSID() { EEPROM.begin(512); write_data_to_rom(0, "android-"); write_data_to_rom(1, "phone"); write_data_to_rom(2, "samsung"); write_data_to_rom(3, "huawei"); write_data_to_rom(4, "iPad"); write_data_to_rom(5, "iPhone"); write_data_to_rom(6, "W01_"); write_data_to_rom(7, "W03_"); write_data_to_rom(8, "W04_"); write_data_to_rom(9, "wx01-"); write_data_to_rom(10, "wx02-"); write_data_to_rom(11, "wx03-"); EEPROM.commit(); }

お薦めサンプル

ESP8266やSigfoxモジュールの低消費電力化のためのDeep Sleepや、その他お作法をしっかりとやっているサンプルが、下記GitHubにあがっていますので、参考にしてください。
https://github.com/disk91/esp8266-sigfox-trackr

Sigfox Atlas-WiFiの利用にあたって

このスケッチを動かすと、定期的にWiFiスキャンしたデータをSigfoxクラウドに送信することができます。次は、Altas-WiFiサービスが必要となりますので、Sigfox Operator(日本は、京セラコミュニケーションシステム)にお問い合わせください

本記事で利用するDevkitはこちら

著者情報

Products and Marketing Department 日比 学

京セラコミュニケーションシステム株式会社(KCCS)よりSigfox社(フランス)に出向中の元自称Sigfoxエバンジェリスト

  • KCCSから追い出され、フランスの片田舎で余生を過ごしています
Twitter:https://twitter.com/ghibi