Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
6
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

Organization

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

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
image.png
この設定を入れておくと、ボードマネジャにesp8266が追加されますので、最新版をインストールします。
image.png

ESP8266ボードの設定

ESP-WROOM-02をPCと接続しておき、ボードの一覧から"Generic ESP8266 Module"を選択し、ボードの設定をします。
image.png
これで、スケッチをマイコンボードに書き込むことが可能になりました。

ESP8266とSigfoxシールドの接続

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

image.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 <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(日本は、京セラコミュニケーションシステム)にお問い合わせください

Sigfox Japan KCCS

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
6
Help us understand the problem. What are the problem?