ラベル Arduino の投稿を表示しています。 すべての投稿を表示
ラベル Arduino の投稿を表示しています。 すべての投稿を表示

2011年12月2日金曜日

ADKアプリの作成 ースケッチー


 AndroidAccessory acc("Utsugen",
                                     "TestADK",
                                     "TestADK by Utsugen",
                                     "1.0",
                                     "http://utsugen.blogspot.com/",
                                     "0000000012345678");

void setup() { pinMode( LED, OUTPUT ); acc.powerOn(); }


Arduinoを接続したときに立ち上げるAndroidアプリを指定する。


void loop() { if (acc.isConnected()) { // INPUT from Android ①int len = acc.read(msg, sizeof(msg), 1); if( len == 3 ){ if( msg[0] == 0x2 ){ if( msg[1] == 0x0 ){ analogWrite( LED, msg[2] ); } } } // OUTPUT to Android data = analogRead( IR ); msg[0] = 0x1; ②msg[1] = ((int)voltage2distance( (double)data / 1024.0 * 5.0 )) & 0xf; msg[2] = 0xff; ③acc.write(msg, 3); } delay(100); }


①Androidからの入力を受け取る。
3byteが種別/対象/値で並んでいる。
Android側と示し合わせておく。
②voltage2distance関数は、赤外線測距モジュールGP2Y0A21YKからの
 電圧を距離に変換している。この方が作成された。
③Androidに値を渡す。

2011年11月20日日曜日

ADKアプリの作成 ーActivityー

今回のアプリは勉強の為に
ActivityはTestADKActivityクラス1つだけで作る事にする。

ADKのDemoKitの実装箇所を参考にする。

onCreate()
public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
     ①mUsbManager = UsbManager.getInstance(this);
     ②mPermissionIntent = PendingIntent.getBroadcast(this,  0,  new Intent(ACTION_USB_PERMISSION),  0);
        IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
        filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
      registerReceiver(mUsbReceiver, filter);
    ③ if(getLastNonConfigurationInstance() != null){
        mAccessory = (UsbAccessory)getLastNonConfigurationInstance();
        ④openAccessory(mAccessory);
        }
    ⑤setContentView(R.layout.main);
        mSlider = (Slider)findViewById(R.id.LedSlider);
        mSlider.setPositionListener(this);
        mLed = (TextView)findViewById(R.id.Led);
        mLed.setOnClickListener(this);
        mLed.setText("0");
    ⑥getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
①UsbManagerの生成
②USB Accessory通信のパーミッションを取得するための
BroadcastReceiverを登録する。
BroadcastReceiver:PendingIntentを登録しておくとこでイベント発生時に呼び出す事が出来る。
③UsbAccessoryがキャッシュに無ければ通信を確立する。
キャッシュ登録:onRetainNonConfigurationInstance
  キャッシュ取得:getLastNonConfigurationInstance
④USB AccessoryとのIOストリームを生成する自作関数。
⑤レイアウトとのひもづけ
SliderレイアウトはDemokitの自作View。
⑥ADKはスリープ状態になると切断されてしまうのでスリープ防止。

onResume()
 protected void onResume() { super.onResume(); Intent intent = getIntent(); ①if (mInputStream != null && mOutputStream != null) { return; } ②UsbAccessory[] accessories = mUsbManager.getAccessoryList(); UsbAccessory accessory = (accessories == null ? null : accessories[0]); if (accessory != null) { ③if (mUsbManager.hasPermission(accessory)) { openAccessory(accessory); } else { ④synchronized (mUsbReceiver) { if (!mPermissionRequestPending) { mUsbManager.requestPermission(accessory, mPermissionIntent) mPermissionRequestPending = true; } } } } else { Log.d(TAG, "mAccessory is null"); ⑤setContentView(R.layout.no_device); } }
①通信確立済みなら何もしない。
②UsbManagerオブジェクトからUsbAccessoryのリストを取得する。
リストの先頭を決め打ち使用(将来の拡張用らしい)
③通信許可を取得済みならIOストリームの生成。
④BroadcastReceiverに同期してユーザに通信許可の問い合わせ。
⑤USBAccessory未接続の場合のView表示。

BroadcastReceiver
 ①private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
②if (ACTION_USB_PERMISSION.equals(action)) {
synchronized (this) {
UsbAccessory accessory = UsbManager.getAccessory(intent);
if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
openAccessory(accessory);
} else {
Log.d(TAG, "permission denied for accessory " + accessory);
}
mPermissionRequestPending = false;
}
③} else if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) {
UsbAccessory accessory = UsbManager.getAccessory(intent);
if (accessory != null && accessory.equals(mAccessory)) {
closeAccessory();
}
} }
};


