STAモードでの起動

本チュートリアルでは、iSDIOコマンドを使って、FlashAirの無線LANをSTAモードで起動してみます。


概要

STAモードの起動には、iSDIOで規定されているConnectコマンドを使用します。

Establishコマンド同様、Connectコマンドが正しく動作するためには、 FlashAirの無線LANが未接続状態になっていなければなりません。

STAモードで起動するためには、接続先のSSIDとネットワークキーが必要です。 近傍にある無線LAN APのSSIDを列挙する Scan コマンドも実行してみましょう。

以下、 チュートリアル4のソースコードを元に追加・変更していきます。


Connectコマンドの発行

Connectは、無線LAN機能をSTAモードで立ち上げるためのコマンドです。 同時に、HTTPサーバー機能とDHCPサーバー機能も立ち上がります。

詳細は、 SD Specifications Part E7 Wireless LAN Simplified Addendum Version 1.10 4.2.2 Connect(ssid, networkKey) に規定されています。

コマンドデータを作るためには、下記の情報が必要です。

  • コマンドID (2)
  • シーケンスID
  • 引数個数 (2)
  • 引数
    • SSID
    • ネットワークキー (パスワード)
arduino_tutorial_5.ino (一部抜粋)
    boolean iSDIO_connect(uint32_t sequenceId, const char* ssid, const char* networkKey) {
      Serial.print(F("\nConnect command: \n"));
      memset(buffer, 0, 512);
      uint8_t* p = buffer;
      p = put_command_header(p, 1, 0);
      p = put_command_info_header(p, 0x02, sequenceId, 2);
      p = put_str_arg(p, ssid);
      p = put_str_arg(p, networkKey);
      put_command_header(buffer, 1, (p - buffer));
      printHex(buffer, (p - buffer));
      return card.writeExtDataPort(1, 1, 0x000, buffer) ? true : false;
    }

Scanコマンドの発行

Scanは、接続可能な無線LAN APをスキャンするためのコマンドです。 無線LAN接続中は実行できません。

詳細は、 SD Specifications Part E7 Wireless LAN Simplified Addendum Version 1.10 4.2.1 Scan() に規定されています。

コマンドデータを作るためには、下記の情報が必要です。

  • コマンドID (1)
  • シーケンスID
  • 引数個数 (0)
  • 引数はありません。
arduino_tutorial_5.ino (一部抜粋)
    boolean iSDIO_scan(uint32_t sequenceId) {
      Serial.print(F("\nScan: \n"));
      memset(buffer, 0, 512);
      uint8_t* p = buffer;
      p = put_command_header(p, 1, 0);
      p = put_command_info_header(p, 0x01, sequenceId, 0);
      put_command_header(buffer, 1, (p - buffer));
      printHex(buffer, (p - buffer));
      return card.writeExtDataPort(1, 1, 0x000, buffer) ? true : false;
    }

スキャン結果は、コマンド完了後に結果レジスタ(0x200番地)をデータポートとして読み取ることで取得できます。

iSDIO Command Response Data (SD Specifications Part E7 Wireless LAN Simplified Addendum Version1.10より抜粋)

Wireless LAN SSID List

このうち、データ本体は Response Dataの部分で、 次のようなフォーマットになっています。

Wireless LAN SSID List (SD Specifications Part E7 Wireless LAN Simplified Addendum Version 1.10より抜粋)

Wireless LAN SSID List

ステータスを読み取って表示するルーチンを作ります。

arduino_tutorial_5.ino (一部抜粋)
    boolean iSDIO_showScanResult() {
      // Try to output some wifi info.
      if (!card.readExtDataPort(1, 1, 0x200, buffer)) {
        return false;
      }

      uint8_t num = get_u8(buffer + 24);
      Serial.print(F("Number of APs: "));
      Serial.println(num);

      uint8_t* p = buffer + 28;
      for (int i = 0; i < num; i++){
        Serial.print(F(" "));
        Serial.print((const char*)p);
        Serial.print(F(", "));
        printBytes(p + 32, 6);
        Serial.print(F(", "));
        Serial.print(get_u8(p + 38), DEC);
        Serial.print(F(", "));
        switch (get_u8(p + 39)){
          case 0 : Serial.print(F("NoSec")); break;
          case 1 : Serial.print(F("WEP")); break;
          case 2 : Serial.print(F("WPA")); break;
          case 3 : Serial.print(F("WPA2")); break;
          default : Serial.print(F("error")); break;
        }
        Serial.println();
        p += 44;
      }

      return true;
    }

メインプログラム

メインプログラムに、ConnectコマンドとScanコマンドを追加します。

