LoginSignup
3
0

More than 1 year has passed since last update.

analogReadの値の変換を誤解していた話(1023、1024問題)

Last updated at Posted at 2021-12-03

analogReadの最大値が1023なのに1024で割るときがあるんですか!?

あるんです。

それはanalogWriteのとき

では皆さん、アナログ入力の電圧によってLEDの明るさを変えるスケッチを書いてください。

dame.ino
int lv = 0;

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

void loop() {
  lv = analogRead(A0);
  analogWrite(11, lv * 255 / 1023);
}

上みたいなスケッチを書いたあなた。ダメです!

どこがマズいのか。* 255 / 1023のところがマズい。

「え、だってanalogReadは10bitで最大値は1023、analogWriteは8bitで最大値は255じゃん。何が間違ってるの?」って大半の人がなっていると思う。僕も最初はそうだった。

こう考える人はこの1023だとか255って数字を連続値だと考えてしまっている。量子化してるのに連続値で考えていいのか。いや、よくない。

簡略化して考える

ぶっちゃけ、1023とか255とかでかい数字だから考えにくい。4bitから2bitへの変換(最大値15から最大値3への変換)を考えてみよう。

次の図を見て欲しい(手書きの図のままになっていたら力尽きて図の更新ができなかったということなので暖かく見守ってください)。
IMG_9E7878304EBC-1.jpeg

そんなに複雑な図じゃない。0-5Vの区間を2bit・4bitで量子化したときの対応を表している。
これを見て何かに気づいた方はいるだろうか?

…ふんふん?なるほど。
そう!2bit側と4bit側で上位2bitが一致している!たとえば2bitの10のところ。4bitの方は1011、1010、1001、1000と上位2bitが10になっている。

じゃあ2bitの方と4bitの方の桁を揃えてみよう。2bitの方の頭に00をつけて桁を揃える。たとえば10は0010になる。
こんな感じになる。
IMG_34F40C219C0E-1.jpeg

また、何か気づいた人はいるだろうか?

そう、4bit側から2bit側へで2桁分の論理右シフト演算になっている。
10進数で言えば$\div 2^2$の計算、これは* 256 / 1024に他ならない。

じゃあいつ1023は出てくるの?

△bitから□bitへの変換、要は量子化とかの細かさの変換には1024とかのキリ番が出てきた。
裏を返せば量子化とかまったく関係ないときに1023は出てくる。

例えば、入力電圧をシリアルモニタに表示するときとか。

sample_1023.ino
int lv = 0;

void setup() {
  Serial.begin(9600);
}

void loop() {
  lv = analogRead(A0);
  Serial.println(lv * 5 / 1023);
}

最後に

長々と書いたが、ぶっちゃけ、255/1023256/1024の違いなんて微々たる差(1%にも満たない)で考慮する必要ないだろと思う。こういうことは言ってはいけない

僕自身、あーだこーだ考えて理解したものだったので共有したくなった。
特に、論理シフトの考え方が出てきたあたりとか、基本情報でやるようなことでも実際のプログラミングで役に立つという話でとてもおもしろかった。

Arduinoプログラミングにも慣れてきた方々、僕と一緒にこういう細かいところにも気を使いつつ楽しんでいきましょう。
初心者はこんなクソ細かいことを気にするより色々作ってみたほうがいい。こういうことも言ってはいけない

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0