WiFiシールドでWebサーバーを作っている際DHCPで割り当てられているIPアドレスを確認するのにいちいちシリアルモニターを開くのは面倒なのでLCDに表示できないかと考えていたが、通常の16×2 LCDシールドだとピンがWiFiシールドと競合してしまう。そこでI2C接続のLCDディスプレイを探していたところ、SwitchScienceから小型で使い勝手がよさそうな商品が出ていたので買ってみた。
クッション封筒で届いたので割れていないか心配になったが、大丈夫だった。
ピンが付属していないので、まずは手持ちのピンを半田付けする。
左からVDD、GND、SDA、SCLのピンアサインになっているので、SwitchScienseさんの説明ページにある様にA2~A5のピンにさくっと挿しこむ。幸いWiFiシールドはアナログピンを使っていないので競合しない。
LCD表示は楽に使える様にSwitchScienseさんのブログを元にクラス化した。
(2015/5/1追記) 改良版のクラスとサンプルコードも作成してみた。
ダウンロード後ライブラリとして追加したら使える、と思う。ただ、何故かライブラリを取り込んでビルドするとWire.hが見つからないと怒られてしまう謎現象が発生するのでメインコードのi2c_8x2lcd.hのincludeの前にWire.hをincludeする必要がある。
先日のWiFiシールドでWebサーバーごっこを元に、起動時、アクセスポイント接続時、DHCP接続時のタイミングでLCDにメッセージを表示し、IPアドレス取得後IPアドレスを表示する様に修正した。さらに、Webページはテキスト入力を受け付ける様にして、ブラウザから適当なテキスト(半角英数)を入力するとその文字をLCDに表示する様にしてみた。
これはなかなか便利である。小型で邪魔にならないし手軽に使える。
モバイルバッテリーで電源オン、起動後タブレットからWebアクセスして「Hi! (^-^」の文字を入力、LCDに反映される流れを動画に撮ってみた。ついでに先日購入して気に入っているUSB電流計も一緒に撮ってみた。
以下、ソースコード。
#include <Adafruit_CC3000.h> #include <Wire.h> #include <i2c_8x2lcd.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 "yourssid" // cannot be longer than 32 characters! #define WLAN_PASS "mypassword" #define WLAN_SECURITY WLAN_SEC_WPA2 #define LISTEN_PORT 80 char in_buffer[96]; int in_size = 0; char req_page[64]; char in_ch; char last_ch; char subch[64]; char decch[64]; char *cmd; Adafruit_CC3000_Server httpServer(LISTEN_PORT); I2C_8X2LCD lcd(16,17); void setup(void) { lcd.init(35); lcd.printStr("Booting"); 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); } lcd.printStr(0,0,"Connect"); lcd.printStr(6,1,"AP"); if (!cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY)) { Serial.println(F("Failed!")); while (1); } lcd.printStr(6,1,"OK"); Serial.println(F("Connected!")); Serial.println(F("Request DHCP")); delay(500); lcd.printStr(4,1,"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 < 95 && 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, 64); 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]; } char *decodechar(char *txt){ memset(decch,0,64); int deccnt = 0; char hexbuf[3] = {0,0,0}; for (int i=0;i<strlen(txt);i++){ if (txt[i] == '+'){ decch[deccnt++] = ' '; }else if (txt[i] == '%'){ hexbuf[0] = txt[i+1]; hexbuf[1] = txt[i+2]; decch[deccnt++] = strtol(hexbuf,NULL,16); i+=2; }else{ decch[deccnt++] = txt[i]; } } return decch; } void replypage(Adafruit_CC3000_ClientRef *pclient) { Serial.print("req:"); Serial.println(req_page); if (strcmp(getparam(req_page, '=', 0), "/?text") == 0) { char char_param[10]; strcpy(char_param,decodechar(getparam(req_page, '=', 1))); Serial.print("text:"); Serial.println(char_param); lcd.clear(); lcd.printStr(0,1,char_param); } 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[96]; sprintf(buffer, "Requested : %s", req_page); pclient->fastrprint(buffer); pclient->fastrprint("<BR><form method=\"GET\" action=\"/\">"); pclient->fastrprint("<input type=\"text\" maxlength=\"8\" name=\"text\"><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")); lcd.clear(); lcd.printStr(0,0,"FAIL IP"); 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(); lcd.clear(); char ipadd[9]; sprintf(ipadd,"%3d.%3d.",(uint8_t)(ipAddress >> 24),(uint8_t)(ipAddress >> 16)); lcd.printStr(0,0,&ipadd[0]); sprintf(ipadd,"%3d.%3d",(uint8_t)(ipAddress >> 8),(uint8_t)(ipAddress)); lcd.printStr(1,1,&ipadd[0]); return true; } }
[GPG] Arduino CC3000 WiFiシールド SDカードスロット付