ミスが広まる 1/1023 vs 1/1024
定番回路、「これはあかんやろ」を指摘したんが
・液晶表示モジュールを4ビットモードで使ったときの空きピン処理。
誰かが始めた間違ったつなぎ方(この場合はチップメーカーのアプリケーション
ノートか)がずっと踏襲されて広まってしまったというのを発見しました。
これをトラ技の記事にしたのが2009年5月号。
以後、空きピンをGNDにつないでしまう例、だいぶ少なくなってきたように思います。
で、新年早々こんなのを発見しました。
・ラジオペンチ Arduinoを使ったバッテリー放電器
A/D変換データを電圧値にスケーリングする処理がスケッチに書かれています。
ArduinoのanalogRead() は10bit。 0~1023(10進)の値が得られます。
これの処理が間違っていたのです。
ここ↓// battV = analogRead(0) * Vcc / 1023.0; // バッテリー電圧測定(これは間違いで、)
battV = analogRead(0) * Vcc / 1024.0;
// バッテリー電圧測定(正しくはこっち)
10bit値で1/1023と1/1024の違いですので、差は0.1%ほど。
わずかですが、原理的に間違っていますんでこれはまずいです。
※A/Dコンバータが8bitだとミスによる実際の誤差
が目につくでしょう。
1/255 vs 1/256 で差が0.4%ほどになり、
実値との差に気がつく。
テスターで読んだ値と「微妙に違うなぁ」と。
しかし、10bitになると気が付きにくい。
※もっと極端に2bitだと分かりやすいかと。
ATmega328PのA/Dは10bit。
プログラムの処理としては2bit + 8bitに分割して
レジスターから読み出します。
この上位2bitのデータを考えてみましょう。
出てくる数値は 「0 1 2 3」の4種類。
AREFを5Vとすると、1bitが1.25V。
0は0.0V。 そこから電圧を上げて、
1になると1.25V。
中間の2が2.50V。
最大の3が出るのは入力電圧3.75V以上で。
「1/3」して電圧を求めるのは明らかに間違っていて、
「1/4」が正しいことがわかるでしょう。
A/Dの結果が2進だから勘違いするのかな。
BCD出力だと・・・
100カウント、0~99で基準電圧5Vだと 0~4.95Vを表示。
基準電圧に読み出しデータを乗じて1/100します。
「1/99」する人はいないかと。
※理屈の詳細はラジオペンチさんの記事のコメントをご覧ください。
この「1/1023と1/1024」、調べてみると「1/1023」を使っているプログラム例があちこち
に出てきます。
どこが発端なのかは調べ切れてませんが、ArduinoのanalogRead処理で多いような気がします。
ArduinoではArduinoのアナログ基準電圧入力 も勘違いの処理が広まっているかもです。
正しく使えば、「外部基準電圧とAREFピンの間に抵抗を入れておく」なんてことはしなくてもokですから。
| 固定リンク
« ダイソー「明るいランチャーライト」「単3x2本ハンドライト」 LED通電テスト60日 | トップページ | ダイソーReVOLTES単3 JIS C8708:2019充放電試験 200サイクル目完了 »
「Arduino」カテゴリの記事
- 1/nカウント方式とDDS方式の2相パルス発生回路(2024.10.13)
- おっと。map関数の計算桁に注意(2024.10.06)
- DDS方式の2相パルス発生回路、周波数スキャン機能を付ける(2024.10.05)
- 1クロックでも速くしたい 割込を「ISR_NAKED」で(2024.09.30)
- 1クロックでも速くしたい DDS方式の2相パルス発生器(2024.09.27)
「1023 vs 1024」カテゴリの記事
- おっと。map関数の計算桁に注意(2024.10.06)
- サーミスタでの温度測定、「inf」の出現に耐えられるか?(2024.05.13)
- トラ技2024年5月号に「3.3/65535」(2024.04.07)
- ラズピコだと1/65535が出現(2024.03.30)
- Arduino UNO R4のDACサンプルに出てくるmap関数(2024.02.19)
コメント
どーもです、今年もよろしくお願い致します。
Arduino のリファレンスに、「0から5Vの入力電圧を0から1023の数値に変換する」と書いてあるので、それを忠実にコードにすると1023になるんでしょうね。原文でもそうなってます
http://www.musashinodenpa.com/arduino/ref/index.php?f=0&pos=2113
投稿: radiopench | 2020年1月 8日 (水) 13時30分
radiopench さん、コメントどうもでっす。
ソフト作りの時にその手本は見るけれど・・・原点となるチップ(ATmega328)のデータシートは(ハードウェアの話は面倒なんで)読まない。
やっぱりこれかな。
フルスケールは5Vジャストではなく「5V - 1LSB」だっと。
液晶4ビット駆動の話もそうだし(これはPICの参考本が悪い)、ハードの元となる日立HD44780のデータシートを見れば「4ビット動作のとき、この4本は使われませんので、オープンにしてください」と書いてあるのに従わないんだから。
Arefピンの話も、元となるソースを見れば処理が分かるのに・・・
投稿: 居酒屋ガレージ店主(JH3DBO) | 2020年1月 8日 (水) 16時48分
Arduinoでの解説、英文のほうはずいぶん追記されていますね。
https://www.arduino.cc/reference/en/language/functions/analog-io/analogread/
・・・this yields a resolution between readings of: 5 volts / 1024 units・・・
っと「1/1024」が出てきます。
投稿: 居酒屋ガレージ店主(JH3DBO) | 2020年1月 9日 (木) 09時18分
ArduinoのA/D変換 1023 vs 1024、ちょっと検索
(ラジオペンチさんところに記したのも含む)
・1/1023で計算(間違っている)
https://qiita.com/nyagato_00/items/2937a11630109a3db6e1
https://iot.keicode.com/arduino/arduino-analogread.php
https://deviceplus.jp/hobby/arduino_f07/
https://omoroya.com/arduino-extra-edition-05/
https://www.denshi.club/cookbook/stem/maker-uno-stem-6.html
https://www.denshi.club/cookbook/sensor/temp/l.html
http://easylabo.com/2015/04/arduino/8336/
https://novicengineering.com/%E3%80%90arduino%E3%80%91map%E9%96%A2%E6%95%B0/
※map()での数値範囲をミスってるところがあります。
map(ad, 0, 1024, 0, 256)というふうにしないと。
map(ad, 0, 1023, 0, 255)では、10bit A/Dの中央値512で
8bitの中央値128が得られません。
※電圧計算で、Arduinoの電源電圧や内部基準電圧の値を5.0V、1.1Vと
決め打ちしているのが目に付きます。
ほんとにそうか、計ったことありますかな?
私とこのUNOは5.033V。 5Vより0.7%ほど高い。
電圧測定という課題で、基準を決め打ちするのは問題でしょう。
1/1023の処理とともに、テスターでの実測値とArduinoでの測定値
との差が気にならないのか心配です。 (計って比べてない?)
・正しく1/1024で
https://n.mtng.org/ele/arduino/tutorial008.html
https://hsh.s2jp.com/2011/09/arduino-voltmeter/
https://ogapsan.com/archives/150
https://yoshipc.net/arduino-temp/
http://maicommon.ciao.jp/ss/Arduino_g/AnSr/index.htm
https://nekosan0.bake-neko.net/structure_analog_in.html
https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q14183208509
http://tyk-systems.com/arduinobasic/arduinobasic.html
投稿: 居酒屋ガレージ店主(JH3DBO) | 2020年5月 3日 (日) 14時16分
メモ:コメント先
https://novicengineering.com/%E3%80%90arduino%E3%80%91map%E9%96%A2%E6%95%B0/
投稿: 居酒屋ガレージ店主(JH3DBO) | 2020年5月14日 (木) 13時30分
「map関数」も「1023 vs 1024」です。
・2020年5月17日:Arduino なんとかして誤用を正したい:A/Dの1/1023とmap関数
http://igarage.cocolog-nifty.com/blog/2020/05/post-115911.html
投稿: 居酒屋ガレージ店主(JH3DBO) | 2020年6月 6日 (土) 09時37分
★書籍でもやってる「1/1023」と「map(x, 0, 1023, 0, 255)」
http://igarage.cocolog-nifty.com/blog/2020/09/post-e67167.html
投稿: 居酒屋ガレージ店主(JH3DBO) | 2020年9月 9日 (水) 09時25分
トラ技2021年9月号別冊付録「PIC開発マニュアル2021」でも「1/1023」。
http://igarage.cocolog-nifty.com/blog/2021/08/post-cc3d63.html
投稿: 居酒屋ガレージ店主(JH3DBO) | 2021年8月 6日 (金) 09時31分
EDNは12bit A/Dで「1/4095」をやってます。
『測定電圧=(A-Dコンバーターの変換結果÷4095)×VREF+ 式1』
https://ednjapan.com/edn/articles/2004/06/news004.html
ビット数が増えても考え方はいっしょ。
割る値は12bitなら4096。
投稿: 居酒屋ガレージ店主(JH3DBO) | 2021年8月 7日 (土) 21時55分
16bitのLTC2461。 「1/65535」してます。
data = i2c.read_word_data(addr,0x01)
data16 = swap16(int(hex(data),16))
print (round((Vref * data16 / 65535 ),5))
https://www.denshi.club/pc/raspi/5raspberry-pi-zeroiot35a-d10-2.html
投稿: 居酒屋ガレージ店主(JH3DBO) | 2021年8月 7日 (土) 22時14分
コメント先↓
https://www.jh4vaj.com/archives/28146
投稿: 居酒屋ガレージ店主(JH3DBO) | 2021年8月 7日 (土) 22時33分
ミスが広まる 1/1023 vs 1/1024
こんなの見つけました。
https://www.ti.com/jp/lit/an/jaja085/jaja085.pdf?ts=1629266491845&ref_url=https%253A%252F%252Fwww.google.com%252F
「この中の、12ページ 5.7 ADCのビット(20)」ですが、「2^n-1」で割ってます。
私は、昔から「1/1024」派ですが・・・。数学が不得意なソフトやさんには、「1/1023」派が多い様な気がします。
投稿: 河合 | 2021年8月19日 (木) 09時51分
式(20)の「Vtfullscale」、これが「Vref」そのものじゃなく「Vref - 1LSB」なら「2^n - 1」でok。
これで合ってます。
ただ、件のpdfには「Vtfullscale」の定義が出てこないみたい。
記事の中、例題で示した「2bit A/D」の話。
基準電圧5Vで「2bit A/D」だと、1LSBが1.25V。
「Vref - 1LSB」が3.75V(これ以上の電圧でフルスケール)で、これを「4 - 1」で割って出てくる1LSBは1.25V。
「Vref / 4」も「(Vref - 1LSB) / 3」も同じ答えということで。
Vinを求めるのに、10bitのA/Dだと、
「A/D値 × Vref / 1023」の1/1023がおかしいということで、
「A/D値 × (Vref - 1LSB) / 1023」と
「A/D値 × Vref / 1024」は同じ値になって、この2式は正しいわけです。
1/1023していれば単純に誤りということではなく、Vrefの扱いも見ておかなくてはなりません。
※追記しました
投稿: 居酒屋ガレージ店主(JH3DBO) | 2021年8月19日 (木) 16時02分
引き続き「1/1023」を探索
・YS電子工作ラボ
http://www.ys-labo.com/pic/pic%20chips/pic%20chips%20contets/061001%20Internal%20ADconverter.html
(1)printf(lcd_data,"Vin=%4.3f V",3.968*((float)AdValue/1023)); //10ビット値を電圧値に換算 ←Vref=3.968Vと
4.000Vジャストにしてという目論見だったのだろうか?
4.096Vにすると、10bit A/Dの1LSBが4mVになって、
(12bit A/Dだとちょうど1mV)キリの良い値にはなるんですが。
実測値のA/Dが「829」で表示された計算値が「3.215V」。
1/1024での計算だと「3.212V」に。
実際の入力電圧をテスターで計っていれば、微妙な差に気が付いたかも。
こういったとき、半値や1/4値を見れば「むむっ?」となるはずなんですが。
(2)Vin = (float)ADread/4095*5.0; ←12bit A/Dでも1/4095
(3)Volt =(float)AdcValue/1024*3.3; ←これは正しく1/1024で
16文字×2行の液晶表示モジュール、4bitモードでD0~D3をGNDにしてるし。
※R/W=Lなんで「ちょっと気持ち悪いぞ」でという評価で。
例えばスリーステート出力バッファICのHC540や541、イネーブルを禁止しているからと、
出力端子をGNDにつないでいる状態です。
これ、気持ち悪くないですかという、液晶モジュールの使い方です。
投稿: 居酒屋ガレージ店主(JH3DBO) | 2021年8月21日 (土) 10時14分
『1/1023 vs 1/1024』問題 analogReadを2bitにして確かめてみる
http://igarage.cocolog-nifty.com/blog/2022/11/post-bed4a2.html
投稿: 居酒屋ガレージ店主(JH3DBO) | 2022年11月12日 (土) 16時21分
サーミスタによる温度測定、【1023 vs 1024 問題】が【ゼロ除算問題】に。
A/Dコンバータでサーミスタの抵抗値を読む サーミスタをつなぐ場所は?
http://igarage.cocolog-nifty.com/blog/2023/03/post-ad45c1.html
Arduino サーミスタを使った温度測定で 【ゼロ除算問題】
http://igarage.cocolog-nifty.com/blog/2023/03/post-4bb96a.html
投稿: 居酒屋ガレージ店主(JH3DBO) | 2023年3月25日 (土) 10時41分