Edited at

SPI /IIOサブシステムを用いたラズベリーパイ用高精度A/D変換モジュール「ADPi Pro」による計測方法

More than 1 year has passed since last update.

Raspberry Pi 3を使って、アナログ信号をデジタル信号に変換するプログラムを作成します。A/D変換には、メカトラックス社のラズベリーパイ用高精度A/D変換モジュール「ADPi Pro」を使用します。ADPi Proは、24bit分解能のAnalog Devices社「AD7794」を使用し、温度特性に配慮した外部基準電圧発生ICの搭載し、出荷時校正データを格納した「EEPROM」により、A/D変換したデータを補正します。

ADPi Proは、SPIインタフェースとIIOサブシステムにより接続可能で、SPIインタフェースを使用するときはSPIを用いたラズベリーパイ用高精度A/D変換モジュール「ADPi Pro」のセットアップ、IIOサブシステムを使用するときはIIOサブシステムを用いたラズベリーパイ用高精度A/D変換モジュール「ADPi Pro」のセットアップに従って、それぞれセットアップします。

実際にADPi Proに分圧した1Vのアナログ電圧を入力して、Raspberry Pi 3でA/D変換値を取得する動作環境の様子を次に示します。なお、ADPi Pro の資料は、ADPi Pro(ラズベリーパイ用高精度 A/D 変換モジュール)に公開されています。

adpi01.jpg

作成したプログラムを確認するための1Vのアナログ電圧は、ADPi Proのターミナルブロック4個の差動電圧入力「Vin+」「Vin-」のそれぞれに、5Vを5個の抵抗で分圧した「1V」を次ように接続します。


SPIを用いたADPi Proによる計測

ADPi ProをSPIデバイスとして動作させ、ADPi Proのターミナルブロックに接続されたアナログ電圧値をA/D変換して入力するpythonスクリプトを作成します。なお、SPIを用いたADPi Proのセットアップについては、ADPi Proのセットアップ(SPI)に示します。


SPIを用いたADPi ProのPythonスクリプトの作成

ADPi Proに接続されたアナログ電圧を、SPIインタフェースを使ってA/D変換値を入力し、変換した値に対して補正を行うPythonスクリプトを作成します。


  • Python3 により SPI 通信でADPi ProのA/D変換器「AD7794」をアクセスするために、spidevパッケージを使用します。

  • Python3 により I2C通信でADPi Proの出荷時校正データ「EEPROM」をアクセスするために、smbusパッケージを使用します。

  • adpiパッケージは、ADPi Proを構成する24bit分解能のA/D変換器「AD7794」、出荷時校正データを格納する「EEPROM」、GPIO エキスパンダ「MCP23008」を制御するPythonスクリプトクラスで、Pythonスクリプトのコードをpython-adpiに示します。

  • get_voltage関数は、adpiクラスのインスタンスとA/D変換するチャンネル番号をパラメータにし、チャンネル番号に対応するターミナルブロックに接続されたアナログ電圧値を、single_conversion関数を用いて取得し、取得したデータから対応するチャンネルの入力電圧を計算して、その計算結果を文字列変換して関数の戻り値とします。

  • single_conversion関数は、入力電圧のスケール値とその生の電圧値を取得します。


adpispisample.py

#!/usr/bin/python3


import spidev
import smbus
import adpi
import sys
from time import sleep

RAW_OFFSET = (1 << 23)
RAW_SCALE = (
0.000596040,
0.000298020,
0.000149010,
0.000074500,
0.000037250,
0.000018620,
0.000009310,
0.000004650,
)
TEMP_VREF = 1.17

def v2k(rate, val):
for k, v in rate.items():
if v == val:
return k

def single_conversion(dev, ch):
c = dev.adc.channel[ch]
g, _ = dev.read_configuration()
dev.write_configuration(g, c)
_, r = dev.read_mode()
dev.write_mode(dev.adc.mode['single'], r)
rate = v2k(dev.adc.rate, r)

while True:
sleep(2 * 1.0 / float(rate))
if not dev.read_status() & 0x80:
break

raw = dev.read_data()
return raw, g

def get_voltage(dev, ch):
raw, g = single_conversion(dev, ch)
vol = RAW_SCALE[g] * (raw - RAW_OFFSET)
return "Ch {} : {:.9f}".format(ch,vol)

