RasPiのIOをつくる(後編?)、の巻き! 2020.7.29
(前編はこちら)
12ビットのDACとADCをRasPiのGPIOに接続して動くようにしたのはいいけれど、SPI制御をソフトウエアで行っているので
OSの割り込みの影響をもろにうけてしまって、サンプリング時間に大きなばらつきが発生します。
のんびりした計測ならまだしも、時間間隔を気にするような計測には使えません。
ということで、IO基板について再検討することにしました。
求める仕様は
折角なので、DACとADCについては16ビットのものにしたいと思います。
そして、RasPiで制御できるけれど、測定時間間隔が一定になるように、
DACとADCが動くときは、RasPiの制御からはなれて独立して動く形をとりましょう。
RasPiのGPIOのうちHWで動くSPI制御をつかえば、一定間隔でのサンプリングもできるかもしれませんが、
私にとってはすこしソフトウエアのハードルが高そうです。
まずは素子選び
DACとADCについては16ビットのものを選択します。DIGIKEYの検索機能をつかって素子を選びますが
山ほどでてきます。その中からDACについてはR-2R型、ADCについては逐次比較型、そしてデータの
転送はSPIに絞って選択します。変換方式としてはデルタΣもあるとは思いますが、なんとなく高周波の
ノイズがでそうでやめておきました。
さて、条件を絞っても、相当な数がでてきます。でも、酔っ払いモードで、かつ寝床で寝落ち寸前で
ノートPCを弄っているので、選択はいい加減です。とりあえず発注まで行いましたが、一晩あけて、
注文した型番は覚えていませんでした(笑。
選択したのは
とりあえずADCとDACについては、それぞれ2個づつ注文しました。
1)DACはDAC8831ICD
DACはINL(積分非直線性)が1LSBのもののなかからDAC8831ICDを選択しました。注意したのは末尾のアルファベットです。INLが1LSBになるのはICDだったので
それを間違えないように注文です。
数あるDACの中からこれを選択しました。
INLが1LSBものは沢山ありましたが、DAC8831の使いやすそうなところは、外付けにOPアンプが必要ですがDAC内部の抵抗をつかってバイポーラ出力ができるという点でした。
もっとも、他の電圧出力のDACでもバイポーラ出力にするにはOPアンプが必要ですが、DAC8831は必要な抵抗がDAC内にあるので抵抗の精度とかをあまり気にする
必要はないというところです。
外付けのOPアンプが必要になりますが、バイポーラ出力が簡単につくれます。
2)ADCはなんだったけ?
ADCはほんとに何を注文したか思い出せなくて、あとで注文履歴をみてADS8685IPWRということがわかりました(笑。
で、これにした最大のポイントはデータシートをみて思い出しました。
入力レンジが変更できるということと、なぜか単電源動作なのにバイポーラの入力ができる点です。これについては、勘違いかもしれませんが
酔っ払いモードなので深くは考えていないです。ハイ。
ADCはこれを選びました。
でも、素面の今になって再度読み直してみると書いてありますね。どういう原理で、実現しているかはすごく気になります。
ただ、このADCは機能がいろいろとあるのでレジスターの設定とかがあり、すこし扱うのが難しそうです。
マニュアルをちゃんと読まないとだめですね。
ちょっと選択ミスった?
データシートの最初にHigh Speed : 500kSPSとあったので、速度は全然気にしていなかったけど
ブロック図をみていて気になるものがあります。2nd ORDER LPFなるものがはいっています。
LPFが入っていますが、この特性が気になります。
で、マニュアルを眺めていくとLPFの特性がありました。なんと、500kSPSなのにLPFのカットオフ(-3dB)は15kHzのようです。
ちょっと低いような・・・、こんなもんかも知れないような・・・・100kHzくらいを期待したのですが・・・・ちょっと選択ミスったかな?
でも、エイリアスに悩まされなくてもいいかも・・・・とりあえずポジティブシンキングです。
もう、買っちゃたもん!
パルス信号を観測するには、すこし低いLPFですが、普通の正弦波をあつかうならこんなもんでしょう。10kHzの正弦波を正確にトレースしようと思えば
32点程度の観測点が必要ですが、そうなるとサンプル速度は320kSPSになりますので、このADCの仕様が500kSPSを考えると妥当なLPFの設定でしょう。
それに、そこまで早く動かすのは難しいでしょう(早くても100kSPSくらいが限界です)。
結構低めのLPFが入っています。
部品到着! 2020.8.1
DAC8831とADS8685が到着しました。それぞれのパッケージはSO-14(1.27mm)とTSOP16(0.65mm)なので、
それに合う変換基板を用意します。
DAC8831はSO14なので、SO28用の変換基板をつかってICを2個乗せます。
ADS8685はTSOP16なのでSSOP28用の変換基板の両端を切り落として短くした変換基板を用意しました。
まずは変換基板を用意しました。
まずはADS9685から試してみましょう!
とりあえず変換基板にICを取り付けます。変換基板には必要となるパスコン類やRESET端子のプルアップ抵抗などは
事前にとりつけておきました。とくにパスコン関係はICのできるだけ近くにとりつけたほうがいいので、変換基板上がいいでしょう。
まずは変換基板にICをとりつけて、パスコンも実装です。
動かしてみましょう!
ADS8685の長所としては、+5Vの単一電源ながら、バイポーラ(正負電圧)の測定ができるところにあります。
もし本当なら無茶苦茶便利なDACです。絶対ファンになってしまうと思います(笑。
まずは、カタログどおりに動くかどうかが試してみたくなったので、簡単なボードに乗せて
動作確認です。
小さい基板にのせて評価用の回路をつくります。
こういった評価のためにPICを載せた基板があるので、それに接続して確認してみます。
PICを搭載したテスト用の基板に接続です。
すばらしい!
入力にファンクションジェネレータから振幅2.5V、2Hzの正弦波をADS8685に入力して、生成されるADCのコードを確認してみました。
ADCのサンプルは10ms毎として100点をサンプリングします(約1秒間)。
ADS8685は入力にプログラムできるアンプが搭載されており、バイポーラでの入力範囲を±3VREF(約±12V)〜±0.625VREF(約±2.5V)
の5段階で可変できます。それぞれのゲインでの測定結果は下図になります。
GNDレベルのAD変換コードが0x8000、すなわち32768ですが本当にバイポーラで動いていますね。すばらしいです。
ちゃんと、バイポーラで測定できています。
つぎに、入力をGNDに短絡して変換の安定性をみてみましょう。感度を最大の0.625VREFに設定しての測定です。
変換結果は下図になりますが、±1.5LSBに納まっているようです。簡単な変換基板をつかっていますが、
S/Nは結構いいかんじです。
本来はGND接続なので変換コードは32768になるはずですが、1.5LSB程度のオフセットがのっています。
これは、あとでソフトで補正です。ちなみに、0.625VREFレベルでの1LSBは78uVですから小さいものです。
変換の安定性も高いようです。
ちなみに、評価用のPICを64MHzで動かしてみてどのくらいのサンプリング速度がでるかを計測してみると、
およそ100kSPSとなりました。PICもやればできるものです(笑。データの収集プログラムにはビット演算が含まれるので、
これを省略できればもっと早いサンプル速度が実現できそうです。すなわち、直接AD変換結果をシリアルRAMに書き込むように
すれば、いまとり2〜3倍の変換速度は得られるでしょう。
次はDAC8831かな・・・
リファレンスはどうしよう?
つぎはDAC8831ですが、DACについてはあまり懸念する材料がないので、事前に評価をする必要はないでしょう。
ただ、どうしようかと悩むのは基準電圧源です。データシートでは2.5Vの基準電圧源をつかっています。データシートでは
リファレンス電圧は1.25VからVDDの範囲なので、3.2768Vに設定すれば、1LSB=0.1mVになるので扱いやすいかもです。
ただし、リファレンス入力のインピーダンスが低いのでOPアンプでバッファリングしたものを接続する必要があります。
さて、この電圧はどこから調達しようか? TL431(2.495mV)をベースにするかな?それとも、ADS8685からもリファレンス
電圧(4.096V)がでているので、そこからつかうのがいいかな?
結局、あんちょこに・・・
TL431をつかうことにしました。一応、安定化のために定電流用に”SK246(BL)を搭載はしておきましたが、
どのくらい電圧が安定するかは実際につかってみて確認しましょう。ちなみに、DAC8831のリファレンスの入力抵抗が
7.5kΩで、TL431の出力インピーダンスが0.2Ωです。この程度の差があれば大丈夫だと思うけどな〜。
DAC8831は1つの変換基板に2つ搭載しました。パスコンとリファレンス電源もここに搭載です。
制御回路は
今回のI/O基板はDACとADCがそれぞれ2chしか搭載しません。というか、前につくったRaspi-IO基板のドータ基板みたいな位置づけなので
ディジタルIOは必要ないためです。
またDACとADCのRasPiからのアクセスを直接行うことは考えていません。というのも、RasPiのGPIOから直接アクセスすると、LINUX-OSの割り込み
の影響をうけて、サンプリング時間にばらつきがでるためです。それを解決する方法もありそうですが、ソフト的なハードルが私のハードルとして
すこし高いかな〜ということで、今回はハードウエアで逃げることにしています。具体的には、RasPiとDAC,ADCの間にはシリアルSRAMを挟み込んで、
それを使ってデータの受け渡しを行います。具体的には、DACの場合だと、出力したい電圧のデータあるいはデータ列をシリアルSRAMに書き込みます。
そして、その後に制御をPICに受け持たせます。PICは一定間隔のクロックをシリアルSRAMとDACに送信することで、一定間隔でのデータを出力します。
ADCだとこの反対で、まずはPICの制御下でADCでのサンプル結果をシリアルSRAMに書き込みます。 もちろん、PICの一定クロックで等間隔にデータを
収集します。収集が終われば、RasPiとシリアルSRAM間で通信をしてデータを読み取ります。
まあ、結構面倒なことになりますが、まあこれも遊びのうちです。
ただし、折角PICも搭載するのでこのDACとADCはRasPiなしでも独立して動くようにしようかと思っています。データの受け渡しはUSB接続でのRS232C
を考えているので、そうすればWin-PCに直接データを送ることができます。
制御部の回路図を検討してみましょう
単純なもので、シリアルSRAMの信号をRasPiで行うかPICで行うかの切替を行うだけなので、そう大した回路にはなりません。
必要なのでは
シリアルSRAM・・・・5個 (2個DAC用、2個ADC用、1個はコマンドデータ用)
ロジックIC ・・・・・・6個程度
という感じです。アナログ部分はOPアンプ1個程度です。DAC8831をバイポーラ出力するときの抵抗類はICの中にあるので外付け抵抗はありません。
またADS8685についても、PGA(可変ゲインアンプ)がICの中にはいっていますし、バイポーラ入力ができるので外付け部品はほとんどありません。
検討中の回路図です。
ちょっとTea Time!? PICのI/Oタイミングの憂鬱
RasPi用のIO基板にはシリアルSRAMとしてマイクロチップ社の23LC512を使います。
これは、512kBitの容量があり、バイトに直すと64kバイト、16Bitワードにすれば32Kワードになります。
ADCのサンプルを100kSPSにしても、32kWあれば約0.3秒間のデータを採取することができます。
これだけの容量がありながら、1個170円(秋月)で購入できるのが嬉しいです。
で、このシリアルSRAMについてはできるだけ高速に動かさないと、DACもADCもサンプル速度が遅くなるので
PICは最高速の64MHzで動かす予定です。できれば、オーバクロックさせて80MHzで動かすかもです。
64MHzで動かした場合のI/Oパルスの幅は約63nsになります。これは、PICが4クロックで1命令を実行するので、
1命令の実行時間は1/(64Hz/4)=0.0625(E-6s)になるからです。
動かない・・・
シリアルSRAMのアクセスタイムは25nsなので、1命令の時間に比べると随分早いので
あまり、なにも考えずに動作確認のプログラムを組んだところ、書き込んだデータと読み込んだデータの
不一致が生じるエラーが発生しました。
配線間違っていないかな〜・・・・23LC512が悪いのかなあ〜・・・やっぱりPICのプログラムが悪いのかなあ・・・・
色々悩んだ末に、PICの動作クロックを16MHzと今までの1/4に下げたら
ようやくエラーがなくなりました。
アクセスタイムに余裕があるはずなのになぜだろう?
クロック等の波形をみても、さほど崩れている様子はありません。そのためクロックラインにダンピング抵抗を
入れても改善せずです。
で、エラーがでるときのデータを眺めてみると、まずは現象がつかめました。
1ビットずれている・・・・
すなわち、
書き込みデータ: 0011000011110000
読み込みデータ: 0001100001111000
という感じになっています。
23LC512のテスト基板です。64MHzでなぜか動かない・・・・
この現象から、シリアルSRAMにクロックを送り込んでからのアクセスタイムがおいついていないことがわかりました。
んん??待てよ
シリアルSRAMのアセスタイムがおいついていないんじゃなくて、PICの読み込みタイミングの問題じゃないかな?
いままで、なにも考えずに1命令が62nsなので、1つの命令を実行してから、次の命令まで62nsあると無条件に
思い込んでいましたが、I/Oをあつかう場合は、1命令4クロックの中でどの時点でデータの書き込み、読み出しが
行われるか、それがわからないと単純に考えることはできません。
データシートを調べてみる!
しかしPICのデータシートってなんでこんなに分量あるのだろう?調べようとしているPIC18F46K22は全部で539ページもあります。
と、いいながらもPICのデータシートの電気的特性については巻末にまとめて書いてあることが多いので、後半部を探します。
で、439ページにみつけました。
なるほど!
原因がはっきりしました。PICのI/Oのタイミングですが1命令4クロック(Q1〜Q4)の中でいえば、書き込みがQ4クロックの最後、
そして読み込みがQ1サイクルの最後です。すなわち、I/Oにパルスを書き込んで、データを読み出すまでの時間は1クロック分しかありせん。
64MHzだと1クロック16nsなので、これはシリアルSRAMのアクセスタイム25nsを大幅に下回ります。ちなみにPICのクロックを32MHzにしても
動きませんでしたが、32MHzでは1クロック31nsなのでアクセスタイム以上になりますが、PIC自体のDELAYとかが数nsあるでしょうから
ギリギリ動かなかったのでしょう。16MHzならば1クロック63nsですから、かなりの余裕がでます。
PICのI/Oタイミングです。I/OのWRITEはQ4クロックの最後、READはQ1サイクルの最後です。1クロックの差しかありません。
ということで、対処としてはシリアルSRAMにクロックを送り出した後に、1命令分のWAITを入れることで無事解決しました。
反省・・・
思い込みは危険。なにかトラぶったらまずはデータシートを確認しましょう!(面倒だけど・・・・)。
(Tea Time!? おしまい)
話はもどって
基板に組んでいきましょう!
まずは必要な素子のレイアウトを考えます。余裕で載るかな〜と思っていたら、案外キチキチでした。
ロジックICは半田付けしやすいように、基板のランド穴を1つ飛ばして配置したいので、結構レイアウトが限定されます。
あと、LCD取り付けのピンソケットの位置は動かせないので、それも配置上のネックになります。
まずは必要な素子の配置を検討です。
配置が決まれば、あとは回路図を眺めつつ配線です。
しばし、いやしばらく格闘・・・・。
BGMを鳴らしながら、冷房をきかせて、ルンルンルン〜・・・・
イタタタ!! 床に落ちている抵抗のリード線が足の裏に刺さってしまいました・・・・ やっぱりスリッパ履こう・・・・
イタタタ!! ピンセットの先が太ももに刺さった〜!! ピンセットをこぼれて、とっさに足を閉じてしまいました・・・。
短パンだと太ももが無防備です。
イタタタ!! 腰が・・・・・ しばらく猫背の姿勢を続けていたせいか背中と腰が・・・・ ちょっと休憩・・・グビグビ、プハー!!!
とりあえず完成!
配線が完了しました。
とりあえず配線は完了しました。
DACならびにADCの電源は5Vなので、その電圧レギュレータはこの基板での肝になる部分なので超低ノイズのAK1110を使いました。
評価途中のものを拝借です。
5Vのレギュレータは初物の超低ノイズのAK1110をつかってみました。
舞台裏は相変わらず乱雑です。
ソフト作成!
配線のチェックも兼ねて、ソフトを組んでいきましょう。
しかし、ロジックICの各種制御の点数が多くて、40PinのPICのI/Oをすべて使っています。その定義ファイルを書くだけでも結構面倒です。
まあ、のんびりやりましょう。
正常なのかな? 2020.8.3
ちょこちょこっとソフトをつくり、動作をチェックし、配線の間違いを修正し・・・・という感じで進めています。いつになることやら。
で、ふと消費電流が気になったので測定してみると、なんと250mA!も流れています。
え?そんなに流れるの?予想では100mA前後かな〜と思っていたのですが・・・・・。
とりあえず、今のところ動いているので大丈夫だと思うのだけど、どこかロジックの出力が短絡してるのかな〜???
ICをすべて触っても、ほとんど熱を感じません。ほのかに暖かいのはDCDCのコイルくらいです。
一番電流が流れそうなのはアナログ部分です。5Vで動いていますが15Vからのドロップ電源なので、DCDCに数倍の負荷電流がかかります。
アナログの5Vで10mA流れれば、DCDCには最低で3倍、効率も考えると4倍の電流が元電源の5Vに流れます。
ざっと試算すると
アナログ部
DAC(DAC8831) ほぼゼロ(超低消費電力です)。
ADC(ADS8586) 7.5mA(MAX)×2=15mA
OPアンプ 正負10mAとして20mA
−−−−−−−−−−−−−−−−−−−
合計 35mA
35mAをDCDCの効率を考えて元の5Vの電流にすると約140mA。
ということは残りロジックで100mAとなります。こちらも試算すると
ディジタル部
PIC 約20mA(64MHz)
SRAM 3mA(MAX)×5=15mA
ロジックIC 10mA(多すぎ?)×6=60mA
−−−−−−−−−−−−−−−−−−−−−
合計 95mA
試算結果の合計は235mAです。んん・・・実測に近いから、なんとなく正常のような気もしてきた。
あと、これにバックライト付きのLCDが乗るので、全体で300mA程度になりそうです。
ただ、300mAなのでUSBポートからの給電でもいけそうなのでスタンドアロンでも動くようにしておいたら、
オキラクにつかえるDAC,ADCになりそうです。でも、大丈夫かな〜。というのも、消費電流を測ろうとして
菊水の実験用電源(最大1A)につないだら、電源がトリップしました。突入電流が1Aを越えると、
自動的に電圧が落ちるので、さらにDCDCに電流が流れてまた電流保護が働いて、の繰り返しで動きません。
こんなものをUSBにつないでいいものかどうかが心配です。
精度を確認してみよう! 2020.8.4
ソフトはまだ製作途上ですが、基本的な部分については動作が確認できたので、
ちょっとここいらでどの程度の精度がでているか確認してみたくなりました。
まずは基本となるDACの直線性からです。
ただ、測定機器がテスターしかありませんので、厳密な精度という点では難しいです。
さらに、テスターの分解能(=精度だと思う)が1V以上では1mV、1V未満でも0.1mVしかありません。
それに対してDACの出力は正負2.49Vで分解能が16bitですから1LSB=0.076mVですので、測定できるのは
DAC-CODEとDAC出力電圧の傾きと、あとはDAC-CODE=0時のゼロオフセット程度になります。
もっと、精度の高い電圧計がほしいところです。
あれ、おかしいな?
まずは、DACに一定のコードを入れて、出力電圧をテスターで測定です。測定は手動なので結構面倒です。
これを図にずると下記になります。マクロ的には一直線ですね。もっとも、これがばらついているようだと話になりません。
DAC-CODEと出力電圧の関係。これだけみれば直線にみえますね。
で、誤差を調べるために上図から直線近似線をもとめて、そこからの誤差をプロットです。
げげげ!ゼロ付近で誤差大きい!
なんと、ゼロ付近でおきな誤差がでています。およそ6mV程度の誤差です。1LSB=0.076mVなので
79LSBの誤差です。んん・・・・なんでだろう?
これが単電源でバッファーつきの電圧出力のDACならなんとなく理由はわかるのですが・・・。
すなわち、レールtoレールといわれるICでもあって、GNDあるいはVCCに極近いところだと直線性が乱れます。
でも、このDACって純粋なR-2R出力であり、外部に正負電源で動くOPアンプを接続しているので、
GND付近での直線性は問題ないはず。また基準電圧もVCC(5V)より随分低い2.49Vで動作しているので、
上値がさちることもないはずです。
なにが原因だろう????
DAC-CODEと出力電圧誤差の関係。ゼロ付近で大きな誤差がでています。なぜかな?
原因はDGNDが抜けていました・・・
基板を裏返して、DAC周辺を眺めていて原因らしきものを発見です。なんと、DGND(ディジタルGND)の配線が抜けていました。
おそらく、これでGND付近での精度がでなかったのでしょう。
やり直し!
DGNDの配線を修正して、やり直しです。こんどは、電圧誤差がDAC-CODE全領域を通じて1mV以下になりました。
これでようやく正常になりました。
DAC-CODEと出力電圧誤差の関係。DGNDを接続したら正常になりました。
このとき、DAC CODEと出力電圧の関係は下記式になりました。
有効数字の桁数は適当です。 こんな式を提出しようものなら、ぼろくそに言われそうです(笑。
出力電圧(V) = 0.000075989094 (DAC-CODE) - 2.490112187389
この式からDACの中点の8000h(32768)の値は約-0.1046mVです。-1.37LSBになります。このあたりは、OPアンプのオフセットでしょうか。
ちなみに、2つあるDACの出力は持っているテスターでは、差がまったくでませんでした。すばらしい安定性です・・・というより
もっているテスターがショボイだけかも(汗。
ADCの実力は如何に!
DACの出力範囲が正負2.490Vに対して、ADCのレンジは0.625VREF(VREF=4.096V)の設定で正負2.56Vです。
DACとADCのレンジがほぼコンパラなので、DACの出力を直接ADCに入力して、ADCの精度評価を行います。
そして、(面倒なので)DACの1LSBとADCの1LSBは同じで扱います。
DACの出力を正としての、エラーは下図のようになりました。
いや〜すばらしいですね。およそ±0.5LSBの範囲におさまっています。
データシートをみると、ADC(ADS8685)の標準INLが±0.5LSBで、DAC(DAC8831)の標準INLが±1LSBですから、
合計すると1.5LSB程度の誤差がでてもおかしくないところですが、さすが一流メーカ(ADとBB)ですね。
きちんとした品質管理です。
DACの出力を正として、ADCに直接入力したときの、ADCの変換エラーです。この精度なら満足です。
ちなみに、DAC出力とADC変換値の関係式は下記になりました。
係数の0.972はDACとADCのレンジの差です(2.490/2.56=0.97265)。
0CH (ADC−CODE) = 0.9720954 (DAC-CODE) + 913.6088626
1CH (ADC−CODE) = 0.9721059 (DAC-CODE) + 917.9008595
さて、最終的にほしい式は、DACの場合は設定したい電圧に対してのDAC-CODEであり、
ADCの場合は計測されたADC-CODEからの入力電圧への換算です。面倒ですが、計算しておきましょう。
備忘録です。
DAC-CODE = 13159.783(設定電圧) + 32769.33 (CH0,CH1共通)
入力電圧(ADC-0CH) = 7.81704E-05 (ADC-CODE) - 2.561529
入力電圧(ADC-1CH) = 7.81695E-05 (ADC-CODE) - 2.561864
PICで浮動小数点の計算をさせようものなら、時間がかかって仕方ないですがRasPiなら時間はほとんど気にすることもないので、
関数の引値、戻値はdoubleでいいでしょう。
さて、ひきつづきソフトをつくりましょう。
でも、そろそろ酔いが回ってきました・・・・・・・・
ADCのサンプリング速度を確認してみよう (2020.8.5)
全体の精度が確認できたので、今度は速度についても確認しておきましょう。
今回のIO基板では、DACならびにADCの変換ならびにサンプリング速度を上げるために、
必要なデータは直接的にシリアルSRAMから供給、あるいはシリアルSRAMに格納するようにしています。
PICはSRAMとDAC、ADCの駆動のためのクロック発生に特化します(もちろん、他の仕事もありますが・・)。
そのため、構成はADCの場合ですが下図のようになっています。
SRAMもADCもどちらもインターフェイスがSPIなので、クロックを共有して、データの入出力を直結してやれば、
PICはクロックを出すだけで、ADCのデータが勝手にSRAMに格納されます。
もっとも、これができるのがADCが16ビットであることと、SRAMがバイト単位でのシーケンシャルな書き込み(読み出し)
ができるからにほかなりませんが・・・・。
ADC(ADS8685)のデータは直接シリアルSRAM(23LC512)に叩き込みます。
実際の回路ではSRAMには最初にデータを書き込むアドレスを指定しなくてはならないので、
その間はADCへのクロック(CLK)の供給は停止するようになっています。細かいところは省略ということで・・・・・
ADCとSRAMのタイミングは下図のようになります。
ADC(ADS8685)はCONV信号の立ち上がりでアナログ値をサンプリングして、AD変換を開始します。その時間は1usです。
その間はCONV信号はHIGHのまま保持します。そして1us後にLOWにするとMSB(最上位)からAD変換データがでてきます。
そして、クロックを1つ送るごとに、次のデータビットがでてきます。
SRAM(23LC512)については、一旦書き込み開始のアドレスを設定しておけば、あとはCLKパルスを入れてやればどんどんデータを溜め込んでくれます。
最大容量は32kW(16bit=1ワード)分ですが、それを超えればサイクリックにデータを上書きしていきます。
で、下の図からわかるようにADCのデータ出力とSRAMの必要な入力データ、そしてクロックは同一タイミングになりますから、互いに共有できるというわけです。
ADCとSRAMも動作タイミングです。
サンプリング速度を試算してみよう!
PICは1命令は1サイクル(62.5ns)で実行しますので、サンプリング速度については、実測しなくてもプログラムのステップ数から試算することができます。
下図はサンプリングのプログラムになります。もっとも高速にサンプルするバージョンになっています。
PICのIO操作は1命令1サイクルです。while(loop--){}文については、事前に何サイクル必要が調べておき、9サイクルということがわかっています。
あと、ADC_CLOCK_OUTとあるのはI/OをHIGH、LOWにするマクロなので、これが2命令サイクルになります。
で、トータルで1ループ58命令サイクルになります。時間にすると58cycles×62.5ns=3.625usです。
周波数にすると275.86kHzですから結構な動作速度が得られています。
これをPICだけで実施すれば、数分の1の速度になってしまうはずです。
ADCサンプリングのプログラムです。単純にクロックを叩くだけの作業です。
で、本当に275.86kHzのサンプリング速度がでているかを確認するために、発振器で2759Hzの正弦波をつくって、
ADCで変換してSRAMにデータ格納してみました。ちゃんと1周期100点(0〜99)のデータが得られていますね。
ADCのスペックが最大500kSPSに対して、実際のI/O基板で276kSPSまで得られたのはよしとしましょう。
2759Hzの正弦波をサンプリングしてみました。1周期のデータ点数が100点なので、サンプル速度は276kSPSになります。
PICの割り込みを使わなければ、クロックはつねに一定間隔ででてきますから正確なサンプリングが可能です。
最高サンプリング速度は276kSPSですが、途中で止めたい場合も想定してスイッチ等のポーリングも入れる必要があるでしょうから、
汎用的なADCでのサンプルルーチンはもう少し速度は遅くなるかもしれません。
#ADCの変換時間の1usは完全になにもしていない時間なので、この間にサンプル中断のポーリング処理を入れれば
#サンプル速度を落とさずに済むかもしれないと画策中です。
最終コーナに入る前に!
PICとの接続ソフトをこれから組んでいきますが、流石に裸の基板のままだと何がおこるかわからないので、
ちょっとだけ養生しておきました。2mmのアクリル板を基板の表と裏に配置です。とくに、基板の裏はφ0.16mmのポリウレタン被覆銅線が
むき出し状態なので、ちょっと引っ掛けたら、簡単に切れてしまいます。
すこしだけ養生しておきました。
裏面の配線の保護が必要です。
ADS8685の真の実力は? 2020.8.7
今回ADCに使ったADC8685は16Bitで500kSPSのものですが、この素子はADS868xのシリーズの中位機種です。
その他にADS8681とADS8689がありサンプル速度が異なり、それぞれ1MSPSと100kSPSになります。
ADS868xのマニュアルは1つにまとめられていますが、ADS8681、ADS8685そしてADS8689のスペック上の違いは
変換速度に関するところ以外は、ほとんど差がありません。消費電力は異なりますが、これは動作速度に依存するので
単純に高速で動作できるADS8681が大喰らいなだけです。
一番大きな差は下記のアナログ値の収集時間(Aquisition Time)です。ADCにおいて、性能を左右する一つがこれで、
いかに短時間に正確な入力電圧をサンプリングできるかにかかっていますが、この部分はアナログ的な要素があるので
ICの出来不出来が左右しやすいのかもしれません。
ADS868xシリーズで大きく異なるのはアナログ値の収集時間です。
上記以外で唯一といっていいほど、有意差がありそうなのはダイナミックレンジ(DR)ですが、高速(1MSPS)のADS8981のDRが
すこし低くなっているのは、まあ納得のいく範囲です。
ADS868xシリーズでは変換速度のほかはほとんどスペックに差がありません。DRは多少違いますがまあこんなもんでしょう。
中身は同じでは?
変換速度以外のスペックがシリーズでほぼ同じということから、一つの疑念がでてきます。ひょっとして中身はすべて同じで、単に選別しているだけじゃ?
すなわち、短時間のサンプルで精度がでるものはADS8681(高速版)として出荷し、時間がないと精度が出ないものはADS8689(低速版)で出す。
そして、ADS8681にあと一歩及ばないものはADS8685として出しているのでは、とADS8685に対して都合の良い解釈ができます(笑。
ICの選別は珍しいことではなく、オーディオのDAC素子なんかも、無印、J、Kなど型番に「おまけ」がついていて、性能の差(おもにノイズ面ですが)
で分けていました。ここでの「おまけ」は、型番のほかにハンコみたいなもので押されているので、おそらくICのパッケージにしてから
選別しているのでしょう。というのも、パッケージするときの歪みなどで特性が変わってくるためと思われます。
選別品にはKとかの「おまけ」がついていたりしました。
ihttps://minkara.carview.co.jp/userid/2464068/blog/37237491/
いまでは、ほとんどこういった「おまけ」を見ないところみると、そもそも選別していないのか、
それとも型番に含めているのかのどちらかでしょう。
おそらく模造品がでるのを防ぐためにも、型番に含めて、明確に分けているのだと思います。
とくに高精度なICはウエハ段階でトリミング作業が必要なので、そのときにあわせて性能を評価すれば
いいわけですし、シリコン上でのピーストラッキングができていれば問題ありません。
そもそもパッケージになってからの選別は手間がかかりコストアップになってしまいそうです。
話はもとに戻って、ADS868xがサンプリング回路の出来で選別して型番を分けているとすれば、
今つかっているADS8685(500kSPS)も、上位のADS8681(1MSPS)と同じ変換速度で動くのかもしれません。
精度維持に必要なサンプリング時間については、もともとのADS8685の仕様である1000nsは十分にクリアできます。
というのも、ADCのデータ転送時間がサンプリング時間に割り当てられるので、データ転送のクロックをPICで叩いている都合、
最低でも 62.5ns(命令サイクル)×16(ビット数)×2(HIGH→LOW) = 2000ns
必要になるからです。
本来は、PICのクロックを上げるのが変換速度を上げる最大の近道なのですが・・・・。
変換速度を調べてみましょう!
今のプログラムでは変換時間はマニュアル通りに1000nsかかるとして、遅延時間を固定的に設定しています。
ADS8685には変換終了を示す信号(RVS)もでているので、それがどのタイミングででているか調べてみました。
ちなみに、RasPiくらい高速に動くCPUなら、このRVS端子をポーリングしてAD変換終了を検知してもいいかもしれませんが、
低速なPICで、それをやりだしたら信号の入力、判定、分岐等で余計に時間がかかってしまいます。
結果は、下図の通り。ADS8681の変換時間がマニュアルでは665ns(MAX)ですが、実測600nsですので
中速のAD8685も、高速版のADS8681と同じ変換速度がでているようです。
実際の変換時間は600nsですので、ADS8681と同じのようです。
ギリギリを狙うぞ!
変換速度を今の1000nsの設定からもっと短くできそうなので、すこし弄って高速化をはかりましょう。
流石に、変換時間で600nsのギリギリを狙うわけにはいかないので、すこし余裕をみて700nsとします。
命令サイクルでいえば11サイクルです(62.5ns×11=688ns)。データの転送には32サイクルの2000nsかかるので
トータルで43サイクルで2688nsが、計算上の限界値です。周波数にすると372kHzです。ただ、
プログラムの冗長な部分がどうしても生じるので、どこまで高速にできるか・・・・試してみましょう!
結果は?
サンプリングプログラムをすこし変更です。以前と同じ周波数をサンプリングしましたが、従来は100点でしたが、
今回は約127.4の距離になったので点数としては1減らして126.4点。命令サイクルにすると45.87です。切りのいい数字に
なるとすれば46サイクルでしょう。これからAD変換速度の正確な値は347.826kHzになりと想定されます。
2759Hzの正弦波をサンプリング。1周期のデータ点数が約126.4点です。サンプリング速度は347.826kHzになります。
念のため、3.478kHzの周波数で測定です。結果としては、ちょうと1周期の測定間距離が100になったので、命令サイクルは46で良さそうです。
3478Hzの正弦波をサンプリング。1周期のデータ点数が100点になました、命令サイクル46で確定です。
さて、週末はプログラムを仕上げましょう!
これから連休だけど、今年はどこかに行く予定もないのでのんびりできそうです。
最終調整!? 2020.8.10
だいぶソフトも出来上がってきました。といっても、RasPiとのインターフェイス部分は未着手です。本来は、このIO基板の
制御ソフトは必要最小限として、あとの処理はRasPiでやるつもりでしたが、欲張ってPCとRS232でも接続できるようにしたものだから、
加工したデータがPCに転送できるようにと色々と機能を追加することになってきました。例えば、正弦波のジェネレータ機能も
内蔵です。RasPiと接続するなら、RasPiで波形テーブルを計算させてIO基板に転送すればいいのですが、PCとの接続だと、
データの転送にRS232だと非常に時間がかかります。そのためIO基板でも、いくつかの波形データを生成できるようにしたりしています。
で、色々とソフトを作成して調整を進めている上で、ハードにも色々と気になる点があるので修正をしていきます。
DACのグリッジを抑えよう!
DACはデータの送出のタイミングでどうしてもグリッジがでてしまいます。そのグリッジがOPアンプの高周波特性とあいまって
大きなリンギングが発生すると、AD変換時に何をはかっているかわからなくなってしまいます。今回つかったADCには
内部にLPFもあるので、あまり気にすることもないかもしれませんが、気分的にもあまり好ましくないので、DACの出力に
フィルターを入れることにしました。フィルターといっても単にコンデンサを入れているだけです。出力抵抗を75Ωにしているので、
そこに0.01uFのコンデンサを追加することにしました。
フィルターなし(75Ω出力まま) | フィルター有り(75Ω+0.01uF出力) | |
200kHz データ切替速度は MAXの1/8あるいは 1/16 |
値が切り替わるときに大きなグリッジがでています。 またそのリンギングも結構長いです。 |
多少、肩は鈍りますがグリッジはなくなりました。 |
100kHz データ切替速度は MAXの1/2 |
この周波数になるとOPアンプのスルーレイトが見えてきます。 |
このあたりがゲイン低下を抑える限界に近いです。 |
200KHz データ切替速度 MAX |
三角波を出力しているのではありません。OPアンプのスルーレイト が小さいので、矩形波のはずがオーバーシュートも含めて 三角波になります。 |
すこしゲインが落ちました。 |
今回用いたOPアンプはOPA227というもので、いわゆる計測等につかうOPアンプの定番です。DAC8831のデータシートにも、これがつかってありますが
ちょっとスルーレイトが低いです(標準で0.8uV/S)。手持ちのOPアンプでもっとスルーレイトの高いもの(例えばOPA2134など)があったのですが、
交換したら発振してしまいました。他のOPアンプでも多くが発振してしまいました。発振しなかったものもありますが、ちょっと計測用にはオフセットや
ドリフトが大きいものなのでパスです。今度、ついでがあったらデータシートに記載のあったOPA727(30V/us)あたりを買っておきましょう。
でも、そこまで高周波数特性に拘る必要もないので、多分このまま使い続けるかもしれません。それに、OPアンプを変更したら、再度校正が必要になるかもです。
気になるな〜
いま一番気になるのが、ADCの換算電圧エラーです。すなわち、ADCで読み取ったディジタル値は校正式をつかって電圧値に変換しますが、
ADCの入力をGND短絡させたときの、変換電圧値が2つあるADCでそれぞれ、0.22mVと0.08mVを示します。まあ、このくらい気にしなくてもいいのですが
ディジタルで値がでてくるのでちょっと目障りです。それに、ADCの1LSBは0.078mVなので1LSBを越えてしまっています。
この原因はDACの出力を正として、ADCの校正線を導出しましたがDACの出力自体を1mVの分解能しかないテスターで校正しているためです。
すなわち、DACの校正線に誤差があるためです。ということもあり、またまた面倒ですが校正のやり直しです。
今回はどのように校正するかといえば、
・電圧のゼロ点はADCの入力を短絡させたときのAD変換値とする(すなわち、入力短絡時には必ず0V出力となるよつにする)。
・電圧出力のフルスケールはADS8685の基準電圧(4.096V)を信じる。ADC0あるいはADC1のどちらかをマスターに設定。
・決定したマスターのADCをベースにして、DACを校正する。
・校正したDACの値をもとに、マスターと違うADCの基準電圧を校正(推定する)。
まあ、最初からこうすれば簡単だったのですが・・・・。ちなみにADS8685の基準電圧を手持ちの2台のテスターで測定したらそれぞれ4.093Vと4.098Vでした。
ADS8685のデータシートでは標準4.096Vで最低4.095V、最大4.097Vが保証されていることを考えると、手持ちのテスターもいい加減なもんだなあ〜。
ちなみにテスターのスペックを確認したら、最高確度が±(0.5%+2)でした。すみません、スペック以上のものを求めていました・・・・
ああ、せめて5桁くらいの精度のある電圧計がほしいよ〜。
再測定
上記の基準に基づいて、校正線を作成するために、まずはADCの入力を短絡した場合のADのCODEからチェックです。
10000回AD変換して、0.01LSBの値まで読み取りました(意味あるかどうかは別として)。
レンジ(VREF=4.096V) | ADC(CH.0) | ADC(CH.1) |
バイポーラ 3×VREF | 32766.85 | 32768.02 |
バイポーラ 2.5×VREF | 32767.13 | 32767.55 |
バイポーラ 1.5×VREF | 32767.44 | 32768.10 |
バイポーラ 1.25×VREF | 32766.69 | 32768.37 |
バイポーラ 0.625×VREF | 32765.58 | 32769.47 |
ユニポーラ 3×VREF | 0.00 | 0.10 |
ユニポーラ 2.5×VREF | 0.00 | 0.57 |
ユニポーラ 1.5×VREF | 0.00 | 0.17 |
ユニポーラ 1.25×VREF | 0.00 | 0.10 |
あ〜、面倒くさい。でも、なんとなく違いがみえてきました。ADC0は1LSBほどコードがちょっと低め、ADC1はちょっと高めかな。
ADCのレンジによっても誤差の傾向がことなりますが、内部抵抗の精度の問題でしょう。ただし、ADC(CH0)ではユニポーラの
値がゼロになっています。ちょっと、飽和しているようにみえるので、マスターはADC(CH1)ということにしましょう。
ということで、まずはADC(CH1)の校正線をつくります。
中断・・・・
やってるうちに、だんだん頭がこんがらがってきました。アルコールが入っているからかなあ〜。
面倒なので、最終校正はraspiとの結合が完成してからにしましょう。
しまった〜!! 2020.8.11
IO基板とRaspiを接続するのはフラットケーブルを使いますが、RasPiからの直接の接続ではなく、
すでにRaspiにつなげている前につくったIO基板に拡張用の端子を設けているので、そこから接続します。
というのも、今回のIO基板の動作電圧を5Vにしているのでロジックも当然のことながら5Vになっています。
しかしながら、RasPiのGPIOのロジック電圧は3.3Vなので、直接つなぐとRasPiを壊してしまうかもしれません。
接続先の(前の)IO基板はロジック電圧の変換をするICも入っているので、それを経由させる必要があったためです。
で、フラットケーブルの手持ちがなかったので秋月で事前に購入しておきました。で、うっかりミス。
てっきり26Pinの端子だと思っていて注文したのですが、確認すると20Pinでした。6pinあまっちゃいます。
まあ、大は小を兼ねるということで、このまま使ってもよかったのですが、
ケーブルを普通にとりつけるとRS232用のマイクロUSB端子が挿せません。26芯のケーブルを折り曲げるのも
大変だし、それに長さも足りません。ということで、面倒ですが手持ちの部品で接続ケーブルを作成です。
間違えて26Pinのフラットケーブルを買ってしまいました。本当は20Pinでよかった・・。
マイブームのポリウレタン被覆銅線で作成
20Pinの接続ケーブルを普通の電線で作るのはかなり面倒です。それに、線が太いので束ねるとごわごわしてしまいます。
ということで、マイブームのポリウレタン被覆銅線をつかってコネクタを作りました。ついでに、コネクタの長手のほうから線を
引き出すことにしました。こうすることで、RS232のコネクタとも干渉しませんし、なにより線を束ねるのが簡単です。
コネクタをブレッドボードで固定して、ポリウレタン線で配線です。20Pinくらいならすぐにできます。
小さく切った基板とりつけます。コネクタのPINに直接線をとりつけるとPINごと抜ける場合があります。
配線が終わったら、半田付けの部分はホットボンドで固定です。
そして、20本の銅線は数回捻ってバラけないようにしておきます。
これで、IO基板の接続コネクタができました。配線がスリムなのがいいです。
RasPiとの接続ソフトを書いていきましょう!
さて、これでハードウエアは一応完成なのであとはソフトの作成だけです。
RasPiと接続して、通信用のソフトを組んでいきます。
でも、ソフト作成は結構面倒・・・・・・。バグがでたときに、RasPiのソフトが悪いのか、IO基板のPICのソフトが悪いのか、
はたまた接続しているハードが悪いのか、原因を突き止めるのが一苦労です。
まあ、めげずにがんばりましょう!
ハードはバグだらけ・・・ 2020.8.12
IO基板自体はRS2323ベースではハードのバグは取れているので、あとはRasPIとの接続だけです。RasPiとの接続ハードは簡単なので
とくに問題ないと思っていましたが、結構バグが残っていました。結構見つけるのは難儀しました。 なんせ、最初はソフトを疑いますからね〜。
配線バグ
で、配線に関するバグは2箇所。いづれもポリウレタン線の接続不良でした。ICのPINに巻きつけたあとで半田付けを忘れてしまったのか、
それとも被覆が溶け切らなかったのか・・・いまでは原因はわかりませんが、やっぱり配線したあとにテスターで導通チェックをしたほうが良さそうです。
AD変換値のバラつき
ADCは2個搭載していますが、動作チェックは一応両方で行いました。動いているのは確認できているのですが、どうもCH.1の変換値がばらつきます。
入力を接地した状態で変換すると、CH.0については、ほとんど±1〜2LSBの範囲で納まりますが、CH.1に関しては±20LSB以上でばらつきます。
これでは16Bitの分解能が活きません。配線を調べてみてもCH.0とCH.1はどちらも同じだし、とくに違いはありません。ひょっとして、入力線の配線に
ノイズが乗っているのかも?と思い、いろいろと変更するも駄目です。素子のあたりがわるかったのかな?とも思いましたが・・有名メーカだしなあ〜。
念のため再半田してみたら、なんとチップコンデンサ(タンタル)の1つが取れてしまいました。チップコンデンサやチップ抵抗については、片方の半田が付いていれば、
他方に半田をあてたくらいでは取れたりはしません。ということは、片方の半田がイモだったということです。この、チップコンデンサは丁度基準電圧源の
パスコンだったわけで、データシートには容量まで指定のある超重要な場所だったわけです。ということで、原因判明です。コンデンサの半田を修正したら
ADCのバラつきはCH.0と同様にほぼ±1〜2LSBに納まりました。
ついでなので、コンデンサを追加してさらにバラつきを抑えるぞ!!! でも、あまり効果はありませんでした。まあ、物には限度ってものがありますね。
ADCの素子の周りには、できるだけ近くにコンデンサを配置したかったのでチップコンが色々と立体的についています。
ADCの変換基板にはチップコンデンサが立体的に取り付いています。
これで、ようやくハードのバグはなくなりました(のはず。
あとは、ソフトの仕上げです。
ここまできたんだなあ〜!!
ようやくソフトの基本的なところも完成して、RasPiでIO基板との通信によりDAC/ADCが動くようになりました。
前編から含めて取り掛かって約1ヶ月かかりました。またグラフィックをつかって測定データも描画できるようになりました。
これが自分でできるようになるのは、ほんとPC98以来です。ちょっと自分でも感動してしまいました(笑。
ようやくここまでたどりつきました。
単純にRASPIにDACとADCを接続するだけなら、もっと早くできたかもしれませんが、測定時間間隔の正確性に拘ったものですから結構大変でした。
ソフトに精通していれば、プログラムを工夫することで対処できたでしょうか、あまり得意ではないので、仕方ないですよね。
あとは、DACとADCの校正作業が残っていますが、ボチボチと進めましょう。それと、必要なドキュメントも残しておかないと・・・・
1ヶ月もすれば忘れてしまいますからね。
稲妻マーク? 2020.8.13
IO基板もあわせてRasPiを動かすと、なにやら画面の右上に稲妻マークが頻出します。
しらべてみると、RasPiへの電源電圧が落ちた場合に出るようです。RasPiに取り付けた電圧計も
4.8Vくらいになっています。ここまで下がったらだめなのかな?
ACアダプターは秋月の5V2Aのものを使っています。容量としては問題ないと思うのだけど、
電線が長いの電圧降下が大きいのかもしれません。
この稲妻マークですが、でてもCPUの動作には支障がないようなことが書いてあったりしますが、
あまり気持ちのいいものではないですね。
稲妻マークが頻繁にでます。どうやら電圧が低くなってきたら出るマークのようです。
5V2AのACアダプタを使っています。容量は足りると思うけど、電線が長いので電圧降下が大きいのでしょう。
誤って半田ゴテで溶かした傷跡が痛々しいです。
RasPi用の専用電源を用意しましょう!
IO基板ができたことなので、専用の電源を用意することしましょう。さらに容量の大きなACアダプタを選んでも良かったのですが。
電源ケーブルが長ければ、結局電圧降下が生じてしまいますので容量があっても意味がない場合も想定されます。
それに、市販のACアダプタは電圧が固定なので、低めの電圧のものに出くわす可能性もあります。
そこで、以前にジャンク価格で購入した5V3Aのスイッチングレギュレータ基板を使うことにしました。
このタイプはたいてVRが付いているので電圧を調整することができます。ちなみに値段はジャンクそのもの(200円)でしたが、
ちゃんとしたネミックラムダ製です。そういえば、ネミックラムダって2008年にTDKラムダに社名が変わったようなので、
新しくても10年以上前の基板ということです。それで安かったのかな?
ジャンク価格で購入した5V3Aの電源です。価格はジャンクでしたが、中身はNEMIC-LAMBDAです。
RasPiのIO基板は2枚あり、それぞれにDCジャックがついているので、出力も2本設けました。
電圧降下を抑えるために電線は短めにしています。
アクリルのケースに納めました。DCジャックのケーブルは電圧降下が小さいように、短めです。
無負荷時の電圧は少し高めの5.13Vに設定しました。
このくらいに設定すれば、少々電圧降下が生じても5Vを下回ることはないでしょう。
電圧はすこし高めで5.13Vni設定です。
実際にRasPIとIO基板に接続して動かしてみましたが、
CPUの電圧は5.08V程度になりました。これで稲妻マークは出なくなりました。
わかりにくいですが、5.08Vを示しています。これで稲妻マークは出なくなりました。
ついでにDACとADCの校正データも取っておきましょう
RasPiを動かしたついでなので、IO基板のDACとADCの校正データをとっておきました。
結構面倒な作業になるかな〜と思っていましたが、意外と簡単に済みました。
というのも、いままではRS232でIO基板と通信を行っていたので、出てきた電圧値はTERATERMに表示されるので、
まずはそれをメモ帳にコピーして、そしてその値をエクセルに読み込んで、近似線をもとめて・・・・と延々と人間性を考えないような
作業が続きますが、RasPi上ではそれとちがあって勝手がいいです。というのも、RasPiのCプログラムで直接データを読み込めるので、
そのまま、近似線の計算もやってしまえます。それに、RS232だと、大量のデータだと扱うのも面倒ですが、プログラム上での
処理なら、データの量は関係ありません。無茶苦茶多い点数で近似線をもとめました。まあ、点が多ければ精度があがるというものでは
ありませんが・・・・。本来は基板上のPICに校正用のデータをとるプログラムを組めばよかったのですが、残念なことにPICのCコンパイラの浮動小数点
演算が単精度なので、おそらくそれで計算しても精度がでないでしょう。
ということで、RasPiでプログラムを組んで、ちゃっちゃと校正用のデータをとりました。こちらは倍精度演算なので、計算精度は問題ありません。
備忘録代わりに
この校正データは、備忘録みたいなものです。どこかにメモしてもなくしたり、HDDにいれても飛んだりする可能性があるので、
HPに上げておけば、とりあえずはデータはなくなりません(すくなくとももサーバの会社が面倒をみてくれます。
校正値にもとづく計算はコンピュータがやるので、とりあえず有効桁数は無視です(笑。
DACの校正データです。
ADC(CH.0)の校正データです。
ADC(CH.1)の校正データです。
しかし暑いなあ〜 2020.8.16
外に出ると、太陽の日差しが痛いです。
こんなときは、部屋にこもってのんびりするのに限ります。
とはいえ、連休も今日でおしまい。この連休に何をしたの?といわれると・・・う、寂しい。
まずはRasPi用のIO基板は完成したけど、使えるソフトがなければ、放置プレイにもなりかねないので、
汎用的に使えるソフトを取り急ぎ組んでみましょう。なんとなく、小学生が夏休みの宿題ができていなくて、
前日に大急ぎで繕う様子に類似しています(笑。
とりあえずシンプルに
GTKのグラフィックルーチンをつかって、取り込んだ波形を表示するソフトをつくりました。
一応マウスで動くようにしています。ただ、GTKのややこしい(?)関数はつかわずに、力技です。
画面上のマウスの位置から、実行するコマンドを割り出すようにしています。画面の下にコマンドを配置しました。
1kHz(振幅1V)で90度位相の異なる正弦波をサンプルしています(測定点数は1000点、測定レンジは0.625VREF。約±2.5V)
とりあえず、こういったソフトを1つ作っておけば、たとえハードやソフトの中身を忘れてしまったとして、何らかのの形で使えるでしょう。
これで、捨てられる可能性はすこし減りました。
大振幅は綺麗だけど・・・・
上の図のように、大振幅(1V)だと流石に綺麗にデータが取れます。でも、今回使っているADCは一応16Bitです(安かったけど)。
小さい信号でもどこまで測定できるのかが気になるところです。ということで、もっとレベルを小さくして、測定する周波数も上げてみました。
5kHz(振幅10mV程度)で90度位相の異なる正弦波をサンプルしています(測定点数は100点、測定レンジはもっとも大きい3VREF。約±12V)
ただ、手持ちの発振器も自作ということもあり、もあまり出力が絞れるようになっていないのと小さくするとオフセット誤差も顕著にでてきます。
それに、発振器側のノイズもあるだろうし・・・という懸念もありましたが発振器出力を一番絞った状態での測定結果ですが、意外にも
正弦波になっているようです。入力レンジを最大の3VREF(±12V)にしているので、1LSBは0.37mVと大きいですが、このくらい測定できれば
いいでしょう。ちなみに、測定レンジを小さくして0.625VREF(±12V)にすると、1LSB=0.078mVになり分解能があがるため波形は綺麗に
なります(下図)。これから考えると、上図の波形の乱れの要因はやはりADC側にあるのかな?
5kHz(振幅10mV程度)で90度位相の異なる正弦波をサンプルしています(測定点数は100点、測定レンジは0.625VREF。約±2.5V)
さて、これで夏休みの宿題は許してもらえるかな〜。
以前のADC(12Bit)と比較
念のため、前編でつくった12BITのADCと比較です。ソフトでSPIではサンプリング時間がバラバラになるのを嫌になって、
そのままにしていたものです。今回つくったソフトのサンプリング部分のみを書き換えて測定してみました。
やはり、測定の途中でサンプリング間隔が大きく変わってしまっています。
前編での12BITADCでの測定(周波数400Hz、振幅約10mV)。 途中でサンプリング間隔が変わってしまっています。
変換値ですが、1LSB=1.2mVになるので、流石に粗くはなってしまいますが、12ビットならこんなものでしょうか。
平均化をすれば、もっと綺麗になるでしょうが、やはり測定の途中でサンプリング間隔が変わってしまうのは仕方ないですね。
ちなみに、変換速度は(速いときで)40〜50kSPSくらいはでてるかな。
前編での12BITADCでの測定(周波数40Hz、振幅約10mV)。 16Bitに比べると変換誤差が目立ちますが、こんなもんでしょう。
プチ改造(オーバクロック)
とりあえず動くようになって、電圧の校正も完了です。あとは横軸の校正もしたいところです。現時点では横軸は単なるサンプル点数になっていますが、
これを時間に変換したいところです。そのためには、正確なサンプリング時間を得る必要があります。
発振クロックにはPICの内蔵クロックをつかっており、公称は64MHzですが色々と計測してわかったことは、実際の発振周波数は64.211MHzです。
0.211MHz分のおまけがついていますが、これはちょっと余分です。64MHzジャストだったら1命令サイクルが1/16MHz=62.5nsと計算しやすいのですが、
64.211MHzだと1命令サイクルが62.29nsとなり中途半端。
PICの内蔵発振器ってもっと正確かと思っていましたら、結構誤差があるものです。64.211MHzだと0.33%の誤差です。まあ、メーカのデータシートでは
1%以内と書いてあるので仕様内ではありますが・・・・。この誤差が常に一定だったらいいですが、温度でもかわるだろうし・・・・、やっぱり発振器を
水晶に変更しましょう。ついでに、オーバクロックで80MHzで動かします。そうすれば1命令サイクルは1/20MHz=50nsとかなり切りの良い数字になります。
水晶をとりつける位置のPICのIO端子はすでに他の機能でつかっていますが、ちょっと引越しをしてもらいます。一人部屋での引越し先はないのですが、
ICSP(In-Circuit Serial Programming)につかう端子が2本あるのでそこを共有でつかってもらうことにします。まあルームシェアーみたいなものです。
空いた隙間に20MHz水晶を入れました。これを4倍PLLで80MHzでPICを動かします。
20MHzの水晶に交換したら、すこしプログラムを修正です。いまでもギリギリのAD変換時間しか確保していないので、クロックが64MHzから80MHzになると
25%の速度アップですから、完全に足りなくなります。そこで、プログラムの数箇所に遅延のためのNOP(delay_cycles)を組み込みます。少々のNOPが追加
されますが、クロック全体の周波数があがるので、いまよりも変換速度は速くなるはずです。とくにデータ転送に32命令サイクルかかりますが、これが80MHz
になることで2us→1.6usになりますから、この部分が大きいです。
少し早くなりました
64MHzで動作させていたときは、ADCの取り込み周期は44命令サイクル(2.75us)でしたが、80MHz化によりNOPを挿入したことで46命令サイクルに増加
しましたが、周期は2.3usに短くなりました。これでサンプリング周期は434.8kSPSまであがりました(いままで約350kSPS)。ちょっと嬉しいです。
なんか、車のエンジンを弄ってちょっと調子がよくなったような感じでしょうね。
ややこしいな〜・・・
サンプリング速度が速くなったのはいいのだけど、434.8kSPSも中途半端な数字です。そこまで早くなくてもいいので、反対に切りの良い数字に
なるように調整していきましょう。そうすればチャートを書くときの時間軸の表示も簡潔になるはずです。
サンプリング速度は最高を400kSPSにあとは、250k、200k、100k、50k、40k、25k,20k・・・・・・、1kSPSで変更できるようにしましょう。
ソフトだけなので、夜の夜長の晩酌のあてにもってこいです(笑。
ソフトをプチ修正 2020.8.18
横軸をAD変換のサンプル点数なのを時間に変更しました。
やっぱり、グラフの横軸は時間でないと駄目ですよね〜(汗。
で、今回のIOボードの特徴の一つがDACとADCの同期運転ができます。厳密にいえば、同期はしていなくて
DAC出力→ADC入力→DAC出力→ADC入力→ という流れになります、最高速で250kSPSすなわち4us毎での
動作が可能です。そこで、DACに出力する波形データをメモリー(16kW)に書き込んでおけば、任意の出力波形に
対する、反応挙動を計測することができます。
試しに、1ms幅のパルス波をつくって、コンデンサ(0.068uF)と抵抗(1kΩ)のHPFの通過特性を測定してみました。
横軸を変更しました。時間にすることで、物理的内容がわかり易くなりました。測定例はHPFの応答です。
波形を見るだけならオシロでも十分ですが、ADCを使うとその電圧値を記録することができます。
電圧を記録して何をしたいの?
という疑問がでてくると思いますが、色々と必要になるのです。
たとえばトランスの磁心の磁気特性を測ろうとすれば、1次コイルに電流を流して2次コイルの電圧を測定しますが、
磁束に換算するには2次コイル電圧を積分する必要があります(高校の物理ですね)。
あと、このI/Oボードをつかってゲインフェーズアナライザー(GFA)の機能も持たせようかと考えています。GFAについては
すでに自作したものがありますが、インターフェイスがRS232なので一旦PCにデータを取り込んだのちに、エクセル等でグラフに
する必要があります。実はこれが面倒だったりします。しかしながら、RasPiで直接AD変換値のデータがあつかえるなら、
ゲインと位相を計算して、そのままグラフにすることができます。まあ、いつできるかわかりませんが・・・・。
いかんいかん、完全にやろうとしているとこが手段の実現なのですが、完全に目的と化してきています。
まあ、趣味なのでしかたないですね。。。。。
それにしても、ソフトだけだとだんだんきつくなってきました。やっぱり半田ゴテを握りたいよ〜!!
を!まさしくアルコールによる禁断症状か(笑。
ちょっとゲインフェーズアナライザを実験してみよう
ゲインフェーズアナライザとしてつかえそうか、ちょっと実験してみました。といっても、簡単なソフトを組むだけです。
DACの出力テーブルに正弦波(SIN)を書き込んで、それを出力しながら対象の出力からのAD変換した値を取り込みます。そして、その値に
SINとCOSを掛けたものを積算するだけです。これを測定する周波数毎で行います。さらりと書きましたが、実際の計算量は
結構あり、PICでやったらとても現実的なものではありません。その点、RasPiはかなり速いですから、大量の計算をこなすことができます。
ただ、計算するソフトは超適当です。積算する範囲については正弦波の周期で区切らないと、誤差がでてしまいますが
このあたりは無視です。大量の波数を積算すれば誤差は無視できるでしょう。ただし、低周波領域だとDACテーブルに数波しからのらないから
問題がでるかも・・・ああ、今は無視!
で、簡単に書いてみました。とりあえず、計算結果はテキストベースでだして、あとはエクセルでグラフにしてみました。
グラフィックにしようとしたら、対数結果を表示できるようにしないといけないので、それはそれで手間なので、今回は手抜きです。
まずはリファレンス
DACの出力を直接ADに取り込んで、まずは校正値(リファレンス)の取り込みです。ちょっと気になるはADC(ADS8685)の内部に結構低めの
2次LPF(15kHz)がはいっているので、あまり高い周波数までははかれないでしょう。ということで、すこし遠慮して10kHzまでで測定するように
してみます。まずは校正値は下図のようになりました。やはり、高周波に向けてゲインが低下します。ただ、ADCのフィルターだけでなく、
DACにもグリッジをとるためのフィルターもあるので、その影響もあるだろうな〜。さらに、DACに使っているOPアンプが超のろい・・・・・。
まあ、色々とありますわ〜(笑。
また、低周波数領域ですこしデータがばらついていますが、これは懸念してた積算波数の問題ですね。ただ0.5dB程度なので無視しましょう。
そして、この結果を校正値として、以前使っていたチャンデバのフィルターの特性を測定してみました。
ゲインフェーズアナライザの実験です。まずはDACとADCと直結して校正値の測定です,.
ADCの内蔵フィルターの影響がでています。原因はほかにもありそうですが・・・
チャンデバーの測定結果は・・
再びチャンデバの特性を測定してみることに。
測定結果は下図のようになりました。案外つかえそうな感じがしてきました。16Bitの分解能があるためか-80dBくらいでも
綺麗に測定できています。流石に-90dBは難しいかな?なんせ16BitだとDRが96dBしかないですからね。
以前使っていたチャンデバの特性を測定してみました。簡単なプログラムですが意外と綺麗にはかれそうです。
比較のために、アナログでつくったGFAでの結果と表示範囲を同一にして比較してみました。
完全に一致しそうですね。こりゃ10kHz以下の用途なら使えそうです。ネットワークの特性の評価などにはいいかもです。
ただ、10kHzというのは帯に短し襷に長しだなあ〜。オーディオ用なら最低でも20kHzまではほしいところです。
今回のI.O基板のDACとADCを使って測定したゲイン特性は以前にアナログ式のGFAと良く一致しました。
以前にアナログ式のGFAで測定した結果。
とえあえず、ゲインフェーズアナライザとしても使えそうなことはわかったので、測定用のソフトでも作ろうかな?
作るなら、もうすこしまじめにやらないと駄目ですが・・・・。
プチ改造(その2) 2020.8.22
せっかく作った12BitのADC(MCP3208)が遊んでいるので、これもサンプリングソフトの中に組み込むことにしました。
そうしておけば入力が不足するときに、なんらかの役にたつかも知れません(勿論16BitのADCとの同時サンプリングはできませんが・・・)。
で、簡単にADCのサンプリングが等間隔に行われると仮定して、プログラムを組み込むとLINUXの割り込みの罠にはまってしまって、
サンプリングが無茶苦茶になってしまいます。
単純にADCの取り込み間隔が一定としてサンプリングソフトを組み込むと、LINUXの割り込みの妨害をうけてしまいます。
対策(その1)
そこで、ADサンプルの前に、時間を計測しておくことにしました。関数timespec_get()は現在の時刻をnsecのオーダで取り出すことができるので、
それを使います。そして、サンプリングの横軸として時間データも取り込むようにしたところ、まあまあうまくいきましした。
時間データもあわせて取り込むことで、見かけ上は等間隔でサンプルできています。
でも、すこし罠がまっていました。プログラムとしては
forループ{
時間の測定(timespec_get)
ADCのサンプル(CH0)
ADCのサンプル(CH1)
}
という形になっているのですが、時間の測定からADCのサンプルまでに幾分の時間の隙間があるので、そこに割り込みが入ってきます。
とくにCH.1については時間計測から結構な時間(数10us)が経過するので、割り込みの絶好に標的です。
事象としては、ちょうどADCのサンプル時間が40uS程度で、20000点をサンプルすると0.8秒程度かかりますが、その中で10箇所くらい、下図に示すような
いびつなデータになる箇所があります。極力キーとかマウスとかを動かさない状態でこれですから、マウスを動かしながらサンプリングしたのでは
もっとひどいことになるでしょう。
時間の測定とADCサンプルの合間に割り込みが入り込んできてしまい、時間軸に誤差がでてしまいます。
対策(その2)
ADCサンプルを行うときに時間を測定することに変更はありませんが、時間の測定タイミングをもっと適切な位置に変更することにしましょう。
具体的にはADCサンプルのサブルーチンの中にtimespec_get関数を入れ込んでやります。で、どこに入れるかですが、MCP3208のタイミングチャート(下図)
をみると、t(sample)という区間があり、ここで外部のアナログ値がサンプルされます。一般的なADCのサンプリングであれば、内部のサンプラーの
コンデンサに電圧をチャージします。サンプルの開始でチャージして、サンプルの停止時にホールド(チャージ終了)となるので、ホールドとなる
CLKの立下り直後にtimespoec_get関数を入れることにしました。
こうすることで、ほぼサンプル時の時間を計測することができますし、さらに割り込みの影響をうける隙も小さくなります。
厳密には、まだまだ割り込みが入る可能性もゼロではありませんが、確率的にはかなり小さくなるでしょう。
ADCのサンプル&ホールドの直後に時間を計測します。
この対策をすることで、時間軸の乱れはほとんどなくなりました(まだ、発生を確認していません)。これで、12BitのADCも使ってあげられそうです。
いままで、出番がすくなかったので喜んでいるでしょう(笑。
ADCのサンプル&ホールドのホールド直後に時間計測をすることで、時間軸の乱れはほとんど出なくなりました。
さて、週末は上京です。関東もあついだろうな〜...
プチ改造(その3) 2020.8.24
周波数−ゲイン特性の測定プログラムも組み込みました。
すこしまじめにということで、同期検波の積分期間については正弦波の周期毎にきっちりあわせることにします。
これにより、低周波数側での本来発生しないノイズを抑えることができます。というのも、たとえば20Hzだと、1波しか
演算していませんので積分する期間を波長にピッタシあわせないと誤差がでてきてしまいます。
あと、周波数の測定範囲はオーディオ用らしく20Hz〜20kHzにしました。ADCのフィルターの特性から20kHzでは
感度が落ちますが、校正線を採ったところでは20kHzで-9dBだったので、これを基準にして補正します。全体のダイナミックレンジが
90dB近くあるはずですから10dB程度の補正は問題ないでしょう。
2CHが同時に測定できるので、チャンデバの左右を同時に測定しました。特性はよくあっています。低周波でのバラつきは積分期間の修正で改善しました。
-80dB以下ではすこし曲線がヨレている感じがありますが、まあこんなもんでしょう。BPFとHPFを同時に測定しています。
(つづく、それともおしまい?)