レトロでハードな物語

レトロなゲーム機・マイコン・中古デバイスなどをArduinoやAVRで再活用する方法を模索しています。

スリープでA/Dコンバーターの精度を上げる

2020年12月02日 | 電子工作

ここ最近でAVRの省エネについて学んだので、過去に作ったスケッチを省エネ化し始めました。AVRの種類によってレジスタ名が微妙に違ったりするので、データシートを眺めながら作業する必要があるのですが、そこにA/D変換雑音低減動作という記述があることに気が付きました。読んでみるとA/D変換を行うときにAVRをスリープさせてCPUなどを停止し、ノイズを減らしてA/D変換の精度を上げるということでした。この話は前にちょっと聞いたこともあったのですが、当時はよくわからなかったので深く追求はしていませんでした。
今まで行ってきたA/D変換は、ノイズなど考えずただ安易にanalogRead()コマンドでデータを取り込んでいただけでした。もしスリープで精度が上がるのなら試して見る価値はあるでしょう。

もう一点、データシートで気になったのが内蔵の基準電圧についてです。これまでは電源を基準電圧にしていたので使用する電源によってA/D変換の精度にばらつきがありました。AVR内部の基準電圧を使えばさらに測定の精度が上がるかもしれません。

これらを組み合わせると、どのくらいの精度になるのか知りたくなりました。なのでさっそく試してみましょう。
A/D変換の利用で一番簡単なのは電圧計でしょうか。前に電圧計は作ったことがあるので、その時の基板を再利用してテストしてみます。

AVRはATtiny13Aを使います。しかし、ATtiny13A単体で電圧計を作るのは結構ハードルが高かったりします。製作中に色々な問題にぶち当たりました。

まずは電圧を表示するためのディスプレイをどうするかです。普通ならI2C接続のディスプレイを使うかソフトウェアシリアルでPCなどに出力するかでしょうが、どちらもライブラリを必要とするので1Kバイトしかないフラッシュメモリを余計に消費するのはあまりうれしくありません。

それとA/D変換で読み取ったデータを電圧に変換するときの計算で小数点の演算が必要になるのですが、ATtiny13Aでは浮動小数点数演算ライブラリ(?)が大きすぎてコンパイルしたバイナリがフラッシュメモリに収まりません。
仕方がないので固定小数点演算(小数点を何倍かして整数演算する)を使ってみたのですが、計算の途中で数値が16ビットに収まらなくなり、32ビットの整数演算が必要になってしまいました。ところが32ビット変数(uint32_tとかlongなど)を演算に使うと、演算結果が下位16ビットだけにしか入らず、上位16ビットは全て0になるという現象が起きてしまいました。

問題の大部分はプログラムを収納するフラッシュメモリの容量の少なさから来るので、ATtiny85とかを使えばなんとかなるのでしょうが、たかだか電圧計ごときにATtiny85を使うのはオーバースペックでもったいなさすぎます。ここは頑張ってATtiny13Aを使います。

結果、かなり試行錯誤することになりましたが、どうにかスケッチが完成しました。

Attiny13VoltmeterKai.ino



スケッチのコンパイルにはMicroCoreを使います。ボード設定は以下の通り。



動作クロック600kHzの省エネ志向です。ヒューズビットを書き換える為に最初にブートローダー書き込みを行っておきます。

さてディスプレイについてですが、これには汎用のライブラリは使いたくなかったので以前自作したPICベースのLCDディスプレイ装置を利用することにしました。



使用するピンは2本で表示したいキャラクタを送信するだけなので、表示ルーチンを最小限にすることが出来ました。(スケッチのsendChar())

電圧を求める計算には苦労しましたが固定小数点演算にして、使用する変数を最大16ビットに抑えました。演算のアルゴリズムは筆算と同じです。こんな感じですかね。

例) 入力値が10ビット最大の1023(0x3FF)のとき

  1023
X  323 (固定小数点による係数 スケッチ参照)
−−−−−−−−−−−
  3069 (この値を一旦16ビット変数に収納)
 2046  (        〃       )
3069   (        〃       )
−−−−−−−−−−−
330429 (1桁ずつ計算してバイト配列に収納 加工表示のため)


さて本題のA/D変換ですが、ノイズ軽減の効果も期待して必要ない回路の電源を切ります。今回はアナログ比較器(コンパレータ)の電力をカットしました。アナログ入力の端子はADC3(ピン3)を使っていますので、このピンのデジタル入力も禁止しました。

次に基準電圧ですが、ATtiny13Aの内部基準電圧は1.1Vのみです。(ATtiny85は1.1Vと2.56Vが選べるのに)
これだと最大1.1Vまでしか計測できませんので、計りたい電圧を分圧して1.1Vに収まるようにする必要があります。
幸い今回利用した基板はADC3に100kΩ×3個の抵抗が付いていて、200kΩ:100kΩで1/3の分圧にしてありました。つまり3.3Vまでは計測できるわけです。これなら乾電池やコイン電池などの電圧計に使えます。

レジスタで内部基準電圧を1.1Vにしたら、次はA/D変換クロックの設定です。クロックは50〜200kHzがいいみたいなので、本体クロックの600kHzを1/4にして150kHzに設定しました。

スリープモードはA/D変換器や外部割り込みだけを動作させるモードに設定します。A/D変換開始直後にスリープモードに移り、A/D変換完了割り込みによって復帰します。この手順でちゃんと動作していると思うのですが、もしかしたらデータシートを読み違えているかもしれません。スリープ動作は見た目で確認できないので、正しく行われているのか分からないんですよね。
A/D変換完了割り込み処理の中でアナログ入力値を変数に収納していて、動作中は正しい値が入力されているので変換処理は機能しているはずです。

このスケッチで、幾つもの使い古しの乾電池の電圧測定をしてみました。手持ちのテスターによる計測と比較したところ誤差は0.01V前後で、テスターに表示されている小数点以下3桁目の数値を四捨五入すると殆どの場合一致しました。これは前に作ったいいかげんな電圧計と比べると驚異的な精度です。

電源はLCDに5Vが必要なので、これをPCのUSB端子から取ったり、ダイソーのモバイルバッテリーを改造したものを使ったり、3.7Vのリチウムイオン二次電池を直につないだり(LCDはコントラスト調整でギリギリ表示できた)して電圧を測ってみましたが、計測値はどれでも同じでした。1.1Vの内部基準電圧を利用した効果もあったようです。


使い古しの電池を集めた電源でも正確に計測できました。

これなら電圧計として実用になります。ATtiny13Aもやれば出来る子なんですねぇ、すばらしい。



最新の画像もっと見る

2 コメント

コメント日が  古い順  |   新しい順
Unknown (たっくん)
2025-01-06 14:52:47
記事を興味深く読ませていただいております。

ATtiny13Aを利用して電圧測定を行いたく、「Attiny13VoltmeterKai.ino」を参考にさせて頂こうとおもったのですが、リンクが切れているようでした。

お手数なのですが、可能でしたら
takkunmotive@yahoo.co.jp
にお送り頂くことは出来ませんでしょうか。

是非参考にさせて頂きたく存じます。
返信する
Attiny13VoltmeterKai.ino (Unknown)
2025-01-08 22:01:18
以前にもあったのですが、メールアドレス収集のためのコメントの可能性もあるのでメールでは送りません。
Attiny13VoltmeterKai.inoのリンクを別のアップローダに貼りなおしました。14日後に消えてしまうのでダウンロードはお早めに。
返信する

コメントを投稿