Arduino自体のCPUはARMプロセッサーの様に強力ではなく、UNOレベルだとメモリも2K程度と非力ではあるが、Arduinoの可能性を無限に広げるシールドとライブラリの豊富さに驚かされる。
WiFiシールドもその一つで、Arduinoにさくっと乗せてソフトをちょこっと書くだけで無線LAN通信が出来、簡単ではあるがWebサーバーも出来てしまう。
今回使用するのはCC3000のチップを使用したWiFiシールド。AdafruitのCC3000 WiFiシールドと互換性がありライブラリもそのまま利用できる。
チップ自体が技適認証を取得済のため、国内使用も安心である。
まずはライブラリをインストール。Adafruitのページからライブラリをダウンロードし、Arduino IDEでライブラリをインポートする。
https://github.com/adafruit/Adafruit_CC3000_Library/archive/master.zip
インポート後、スケッチの例を開くと色々なサンプルが出てくる。とりあえずはbuildtestのサンプルスケッチを開く。
スケッチを開いた後、下記行を編集し、接続したいアクセスポイントとパスワード、セキュリティ方式を記述する。
#define WLAN_SSID "myNetwork" // cannot be longer than 32 characters! #define WLAN_PASS "myPassword" // Security can be WLAN_SEC_UNSEC, WLAN_SEC_WEP, WLAN_SEC_WPA or WLAN_SEC_WPA2 #define WLAN_SECURITY WLAN_SEC_WPA2
後はビルドして実行。シリアルポートモニターを開くと接続状況が表示される。(デフォルトは115200 baud)
最初にCC3000のファームバージョンやMACアドレス、次にスキャンしたアクセスポイントのリスト、アクセスポイント接続後にIPアドレス等の情報、最後にadafruitへのpingテストを行い終了している。
Hello, CC3000! RX Buffer : 131 bytes TX Buffer : 131 bytes Free RAM: 1237 Initialising the CC3000 ... Firmware V. : 1.24 MAC Address : 0x08 0x00 0x28 0xFF 0xFF 0xFF Started AP/SSID scan Networks found: 7 ================================================ SSID Name : PRS300SE-123456789-1 RSSI : 36 Security Mode: 3 SSID Name : PRS300SE-123456789-2 RSSI : 36 Security Mode: 1 SSID Name : PS3-123456789 RSSI : 44 Security Mode: 2 SSID Name : espresso RSSI : 61 Security Mode: 3 SSID Name : latte RSSI : 53 Security Mode: 3 SSID Name : mocha RSSI : 64 Security Mode: 3 ================================================ Deleting old connection profiles Attempting to connect to mocha Started AP/SSID scan Connecting to mocha...Waiting to connect...Connected! Request DHCP IP Addr: 192.168.1.178 Netmask: 255.255.255.0 Gateway: 192.168.1.30 DHCPsrv: 192.168.1.30 DNSserv: 192.168.1.30 www.adafruit.com -> 207.58.139.247 Pinging 207.58.139.247...5 replies Ping successful! Closing the connection
CC3000はSmartConfigと言う機能を持っており、接続先アクセスポイントの情報をiPhoneやAndroidのアプリから設定する事が出来る。SmartConfigCreateスケッチをArduinoに書き込みAP情報をスマホから設定するとCC3000に接続先情報が保存され、SmartConfigReconnectのスケッチを参考に接続を行うと、次回からCC3000に保存された情報を元にアクセスポイントに接続する様になる。詳細については割愛する(GoogleでCC3000 SmartConfigで検索)。
ライブラリには以下のサンプルスケッチが含まれているので、これらのサンプルをベースに大体の事は出来るのではないかと思う。Tweetのサンプルにはアカウント認証のコードも含まれている。
- buildtest 基本接続テスト
- ChatServer 受信データを全クライアントへ再配信
- EchoServer 受信データをそのままエコー配信
- GeoLocation freegeoip.netのサービスを使い、現在地情報を取得
- InternetTime ntpサーバーから時刻を取得、一日一回同期を行う
- ntptest ntpサーバーから時刻取得と表示(一回のみ)
- SendTweet ツイートを書き込む
- WebClient Webページを取得する
EchoServerのスケッチを開き、実行後telnetからポート7を開くと接続できるので、適当に入力すると一文字一文字エコーが返ってくる。(最近のWindowsは標準でtelnetが入っていないので、プログラムの追加と削除からtelnetクライアントを追加する)
IPアドレスはシリアルモニターで確認、Windowsのコマンドプロンプト等からtelnetでポート7に接続する。
telnet 192.168.1.5 7
では、echoサーバーをベースとして簡易Webサーバーを作ってみよう。
HTTP通信はポート80なので、LISTEN_PORTを80に変更する。そして、クライアントからのデータを一時バッファーに保管し、改行コードが来た時点でデータの中身を確認する。本互換ボードは6番PinがLEDライトになっているので、AP通信後とデータ通信時にオン・オフする様にして、通信状況が分かる様にしている。(緑が電源、オレンジが6番PIN制御)
行頭がGETの場合、その後に取得したいページの情報やCGIのGETメソッドのパラメーターが続く(HTTPの詳細についてはここでは割愛)。クライアントのデータは最後が連続した改行が二回続くので、改行が二回来た時点でWeb情報をクライアントに返信する(HTMLコードを返す)。
下記例ではCGIで数字入力のページを表示するサンプル。下記スケッチを実行後ブラウザからアクセスすると、入力エリアと送信ボタンが表示される。
適当な数値を入力してGoボタンを押すと、Arduinoの下記サンプルスケッチではreplypage関数のservo_param変数にその値が入る様にしているので、ここでサーボモーターを制御するコードやリレーを制御すれば、Webから操作できるArduino工作の出来上がりである。
Webから情報を取得したり、ブラウザーから何かを制御したり、センサーの情報をブラウザーから確認出来る様にするなど、WiFiシールドを使う事で大幅にArduinoの可能性が広がる。
(SwitchScienceさんの小型LCD表示を追加してみました)
#include <Adafruit_CC3000.h>
#include <SPI.h>
#include "utility/debug.h"
#include "utility/socket.h"
#define ADAFRUIT_CC3000_IRQ 3 // MUST be an interrupt pin!
#define ADAFRUIT_CC3000_VBAT 5
#define ADAFRUIT_CC3000_CS 10
Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS, ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_VBAT, SPI_CLOCK_DIV2);
#define WLAN_SSID "ssidname" // cannot be longer than 32 characters!
#define WLAN_PASS "xxxxxxxx"
#define WLAN_SECURITY WLAN_SEC_WPA2
#define LISTEN_PORT 80
char in_buffer[256];
int in_size = 0;
char req_page[64];
char in_ch;
char last_ch;
char subch[128];
char *cmd;
Adafruit_CC3000_Server httpServer(LISTEN_PORT);
void setup(void)
{
pinMode(6, OUTPUT);
Serial.begin(115200);
Serial.println(F("Hello, CC3000!\n"));
Serial.print("Free RAM: "); Serial.println(getFreeRam(), DEC);
Serial.println(F("\nInitializing..."));
if (!cc3000.begin()) {
Serial.println(F("Couldn't begin()! Check your wiring?"));
while (1);
}
if (!cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY)) {
Serial.println(F("Failed!"));
while (1);
}
Serial.println(F("Connected!"));
Serial.println(F("Request DHCP"));
while (!cc3000.checkDHCP()) {
delay(100); // ToDo: Insert a DHCP timeout!
}
while (! displayConnectionDetails()) {
delay(1000);
}
Serial.println(F("\r\nNOTE: This sketch may cause problems with other sketches"));
Serial.println(F("since the .disconnect() function is never called, so the"));
Serial.println(F("AP may refuse connection requests from the CC3000 until a"));
Serial.println(F("timeout period passes. This is normal behaviour since"));
Serial.println(F("there isn't an obvious moment to disconnect with a server.\r\n"));
httpServer.begin();
Serial.println(F("Listening for connections..."));
digitalWrite(6, HIGH);
}
void loop(void)
{
Adafruit_CC3000_ClientRef client = httpServer.available();
if (client) {
digitalWrite(6, LOW);
if (client.available() > 0) {
in_ch = client.read();
if (in_size < 255 && in_ch != '\r' && in_ch != '\n')
in_buffer[in_size++] = in_ch;
if (in_ch == '\r') {
in_buffer[in_size] = '\0';
Serial.println(in_buffer);
cmd = getparam(in_buffer, ' ', 0);
if (strcmp(cmd,"GET") == 0)
strcpy(req_page,getparam(in_buffer, ' ', 1));
in_size = 0;
if (last_ch == '\r') //double linefeed, end of request
replypage(&client);
}
if (in_ch == '\r' || in_ch == '\n')
last_ch = '\r';
else
last_ch = ' ';
}
digitalWrite(6, HIGH);
}
}
//return n-th char array separated with specified character
char *getparam(char *txt, char seperator, int index) {
int strcnt = 0;
int indcnt = 0;
memset(subch, 0, 128);
for (int i = 0; i < strlen(txt); i++) {
if (txt[i] == seperator) {
indcnt++;
if (indcnt > index)
break;
} else if (indcnt == index) {
subch[strcnt++] = txt[i];
}
}
return &subch[0];
}
void replypage(Adafruit_CC3000_ClientRef *pclient) {
Serial.print("[req]");
Serial.println(req_page);
if (strcmp(getparam(req_page,'=',0),"/?servo") == 0){
int servo_param = atoi(getparam(req_page,'=',1));
Serial.print("[Servo]");
Serial.println(servo_param,DEC);
//form input value stored to servo_param, do whatever needed here.
}
pclient->println("HTTP/1.1 200 OK");
pclient->println("Content-Type: text/html");
pclient->println("");
pclient->fastrprint("<html><title>Arduino Web</title><body>");
char buffer[128];
sprintf(buffer,"Requested : %s",req_page);
pclient->fastrprint(buffer);
pclient->fastrprint("<BR><form method=\"GET\" action=\"/\">");
pclient->fastrprint("<input type=\"number\" name=\"servo\"><input type=\"submit\" value=\"Go\"></form>");
pclient->fastrprint("</body></html>");
delay(1000);
pclient->close();
}
bool displayConnectionDetails(void)
{
uint32_t ipAddress, netmask, gateway, dhcpserv, dnsserv;
if (!cc3000.getIPAddress(&ipAddress, &netmask, &gateway, &dhcpserv, &dnsserv)){
Serial.println(F("Unable to retrieve the IP Address!\r\n"));
return false;
}else{
Serial.print(F("\nIP Addr: ")); cc3000.printIPdotsRev(ipAddress);
Serial.print(F("\nNetmask: ")); cc3000.printIPdotsRev(netmask);
Serial.print(F("\nGateway: ")); cc3000.printIPdotsRev(gateway);
Serial.print(F("\nDHCPsrv: ")); cc3000.printIPdotsRev(dhcpserv);
Serial.print(F("\nDNSserv: ")); cc3000.printIPdotsRev(dnsserv);
Serial.println();
return true;
}
}
WiFiシールド自体ピンを多数使うのがやや難点ではある。