①onCreate()で指定したBroadcastReceiver
②受け取ったイベントがUSB通信許可だった。
③受け取ったイベントがUSBAccessory切断だった。
openAccessory()
private void openAccessory(UsbAccessory accessory){
mFileDescriptor = mUsbManager.openAccessory(accessory);
if (mFileDescriptor != null) {
mAccessory = accessory;

①FileDescriptor fd = mFileDescriptor.getFileDescriptor();
mInputStream = new FileInputStream(fd);
mOutputStream = new FileOutputStream(fd);

②Thread thread = new Thread(null, this, "TestADK");
thread.start();

Log.d(TAG, "accessory opened");
} else {
Log.d(TAG, "accessory open fail");
}
}

①IOストリームの生成
②入力受付用のスレッド生成


run()
public void run() {
    int ret = 0;
    byte[] buffer = new byte[16384];
    int i;

    while (ret >= 0) {
        try {
          ①ret = mInputStream.read(buffer);
        } catch (IOException e) {
            break;
        }

        i = 0;
        while (i < ret) {
            int len = ret - i;

            switch (buffer[i]) {
         ②case 0x1:
                if (len >= 3) {
                 ③Message m = Message.obtain(mHandler, MESSAGE_DISTANCE);
                    m.obj = new DistanceMsg(buffer[i + 1]);
                    mHandler.sendMessage(m);
                }
                i += 3;
                break;

            default:
                Log.d(TAG, "unknown msg: " + buffer[i]);
                i = len;
                break;
            }
        }
    }
}
①Arduinoからの入力を受け取る
②1byte目が入力種別(ここでは赤外線測距のcm)
これはArduinoと示し合わせておく
③MessageクラスはHandlerへ値を渡す為の器。
Handler:UIスレッドはシングルスレッドであるため、
この入力信号待ちスレッド等の別スレッドからアクセスすると
例外が発生する。
Handlerを使うとUIスレッドが実行するキューに登録できる。


Handler
Handler mHandler = new Handler() {
    @Override
 ①public void handleMessage(Message msg) {
        switch (msg.what) {
        case MESSAGE_DISTANCE:
         ②DistanceMsg o = (DistanceMsg) msg.obj;
            mDistance.setText(String.valueOf(o.getDistance()) + "cm");
            break;
        }
    }
};
①HandlerのsendMessageを受け取る。
②Messageクラスから値を取り出してViewに反映。


onPause()
通信切断

onDestroy()
BroadcastReceiverを登録削除

onPositionChange()
①public void onPositionChange(double value) {
int v = (int) (255 * value);
mLed.setText(String.valueOf(v));
②sendCommand(LED_SERVO_COMMAND, (byte)LED_RED, (byte) v);
}
①onCreate()で登録したスライダViewのリスナー
②出力用自作関数

sendCommand()
public void sendCommand(byte command, byte target, int value) {
  ①byte[] buffer = new byte[3];
if (value > 255)
value = 255;
buffer[0] = command;
buffer[1] = target;
buffer[2] = (byte) value;
if (mOutputStream != null && buffer[1] != -1) {
try {
mOutputStream.write(buffer);
} catch (IOException e) {
Log.e(TAG, "write failed", e);
}
}
}
①3byteで「コマンド/対象/値」を表している。
Arduino側の処理と示し合わせておく。






2011年11月19日土曜日

ADKアプリの作成 ープロジェクト作成ー

Androidプロジェクトで、SDKはGoogleAPIs API Level10を選択。
これで2.3.4でUSB Accessory Modeを使用できる。

AndroidManifest.xml
<application android:icon="@drawable/ic_launcher"
                    android:label="@string/app_name" >
 ①<uses-library android:name="com.android.future.usb.accessory" />
    <activity android:label="@string/app_name"
                  android:name=".TestADKActivity" >
        <intent-filter >
            <action android:name="android.intent.action.MAIN" />
         ②<action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />                
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
     ②<meta-data android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"
                        ③android:resource="@xml/accessory_filter" />
    </activity>
