mbedからheroku上に作成したWebアプリケーションのデータを取得してグラフィック有機ELモジュールに表示するということをやってみました。
mbedとは
ARM社が開発しているラピッドプロトタイピング用のマイコンボードです。 同じようなものにArduinoがあります。
Arduinoと比較すると、
- ブラウザ上で開発できる
- コードやライブラリなどの公開・共有ができるhttps://mbed.org/
- 全体的にスペックが高め
- イーサネットの物理層がチップに載っているのでコネクタをつけるだけでネットワークに接続できる
- 一部の機種ではアナログ出力(PWMではなく)が使える
といった特徴があります。
特にネットワークにつなぎやすいというのは大きな特徴で、Arduinoだと別途イーサネットシールドを買わなければならず、結局、費用が高くついてしまいます。
mbedはマイコンボード自体はArduinoより価格が高いですが、ネットワークにつなぐ時にはコネクタを用意すればいいだけなのでトータルコストでは安くなります。
- ArduinoUno + Arduino イーサネットシールド = 約7800円
- mbed NXP LPC1768 + mbed用イーサネット接続キット = 約6000円
というわけで、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モジュールに出力が成功した写真です。
次の記事ではWebアプリケーション部分をもう少し豪華にして、いろいろとOLEDに表示できるようにします。