![[GPG] Arduino CC3000 WiFiシールド SDカードスロット付](https://images-na.ssl-images-amazon.com/images/I/51gM4PrJ6IL._SL160_.jpg)






ありがたく記載されてる情報を参考にさせてもらっている者です。
実は、Arduino_UNOとCC3000を組み合わせて、そちらの内容に従ってモバイルWiFiルータとの間でbuildtestを行おうとしたところ、シリアル通信からの表示が”Initialising the CC3000 …”のところで静止してしまいます。一応PCによる無線LAN機能で”SSID”と”password”の確認は行っており、そちらでは問題なかったのですが・・。考えられる原因などありましたら、ご指導願えないでしょうか?
よろしくお願いいたします。
buildtestの場合、Initializingの次にFirmwareの情報が出ますので、Initializingで止まる場合、恐らく信号がシールドから来ずずっと待ち状態が続いていると考えられます
接続は半田不良等で上手くシールドと通信できていないか、シールドが異常かもしれません。シールドを抜差ししても改善しない様であれば他のArduinoがあれば差し替えてみて、それでもだめならシールド不良(ファームウェアかハード的な不良)かもしれません。
なるほどです。
確認したところ、ご指摘のとおりピンの半田に不良があったようです。(応力がかかると導通障害を起こしていたようで、基板単体での導通は問題なかったです。)修正を行ったところ、無事に通信しました。
ありがとうございました。