SSブログ

macOSからPi Picoを使う - その10 [Pi Pico]

最近になってやっとcmakeがちょっとわかった。cmakeでは.oも.aも.soもコンパイル後リンク前のファイルは全部libraryと呼ぶのね。僕はずっと勘違いしてた。.cのソースファイルは全部共通の扱いで、libraryといえば.aとかだとばかり思い込んでいた。そのせいでファイルによってinclude pathが通らなかったりしてた。このせいで長いこと悩んでた。

cmakeのチュートリアルは僕にはなんだか難しすぎて、読んでも全然頭に入らないし。これは英語だからかそれとも僕の頭が悪いのかそれとも書き方が悪いのか。あ、日本語があったんだ。でも英語だから難しかったわけではないみたい。残る可能性はあとふたつ....

10  お試しコード

これまでの
  • ADC
  • PWM
  • multicore
を同時に使うお試しコードを考えてみる。ただしこのために回路を組むのは面倒なので
  1. PWMをローパスで平滑化してアナログレベルを作る
  2. それをADCで読む
  3. それぞれを別のコアで実行する
としよう。ローパスはRC1次のパッシブなやつでいいだろう。core0がUSBからのコマンド読み込みとPWMの発生を担当して、core1がADCを走らせてFIFO経由でcore0に返して、それをcore0がUSB経由でホストに戻す、というようなもの。絵にすると
0615testcode.png
というようなもの。絵にするまでもないか。

ADCはフリーランの状態で、ある周期で、その間ずっとデータを足し算して最終的に回数で割ることで平均化して報告する。えらそうにオーバーサンプリングなんて言い方がある(Fourier変換から言うと正しい言い方だけど)。ADCは12ビット幅で500kspsなので足し算レジスタにuint32_tを使うと約2秒で溢れてしまう。

人間が理解できるスピードだとせいぜい10msecぐらいなので、そこから2秒ほどまでの周期が選択できればいい。

また、PWMはADCの分解能とあわせてwrap値を4096にしよう。ベースクロックが125MHzなのでPWMの周波数は30.5kHzほどになる。ローパスは1次なのでこの一桁下3kHzぐらいをカットオフにしよう。それでもデューティ50%のときは30.5kHzが0.3Vぐらい漏れることになる。これが嫌ならローパスではなくてノッチにすべきなんだろうけど、そこはオーバーサンプルでカバーということにしよう。従ってオーバーサンプルの周期はPWM周期の整数倍にするのが望ましい(けどとりあえずまあいい)。

ホストからはユーザが
  • ADCの積分周期
  • PWMのデューティ
を簡単な文字列で指定できるようにする。ADCの積分1回が終わったら結果を文字列でホストに返す、とこんなところ。

ADCの入力インピーダンスがどのくらいなのか、datasheetにみつからなかった。試しにたまたま手にした640kΩの抵抗のいっぽうを3.3Vにさわって反対側をADCの入力にさわってADCを読んでみると6ビット目が立つぐらいにしかならない。10kΩのオーダの入力インピーダンスということになって結構低い。

手元にあまり大きなコンデンサを持っていなかったので、しょうがない、ローパスはオペアンプでバッファしよう。つまり回路としては
0615bufferedlowpass.png
というようなのにする。反転型のオペアンプ回路の帰還に入れるのが普通(その方がゲインも取れる)だろうけど、抵抗が2本になるのでめんどくさいし、ゲインは正確に1のほうがこの場合望ましい。またPWMのデューティを反転する必要もないし、不安定な電源の方を基準にしなくてもよくなる。GNDがどのくらい安定かというとよくわからないけど。

たまたま手持ちであった抵抗とコンデンサとTL082で、このオペアンプは両電源でないと動かないので古い基板からMAU106を剥がしてUSBの+5Vから±5Vを作った。半田付けがめんどくさいのでブレッドボードへ。Pi Picoを一緒に乗せるとギリギリになった。
0615breadboard.jpg
これでPWMのデューティを1ビットずつ増やしていってそれをADCで読んだらどうなるかをみてみる。

シングルショットでの精度は期待していないので、多めにA/Dして平均を取る(オーバーサンプリング)。

それほど高速の信号は外には出ていないけど、ブレッドボードなのでS/N的には厳しいかもしれない。せめてPWM出力も速めのトランジスタでバッファしたほうがいいかもしれない(でもそれだと反転するのでローパスでまた反転にすることになるな)。

一方で、PWMの電源とADCの基準電位が共通なので、電圧変動はキャンセルされてしまって良く見えることになる。

このコードもgithubにあげた。

10.1  測定結果

測定はPWMのデューティの値(levelレジスタの値)に対して、ある一定期間の
  • 平均値(整数部)
  • 最小値
  • 最大値
  • 変換エラーの回数
をとる。

10.1.1  256回の平均の場合

256回A/D変換してそのデータの平均の整数部を結果にする。変換は500kspsでできるので余計なことをしなければ1秒間に2000個データが取れる。4096点でもあっという間に終わる。
PWMのlevelを0〜4096と変化させてADCの読みの平均値、最大最小値をプロットしたのがこれ。
0615a100axn.png
0付近と最大値付近は暴れている。詳しくみるとPWMのパルス数で0〜16のところは平均値が跳ね上がっている。0が最小値の符号なしなのでノイズが乗ると普通こうなるが、上は最後の2、3個ぐらいが暴れるだけになっている。電源付近は強いらしい。

ちょっと長くなったので、この解析は次回に。
nice!(0)  コメント(0) 

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。