概要
analogRead()は、アナログ‐デジタル(AD)変換器を使って、アナログピンから値を読み取ります。
Arduino Unoは、10ビットのAD変換機を6個持っています。analogRead()では、ADMUXとADCSRA、ADCL、ADCHという4つのレジスタを利用します。
ADMUX
ADMUX(ADC Multiplexer Selection Register)は、参照電圧の設定と出力値の形式(ビットを左詰めにするか右詰めにするか)、チャネル(アナログピン)の選択を制御するレジスタです。
ADMUX | ||||||||
---|---|---|---|---|---|---|---|---|
ビット | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
名称 | REFS1 | REFS0 | ADLAR | - | MUX3 | MUX2 | MUX1 | MUX0 |
REFS0とREFS1は、参照電圧の設定を行います。組み合わせにより意味が異なります。
REFS1 | REFS0 | 意味 | analogReference()の引数 |
---|---|---|---|
0 | 0 | AREFピンに与えた電圧 | EXTERNAL(0) |
0 | 1 | デフォルトの参照電圧(Arduino Unoの場合は5V) | DEFAULT(1) |
1 | 0 | 予約(未使用) | - |
1 | 1 | 内蔵の参照電圧(Arduino Unoの場合は1.1V) | INTERNAL(3) |
ADLARは、読み取った値を格納するレジスタ(ADCLとADCH)の値が、左詰め(1)か右詰め(0)かを指定します。Arduinoでは、右詰め(0)固定です。
MUX0からMUX3はアナログピンの選択のためのビットです。4つのレジスタの値の組み合わせによりピンを選択します。Arduino Unoでは、以下の組み合わせが有効です。
MUX3 | MUX2 | MUX1 | MUX0 | アナログピン |
---|---|---|---|---|
0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 1 | 1 |
0 | 0 | 1 | 0 | 2 |
0 | 0 | 1 | 1 | 3 |
0 | 1 | 0 | 0 | 4 |
0 | 1 | 0 | 1 | 5 |
0 | 1 | 1 | 0 | 6 |
MUX3…MUX0=1000を選択すれば、内蔵温度センサから値を読むことができますが、この機能はanalogRead()では利用できません。詳細は、内蔵温度センサの実験のページをご覧ください。
ADCSRA
ADCSRA(ADC Control and Status Register A)は、AD変換器の制御を行うためのレジスタです。
ADCSRA | ||||||||
---|---|---|---|---|---|---|---|---|
ビット | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
名称 | ADEN | ADCS | ADATE | ADIF | ADIE | ADPS2 | ADPS1 | ADPS0 |
ADEN(ADC Enable)を1に設定すると、AD変換を有効にします。AD変換を有効にする処理は、main()関数から呼ばれるinit()という関数の中で行なわれています。
ADSC(ADC Start Conversion)を1にするとAD変換を開始します。AD変換が行われているときはこのビットは1で、AD変換が終了すると0になります。
ADATE(ADC Auto Trigger Enable)は、AD変換の自動起動を制御します。Arduinoでは使われていないようです。
ADIF(ADC Interrupt Flag)とADIE(ADC Interrupt Enable)は、割り込みに関する制御を行います。Arduinoでは使われていないようです。
ADPS(ADC Prescaler Select Bits)2とADPS1、ADPS0は、クロックの分周比を設定するためのビットで、AD変換の際のクロック数を決めます。組み合わせの意味は以下の通りです。
ADPS2 | ADPS1 | ADPS0 | 分周比 |
---|---|---|---|
0 | 0 | 0 | 2 |
0 | 0 | 1 | 2 |
0 | 1 | 0 | 4 |
0 | 1 | 1 | 8 |
1 | 0 | 0 | 16 |
1 | 0 | 1 | 32 |
1 | 1 | 0 | 64 |
1 | 1 | 1 | 128 |
AD変換で10ビットの精度を得るためには、50kHz~200kHzのクロックを供給する必要があります。精度を落としていいのであれば、200kHzよりも高い周波数でもいいようです。Arduino Unoでは、init()の中で、ADPSを0b111、すなわち、分周比を128に設定しています。Arduinoで使っているクロックの周波数は16MHzなので、結果として、16MHz/128 = 125kHzとなります。また、AD変換には13クロックを要するため、AD変換を行うのに必要な時間は、1/125kHz*13 = 0.000104秒 = 104マイクロ秒となります。
ADCH、ADCL
ADCHとADCLは、AD変換の結果を格納するレジスタです。ADMUXレジスタのADLARビットの値により、結果の格納方法が異なります。Arduinoでは、ADLARビットは0と設定するため、10ビットの変換結果の上位2ビットがADCHに、下位8ビットがADCLに格納されます。
analogRead()のリファレンスはこちらをご覧ください。
ソースコード
analogRead()は、hardware/arduino/avr/cores/arduino/wiring_analog.c に定義されています。以下に全ソースコードを示します。Arduino Unoの場合に適用される部分だけを抜粋しています。実際には#if によりさまざまなチップに対応しています。
|
|
入力はpinで、uint8_t型の変数です。出力はintで、AD変換の結果の10ビットを返します。
まず、pinの番号の変換を行います。
|
|
例えば、アナログピンの0番は、0という数値かA0という変数で表します。Arduino Unoでは、A0は14、A1は15というように定義されています(hardware/arduino/avr/variants/standard/pins_arduino.h)。このため、最初にpinが14以上の場合はA0などの表記が使われたとみなし、14を引く処理をしていると思われます。A0が14と定義されているのは、アナログピンをデジタルピンとして使うこともでき、アナログピンの0番がデジタルピンの14番として利用できるためです。
次に、ADMUXレジスタを設定します。
|
|
analog_referenceはADMUXのREFS1(ビット7)とREFS0(ビット6)に設定されます。pinは、0x07(二進数では0b00000111)と論理積をとり、これらを論理和で連結します。ADLARは明示して設定はしていませんが、0が設定されます。
AD変換を開始します。
|
|
sbi()は、第1引数で指定したアドレスの内容の第2引数ビットを1に設定するマクロです。ADCSRAのADSCビットをセットすることでAD変換が開始されます。
AD変換が終了するのを待ちます。
|
|
bit_is_set()は、第1引数の第2引数ビット目が1かどうかを調べるマクロです。ADCSRAのADSCが1の間はループで待ちます。0になればAD変換完了です。
AD変換結果が格納されているADCLとADCHを読み取り、16ビット(上位6ビットは0)の数値に変換して、リターンします。
ADCLを読みだすと、その後ADCHを読みだすまではADCHは更新されません。このため、先にADCLを読む必要があります。
この変換は、ADCマクロで行います。
|
|
バージョン
Arduino AVR Boards 1.8.6
最終更新日
March 21, 2023