Arduino初心者熱烈大歓迎質問スレ part33
■ このスレッドは過去ログ倉庫に格納されています
>>678さんがやっているような実測をもって、この0.5LSBの補正がなされているかどうかの
検証をすることには、ほぼ意味がないと思う。それ以上のオフセットエラーがある。
それに入力電圧が0Vのときに変換値が0にならないようなオフセットエラーはハードでも
ソフトでも補正が効かないので、素子自体は変換値0となる電圧範囲は広く取られることが
多いのでは。 >>696
DeepLをGoogle検索するぐらいはやったうえで、分からん、って言ってるのかな? >>698
最初の質問(>>585)の結論を出すことが目的だとして
現状結論を出せていない
0.5LSBの補正が「有る・無し」が答えのカギとなると思う >>700
>結論:ADCからVinへのスケーリングは「1/1024」で計算しなけ
> ればならない。
> 「1/1023」は間違いである。
これは、明白なことなので、ここでやっているような議論をする意味がない。
誤差のある現実世界のデバイスを実測してみても、あまり意味はない。
様々なエラーを含んだデバイスを、誤差のある測定を行って、仮に
「得られた結果は1LSBは1/1023に近いものだ」
となったとしても、1LSBが1/1024であることに変わりはない。
>>698の主旨は、実験で判断してはいけない、ということなのは理解してもらってるだろか?
こういうことはデータシートかメーカーの公式資料を引用して議論するか、
個人的に納得したいなら、メーカーか公式フォーラムに尋ねるのがいい。
実測で判断したいなら、誤差のないデバイスを持ってくるべき。(数を増やして平均してもだめだよ) UNO(atmega328)の場合
Vin = ( ADC + Offset Error ) * VREF / ( Resolution -1 + Gain Error )
※Gain Error = 2LSB Typ , Offset Error = 2LSB Typ
つまり
Vin = ( ADC + 2 ) * VREF / 1025
これかもしれない・・・(;´・ω・)
詳しい人助けて( ;∀;) >>701
実機は理論通りには動かないってことだな。 >>701のまとめに同意だな。
>>678 が測定してくれたVref5000mVの場合で説明すると、
近似直線は、Vin = 4.8776 * ADC + 7.4907 となっている。
傾きの理論値は 5000/1024=4.8828 なので、実際には少し小さな値で計算しないといけない
ことが判る。そこで、コードは、
#define KA 0.998932 // 感度補正係数
#define KB 7.4907 // オフセット補正量
Vin = KA * ADC * 5.0 / 1024.0 + KB; // 電圧の計算式 (mV)
と書くのが判り易くて良いと思う。
なお、式の中で定数になる部分はコンパイラがあらかじめ計算してくれるので、実際には何度も
計算が必要になる訳では無い。 あと、オフセットの話だけど、
片電源のオペアンプは入力電圧ゼロ付近に30mVくらいの不感帯、つまりオフセットがある。
それに比べるとATmaga328Pのアナログ回路は優秀だと思うよ。 正確な実測データがあるならそれ使って校正するのは測定器なら普通のことだしなぁ。個体のクセは実測データでしか補正できないし。まぁ、正確な実測データを得るのが難しいんだけど。 Vref=5Vのとき
1LSB=5/1024=0.0048828125[V]
(Vrefー1LSB)が1023(0x3ff)になるのだから
5-0.0048828125=4.995117188[v]が0x3ff
最大値が3ffだから1023で割るのかな?と思っちゃった人は
「植木算」を思い出そうず(^p^)
(1〜3ffじゃなくて)0起算だから1024段階、という単純なハナシかとおもいきや、
なんかみんなえらく難しそうなこと話してるなぁ・・・ 1bit DAC は、0Vと2.5Vを出すのだろうか?
0Vと5Vを出すのが自然ではないか。 デジタルとアナログの区別がつかないからDACが成立しないのでは?
1chステレオサウンドといってるようなもの >>710
だがしかしラダー抵抗で解説されているページが検索でヒットしたので
ざっと拝読したところ三ビット出力111で4.375Vだそうですよん(5Vではなかった)。
http://mitt.la.coocan.jp/pic/pic7_16.html DACでもvrefがどの値に対応してるかによる。秋月で売ってるやつ何個か見てみたけど
vrefと2^n(nはビット分解能)
が対応。出力は2^n―1までってのが多かった。microchipとLTだけだから他のところのまではわからんけど。 >>710
どういう回路構成のD/Aを想定してる?
今、話題になっている逐次変換型A/Dの場合は、ラダーD/A+コンパレータの構成をとるものが
多いので、必然的に1LSBの電圧がどうなのかについてはラダーD/Aを前提に考えることになる。
ところが、1ビットD/AだとラダーD/Aにする意味がほぼない。
ラダーを1ビットにすると、単なる分圧になるので2.5V。
でも意味が乏しいからラダーにしないので1ビットなら0-5Vとなると思う。 10ビットA/DでVref/1023考えると精度が要らないから2ビット無視して
8ビットA/Dとして使うときVref/255になるのかVref*4/1023になのかと
考えると1023というのがおかしいことが分かる。
10ビットでVref/1024
8ビットでVref/256
となるのが自然な考え。 ◆Offset
The deviation of the first transition (0x000 to 0x001) compared to the ideal transition (at 0.5 LSB). Ideal value: 0 LSB.
0>1に変化する理想の場所は0.5LSBの位置と有るのでこの説明だと量子化補正の有る理想ADCとの比較が前提となってる
◆Gain error:
After adjusting for offset, the gain error is found as the deviation of the last transition (0x3FE to0x3FF) compared to the ideal transition (at 1.5 LSB below maximum). Ideal value: 0 LSB
1022>1023に変化する理想の位置は最大値(VREF)から-1.5LSBの位置と有るので量子化補正の有る理想ADCとの比較が前提となってる
データシート読むとゲインエラーはオフセット補償をした後の値と有るので
Arduino(UNO)はこれが正解じゃないだろうか・・・
Vin = ( ADC + Offset ) * Vref / ( 1024 + Offset + ( Offset - Gain error ) )
Vin = ( ADC + 2 ) * Vref / ( 1024 + 2 + 2 - 2 )
Vin = ( ADC + 2 ) * Vref / 1026
(※オフセット・ゲインエラーはデータシートの標準値を適応)
参考資料
ATmega48A/PA/88A/PA/168A/PA/328/P(Data Sheet)
AVR120: Characterization and Calibration of the ADC on an AVR (APPLICATION NOTE)
AVR127: Understanding ADC Parameters (APPLICATION NOTE) >>717
328PのデータシートのADCのエラーは、2LSBって書いてあったら、それは±2LSBだよ。(おそらく常識的に)
あと、実回路ではA/D変換に入るまでの回路の誤差もついてくる。
Vref/1024は理屈での話にすぎない。(理屈の話において、Vref/1023は誤り)
オフセットもゲインも実際のセットではリテラル値ではなく、ファームまたは
ハードウェアで作られる変数にするわけだしね。
(ファームならEEPROM、ハードウェアなら半固定抵抗などですね)
入力電圧がいくらなのか、って話をするときに、理屈の話なのか、実際の電圧を知りたいんだ、なのかは
切り分けないといけない。
Vref/1023かVref/1024かは、結果的にはゲインエラーとして効いてくるけど、1024と1023とを取り違えた
ところで、ここで発生する誤差は0.1%にすぎない。でもそのもとのVrefの誤差のほうがはるかにでかい(ことが多い)。
議論の中でVref=5Vがたびたび出てきたけれど、回路内で完結する何かの電圧が同じ5Vから分圧して得られている
ケースをのぞけば、この5Vの誤差がそのままゲインエラーにつながる。
7805みたいなレギュレータで作った5Vなら、数%の誤差があるよね。
328Pには1.1V内蔵リファレンスもある。こっちは正確かなw >>713
3bit程度なら電流加算型にすればいいじゃん 出力の時に1024とか4096で計算すると振り切らない? 使わないボードを選択する一覧から消したいのですが、どこを消せばいいのでしょうか?
promicro,promini5v,promini3.3v
この3つを頻繁に切り替えるので他のやつを非表示にしたいです。 >>718
最初は自分もデータシートの誤差は±2LSBって意味だと思ってた
でもデータシートでは数値は以下の様に明確に区別されてるので±ではないと思われる(たぶん・・・)
https://i.imgur.com/SyzxuYu.png
もう一つの理由としてオフセット誤差・ゲイン誤差の数値がMaxではなくTypとして表記されてる事もある
±2等の誤差で有ればTypではなくMaxの方に記載されてるもしくは(Min>-2LSB MAX +2LSB)の様な表記になるはず
以上の事から自分は±ではなく2LSBの誤差を標準値として考慮する必要があると判断した
議論の中心はanalogReadから入力電圧を求める正しい式は何か?だと思ってる
機種の話は直接的には出てないけどArduino UNO(atmega328)を前提に考えてる
個体差での誤差は考慮出来ないので標準的な誤差はデータシートのTypを元に補償する場合での正しい式を求めようとしてる
ついでに混乱の原因としてAVRのデータシートでも2種類の計算式が記載されてる
https://i.imgur.com/sWKwOtU.png
https://i.imgur.com/GvoiOZ4.png (ATmega4809)
UNO(ATmega328) -> 1024
Micro,Leonardo,(ATmega32U4) -> 1023
Nano Every(ATmega4809) ->1023 >>723
もし標準的に+2LSBになるようにデバイスを製造できるのなら、標準的に0LSBに合わせて製造すればいいのに
なんでそうしなかったんでしょね。
>議論の中心はanalogReadから入力電圧を求める正しい式は何か?だと思ってる
現実の入力電圧を求めるのはハードウェアかソフトウェアの個別チューニングですよ。あくまで理屈の話でしかありません。
「Vref/1024で計算しているから」あるいは「データシートに書かれた標準誤差を含めた計算をしているから」という根拠で
「この装置は正しい入力電圧を得ている」と言えることなんてないです。
それより、>723で興味深いのは、1023と書いているデータシートです。
https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7766-8-bit-AVR-ATmega16U4-32U4_Datasheet.pdf
これの310ページで、たしかにADC=VIN*1023/VREFとなっています。
でも差動チャンネル(10ビットを±9ビットで使う)だと511ではなくて、512なんですね。
一方で、307ページには、
An n-bit single-ended ADC converts a voltage linearly between GND and VREF in 2^n steps (LSBs).
「シングルエンドの10ビットのADコンバータは、GNDからVREFを1024ステップで直線的に変換する」とあります。
また、1023と書かれている310ページにも
0x000 represents analog ground, and 0x3FF represents the selected reference voltage minus one LSB.
変換値0は、アナロググランド、変換値1023は、[選択したリファレンス電圧]-[1LSBの電圧]
となっています。記述に矛盾がありますので、どこかが間違っている可能性が高いと思います。 電池駆動のとき電源電圧が変動すると思うんですが、
例えば、4.8V-3.3Vに変動したとき、処理速度とかAD変換とか
何か弊害が出ることはありますか? >>725
16MHz動作は5V付近でしか保証されなかったような。 できるだけ変動しないようにすればいいんじゃないの? >>725
A/D変換のリファレンス電圧が電源電圧からとられたものだったら、その分狂うね。
ただし、たとえば電源電圧とGNDをサーミスタと抵抗で分圧して温度を測るような
しくみだったら、実害は小さいだろうね。 >>722
ttps://programresource.net/2020/02/28/3015.html
boards.txt を編集して、非表示にしたいボードに .hide=true を設定すればおk int raw = analogRead(A0);
map(raw, 0, 1024, 0,5000);
ってするとえわわわに届かない アドバイス求む
Arduino Pro miniをピンヘッダーを設置と同時に「ヒューズビット」及び
「.hex」ファイルの書換えを行いました。
ユニバーサル基板に「Arduino Pro mini」「USB to TTL converter」「ICSP端子」「その他必要配線」を設置したので
動作確認の為、AVRライターでPro miniと通信しようとしたが、何故かエラーで通信できない?
◆試した事
・デジタルマルチメーターでの導通test -> 問題無し
・ポリウレタン銅線を2度の取替 -> 改善せず
・配線ミスの確認
・本体「Arduino Pri mini」は問題無く動作確認済
●先人の方に何か見落とし等がありましたらアドバイス願います。 >>732
そりゃ〜最大ぬわふあまでなんだからそうなるでしょ お騒がせ致しました。
PCのUSB端子口を変えたら問題無く通信出来ました。 ∧_∧ / ̄ ̄ ̄ ̄ ̄
( ´∀`)< オマエモナー
( ) \_____
| | |
(__)_) わたい江戸っ子だんねん
生まれはかみたと申しますえ 「変ちきなジジイがおりましてさ、百二十畳敷きの紙に大達磨を描いてみたり、かと思えば米一粒に雀を二羽描いてみたり」 nanoにUSBコネクタに繋いで
5Vピンからも5V注入したら壊れる? >>741
Arduino nano は USB 付いてるだろ。 電池駆動だとどこから電源供給するのが良いの?
VINだと6Vから12V
余分な電圧は熱になるが5Vは安定しそう
5Vから入力だと5Vピッタリじゃないとダメなので電池の電圧が瞬間的にちょっと下がっても無理そうだし 電池駆動だとnanoじゃなくpro-miniにするよな >>744
すいませんこれいきなり質問しました
ものは問いません何でもいいです
とりあえずUNOとかm5stackとかは気になります UNOはNanoと同じ、これをバッテリー運用しようとはあまり思わないだろう
M5はバッテリー内蔵をチョイスする uint8_t id[8]
char buf[17];
snprintf(buf, sizeof(buf), "%02X%02X%02X%02X%02X%02X%02X%02X", id[0], id[1], id[2], id[3], id[4], id[5], id[6], id[7]);
これってもっと短く書けない?
速度も重視な感じで。 >>748
sprintfを使わない分メモリ使わないし早い。
見かけの行数は増えるけどね。
uint8_t id[8];
char buf[17];
const char *hex = "0123456789ABCDEF";
for (int pos = 0; pos < 8; pos++) {
buf[pos*2] = hex[(id[pos] >> 4) & 0x0f]; // マスクは不要だが符号ありにも対応するため
buf[pos*2+1] = hex[id[pos] & 0x0f];
}
buf[16] = '\0';
動かしてないからミスがあったらゴメン 短くというよりもっとスマートに書けないものかという要望だと思われ
特に[0]-[7]まで並べる部分が生産性低そうでアホっぽく見えるな sprintfはバッファオーバーフロー起こすからsnprintfやsprintf_s使った方がいいよ バッファオーバーフローなんて起こさないようにプログラムすればいいだけ 気をつければ済む話、というのはだんだん廃れていってる考え方だね。 >>756
組み込みで自分で作って自分で使うものなら問題ない
ファンクションのバッファオーバーフローが問題になってるのはプロジェクトが大きくなってそこでバッファオーバーフローが起こるか起こらないかを把握する事が難しくなったからCPUパワー使ってもファンクション側でチェックすれば安全という考え
絶対にオーバーフローしないような実装ならチェックするだけ無駄 関数の呼び出しコストや
ビットオーダーの問題考えたら考えると
sprintfでよくね? %sで何が突っ込まれるかわからないみたいな状況じゃなきゃ問題は起こらないし
そもそも↑の様な状況を作ってはいけないからな >>753
Arduino に sprintf_s() あるの? >>761
c++で使える関数全部使えるんじゃなかったっけ? すいませんここで聞いていいのか分かりませんが
オペアンプを8個ボルテージフォロワで使いたいのですが
小さくなったICとかでありますか?
用途はアナログセンサーの基準電圧に使いたいです >>763
別にここでもいいけど初心者質問スレの方が適切。あと基準電圧ならボルテージフォロア必要ないと思うが。センサーと言ってもいろいろあるんだから型番ぐらい先に出しとけ。 ド素人の質問です。
elegoo unoにEthernet2Shieldを載せてWebSerberのサンプルスケッチを実行しているのですが、
PCからブラウザでunoのipを入力しても見ることができません。
環境はWiFiルータにunoを有線接続し、PCは無線接続しています。
WebServerのスケッチのMACアドレスをEthernet2Shieldに記載のものにし、
IPはPCと同じセグメントでホストだけ変えています。
何が悪いのかさっぱりわかりません。 例えばDHCPクライアントでもないのに
勝手に無線有線間でルーターのAP機能がオンになるんだろうか?
結局適切なテスト環境でっち上げてピング撃ちまくらないと
原因究明できない気がする >>765
ブラウザで接続を試みた直後、PC側のarpキャッシュにエントリーは出来てない?
あとはPCにwireshark入れてパケットキャプチャ >>766,768,769
なんか朝イチでやってみたところつながりました。
単に入力IPを間違えていたか、Arduinoの電源を入れてからLANケーブル差していたかも。
ボケててすみませんでした。 実はもう一つ質問があります。
あるサイトでEthernet2Shieldは10,11,12ピンを使用するので、
それらのピンは使用できなくなると書いてありましたが、そうなのでしょうか?
そうだとしたらShield自体にもそれらのピンを差すところがありますが、
なんの意味があるのでしょうか?
実際にそれらのピンを使用する回路で、Shield有りの場合は正常動作しませんでした。
Shieldを使用したい場合、それらのピンの使用は諦めて代替手段を考えるべきでしょうか?
なおShieldのSDカード利用は考えていません。 >>752
ループで何回も関数呼ぶよりまとめてスタックに積んだほうが合理的だけどな >>748
じゃあ僕は速度重視だだだ!(^p^)
inline uint16_t Int2Ascii02x(uint8_t uArg){
switch(uArg){
default: return 0x0; // error code.
case '\x00': return 0x3030;
case '\x01': return 0x3031;
... // 中略、全256パターン列挙
case '\xff': return 0x6666;
}
}
を使って直にバッファに書こうぜ!(^p^)(展開後何行だよ・・・) >>771
SPIで通信に使っちゃってるんだから仕方ない
ヘッダがそのピン用にも付いてるのは複数のSPIスレーブデバイスをぶら下げるためか、そこだけ削るのが面倒か >>771
10,11,12ピンはSPIインターフェイスだけど、チップセレクトでデバイスを適切に選択すれば他のSPIからでも使えるはず。
でも、そんなに色々やるとRAMが足らなくなりそうな気が、 嗚呼成程グローバル変数に変換テーブルとして配列を宣言しておいて、
unsigned char ucAscii[]={
'\x3030', //00
'\x3031', //01
'\x3032',//02
...
'\xfe',//254
'\xff'//255
};
buf[0]=ucAscii[id[0]];
buf[1]=ucAscii[id[1]];
...
buf[7]=ucAscii[id[7]];
か。
(※ buf[i]=ucAscii[id[i]];でループ回すより7パターンぐらいなら並べた方が展開後ステップ数は短く早いかも) あぁぁぁあ やってもうた(^p^;)
'\x6665',//0xfe
'\x6666'//ff
でしたな、さーせん><; >>774,775
SPIのスレーブ用ということで理解しました。
Shield以外での当該ピンの使用は諦めてI2Cモジュールでも使います。
ありがとうございました。 inline void byte2str(const uint8_t (&num)[8], char (&str)[17])
{
static const char *hex = "0123456789ABCDEF";
char *ps = str;
for (uint8_t i = 0; i < 8; i++)
{
*ps = hex[num[i] >> 4];
ps++;
*ps = hex[num[i] & 0x0f];
ps++;
}
*ps = '\0';
} v(ブイ) v(ブイ) v(ブイ) ビクトリーコンパイル出撃だー
たとえ最適化がこようとも、たとえ割り込みこようとも いや、さすがのこんばとらーVolatile(?)も、割り込みがかかったら勝たんやろ・・・w 電池駆動で自身の電源電圧を読んで電圧によって動作を変えたいのですが、調整する時にPCとSerial接続していると読み取り値が微妙にずれてしまいます。
スマートに調整する方法は無いでしょうか? ■ このスレッドは過去ログ倉庫に格納されています