Program Resource

開発者向け各種コード、アルゴリズム、リソース情報ライブラリ もしくはねふぁの覚え書き

WiFiシールドでWebサーバーを作っている際DHCPで割り当てられているIPアドレスを確認するのにいちいちシリアルモニターを開くのは面倒なのでLCDに表示できないかと考えていたが、通常の16×2 LCDシールドだとピンがWiFiシールドと競合してしまう。そこでI2C接続のLCDディスプレイを探していたところ、SwitchScienceから小型で使い勝手がよさそうな商品が出ていたので買ってみた。

I2C接続の小型LCD搭載ボード(5V版)
I2C接続の小型LCD搭載ボード(5V版)

クッション封筒で届いたので割れていないか心配になったが、大丈夫だった。

DSC03477

ピンが付属していないので、まずは手持ちのピンを半田付けする。

DSC03478

左からVDD、GND、SDA、SCLのピンアサインになっているので、SwitchScienseさんの説明ページにある様にA2~A5のピンにさくっと挿しこむ。幸いWiFiシールドはアナログピンを使っていないので競合しない。

DSC03482

LCD表示は楽に使える様にSwitchScienseさんのブログを元にクラス化した。

i2c_8x2lcd.zip – download

(2015/5/1追記) 改良版のクラスとサンプルコードも作成してみた

ダウンロード後ライブラリとして追加したら使える、と思う。ただ、何故かライブラリを取り込んでビルドするとWire.hが見つからないと怒られてしまう謎現象が発生するのでメインコードのi2c_8x2lcd.hのincludeの前にWire.hをincludeする必要がある。

先日のWiFiシールドでWebサーバーごっこを元に、起動時、アクセスポイント接続時、DHCP接続時のタイミングでLCDにメッセージを表示し、IPアドレス取得後IPアドレスを表示する様に修正した。さらに、Webページはテキスト入力を受け付ける様にして、ブラウザから適当なテキスト(半角英数)を入力するとその文字をLCDに表示する様にしてみた。

DSC03479

DSC03480

DSC03481

これはなかなか便利である。小型で邪魔にならないし手軽に使える。

モバイルバッテリーで電源オン、起動後タブレットから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;
  }
}

I2C接続の小型LCD搭載ボード(5V版)
I2C接続の小型LCD搭載ボード(5V版)

[GPG] Arduino CC3000 WiFiシールド SDカードスロット付
[GPG] Arduino CC3000 WiFiシールド SDカードスロット付

ルートアール USB 簡易電圧・電流チェッカー 積算機能・時間・ワットVA同時表示対応 RT-USBVAC2
ルートアール USB 簡易電圧・電流チェッカー 積算機能・時間・ワットVA同時表示対応 RT-USBVAC2

ルートアール USB 簡易電圧・電流チェッカー 積算電流・通電時間計測 RT-USBVATM
ルートアール USB 簡易電圧・電流チェッカー 積算電流・通電時間計測 RT-USBVATM


コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です


*