2011-01-23

Arduino Pro mini でフィジカルしてみる

今回はArduinoでフィジカルしてみよう的な。
前にもちょろっとやったけど、それとは違うやつで。もうちょっと簡単に。

使ったハードウェアはこれ。
> Arduino - ArduinoBoardProMini
http://www.arduino.cc/en/Main/ArduinoBoardProMini
中でも、こいつの場合は
・3.3V 8MHz
・5V   16MHz
の2つあるわけだが、ここでは前者を選択した。
携帯することを考えるとバッテリーは少ないほうがいい。

Arduino mini小さすぎワロタwピンヘッダ、はんだ付けちゃんとできるか不安になってきた… on Twitpic
▲買ってみたら、思った以上に小さくてびっくり。

なお、Arduino Pro miniの場合、単体ではプログラムを書き込む手段がないので、別売で以下のようなUSBによるシリアル通信用の機器もセットで買う必要がある。
3.3v, 5vで製品が違うので注意。
http://www.sparkfun.com/products/9873


まずやること。ハンダ付け。
見ての通り、買ってきたArduinoには足が無いので自分でピンヘッダをハンダ付けする。





赤いのがシリアル通信用。これを接続した時に上にくるようにハンダ付けしないと、ブレッドボードにさしたときに困りるので注意。

次にやること。環境整備。
まずは通信ドライバー。
> VCP Drivers
http://www.ftdichip.com/Drivers/VCP.htm

Windowsの64bitで、2.08.08を選択。

さらにコーディング、プログラムのアップロードを行うソフトArduino IDEが必要。
> Arduino - Software
http://arduino.cc/en/Main/Software

ここから、Windows版のArduino IDE、バージョン0022をDL。



ブレッドボードで回路制作とプログラミング。
Arduinoの本とかではよくスケッチとかっていってるみたい。



回路はこんな感じ。
Resetボタンから向かって右側のVCCとGNDはそれぞれ電源の3.3V、GNDにつなげること。ここがArduinoの電源供給端子。
左側のGNDはシリアル通信用なので今回は関係ない。

構成は、以下のような感じ。
・7番ピン:スイッチ
・10-12番ピン:LED
で、以下のようなコーディング。
コーディングはArduino IDEで。

USB接続機器をPCに接続後、Arduino IDE起動。
まず行う設定は、以下の2つ。
・[Tools]-[Board] → Arduino Pro or Pro Mini (3.3v,8MHz)  w/ATmega328
 使用するArduinoを選択しておく。これがあっていないとハードにあった適切なコンパイルが
 されないので注意。
・[Tools]-[Poot] → COM6
 PCの環境によって違う。Windowsではたいてい5,6あたり。
 そもそも、USB接続機器が認識できてないとCOM1しか表示されてないはずなので、
 USB接続機器のほうがうまくいっているか確認すること。

使うのはArduinoIDE。見た目はほとんどC言語と同じ。
// スイッチで3パターンに変化するLEDx3の点灯
#define LED1 12
#define LED2 11
#define LED3 10

#define SW1  07

boolean sw1ValOld = 0;
boolean sw1Val = 0;

int state = 3;
int count = 0;
int init_port = B00000010;

void setup()
{
  //こっちだとプログラムが重くなる
  //pinMode(LED1, OUTPUT);
  //pinMode(LED2, OUTPUT);
  //pinMode(LED3, OUTPUT);
  DDRB = DDRB | B00011100;
  pinMode(SW1, INPUT);
}

void loop()
{
  static int portb;
  sw1Val = digitalRead(SW1);
  
  // スイッチ判定(立ち上がりのみおk)
  if( sw1Val == HIGH && sw1ValOld == LOW) {
    state++;
    if( state >= 3 ) state = 0;
    delay(100); // チャタリング防止。値はテキトー
  }
  // 値更新
  sw1ValOld = sw1Val;
  
  switch(state) {
  case 0: 
    //こっちだとプログラムが重くなる
    //digitalWrite(LED1, HIGH);    
    //digitalWrite(LED2, HIGH);
    //digitalWrite(LED3, HIGH);
    PORTB = B00011100;
    delay(1000);
    PORTB = B00000000;
    //こっちだとプログラムが重くなる
    //digitalWrite(LED1, LOW);    
    //digitalWrite(LED2, LOW);
    //digitalWrite(LED3, LOW);
    delay(1000);
    break;
    
  case 1: // 全部点滅早く
    //こっちだとプログラムが重くなる
    //digitalWrite(LED1, HIGH);    
    //digitalWrite(LED2, HIGH);
    //digitalWrite(LED3, HIGH);
    PORTB = B00011100;
    delay(500);
    //こっちだとプログラムが重くなる
    //digitalWrite(LED1, LOW);    
    //digitalWrite(LED2, LOW);
    //digitalWrite(LED3, LOW);
    PORTB = B00000000;
    delay(500);
    break;
    
  case 2: // 1つずつずれる
    count++;
    if(count >= 3) {
      count = 0;
      portb = init_port;
    }
    //ビットシフト使う場合はこっちでやったほうが楽
    portb = portb << 1;
    PORTB = portb;
    delay(1000);
  }
}
Arduinoは、上記で使われているsetup関数でセットアップ、その後loop関数を繰り返し実行する。
そのため、必要な初期化はsetupに、それ以外の処理の実態は全てloop関数内に書くことになる。

pinModeでピンに出力、入力をセット。
しかし、何度も使う場合は上記のように直接ポートに01を立てる方法の方が容量も負荷も小さくなることもある。

digitalReadでデジタル信号の受け取り、digitalWriteでデジタル信号の出力。
こちらも同様に、直接ポートをいじったほうがプログラム容量が小さくなる場合がある。

以下はコンパイル時に確認できるプログラムサイズ。

▲びふぉあ


▲あふたぁ

多少ではあるが、改善が見られる。
マイコンの場合は、あまり容量の大きなプログラムは乗らないので、少しでも少なくすむようにすべきである。


▲Arduino IDEのインタフェース。三角形でVerify(コンパイル)。右から2つ目の→でUpload。

コンパイルが通ったら、UploadボダンでArduinoにプログラムアップロードする。

実験結果。



プログラムでは、7番ピンにさしたスイッチを押すたびにLEDの点灯ルールが変わるようにswitch case文を使って条件分岐を書いている。
スイッチは押すたびに1000msで点滅→500msで点滅→1つずつ点灯と点灯ルールが変更になる。


思った以上に簡単だった。
むしろ、アセンブリとかH8とか少しでもかんだことある人だったらヌルイぐらいである。
ポートの処理ですらAPIにやらせようとするわけで、かなりブラックボックスにしちゃったかんじ。

さて、これで何作るかねー。

2011-01-04