Raspberrypi3
SPIインタフェース
ADPi
IIOサブシステム

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

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変換値を確認します。