Arduino(アルドゥイーノ)始めます -7ページ目

オペアンプの続き

OPアンプを使わない場合の分解能は約4.9mV。5Vを1 / 10bit(1024)に分割するからだ。

これをOPアンプを使って1mVまでモニタできるようにする。

Vin 1mVが4.9mV(1bit分)になればいい。非反転増幅回路を使おう。増幅率を4.9倍にする。

MOTのブログ


非反転増幅回路の増幅率は1 + (R2 / R1)。R1 = 1kΩとすれば,R2 = 3.9kΩになる。C1は0.1μF。

これをAruduinoで組むと,


MOTのブログ

けっこう複雑だ。拡大してジャンパーワイヤを追ってみてください。


ボード図で描くと次のようになる。少しはスッキリするだろうか。


MOTのブログ

GND-OPアンプ pin3の電圧が1Vになるようボリュームを調整。

出力pin6が4.9Vになっていることを確認してほしい。増幅率4.9ということだ。

ただし,入力電圧は約1V以上は測定できない。増幅できるのは最大でも電源電圧5Vまでだからだ。

(1V * 4.9 = 4.9V)

実際はモニタできるのは0.7V程度までとどまることがある。理由は改めて説明しよう。

アナログ変換の続き オペアンプ

Arduinoアナログ変換の分解能は10bit。10bit = 1024。

ということはモニタできる最小単位は5V / 1024 = 約4.9mVだ。

これより細かい電圧をモニタする場合はどうすればいいか。


オペアンプ(OPアンプ)を使う。OPアンプの詳しい説明はここではしないので自分で調べてください。


MOTのブログ


このアンプのピン配列。1回路入りのオペアンプだ。ほかに2回路,4回路入りのものがある。

VDDは電源のプラス,VSSは電源のマイナス,NCはnot connected 未接続。
MOTのブログ


覚えておいてほしいオペアンプの使い方は

・反転増幅回路

・非反転増幅回路

・ボルテージフォロア(バッファ)


【反転増幅回路】

Vout = -1 * Vin * (R2 / R1)。

入出力の極性が反転する。式の通り増幅率-1 * (Vout / Vin)は-1より小さい(絶対値)も可。-0.5とか。

入力インピーダンス※1はR1。


MOTのブログ


【非反転増幅回路】

Vout = Vin * (1 + R2 / R1)

入出力の極性は同じ。式の通り増幅率1より小さくはならない。

入力インピーダンスは高い※2


MOTのブログ

【ボルテージフォロア】

Vout = Vin ※3

入力インピーダンスは高い。

MOTのブログ

上の回路で電源は±になっているが,Arduinoには+5Vしかない。

なので,単一電源で動作するOPアンプを使おう。

その場合電源のマイナスはGNDにつなぐこと。

もうひとつ,バイパスコンデンサを電源とGNDの間にはさむ。ノイズを減らす役目がある。



MOTのブログ


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

※1 Vinからの電流の流れにくさ。単位はΩ。

※2 オペアンプの入力端子自体の入力インピーダンスは非常に高い。

   データシートではInput Resistanceの欄を見る。

※3 増幅率1倍に何の意味があるのか不思議に思ってくれるとうれしい。

   理想オペアンプは入力インピーダンスが無限大,出力インピーダンスが0Ω。

   これの意味するところは,VIn, Voutにつながる回路に影響を与えない(変化しない)こと。

   インピーダンス変換,回路の分離に使われる。

アナログ変換 電圧の読み方 ついでに関数電卓

アナログな人間だから、は自嘲的な言いかた。
デジタルはなんだかカッコイイ(かな?)
電子回路でもデジタルが幅を利かせているように見える、がキモはアナログだと思う。


前置きが長くなった。電圧を読むスケッチを作ろう。その前につなぎ方の回路図は以下の通り。


MOTのブログ


VR01はボリューム(半固定抵抗器)。プラスドライバなどで回すとの位置が動いて

5V - ← の抵抗値が変わる(当然GND <-> も変わる)。


MOTのブログ


使うのは10kΩでいいでしょう。(103は10kΩ。10 * 10^3ということ)


MOTのブログ

電圧は抵抗で分圧できる。抵抗が10kΩ,GND <-> 間の抵抗nkΩだとすると

←の電圧は5V * (n / 10)。5kΩだとすれば2.5Vになる訳だ。


スケッチの例から01Basics-AnalogReadSerialを使おう。

