粗大メモ置き場

個人用,たまーに来訪者を意識する雑記メモ

Raspberry Pi から高精度AD/DA変換ボードを用いてAD/DA入出力

Raspberry PiでAD/DA変換をする方法

Raspberry PiにはHigh/Lowのディジタル入出力が可能なGPIOがついていますが,アナログセンサデータを読んだりアナログ電圧を出力することはできません。 従ってこの記事で紹介されているようなAD/DAコンバータが必要になります。

回路を組むのはだるいのでAmazonで以下のAD/DA変換ボードを購入してみました。

高精度AD/DA変換ボード

高精度とうたっていますがカタログスペックは以下の通りです。

  • ADポート6チャンネル(16bit)
  • DAポート2チャンネル(12bit)

Vccは5VなのでDA出力が 0~5Vとすると,12bitで分割して大体8mVくらいの分解能があります。すごい。嘘やけど。

ボードのセットアップ

今回の環境は前回 SetupしたUbuntu MATEとします。ROSは使ってないのでROSの項は飛ばしてもOK。

bcm2835 のインストール

ここからtarファイルを落として7zで解凍します。

解凍した中にINSTALLという名前のファイルがあるのでその指示に従います。

一応実行するコマンドは以下の通りです。途中sudoが必要な点に注意。

./configure
make
sudo make check
sudo make install
make installcheck

でインストール状況をチェックできます。

提供されているサンプル

ここで配ってますが正直読むのは結構だるいので誰か解説してやってください。

コマンドラインからDA出力を制御する自分用ライブラリ

てなわけで自分でプログラムつくりました。 下記からCloneしてmakeすれば完了です。

github.com

こういうふうに5VとVcc,Vref そしてDA0,AD0とDA1,AD1を接続します。

makeした後に出てくる実行ファイルは2つです。

Vcc補正用プログラム:calib

このAD/DAコンバータでは正確な5Vが必要っぽいのですが,ラズパイから電力供給するとVccが微妙に5Vにならないという問題を抱えているため,その補正用です。

以下に実行結果を示します。

$ sudo ./calib
Supposed DA output[V] DA0:3.000000 DA1:3.000000 
Measured DA output V0 = 3.070409, V1 = 3.066153 
Supposed Vref = 5.058334 
magnitude offset: 1.011667, 1.010965

この実行結果から,3Vを出しているのに3.07Vが出ている(とADで読める)ズレが有ることがわかります。これでは12bitの分解能が台無しです。 この関係から実際のVcc=Vrefを5.058Vと推定しています。テスタで測ると5.053なので5.0Vとして考えるよりはマシになりそうです。

このときの5Vに対するVccの倍率を一番下の行で計算しています。僕の環境では1.01倍と出ていますね。

注意:原理は多分Vrefとの比較でADやDAのしきい値を変えているのでVrefの倍率分DAやADの値が変化すると読んで計算しています。もっといい方法なんかあるなら知りたいっす…

出力プログラム:dac8532_output

こちらでは,引数にDA0とDA1の出力電圧[V],Sleep時間[ms]を与えることでコマンドラインから出力を可能にしています。

$ sudo ./dac8532_output  <電圧1>  <電圧2>  <時間>  <補正> 

と打ちます。 <補正>項はデフォルトで1.01にしているので抜いてもOKです。

  • データ例

試しに4Vと2Vを出力させるよう

$ sudo ./dac8532_output  4 2 10  1.01

を実行しました。

結果は3.998Vと1.999Vでした。

Vccの電圧をきちんとしない限りカタログスペックの12bit分解能は正直出ないと思われます。 でもまぁそこまで気にしないのならそこそこの精度かなと思います。 5Vや0V等の上限下限近づいた場合はこの限りではないので注意。

Pythonからの実行

結局最近プログラムの多くをPythonで書くようになったのでDA出力もPythonからしたいです。

実はsubprocessというやつを用いるとコマンドライン実行をめちゃ簡単にできます。

import subprocess

da0 = 3
da1 = 4
duration = 20

subprocess.call(["./dac8532_test",str(da0),str(da1),str(duration)])

呼び出し先のプログラムにはsudo権限がいるのでこのPythonコードをsudoで実行すればいいわけです。 (/dev/memにアクセスするからのようですが,できればsudoなしでアクセスしたい…)

総括

カタログスペックは高いですが電源をちゃんとするとかしないと正直カタログのような超精度は出なさそうです。 ただ,ラズパイの上に乗って収まりが良く,はんだ付けなどなしで動作させられるのでアプリケーションによっては結構ありかも? 私は今回は車載用センサ処理に使っています。

久々にリポジトリ作りました。汚いですが指摘などあれば歓迎です。超暇なら直します。