mbedからheroku上のデータを取得してOLEDに表示してみる

mbedからheroku上に作成したWebアプリケーションのデータを取得してグラフィック有機ELモジュールに表示するということをやってみました。

mbedとは

ARM社が開発しているラピッドプロトタイピング用のマイコンボードです。 同じようなものにArduinoがあります。

Arduinoと比較すると、

  • ブラウザ上で開発できる
  • コードやライブラリなどの公開・共有ができるhttps://mbed.org/
  • 全体的にスペックが高め
  • イーサネット物理層がチップに載っているのでコネクタをつけるだけでネットワークに接続できる
  • 一部の機種ではアナログ出力(PWMではなく)が使える

といった特徴があります。

特にネットワークにつなぎやすいというのは大きな特徴で、Arduinoだと別途イーサネットシールドを買わなければならず、結局、費用が高くついてしまいます。

mbedはマイコンボード自体はArduinoより価格が高いですが、ネットワークにつなぐ時にはコネクタを用意すればいいだけなのでトータルコストでは安くなります。

というわけで、mbedを今回は使って進めました。

heroku上にWebアプリケーションを作成する

今回はmbedの方のシステムを検証したかったので、herokuのGetting Started with Herokuの通りに進めて Hello, world を表示するだけのアプリケーションにしました。

次の記事で、Webアプリケーションの方は本格的に作成します。

mbedでネットワーク上のデータを取得する

mbedのRD-, RD+, TD-, TD+イーサネットコネクタに接続してネットワークに接続できるようにします。

最初にmbed_officialのTCPSocketのサンプルコードを動かしてみました。

なお、依存関係のある以下の3つのライブラリは先にインポートしておきます。

mbedに書き込んでリセットボタンを押してしばらく待ちます。 シリアル出力をコンソールで見ると以下のようになって正常に動いていることを確認できます。

IP Address is 192.168.0.1
                         Received 299 chars from server:
                                                        HTTP/1.1 200 OK
Server: nginx/1.1.19
Date: Tue, 15 Jul 2014 16:10:28 GMT
Content-Type: text/plain
Connection: close
Last-Modified: Fri, 27 Jul 2012 13:30:34 GMT
Cache-Control: max-age=36000
Expires: Wed, 16 Jul 2014 02:10:28 GMT
Vary: Accept-Encoding
X-Mystery-Header: 894274989
X-be: web2
          Received 57 chars from server:
                                        _prod_sjc
X-Varnish: 894274989
Age: 0

Hello world!

次に先ほど作成したheroku上のアプリケーションに接続するため以下の部分を書き換えます。 your_appの部分は自分の作ったアプリケーション名です。

11〜13行目:

    sock.connect("your_app.herokuapp.com", 80);

    char http_cmd[] = "GET / HTTP/1.1\r\nHost: your_app.herokuapp.com\r\nConnection: close\r\n\r\n";

ホスト名の書き換えの他に、HTTPのプロトコルを1.1にして、2つリクエストヘッダーを追加しています。

herokuは自分が試した限りではHTTP1.0のプロトコルでは接続できないようで、HTTP1.1を指定する必要があるようでした。

余談ですが、ここが原因であることを突き止めるまでに作業の大半の時間がかかりました・・・

HostはHTTP1.1では必須の項目です。

Connectionは指定しないとkeep-aliveが指定され接続がタイムアウトするまで次に処理が進みません。 今回はすぐに接続を切ってしまって大丈夫なのでcloseを指定します。

この書き換えを行って再度シリアル出力をコンソールから見ると、以下のようになり正常にデータを取得できていることがわかります。

IP Address is 192.168.0.1
                         Received 194 chars from server:
                                                        HTTP/1.1 200 OK
Content-Type: text/html;charset=utf-8
Date: Tue, 15 Jul 2014 16:25:58 GMT
Server: WEBrick/1.3.1 (Ruby/2.0.0/2014-05-08)
Content-Length: 12
Connection: Close

Hello, world

有機ELモジュールに取得したデータを表示する

使った有機ELモジュールはこちらです。

今回使った有機ELモジュールはGraphicOLEDというライブラリですでに動作実績があるので、このライブラリを使います。

このライブラリには美咲フォントという日本語フォントが同梱されているため、日本語も表示することができます。

まず有機ELモジュールをmbedに以下のように接続します。

有機ELモジュール <-> mbed

1(VDD) <-> VOUT

2(VSS) <-> GND

4(RS) <-> p24

6(E) <-> p26

11(DB4) <-> p27

12(DB5) <-> p28

13(DB6) <-> p21

14(DB7) <-> p22

以下のライブラリをインポートします。

mbedに書き込むプログラムを以下のように変更します。

#include "mbed.h"
#include "EthernetInterface.h"
#include "GraphicOLED.h"
#include <string>

//有機ELモジュールのインスタンスを生成
GraphicOLED oled(p24, p26, p27, p28, p21, p22);

int main() {
    // ネットワークに接続する
    EthernetInterface eth;
    eth.init(); //Use DHCP
    eth.connect();
    printf("IP Address is %s\n", eth.getIPAddress());
    
    // アプリケーションへアクセス
    TCPSocketConnection sock;
    sock.connect("your_app.herokuapp.com", 80);
    
    char http_cmd[] = "GET / HTTP/1.1\r\nHost: your_app.herokuapp.com\r\nConnection: close\r\n\r\n";
    sock.send_all(http_cmd, sizeof(http_cmd)-1);
    
    // レスポンスの取得
    char buffer[300];
    int ret;
    while (true) {
        ret = sock.receive(buffer, sizeof(buffer)-1);
        if (ret <= 0)
            break;
        buffer[ret] = '\0';
        printf("Received %d chars from server:\n%s\n", ret, buffer);
    }
      
    sock.close();
    eth.disconnect();

    // レスポンスのボディ部を取得するためにヘッダー部は取り除く    
    string response(buffer);
    string response_body;
    response_body = response.substr((int)response.find("\r\n\r\n") + 1);

    // 有機ELモジュールに出力
    oled.cls();
    oled.printf(response_body.c_str());
    
    while(1) {}
}

先ほどのサンプルプログラムからの大きな変更点はGraphicOLEDを使うようになったことと、Webアプリケーションのレスポンスからボディ部を取得する処理を追加したことです。

レスポンスのヘッダー部とボディ部は\r\n\r\nで区切られていますので、そこから最後までを取得するとボディ部だけを抽出することができます。

以下は有機ELモジュールに出力が成功した写真です。

f:id:mia_0032:20140713004208j:plain

次の記事ではWebアプリケーション部分をもう少し豪華にして、いろいろとOLEDに表示できるようにします。

関連エントリ


mbed NXP LPC1768

mbed NXP LPC1768

mbed用イーサネット接続キット

mbed用イーサネット接続キット