if __name__ == "__main__":
spibus = 0
spics = 0
eeprombus = 1
eepromaddr = 0x57
gpiobus = 1
gpioaddr = 0x27
spi = spidev.SpiDev()
i2c = smbus.SMBus(eeprombus)
try:
spi.open(spibus, spics)
spi.mode = 0b11
spi.max_speed_hz = 1000000
ad = adpi.ADPiPro(spi, i2c, eepromaddr, gpioaddr)
print(get_voltage(ad, "1"))
print(get_voltage(ad, "2"))
print(get_voltage(ad, "3"))
print(get_voltage(ad, "4"))

except (IndexError, ValueError):
sys.exit(2)
finally:
spi.close()



作成したPythonスクリプトの実行

作成したPythonスクリプトを次のコマンドで実行すると、4チャンネル分のA/D変換値が表示されます。

$ python3 adpispisample.py

Ch 1 : 1005.942668400
Ch 2 : 1005.440802720
Ch 3 : 1006.350359760
Ch 4 : 1005.499810680


IIOサブシステムを用いたADPi Proによる計測

ADPi ProをIIO サブシステムとして動作させ、ADPi Proのターミナルブロックに接続されたアナログ電圧値をA/D変換して入力するシェルスクリプトを作成します。なお、IIOサブシステムを用いたADPi Proのセットアップについては、ADPi Proのセットアップ(IIOサブシステム)に示します。


IIOサブシステムを用いたADPi Proのシェルスクリプトの作成

ADPi Proに接続されたアナログ電圧を、IIOサブシステムを使ってA/D変換値を入力し、変換した値に対して補正を行うシェルスクリプトを作成します。シェルスクリプトは、IIO サブシステムに示すIIO サブシステムを用いて、ADPi Pro に搭載された ADC へアクセスします。


  • cat ${IIO_PATH}/in_voltage${idx}-voltage${idx}_offset 」により、チャンネルに対応したオフセット値を取得します。

  • cat ${IIO_PATH}/in_voltage-voltage_scale 」により、入力電圧のスケール値を取得します。

  • cat ${IIO_PATH}/in_voltage${idx}-voltage${idx}_raw 」により、チャンネルに対応した生の電圧値を取得します。

  • get_voltage関数は、A/D変換するチャンネル番号をパラメータにし、チャンネル番号に対応するターミナルブロックに接続されたアナログ電圧をデジタル変換し、取得した入力電圧のスケール値、オフセット値、生の電圧値からチャンネルごとの入力電圧を計算して表示します。


adpiiiosample.sh

#!/bin/bash

set -e

LIB_PATH=/usr/lib/adpi-utils-backend-iio/
IIO_PATH=/sys/bus/spi/devices/spi0.0/iio:device0

INDEX_OFFSET=-1

#
# Usage: get_voltage <N>
#
get_voltage ()
{
local idx
local ofs
local scl
local raw

idx=$(($1 + $INDEX_OFFSET))
ofs=$(cat ${IIO_PATH}/in_voltage${idx}-voltage${idx}_offset)
scl=$(cat ${IIO_PATH}/in_voltage-voltage_scale)
raw=$(cat ${IIO_PATH}/in_voltage${idx}-voltage${idx}_raw)

printf "Ch %d : " $(echo $1)
printf "%.9f\n" $(echo "($raw + $ofs) * $scl" | bc -l)
}

#
# execute command
#
status=2
get_voltage 1
get_voltage 2
get_voltage 3
get_voltage 4
status=$?

exit $status



作成したシェルスクリプトの実行

作成したシェルスクリプトを次のコマンドで実行すると、4チャンネル分のA/D変換値が表示されます。

$ ./adpiiiosample.sh

Ch 1 : 1005.272123400
Ch 2 : 1005.208347120
Ch 3 : 1006.048167480
Ch 4 : 1005.173776800


ADPi Proに関連する記事

1. SPIを用いたラズベリーパイ用高精度A/D変換モジュール「ADPi Pro」のセットアップ

ADPi ProをSPIデバイスとして動作させ、Python言語で作成されたサンプルスクリプトを実行して、ADPi Proに接続したアナログ電圧のA/D変換値を確認します。

2. IIOサブシステムを用いたラズベリーパイ用高精度A/D変換モジュール「ADPi Pro」のセットアップ

ADPi ProをIIOサブシステムとして動作させ、作成されたサンプルシェルスクリプトを実行して、ADPi Proに接続したアナログ電圧のA/D変換値を確認します。