« [iPhone][Jailbreak]iPhoneにつないだキーボードから文字を入力してみた | Main | [iPhone]iPhone 3Gにヘッドホンアンプをつないでみた »

2008.11.04

[iPhone][AVR][Jailbreak]自走式iPhoneを作ってみた

iPhoneのシリアルポートを使った工作が面白いので、今度は「自走式iPhone」を作ってみた。

Selfpropellediphone01

ハードウェア

ベースは、TAMIYAの楽しい工作シリーズNo.68「壁づたいねずみ工作基本セット」。 CPUボード&開発環境にArduino(ボードはArduino Diecimila)を利用。

Selfpropellediphone02

ArduinoのProtoShield上にモータードライバのTA7291P (PDF)を二つ設置、これでモーターを制御。 TA7291P×2の入力ピン計4本に、ArduinoのPWM出力ができるピン、5, 6, 9, 10を接続。 自走式iPhoneの重量に耐えるため、AA×4本を直列につないだ電源でモーターを駆動。

Selfpropellediphone03

そのほか、Arduinoの電源となる009P電池、そこから安定化した5Vを作るレギュレータ回路なども載ってぶら下がっている。

Selfpropellediphone04

Selfpropellediphone05

ソフトウェア

Arduinoのソフトウェアは、シリアル通信を監視して、コマンド文字が来たらそれに応答、という簡単なもの。 コマンド文字に応じて、TA7291Pの所定のピンをHレベルにする。 PWM制御できるポートを使っているので、一応0〜255までの256段階でモーターのスピードを調整できるが、トルクが無いのでなかなか調整が難しい。

#define FORWARD 1
#define BACKWARD 2
#define STOP 3
#define RIGHT 4
#define LEFT 5

int rightForward = 10;
int rightBackward = 9;
int leftForward = 6;
int leftBackward = 5;

int incomingByte = 0;
int spd = 100;
int currentVector = STOP;

void setup() {
  pinMode(rightForward, OUTPUT);
  pinMode(rightBackward, OUTPUT);
  pinMode(leftForward, OUTPUT);
  pinMode(leftBackward, OUTPUT);

  Serial.begin(9600);
  Serial.println("start");
}

void loop() {
  if(Serial.available() > 0)
  {
    incomingByte = Serial.read();
    Serial.println(incomingByte);
    switch (incomingByte) {
      case 120:
        goBackward(spd);
        break;
      case 119:
        if (spd > 0)
        {
          spd -= 10;
        }
        updateSpeed();
        //Serial.println(spd);
        break;
      case 115:
        turnLeft(spd);
        break;
      case 113:
        if (spd <= 250)
        {
          spd += 10;
        }
        updateSpeed();
        //Serial.println(spd);
        break;
      case 101:
        goForward(spd);
        break;
      case 100:
        turnRight(spd);
        break;
      case 97:
        stop();
        break;
    }
  }
}

void updateSpeed()
{
  switch (currentVector)
  {
    case LEFT:
      turnLeft(spd);
      break;
    case RIGHT:
      turnRight(spd);
      break;
    case STOP:
      stop();
      break;
    case BACKWARD:
      goBackward(spd);
      break;
    case FORWARD:
      goForward(spd);
      break;
  }
}

void goForward(int spd)
{
  stop();
  analogWrite(leftForward, spd);
  analogWrite(rightForward, spd);
  currentVector = FORWARD;
}

void goBackward(int spd)
{
  stop();
  analogWrite(leftBackward, spd);
  analogWrite(rightBackward, spd);
  currentVector = BACKWARD;
}

void turnRight(int spd)
{
  stop();
  analogWrite(leftBackward, spd);
  analogWrite(rightForward, spd);
  currentVector = RIGHT;
}

void turnLeft(int spd)
{
  stop();
  analogWrite(leftForward, spd);
  analogWrite(rightBackward, spd);
  currentVector = LEFT;
}

void stop()
{
  analogWrite(rightForward, 0);
  analogWrite(rightBackward, 0);
  analogWrite(leftForward, 0);
  analogWrite(leftBackward, 0);
  currentVector = STOP;
}

iPhone上で動かすソフトウェアは、適当なポートでListenし、送られてきた文字をシリアルポートにフォワードするというもの。 この働きで、iPhoneが無線モジュールとして機能することになる。これはRubyで書いた。

#!/usr/bin/env ruby

require "socket"
require "serialport"

class Arduino

  def initialize(serialport = "/dev/tty.iap", serverport = 12345)

    if (not File.exist?(serialport))
      raise "ERROR: Specified device does not exist."
    end
    @sp = SerialPort.new(serialport, 9600, 8, 1, SerialPort::NONE)

    @gs = TCPServer.open(serverport)
    while true
      @socks = [@gs]
      @addr = @gs.addr
      @addr.shift
      printf("server is on %s\n", @addr.join(":"))
      run()
    end
  end
  def run()
    while true
      nsock = select(@socks)
      next if nsock == nil
      for s in nsock[0]
        if s == @gs
          @socks.push(s.accept)
          print(s, " is accepted\n")
        else
          if s.eof?
            print(s, " is gone\n")
            s.close
            @socks.delete(s)
          else
            str = s.gets
            if str.chomp == "end"
              s.close
              return
            end
            @sp.puts(str)
          end
        end
      end
    end
  end
end

arduino = Arduino.new("/dev/tty.iap", 12345)

クライアントは特に書いてないので、telnetから操作した。

$ telnet 192.168.0.5 12345

なかなか面白い遊びであった。

|

« [iPhone][Jailbreak]iPhoneにつないだキーボードから文字を入力してみた | Main | [iPhone]iPhone 3Gにヘッドホンアンプをつないでみた »