2013年2月11日

iPodをArduinoでコントロール

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

コントロールと言っても音楽やメディア(YouTube、ストリーミング等)の再生停止、送り戻し、音量の調節くらいですが、今更ながらDockコネクタ経由でやってみたり。
#時代はLightningとか言わない
一応、iOSデバイス(iPhone/iPad)も制御できますが、あくまでもメディア(音楽・動画)のコントロールのみなのでタイトルを「iPod」としました。

使用したのはArduino Pro mini 3.3V、スイッチ、抵抗(1kΩ*3、1MΩ*1)、Dockコネクタのbreakoutボードの4つ。
5V系を使う場合はTXからの出力を抵抗分圧等で3.3VにレベルシフトしてあげればOK。
(ただし、Arduinoへの電源供給は別途しなければならない)


とりあえず、再生停止、曲送り、曲戻しの3ボタンを用意。
Dockコネクタとの接続はこちら(http://pinouts.ru/CellularPhones-A-N/iPhone_connector_pinout.shtml)を参考に、ArduinoのTXをDockコネクタの13ピン、VCCを18ピン、GNDを11ピンに。
Dockコネクタの21ピン(Accessory Indicator)は1MΩ経由でGNDに接続しました。(500kΩでも問題なし)

iPod(iPhone/iPad含む)のシリアル通信に関しては既に調べ尽くされているので、その情報を参考にしました。
https://instruct1.cit.cornell.edu/courses/ee476/FinalProjects/s2007/awr8_asl45/awr8_asl45/index.html
http://web.student.tuwien.ac.at/~e0026607/ipod_remote/ipod_ap.html

シリアル通信には複数のモードがあり、最も簡単な制御モード(iPodへの一方行通信)がmode2、曲名やアルバム名なども取得できる制御モード(iPodとの双方向通信)がmode4となっている模様。
接続直後はmode0となっているので、そこにmode2への切り替えコードを叩いてあげるとmode2の制御コマンドを受け付けるようになってくれます。
と言うわけで、プログラムは上記ページを参考にしながら以下の様な感じで。
#include <Bounce.h>

#define BUTTON1_PIN 3
#define BUTTON2_PIN 4
#define BUTTON3_PIN 5

boolean state[3];

Bounce button1 = Bounce( BUTTON1_PIN,20 );
Bounce button2 = Bounce( BUTTON2_PIN,20 );
Bounce button3 = Bounce( BUTTON3_PIN,20 );

byte mode2[] =      {
  0xFF, 0x55, 0x03, 0x00, 0x01, 0x02, 0xFA};
byte playStop[] =   {
  0xFF, 0x55, 0x03, 0x02, 0x00, 0x01, 0xFA};
byte prevTrack[] =   {
  0xFF, 0x55, 0x03, 0x02, 0x00, 0x10, 0xEB};
byte nextTrack[] =   {
  0xFF, 0x55, 0x03, 0x02, 0x00, 0x08, 0xF3};
byte buttonReleased[] = {
  0xFF, 0x55, 0x03, 0x02, 0x00, 0x00, 0xFB};

void setup() {
  pinMode(BUTTON1_PIN, INPUT);
  pinMode(BUTTON2_PIN, INPUT);
  pinMode(BUTTON3_PIN, INPUT);
  Serial.begin(19200);
  for (int i = 0; i < 7; i++) {
    Serial.write(mode2[i]);
  }
}

void loop() {
  button1.update();
  if ((button1.read() == HIGH)&&(state[0] == 0)) {
    for (int i = 0; i < 7; i++) {
      Serial.write(playStop[i]);
    }
    state[0] = 1;
  }
  if ((button1.read() == LOW)&&(state[0] == 1)) {
    for (int i = 0; i < 7; i++) {
      Serial.write(buttonReleased[i]);
    }
    state[0] = 0;
  }
  button2.update();
  if ((button2.read() == HIGH)&&(state[1] == 0)) {
    for (int i = 0; i < 7; i++) {
      Serial.write(prevTrack[i]);
    }
    state[1] = 1;
  }
  if ((button2.read() == LOW)&&(state[1] == 1)) {
    for (int i = 0; i < 7; i++) {
      Serial.write(buttonReleased[i]);
    }
    state[1] = 0;
  }
  button3.update();
  if ((button3.read() == HIGH)&&(state[2] == 0)) {
    for (int i = 0; i < 7; i++) {
      Serial.write(nextTrack[i]);
    }
    state[2] = 1;
  }
  if ((button3.read() == LOW)&&(state[2] == 1)) {
    for (int i = 0; i < 7; i++) {
      Serial.write(buttonReleased[i]);
    }
    state[2] = 0;
  }
}
Bounceライブラリを使うとなんか冗長的な感じになってしまうのがアレですが、とりあえず仕組みは理解できたので今回はこれで良しとします。

これで何を作りたいのかと言うと、iOSデバイス上での音楽再生を停止させるスリープタイマーの外部インターフェース版。
普通はiOSデバイス単体でスリープタイマーを設定出来るようになっていますが、そういう設定が面倒くさい人(父)の為に、ボタンを「物理的に」何回か押せば簡単にタイマーが設定出来る装置を作ろうかと。

色々と資料を見ているとmode4も面白そうなので、次はmode4で取得した情報をLCDに表示させたりしてみようと思っているところ。