電圧を読むことができるpinはA0-A5(Analog0-5ということか)。

早速スケッチを見てみる。


void setup() {
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
}

// the loop routine runs over and over again forever:
void loop() {
  // read the input on analog pin 0:
  int sensorValue = analogRead(A0);
  // print out the value you read:
  Serial.println(sensorValue);
  delay(1);        // delay in between reads for stability
}

値はシリアルモニタで確認しよう。

int sensorValue = analogRead(A0);

pin A0から電圧の値を読む関数。

0-5Vを1024分割,0-1023に変換したものだ。

ボリュームを回すと値が変わるのが分かる。これをアナログ・デジタル変換という。


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

アナログ・デジタル変換の細かさを分解能という。Arduinoは10bit。2の10乗だ。1/1024に分割できる。


電卓をたたいてみよう。Windowsの電卓はメニューより表示-関数電卓を選択すると以下のようになる。

MOTのブログ


2の10乗は矢印のボタンを使う。「2」-矢印のボタン-「10」で計算できる。答えは1024。

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

LEDやボタンでは直接ピン番号番号を指定したが。analogRead()は記号を指定。

これは,pins_arduino.hというファイルの中でstatic const uint8_t A0 = 14

と定義されている。なので、

int sensorValue = analogRead(14);でも構わない。

ちょっと休憩 delay

スケッチの説明でさりげなくdelay()に触れてきた。
これはプログラムの実行を遅延するための関数だ。
delay(ms) はミリ秒(1ミリ秒は1/1000秒)待つ。遅延時間なのでms の値は1以上 4,294,967,295まで。
なので約50日待つことができる(誰が使うのだろう)


これ以外に
delayMicroseconds(us)  マイクロ秒待つ(1マイクロ秒は1/1000000秒)
millis()            プログラムが開始してからの経過時間(ms)
など。


millis()はスケッチの例02Digital-BlinkWthoutDelayを参照のこと。


delay~はLED点滅以外にも、周辺機器の動作完了待ち(メカニカルリレーとか)、
フィルタの安定時間待などにも使う。


ボタンを押すと何が起こるのか?

以前,デジタル出力はLDで説明した。今回はデジタル入力について説明しよう。

pin の入力がHIGHかLOWかを検知する。

Aruduinoは下の通り。

pin 2からブッシュボタンの片側の足につなげ,もう片方の足はGNDへ。


MOTのブログ


(ブレッドボード中央の黒い丸がボタン。足が左右に2本ある)
回路図にすると次の通り。


MOTのブログ

スケッチの例からDigitalReadSerialを選択しよう。

前々回のブログ「シリアル通信 日本語は送信できるか?」を参照のこと。

いつもの通り,最初のコメントは省略。
int pushButton = 2;

// the setup routine runs once when you press reset:
void setup() {
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
  // make the pushbutton's pin an input:
  pinMode(pushButton, INPUT);
}

// the loop routine runs over and over again forever:
void loop() {
  // read the input pin:
  int buttonState = digitalRead(pushButton);
  // print out the state of the button:
  Serial.println(buttonState);
  delay(1);        // delay in between reads for stability
}
-------------------------------------------------------
 int pushButton = 2;
ボタンにつながるピンは2を使う。 
  pinMode(pushButton, INPUT);
pushButton = 2(pin)を入力(INPUT)に設定する。
  int buttonState = digitalRead(pushButton);
pushButtonの状態をdigitalRead()はbuttonStateに返す。

buttonStateはHIGHかLOWのどちらかなのだが,ボードに書き込んでモニタすると,

(モニタはメニュー-ツール-シリアルモニタ)
押されたら0, 離したら1になるはずだ。これは、Arduino.hというファイルの中で

#define HIGH 0x1
#define LOW 0x0
と定義されているからだ。つまりHIGHのときはbuttonState = 1ということ。