</application>
①USB Accessory APIを使う宣言。
②USBホスト接続時のアプリ起動指定。
③Arduinoのスケッチ内で起動するAndroidアプリを特定する情報を記載する。

accessory_filter.xml
<resources>
    <usb-accessory manufacturer="Utsugen" model="TestADK" version="1.0" />
</resources>

Arduinoスケッチ
AndroidAccessory acc("Utsugen",
    "TestADK",
    "TestADK by Utsugen",
    "1.0",
    "http://utsugen.blogspot.com/",
    "0000000012345678");




2011年11月17日木曜日

ADK! Arduino側の準備


  1. ADK一式ダウンロード
    http://developer.android.com/guide/topics/usb/adk.html
  2. Arduinoライブラリのコピー
    ADK_release_0512 -> firmware -> arduino_libs -> USB_Host_Shield
                                                                              -> AndroidAccessory
    ADK内の上の2つのディレクトリを以下にコピー。
    Arduino -> パッケージの中身を表示 -> Contents -> Resources
    -> Java -> Libraries
  3. USBホストシールドライブラリのダウンロード
    http://www.circuitsathome.com/arduino_usb_host_shield_projects
    このページ内のLegacy USB Host libraryからダウンロード。
  4. USBホストシールドライブラリのコピー
    3の全てのファイルを2のUSB_Host_Shieldに上書きコピー。
  5. サンプルスケッチ
    3のページ内のAndroid ADK-compatible library releaseのスケッチをUpload。
    #include <Max3421e.h>
    #include <Usb.h>
    #include <AndroidAccessory.h>
     
    AndroidAccessory acc("Google, Inc.",
           "DemoKit",
           "DemoKit Arduino Board",
           "1.0",
           "http://www.android.com",
           "0000000012345678");
    void setup();
    void loop();
     
    void setup()
    {
     Serial.begin(115200);
     Serial.print("\r\nStart");
     acc.powerOn();
    }
     
    void loop()
    {
      byte msg[3];
     
     if (acc.isConnected()) {
                    Serial.print("Accessory connected. ");
      int len = acc.read(msg, sizeof(msg), 1);
                    Serial.print("Message length: ");
                    Serial.println(len, DEC);
            }
     
     delay(100);
    }



2011年11月5日土曜日

9V電池でArduinoを動かす。

これまではPCとArduinoをUSBで接続して給電していた。
今後は無線で動き回る物を作りたいので電源について考えた。

Arduino UNOの入力電圧は7〜12V。最低限必要な動作電圧は5V。
ACアダプタは9Vの2.1mmセンタープラス型推奨。

9V電池が一番簡単そうだ。
DCポート用の2.1mmプラグが手元に無い。
だが、DCポートとVinポートは内部で繋がっているとのことなので、
電池ボックスの赤リード線(+)をVin、黒リード線(-)をGNDに接続する。



動作OKのようだ。

次は電池はDCポートに接続して、Vinからの9Vでモーターの制御を行いたい。


2011年11月4日金曜日

アナログ入力とシリアル通信

Arduinoのアナログ入力はアナログ0〜5ピンを使用する。

CdSセル(光センサ)の入力値を、LEDのPWM出力に使ってみる。

さらにCdSセルの入力値はシリアル通信でPCに送るのは簡単で
Serial.println 関数を呼ぶだけ。


2011年11月3日木曜日

PWMをやってみる。

モーターの回転数制御に欠かせないPWMをLEDで試してみる。

PWMとは、電圧を上下させる代わりに、HIGH/LOWの比率を変化させる事で
モーターの回転数を制御する仕組み。
回転数 速い
回転数 遅い

ArduinoのデジタルIOピン0〜13のうち、3,5,6,9,10,11の6本がPWMに使用できる。
PWMはアナログ出力を使う。
  analogWrite(ピン番号, 0〜255)





#define  LED  11
#define  SW   6

int val = 0;
int valOld = 0;
int state = 0;
int stateOld = 0;

void  setup()
{
  pinMode( LED, OUTPUT );
  pinMode( SW, INPUT );
}

