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
この設定を入れておくと、ボードマネジャにesp8266が追加されますので、最新版をインストールします。
###ESP8266ボードの設定
ESP-WROOM-02をPCと接続しておき、ボードの一覧から"Generic ESP8266 Module"を選択し、ボードの設定をします。
これで、スケッチをマイコンボードに書き込むことが可能になりました。
#ESP8266とSigfoxシールドの接続
今回は、ESP8266をArduino化し、Sigfoxシールドと接続します。
Sigfoxシールド(UnaShield)は、Arduinoボードとの複数のPIN接続がありますが、内蔵Sigfoxモジュールを動かすためだけであれば、下図の通り、3V3*,5V,GND,RXD*(D5),TXD*(D4)の5つのPINだけでも動作可能です。
#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 <SoftwareSerial.h>
#include <ESP8266WiFi.h>
#include <EEPROM.h>
int _wifiscan_ssidfilerlen = 12;
struct AP {
String ssid = "";
int rssi = -999;
String mac = "";
};
SoftwareSerial SerialSig(14, 12);
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(日本は、京セラコミュニケーションシステム)にお問い合わせください