概要
オリンパスが2015年3月に発売したオープンプラットフォームカメラAIR A01は、Wi-FiからコントールできるAPIを提供するカメラです。SDKはiOS用とAndroid用が提供されていますが、通信仕様書が公開されているため、他の環境からでもコントロールできます。
これは、小型かつ低価格でArduino IDEでも利用できるWi-FiモジュールESP8266からA01をコントロールするサンプルです。これだけであればインターバル撮影と同じですが、センサなどを入力として拡張することを想定しています。また、A01が備えている基本的な顔認識の機能との組み合わせも可能だと思います。そうすることで、特定の何かが起きた時に撮影するようなものをスマートフォンなしで実現できます。
実装
オリンパス OPC Hack & Make Projectのウェブサイトで公開されている通信仕様書を参考にして実装したごく簡単なサンプルです。A01との通信はA01をサーバとしてHTTPで行います。
settings.h
// 変更箇所がわかるように別ファイル(Arduino IDE上では別のタブ)に
// A01のキャップを外して確認できるSSIDとパスワードをここに記入
const char* ssid = "AIR-A01-BHD******";
const char* password = "********";
Air.ino
#include <ESP8266WiFi.h>
#include "settings.h"
// A01のIPアドレス(固定)
IPAddress airIpAddress(192, 168, 0, 10);
void setup() {
Serial.begin(115200);
Serial.print("Connecting to ");
Serial.println(ssid);
// setting.hに記入したSSIDとパスワードでA01に接続
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
Serial.println("IP address: ");
// 撮影モードへの切り替えをリクエスト
if (sendRequest("/switch_cameramode.cgi?mode=rec&lvqty=0320x0240") == 200) {
// 撮影モードへの切り替えに成功したらライブビューを開始
// 実際にはライブビューは使用しないが、開始せずに撮影しようとするとエラーになるため
Serial.println("Rec mode");
sendRequest("/exec_takemisc.cgi?com=startliveview&port=5555");
} else {
Serial.println("Failed to switch to rec mode");
}
}
void loop() {
// 静止画撮影開始
if (sendRequest("/exec_takemotion.cgi?com=newstarttake") == 200) {
Serial.println("Started taking");
// 撮影開始に成功したら静止画撮影停止
sendRequest("/exec_takemotion.cgi?com=newstoptake");
Serial.println("Stopped taking");
} else {
Serial.println("Failed to start taking");
}
delay(5000);
}
// HTTPでリクエストを送信して結果を返す
int sendRequest(String command) {
int result = -1;
Serial.println("Connecting to the AIR\n");
WiFiClient client;
const int httpPort = 80;
if (!client.connect(airIpAddress, httpPort)) {
Serial.println("Connection failed");
return result;
}
Serial.print("Command: ");
Serial.println(command);
client.println(String("GET ") + command + " HTTP/1.1");
client.println("Host:192.168.0.10");
client.println("User-Agent:OlympusCameraKit");
client.println();
// 暫定的に一定時間待つようにしている
// ここはタイムアウト付きで一定の返答があるまで待つように変更する予定
delay(100);
// クライアントにメッセージが届いていればそれを読み取って処理する
while (client.available()) {
String line = client.readStringUntil('\r');
if (line.startsWith("HTTP/1.1")) {
// 11111
// 012345678901234
// HTTP/1.1 200 OK
result = line.substring(9, 12).toInt();
}
Serial.print(line);
}
Serial.println();
if (client.connected()) {
client.stop();
}
return result;
}
既知の問題
- 連続動作中にA01と通信ができなくなってしまうことがある(再現条件を調査中)