arduino_tutorial_05.ino (一部抜粋)
    void loop() {
      char ssid[16];
      char networkKey[16];

      if (!iSDIO_status()) {
        Serial.println(F("\nFailed to read status."));
      }

      Serial.print(F("\n0. Show status"));
      Serial.print(F("\n1. Disconnect"));
      Serial.print(F("\n2. Establish"));
      Serial.print(F("\n3. Connect"));
      Serial.print(F("\n4. Scan"));
      Serial.print(F("\n\nCommand? (next sequence id = "));
      Serial.print(nextSequenceId, DEC);
      Serial.println(F(")"));

      while (Serial.available() == 0);
      char command = Serial.read();

      switch (command - '0') {
        .. (snip) ..
        case 3 :
          Serial.print(F("SSID? "));
          inputText(ssid, sizeof(ssid));
          Serial.print(F("Network Key? "));
          inputText(networkKey, sizeof(networkKey));
          if (iSDIO_connect(nextSequenceId, ssid, networkKey) &&
              iSDIO_waitResponse(nextSequenceId)) {
            Serial.println(F("\nSuccess."));
          } else {
            Serial.print(F("\nFailed or waiting. errorCode="));
            Serial.println(card.errorCode(), HEX);
          }
          nextSequenceId++;
          break;
        case 4 :
          if (iSDIO_scan(nextSequenceId) &&
              iSDIO_waitResponse(nextSequenceId) &&
              iSDIO_showScanResult()) {
            Serial.println(F("\nSuccess."));
          } else {
            Serial.print(F("\nFailed or waiting. errorCode="));
            Serial.println(card.errorCode(), HEX);
          }
          nextSequenceId++;
          break;
        default :
          Serial.println(F("\nUnknown command."));
          break;
      }
    }

24行目~27行目 Connectコマンドで使用するSSIDとNetworkKeyをユーザー入力する部分です。

上記で利用している、 inputText()関数を作ります。 ;が入力されたら、入力終わりと判断するようにしています。

arduino_tutorial_05.ino (一部抜粋)
    char* inputText(char* buf, uint8_t len) {
      // Read characters until user inputs enter or buffer gets full.
      uint8_t i = 0;
      while (i < len - 1) {
        while (Serial.available() == 0);
        char c = Serial.read();
        if (c == ';') break;
        buf[i] = c;
        i++;
      }
      buf[i] = 0;
      Serial.println(buf);
      return buf;
    }

実行結果

実行してみましょう。

... (snip) ...
0. Show status
1. Disconnect
2. Establish
3. Connect
4. Scan

Command? (next sequence id = 1)

Scanを実行してみます。

シリアルターミナルのボックスに、 4、Enterと入力します。

Scan: 

00: 01010000180000000000000000000100
01: 0700000000000000

Waiting response 
  Command Processing...
  Process Succeeded
Number of APs: 5
 mynetwork, B86B23663750, 70, WPA2
 flashair_led, B86B23583750, 64, NoSec
 flashair203r, B86B23005049, 61, WPA2
 HWD14_VEGETA, C40528C98B0C, 52, WPA2
 FlashairT5-v2, E8E0B744A7FB, 49, WPA2

Success.

近傍の無線LAN APの、SSID、BSSID (MACアドレス)、信号強度 (0~100)、セキュリティが表示されます。

続いて、Connectを実行しましょう。

シリアルターミナルのボックスに、 3、Enterと入力します。 すると、下記のようなプロンプトが表示されます。

SSID?

接続先のSSIDを入力しましょう。文字列の終わりを示すため、SSIDの最後に ;を付け加えてしてください。 たとえば、 mynetworkに接続する場合は、

mynetwork;

とEnterを、シリアルターミナルのボックスに入力します。 入力すると、

Network Key?

と表示されますので、同様にしてネットワークキーを打ち込みます。

接続に成功した場合は、次のようになるはずです。

Connect command: 

00: 01010000340000000000000000000200
01: 0B00000002000000090000006D796E65
02: 74776F726B0000000800000031323334
03: 35363738

Waiting response 
  Command Processing...........
  Process Succeeded

Success.

Read iSDIO Status Register
... (snip) ...
 [0440h] Command Response Status #1: id = 2, sequence id = 3, status = Process Succeeded
... (snip) ...
 [0506h] WLAN: No Scan, No WPS, Group Client, STA, Infrastructure, Connected, 
 [0508h] SSID: mynetwork
 [0528h] Encryption Mode: WPA2-PSK and AES
 [0529h] Signal Strength: 98
 [052Ah] Channel: 1
 [0530h] MAC Address: E8E0B758A7FB
 [0540h] ID: 
 [0550h] IP Address: 192.168.43.213
 [0554h] Subnet Mask: 255.255.255.0
 [0558h] Default Gateway: 192.168.43.1
 [055Ch] Preferred DNS Server: 192.168.43.1
 [0560h] Alternate DNS Server: 0.0.0.0
... (snip) ...
Command? (next sequence id = 11)

サンプルコード

arduino_tutorial_05.zip (24KB)

本チュートリアルのサンプルコードはGPLv3および二条項BSDライセンスで提供されています。 詳細はダウンロードした各ファイルを参照してください。