(Arduino.h, #defineの説明は別の機会に)


HIGHかLOWの境界は1.1Vらしい(要出典)


MOTのブログ

なので、入力が0VでLOW,5VでHIGHになる。


ボタンを押したら pin はGNDにつながるので0Vでいいだろう。では離したときの5Vは?

実は,プルアップといってpinを抵抗経由で5Vにつながった状態,下の赤で囲まれた部分だ。

ボタンを離すと5Vになり、押してても抵抗があるので電流はほとんど流れない。


MOTのブログ
ボタンを離した状態で,

1

0

1

1

0

になったかもしれない。(運がよければ11111)

プルアップがないめたに,pin 2は宙ぶらりんでどんな電圧か分らない。そのためだ。

上の回路図の通り外部プルアップでもいいが,Arduinoは内部にプルアップを持っている。

プルアップを使うには明示的に指定しなければならない。

それが,

pinMode(pushButton, INPUT_PULLUP);

INPUT_PULLUPはピンは入力でプルアップしろという意味。


なぜ,スケッチ例でINPUTを使ったのだろう?

シリアル通信のしくみ

スケッチをの解説をしよう。いつもどおり最初のコメントは省略。


int pushButton = 2;

// the setup routine runs once when you press reset:
void setup() {
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
  // make the pushbutton's pin an input:
  pinMode(pushButton, INPUT);
}

// the loop routine runs over and over again forever:
void loop() {
  // read the input pin:
  int buttonState = digitalRead(pushButton);
  // print out the state of the button:
  Serial.println("communication test");
  delay(1);        // delay in between reads for stability
}
-----------------------------------------------------------------
Serial.begin(9600);
はシリアルの通信速度を指定する。1回でいいのでsetup()の中で記述。

Serial.println("communication test");
は送信する内容を指定する。数字,文字列の指定ができる。
数字のとき""は不要。


シリアルモニタでは改行してスクロールされるが,それは
Serial.println()が末尾に自動的に改行コードをつけるため。
Serial.print()という関数は改行コードをつけない。
両方の関数ともSerial.print(78, HEX)というように2番目のパラメータでフォーマット
を指定することができる。省略も可。
 

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

ちなみに,通信速度はボーレート(baud rate)と言い,

Aruduioは 300, 600, 1200, 2400, 4800, 9600, 14400,
19200, 28800, 38400, 57600, 115200に対応している。単位はbit per second(bps)。
それ以外に以下の設定をするのだが,(デバイスマネージャで確認できる)

MOTのブログ


Aruduioではボーレート以外設定しない。デバイスマネージャの設定は無視される。

既定値があると思う。
なのでPCやAruduioとの通信は気にしなくてもいいが,ほかの機器と通信するときは注意が必要。


それにしてもデフォルトで9600とは。遅くない?


シリアル通信 日本語は送信できるか?

TxD(送信 Transmit eXchange Data),RxD(受信 Recieved eXchange Data)で通信をする。

Arduino基板にはTX->,RX<-と書かれてる。

書き込みUSBもシリアル通信。(なのでシリアルポートを選ぶ必要がある)


MOTのブログ

通信先は? とりあえずUSBに接続されているPC。Arduino-Arduinoでも通信できる(はず)。


スケッチの例を使おう。この例は押ボタンの状態PCでモニタするのだが、押ボタンの説明は後ほど。

とりあえず文字を送ってみる。


MOTのブログ

// the loop routine runs over and over again forever:
void loop() {
  // read the input pin:
  int buttonState = digitalRead(pushButton);
  // print out the state of the button:
  Serial.println(buttonState);
  delay(1);        // delay in between reads for stability
}
-------------------------------------------------------

Serial.println(buttonState);

Serial.println("ここに好きな文字をいれる");

と書き換える。文字(列)の場合はダブルクォーテーション""で囲むこと。

早速書き込んでみよう。Ctrl+U(uploadの略か?)


PC側ではシリアル通信を送受信するソフトが必要だが、Arduinoにはシリアルモニタがある。


MOTのブログ


シリアルモニタに文字が表示される。が、日本語は対応していないようだ。文字化けする,残念。


MOTのブログ

オープンソースのTera Termを使おう。日本語表示にも対応している。(キーワード:PuTTY)

http://sourceforge.jp/projects/ttssh2/


-------------------------------------------------------
ちなみにシリアル通信とはデータをデータを1ビットずつ連続的に送受信する通信方法のこと。

シリアル通信の規格はRS-232C,RS-485など。

SPI(ADコンバータ、SD制御など),I2C(RTC制御など)もシリアル通信。


昔のWindows(Xpまで?)にはハイパーターミナルというシリアルモニタがついていた。


ArduinoではUSBチップにATMEGA16U2を使っているようだ。

ドライバのインストールではFTDI USB Driversのフォルダを指定しているようだがFTDIとの互換はない?

スケッチの場所など

前のブログでも書いたが、スケッチの保存先はデフォルトでは

C:\Users\ユーザー名\Documents\Arduino

これはメニューのファイル-環境設定の環境設定ダイアログから変更できる。

環境設定ダイアログの「以下のファイルを直接編集すれば、より多くの設定を行うことができます。」

下のに表示されるC:\Users\~ をクリックすると環境設定ファイルpreferences.txtのフォルダが開く。

現在開いているスケッチは「ファイル-スケッチ-スケッチのフォルダを表示」で表示できる。


HTML形式でもスケッチをコピーできる。「ファイル-編集-HTML形式コピーする」

Webにアップするのに利用できるだろう。このブログでも時々使う。


スケッチをzip形式で圧縮することもできる。「ファイル-ツール-スケッチをアーカイブする」。


スケッチの例-01Basics-BareMinimumで必須関数のsetup(), loop() を含む{ }が空のファイルが

作成される。


フェードイン/アウトのしくみ

スケッチを見てみよう。最初のコメントは省略。


int ledPin = 9; // LED connected to digital pin 9

void setup() {
  // nothing happens in setup
}

void loop() {
  // fade in from min to max in increments of 5 points:
  for(int fadeValue = 0 ; fadeValue <= 255; fadeValue +=5) {
    // sets the value (range from 0 to 255):
    analogWrite(ledPin, fadeValue);
    // wait for 30 milliseconds to see the dimming effect
    delay(30);
  }

  // fade out from max to min in increments of 5 points:
  for(int fadeValue = 255 ; fadeValue >= 0; fadeValue -=5) {
    // sets the value (range from 0 to 255):
    analogWrite(ledPin, fadeValue);
    // wait for 30 milliseconds to see the dimming effect
    delay(30);
  }
}
-------------------------------------------------------

setup() の中に関数がない。analogWrite()は出力の指定をする必要がないだ。

なのでpinMode(ledPin, OUTPUT)は不要。


for文について簡単に説明しよう。詳細は別の機会に。

  for(int fadeValue = 0 ; fadeValue <= 255; fadeValue +=5) {
  }
条件に応じてで{ }の中が繰り返される。条件とは,

1. 変数fadeValue = 0にする

2. fadeValueが255より小さいときは(fadeValue <= 255)

3. fadeValueに5を足す(fadeValue += 5)

4. fadeValueが255になったら{ }を抜けて次に進む

次のfor文

  for(int fadeValue = 255 ; fadeValue >= 0; fadeValue -=5) は,

1. 変数fadeValue = 255にする

2. fadeValueが0より大きいときは(fadeValue >= 0)

3. fadeValueから5を引く( fadeValue -= 5)

4. fadeValueが255になったら{ }を抜けて次に進む


for(変数初期化; 繰り返し条件; 変数変更){

}


デューティーを0-255まで5ずつ増やし、255-0まで5ずつ減らす。

これでフェードイン/アウトするのだ。


pins 5, 6を使うときは注意が必要。 Notes and Known Issues 参照のこと

http://arduino.cc/en/Reference/AnalogWrite?from=AnalogWrite.PWM

LED フェードイン/アウト

これまではLEDの点灯、消灯を扱ってきたき。今回はフェードイン/アウト。

いまでは携帯のLEDなどはフェードイン/アウト珍しくもないが、その昔マイクロコンピュータでLEDをフェードイン/アウトさせるのはかなり面倒な作業だった。

なので、マイコン愛好家にとってフェードイン/アウトのテクニックは憧れだった(かもしれない)。


Arduinoはこのフェードイン/アウトを簡単に実現することができるのだ。

(今のマイコンでも簡単になっているのだけどね)

それはPWM(pulse width modulation),パルス幅変調のおかげ。

パルス幅変調とは工学的な響きだが、一番わかりやすいコトバかもしれない。

原理は下の通りで、5V, 0V(HIGH, LOW,)を高速で繰り返す。

Arduinoの場合周期は約490Hz。時間にすると約2ms.になる。



MOTのブログ

このパルス幅の比率をデューティー比という。

LEDを明るくするには下のようにデューティー比を大きくすればいい。

(高速で点滅しているので残像効果のため)

MOTのブログ


パルス幅は0-255段階で指定できる。関数は


analogWrite(pin, value)


pinは3, 5, 6, 9, 10, 11が使える。

valueが0-255。255の時がデューティー比100%で一番明るい。



説明が長くなったが、スケッチしてみよう。スケッチの例から、

MOTのブログ


LEDのつなぎは前回と同じ。早速マイコンボードに書き込もう。
フェードイン/アウトしただろうか。