スポンサーリンク
ものづくり・DIY

Arduinoで可変抵抗を読む|analogReadと分圧のしくみ、map()でLEDの明るさを変えるまで

値を使いやすく変換する:電圧の計算とmap()

電圧に直して表示する

analogRead の値は0〜1023の段階の番号なので、電圧として見たいときは計算で直します。基準電圧が5Vの場合、次のように書きます。

スポンサーリンク
int value = analogRead(A0);
float voltage = value * 5.0 / 1023.0;
Serial.println(voltage);

ここで「5.0」「1023.0」と小数点を付けているのには意味があります。Arduinoのスケッチでは、整数どうしの割り算は小数点以下が切り捨てられます。value * 5 / 1023 と書くと、計算の途中がすべて整数になり、結果が0から5の整数にしかならないためです。小数で計算したいときは、式のどれかを小数(float)にしておきます。

1023で割るか1024で割るかは、資料によって書き方が分かれます。最大値の1023を5Vとして表示したいなら1023、1段階の幅をそろえる考え方なら1024です。違いは5mV程度なので、可変抵抗の位置を見る用途ではどちらでもかまいません。

map()で別の範囲に変える

実際の作品では、0〜1023の値をそのまま使うより、「0〜100の割合」「0〜255の明るさ」「点滅の間隔100〜1000ミリ秒」など、別の範囲に直して使うことが多くなります。そのための関数が map() です。

int value = analogRead(A0);
int percent = map(value, 0, 1023, 0, 100);

map(値, 元の最小, 元の最大, 新しい最小, 新しい最大) の順に書くと、元の範囲での位置を新しい範囲に比例で写した値が返ります。上の例では、512なら50付近、1023なら100になります。新しい範囲の最小と最大を逆に書くと、向きを反転させることもできます。map(value, 0, 1023, 100, 0) なら、回し切ったときに0になります。

map()を使うときの注意

map() には、知っておくと迷わない性質が二つあります。

  • 計算は整数で行われる:小数点以下は切り捨てられます。0〜1023を0〜3に写すと、3になるのは1023のときだけで、各段階の幅がそろいません。段階に分けたいときは、value / 256 のように割り算で区切るほうが、幅のそろった4段階(0〜3)になります。
  • 範囲の外の値も、そのまま比例で計算される:入力が元の範囲を超えると、結果も新しい範囲を超えます。可変抵抗の値は0〜1023に収まりますが、センサーの値などを写すときに範囲を守りたい場合は、constrain(値, 最小, 最大) で外側を切り落とします。
変換の書き方の使い分け(map()と割り算で区切るの比較)
連続した値か、段階かで選ぶ。
スポンサーリンク

LEDの明るさを変える:analogWriteとPWM

回した量で明るさを決める

可変抵抗を読めるようになったら、その値で何かを動かしてみます。分かりやすいのは、LEDの明るさをつまみで変える作例です。先ほどの配線に、LEDと抵抗を加えます。

可変抵抗のつまみを回してLEDの明るさを変える手元
つまみの位置でLEDの明るさが変わる
  1. USBを抜いてから、デジタル9番からLEDのアノード(足の長い側)へ、抵抗を通してつなぐ。
  2. LEDのカソード(足の短い側)をGNDにつなぐ。
  3. 抵抗は、5Vで赤いLEDなら数百Ω(220Ω〜330Ω程度)を目安にする。
const int potPin = A0;
const int ledPin = 9;

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

void loop() {
  int value = analogRead(potPin);
  int brightness = map(value, 0, 1023, 0, 255);
  analogWrite(ledPin, brightness);
}

つまみを回すと、LEDが消えた状態から少しずつ明るくなるはずです。analogWrite に渡せるのは0〜255の値なので、map() で0〜1023を0〜255に写しています。0〜1023を4で割っても同じ範囲になるので、value / 4 と書くこともできます。

PWMは「速い点滅」で明るさを作る

analogWrite という名前ですが、Unoは実際に電圧を細かく変えているわけではありません。出力をHIGHとLOWで速く切り替え、HIGHの時間の割合(デューティ比)を変えています。この方式をPWM(パルス幅変調)と呼びます。255なら常にHIGH、0なら常にLOW、128ならおよそ半分の時間がHIGHです。

切り替えは1秒間に数百回以上と速いため、目には点滅が見えず、平均した明るさとして感じられます。LEDの明るさやモーターの回り方のように、平均で効くものを調整するのに向いた方式です。一方、本当に一定の電圧が必要な回路には、そのままでは使えません。

スポンサーリンク

PWMが使える端子

Unoでは、PWMを出せるのはデジタル3、5、6、9、10、11番の6本で、ボードの表記では数字の横に「~」の印が付いています。印のない端子で analogWrite を使うと、中間の明るさにならず、点くか消えるかのどちらかになります。ほかのボードではPWMを出せる端子が違うので、ボードの資料で確かめてください。

analogReadとanalogWrite(analogReadとanalogWriteの比較)
名前は似ていても中身は別物。

人の目に合わせて明るさを整える

試してみると、つまみを半分回した時点でかなり明るく見え、後半はあまり変わらないように感じるかもしれません。人の目は暗いところでの明るさの変化に敏感で、明るいところでの変化には鈍いためです。気になる場合は、値を2乗してから範囲を合わせると、回した感覚に近い変わり方になります。

long v = analogRead(potPin);
int brightness = v * v / 4096;  // 0〜約255
analogWrite(ledPin, brightness);

1023×1023は約104万で、普通の int(Unoでは約3万2千まで)には収まらないため、long 型で計算しています。整数の範囲を超えると思いがけない値になるので、掛け算で大きくなる計算では型に注意します。

次のページへ値のふらつきを抑える
スポンサーリンク
  1. 秋の戸口に並ぶかぼちゃの明かりとかぶ、麦束
  2. 資料を手に落ち着いて話し合う二人
  3. ノートパソコンと資料、外付け記憶装置がある机
  4. 冬の木で越冬する卵のうやミノムシ、テントウムシ
  5. 青い折り鶴と三角に折った紙、無地の折り紙