2010年11月19日金曜日

AndroidとPCとArduinoをつなぐ


AndroidとPCをネットワークでつなぐ その1ではAndroidからPCまでの経路を作成しました。
今回はそこからさらにArduinoまで接続し、Androidからモノを動かしちゃいます。
しかも低予算で実現する事ができちゃったらみんな幸せじゃないですか?

詳細はつづきから




  • ゴール
今回のゴール地点はこんな感じになる予定です。


  • Arduinoってなに?

Arduinoとはイタリアで作られた、安価なロボット制御用テストシステムを製造することができるシステムです。

テストシステムと書いていますが十分個人では楽しめるシステムです。
マイコンでなくてシステムなのは、Arduinoは開発環境等も含めて構成されています。
現物は冒頭の写真なのですが、これは基盤部分。
あと、PC側に開発環境が必要となります。
基盤はAmazonで3200円で購入可能です。
初めて購入する場合はAmazonで下のキットを購入したほうが便利です。
ブレッドボードが同梱されているのと、コネクタ線もあるので面倒な下準備がほとんど必要なく使えます。







  • 開発環境の準備

開発環境は公式サイトからダウンロード可能です。



  • 公式サイトのページ上段のメニューからDownloadをクリック




  • お使いの環境にあった開発環境をダウンロードします。





  • macの場合はアプリケーションへ追加してインストール完了


インストールが完了するとアプリケーションに以下のアイコンが出てきます。
これが、開発環境です。
開発環境には、
  • エディタ
  • コンパイラ
  • 書き込みツール
  • シリアルモニタ
が一体となっています。これはProcessingの開発環境とほぼ同じ使い方です。
書き込みツールとシリアルモニタがArduinoの開発環境で追加されています。

  • コーディング
今回使用するコードは以下です。

#include <Servo.h>

/***********************
 * 定数定義
 **********************/
 
/** ビットレート */
#define bitrate    (9600)

/** サーボ1のチャンネル */
#define SERVO1     (11)

/** サーボ2のチャンネル */
#define SERVO2     (10)

/** サーボ1の初期角度 */
#define S1_DEF_ANG (90)

/** サーボ2の初期角度 */
#define S2_DEF_ANG (90)

/** 受信データの終了コード */
#define RECEV_END  (0xFF)



/***********************
 * 変数定義
 **********************/

/** サーボ */
Servo s1, s2;

/** サーボへの出力値 */
int  pwm1 = 0, pwm2 = 0;



/***********************
 * 関数定義
 **********************/

/**
 * 初期設定
 */
void setup() {
  
  // シリアル通信開始
  Serial.begin(bitrate);
  
  // サーボのチャンネル指定
  s1.attach(SERVO1);
  s2.attach(SERVO2);
  
  // サーボの初期角度指定
  s1.write(S1_DEF_ANG);
  s2.write(S2_DEF_ANG);
}



/**
 * シリアルからデータ受信
 */
void recvData() {
  unsigned char c;    // 受信データ
  
  if (Serial.available() > 1) {
    digitalWrite(13, HIGH);
    pwm1 = Serial.read();
    pwm2 = Serial.read();
    Serial.print(100, BYTE);
  } else {
    digitalWrite(13, LOW);
  }
  
  s1.write(pwm1);
  s2.write(pwm2);
  
}



/**
 * ループ
 */
void loop() {
  
  // シリアル受信処理
  recvData();

}

作りとしては単純にシリアルの受信したデータの1バイト目と2バイト目をサーボの出力に直接当てているだけです。

そして、PC側

/**
 * ArduinoServer
 */
import hypermedia.net.*;
import processing.net.*;
import processing.serial.*;



/*************************************************
 * 定数定義
 ************************************************/
 
/** シリアルのデバイス */
private static final String SERIAL_DEV = "/dev/tty.usbserial-A700dZbD";

/** ボーレート */
private static final int BAUDRATE = 9600;

/** ポート番号 */
private static final int PORT = 1113;

/** 画面横幅 */
private static final int WIND_WIDTH = 320;

/** 画面縦幅 */
private static final int WIND_HEIGHT = 240;

/** サーボ最大角 */
private static final int S1_MAX = 180;
private static final int S2_MAX = 180;

/** サーボ最小値 */
private static final int S1_MIN = 0;
private static final int S2_MIn = 0;

/** サーボのデフォルト値 */
private static final int S1_DEF = 90;
private static final int S2_DEF = 90;

/** 区切り文字 */
private static final char DELIM = ',';





/*************************************************
 * 変数定義
 ************************************************/

/** シリアル */
private Serial mSerial;
 
/** サーバー */
//private Server mServer;

/** UDP */
private UDP udp;

/** タイムアウト回数 */
private int timeout = 50;

/** サーボへの出力値 */
private int pwm1 = S1_DEF, pwm2=S2_DEF;



/*************************************************
 * Arduino制御用メソッド
 ************************************************/

/**
 * Arduinoのサーボを制御
 */
void ctrlArduino(int pwm1, int pwm2) {
  byte[] data = {(byte)(0xFF&pwm1), (byte)(0xFF&pwm2)};
  
  mSerial.write(data);
  int c = mSerial.read();
  
}


/*************************************************
 * 通信
 ************************************************/

void receive(byte[] data) {
  pwm1 = data[0];
  pwm2 = data[2];
  
  ctrlArduino(pwm1, pwm2);
}


/*************************************************
 * Processingのメソッド定義
 ************************************************/

/**
 * セットアップ
 */
void setup() {
  
  size(WIND_WIDTH, WIND_HEIGHT);
  frameRate(10);
  
  // シリアル
  mSerial = new Serial(this, SERIAL_DEV, BAUDRATE);
  
  // サーバーのインスタンスの生成
  //mServer = new Server(this, PORT);
  
  // UDPのインスタンス生成
  udp = new UDP(this, PORT);
  udp.listen(true);
  
  // サーボを初期位置に動かす
  ctrlArduino(pwm1, pwm2);
  
  noStroke();
}



/**
 * 描画ループ
 */
void draw() {

  background(0,0,0);
  
  fill(color(255,255,255));
  text("PWM1:" + pwm1, 0, 30);
  text("PWM2:" + pwm2, 0, 45);
  
}


こちらは、UDPでAndroidから送られて来たデータをシリアルへ投げるだけのサーバーです

そしてAndroid側は前回紹介した、下記コードでデータを送ります。
// 一部抜粋
DatagramSocket sock;
DatagramPacket packet;
byte[] buf = {(byte)1, (byte)2};
int ret = buf.length;
 
sock = new DatagramSocket();
packet = new DatagramPacket(buf, ret, InetAddress.getByName(mIp), mPort);
sock.send(packet);
sock.close();

ちょっとコードが多くて面倒かもしれませんが、一度作ってしまえば後は汎用的につかえるはずです。


  • まとめ
前回の記事で紹介した内容をベースにもうちょっと踏み込んだ事をしてみました。
制御用のArduinoも安く、サーボも秋月電子で1000円ほどの物を使用しています。
今回の目的である低予算でAndroidからモノを動かすは達成できたと思います。



0 件のコメント:

コメントを投稿