void  loop()
{
  val = digitalRead( SW );
  if( val == HIGH && valOld == LOW ){
    state = 1 - state;
    delay(10);
  }
  valOld = val;
 
  if( state != stateOld ){
    if( state == 1 ){
      for( int i=0; i<=255; i++){
        analogWrite( LED, i );
        delay( 10 );
      }
    } else {
      for( int i=255; i>=0; i--){
        analogWrite( LED, i );
        delay( 10 );
      }
    }
    stateOld = state;
  }
}

2011年10月21日金曜日

タクトスイッチを使う。

Arduinoの5V出力をタクトスイッチにつなげて、
Arduinoの入力ピンで状態を受け取る。

LEDには330Ωの抵抗を使ったが、タクトスイッチには?
仮に抵抗を使わなかった場合には、
5V / 0Ω = ?
無限大の電流が流れて、ショートの状態となってしまう。

10KΩの抵抗を使う。
茶 黒       橙     金
1 0 x 1000  ±5%



スケッチはこのように書いた。
#define  LED  13
#define  SW   6

int val = 0;

void  setup()
{
  pinMode( LED, OUTPUT );
  pinMode( SW, INPUT );
}

void  loop()
{
  val = digitalRead( SW );
  if( val == HIGH ){
    digitalWrite( LED, HIGH );
  } else {
    digitalWrite( LED, LOW );
  }
}


これはスイッチを押している間だけLEDが点灯するスケッチ。
やはりスイッチはON/OFFに使いたい。

Arduinoは1秒間に数百万行のコードを実行できる。
指でスイッチを押している間にも、loop関数は何度も呼び出される事になる。

そのうちの押し初めの1回だけ検出する = 「前回がLOW、今回がHIGH」

#define  LED  13
#define  SW   6

int val = 0;
int valOld = 0;
int state = 0;

void  setup()
{
  pinMode( LED, OUTPUT );
  pinMode( SW, INPUT );
}

void  loop()
{
  val = digitalRead( SW );
  if( val == HIGH && valOld == LOW ){
    state = 1 - state;
    delay(10);
  }
  valOld = val;
  if( state == 1 ){
    digitalWrite( LED, HIGH );
  } else {
    digitalWrite( LED, LOW );
  }
}

2011年10月17日月曜日

抵抗をつけてみる。

Lチカで気になることがある。
Arduinoの5V出力をそのままLEDに繋げているが無理は無いのだろうか?

LEDの定格電圧と定格電流はどれくらいだろう。
「Arduinoをはじめようキット」には記載が無いが、
ちまたでは、赤色LED3mmは 1.80V 10mA ぐらいのようだ。

オームの法則は 抵抗Ω = 電圧V / 電流A となる。
5V電源でLEDに10mA流すには
(5 ー 1.80)/ 0.01 = 320Ω

キットには330Ωの抵抗が入っているのでこれを使おう。
抵抗の値は色線で表されている。
330Ωは 橙 橙 茶 金 → 33 x 10 = 330Ω±5%

こころなしか明るさがマイルドになった感じ。

ブレッドボードを使ってみる。

前回のArduino直差しをブレッドボードに移してみるとこうなる。
スケッチはそのままで、13番ポートとGNDがジャンパー線で繋がっている。

ブレッドボードの内部はこんな配線になっている。
オレンジが配線。











2011年10月16日日曜日

初めてのスケッチ Lチカ

Arduino IDEを使って初めてのスケッチを書いてみる。
まずはLEDチカチカ。

ArduinoにLEDを差してみる。

LEDは長い方がアノードといいプラスにつなぐ。
短い方はカソードといいマイナスにつなぐ。
今回は長い方を13番ポート、短い方をGNDに直差しです。
本当は抵抗がいるとかなんとか。。。

スケッチはこんな感じです。
------------------------------------------------

#define  LED  13

void  setup()
{
  pinMode( LED, OUTPUT );
}

void  loop()
{
  digitalWrite( LED, HIGH );
  delay( 2000 );
  digitalWrite( LED, LOW );
  delay( 1000 );
}

------------------------------------------------

IDEのVerifyボタンを押してUploadボタンを押すと

点いた!

ちなみにGND(グランド)とは、電源を使い終わったら繋ぐところ。らしい。