Raspberry Pi

RaspberryPiでA/D変換する方法【Adafurit ADS1015】

はじめに

RaspberryPi でPythonを使って、ADC(アナログ-デジタル変換)を行う方法について解説します。変換にはI2C接続のADコンバータ「Adafurit ADS1015」を使います。

RaspberryPiで「アナログ電圧」を読み取りたい場合、A/D変換用のピンがないため、A/D変換のチップ(ボード)から、I2Cなどの通信で取得する必要があります。

取得の処理はデータシートを熟読し、ビット演算などを駆使して行うこともできますが、ボードメーカからライブラリが提供(公開)されているものであれば、数行で処理を書くことができます。

今回は、ライブラリが公開されている「Adafurit ADS1015」を使って「アナログ電圧」を取得する方法を解説したいと思います。

※ 今回の内容は吉田 純造さんよりリクエストいただきました。ありがとうございます。

環境

この記事は以下の環境で作成しています。

環境 バージョンなど 備考
RaspberryPi 2 Model B RaspberryPi 2/3/4  Zero各種でも使えます
OS RaspberryPi OS (bullseye) 32bit版です
Python 3.9.2 OS プリインストールのバージョンです
ライブラリ Adafruit_ADS1x15 メーカ公式のライブラリです

RaspberryPiとの接続

「RaspberryPi」と「ADC1015」を以下のように接続します。アナログ電圧の部分は、抵抗で分圧して、電源(3.3V)の半分の電圧が入力されるようにしています。

RaspberryPiとADS1015のつなぎ方を説明する画像

ピン番号 内容 備考
1 3V3 power 回路への電源供給です
3 SDA I2Cの通信線です
5 SCL I2Cの通信線です
6 Ground 回路のグラウンドです。

RaspberryPi本体で「I2C通信が有効化」されていることを前提にしています。初めてI2Cを使う方は、RaspberryPiのデスクトップから設定を行ってください。

ピンアサイン

RaspberryPi 公式のGitHubより引用

使用する部品

今回の回路では、以下の部品を使用します。

A/D変換基板

今回使い方を解説するA/D変換基板です。

¥1,749 (2022/08/16 12:57時点 | Amazon調べ)

ブレッドボード

どのメーカーのものでも問題ないです。大きい方が自由度が高く・品質もいいので、サンハヤト製の以下のタイプをおすすめします。

あきばお〜楽天市場支店
¥945 (2022/09/18 00:07時点 | 楽天市場調べ)

ジャンパワイヤ

「オスーメス」タイプであれば、どのメーカーのものでも問題ないです。各色が何本かあると配線が分かりやすくなるのでオススメです。

抵抗

抵抗もお手持ちのものでOKです。ない方は一度セットで揃えてしまうと送料や時間が節約できます。

プログラム概要

今回のプログラムの概要は以下の通りです。

  • ADS1015を設定する
  • ADS1015のデータ1単位の電圧を計算する
  • ADS1015からデータを取得する
  • ADS1015のデータを電圧に変換する

実行結果

実行結果は以下の通りです。RaspberryPiから「アナログ電圧」として、電源(3.3V)の半分の電圧(1.65V)が取得できます。

esu@raspberrypi:~/repos/ads1015 $ esu@raspberrypi:~/repos/ads1015 $ python ads1015.py
受信データ:829
電圧      :1.658
受信データ:829
電圧      :1.658
受信データ:829
電圧      :1.658
受信データ:829
電圧      :1.658
受信データ:829
電圧      :1.658
受信データ:829
電圧      :1.658

I2Cの設定

I2Cの有効化

RaspberryPiはデフォルトでI2Cの通信が無効化されています。初めてI2C通信を使う方は、こちらの記事を参考に、I2Cを有効化してください。

ライブラリのインストール

プログラムを書く前に、以下のコマンドでAdafuruit純正のライブラリ「Adafruit_ADS1x15」をインストールします。

sudo pip install adafruit-ads1x15

以下のように「Successfully installed …」と表示されたら、インストールは完了です。

esu@raspberrypi:~ $ esu@raspberrypi:~ $ sudo pip install adafruit-ads1x15
Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Collecting adafruit-ads1x15
  Downloading https://www.piwheels.org/simple/adafruit-ads1x15/Adafruit_ADS1x15-1.0.2-py3-none-any.whl (7.0 kB)
Collecting Adafruit-GPIO>=0.6.5
  Downloading https://www.piwheels.org/simple/adafruit-gpio/Adafruit_GPIO-1.0.3-py3-none-any.whl (38 kB)
Requirement already satisfied: spidev in /usr/lib/python3/dist-packages (from Adafruit-GPIO>=0.6.5->adafruit-ads1x15) (3.5)
Collecting adafruit-pureio
  Downloading https://www.piwheels.org/simple/adafruit-pureio/Adafruit_PureIO-1.1.9-py3-none-any.whl (12 kB)
Installing collected packages: adafruit-pureio, Adafruit-GPIO, adafruit-ads1x15
Successfully installed Adafruit-GPIO-1.0.3 adafruit-ads1x15-1.0.2 adafruit-pureio-1.1.9

※ Adafuruit公式のGitHubはこちらです。

全体コード

全体コードは以下の通りです。詳細な内容は後述する「コードのポイント」で解説します。

import time
import Adafruit_ADS1x15

# ADS1015の設定をします
ads = Adafruit_ADS1x15.ADS1015()

# ゲインの設定です
# 指定によって、取得できる電圧の範囲が変わります

#  - 2/3 = +/-6.144V
#  -   1 = +/-4.096V
#  -   2 = +/-2.048V
#  -   4 = +/-1.024V
#  -   8 = +/-0.512V
#  -  16 = +/-0.256V
GAIN = 1

#
#「ゲイン1」の時の、「受信データ1単位」の電圧を計算します
#

# 「ゲイン1」の範囲はプラス・マイナス 4.096なので、8.192になります
RANGE = 4.096 * 2

# ADSは上記範囲を12bit(4096)で表すので、上記範囲を4096で割ると
# ADSのデータ「1」につき、電圧は0.002[V]になります。
# UNIT=単位
UNIT = RANGE / 4096

# ループを100回繰り返します
for i in range(100):

    # ADSのアナログ入力ピンを指定します
    ads1015_pin  = 0

    data = 0
    volt = 0

    # ADS1015からデータを取得します
    data = ads.read_adc( ads1015_pin, gain=GAIN)

    # 取得データから電圧を計算します
    volt = data * UNIT

    print("受信データ:" + str(data))
    print("電圧      :" + "{:.3f}".format(volt))

    # 1秒待機します
    time.sleep(1)

print("done.")

コードのポイント

ADS1015の設定

ADS1015の設定を行います。前述した接続方法と同じであれば、以下の一行で、I2C通信に関わる設定(バス番号・アドレスの指定)が行えます。

※ 固定の設定(バス番号:1、アドレス:0x48) が設定されます。

# ADS1015の設定をします
ads = Adafruit_ADS1x15.ADS1015()

アドレス等を変えている場合は、引数により設定してください。

ads = Adafruit_ADS1x15.ADS1015(address=0x49, busnum=1)

ゲインの設定

ADS1015の「ゲイン」を設定します。読み取りたい「アナログ電圧」の範囲に応じて設定してください。

以下のコードでは電源電圧「3.3V」を使用するため「ゲイン1」を設定しています。

# ゲインの設定です
# 指定によって、取得できる電圧の範囲が変わります

#  - 2/3 = +/-6.144V
#  -   1 = +/-4.096V
#  -   2 = +/-2.048V
#  -   4 = +/-1.024V
#  -   8 = +/-0.512V
#  -  16 = +/-0.256V
GAIN = 1

受信データ1単位の計算

ADS1015は、読み取ったアナログ電圧値を「12bit(0~4095)の範囲のいくつか?」という形で返すため、そのままでは「何ボルトか?」がわかりません。

そのため、前述した「ゲイン」の設定に合わせて、受信データ1単位当たりの電圧値を計算します。「ゲイン1」の計算は以下の流れです。

① 全体の電圧範囲の計算

「ゲイン1」の場合は、”プラス・マイナス” 4.096[V]なので、プラスからマイナスまでの全体の電圧の範囲は、倍の8.192[V]になります。

4.096[V] × 2 = 8.192[V]

② 1単位あたりの電圧値を計算

ADS1015は、上記8.192[V]を12bit(4096)で表すので、割り算をして受信データ「1」あたりの電圧を計算します。

8.192 ÷ 4096 = 0.002[V]

上記により、「ゲイン1」の場合の、受信データ1単位は「0.002V」であることが計算できます。後述の処理で使うため、結果をUNITに代入しておきます。

#
#「ゲイン1」の時の、「受信データ1単位」の電圧を計算します
#

# 「ゲイン1」の範囲はプラス・マイナス 4.096[V]なので、8.192になります
RANGE = 4.096 * 2

# ADSは上記範囲を12bit(4096)で表すので、上記範囲を4096で割ると
# ADSのデータ「1」につき、電圧は0.002[V]になります。
# UNIT=単位
UNIT = RANGE / 4096

「ゲイン2」など狭い範囲を指定すると、範囲が狭くなる代わりに、1単位の電圧が小さくなり、アナログ電圧を細かく計測できます。

( 2.048 × 2 ) ÷ 4096 = 0.001[V] (「ゲイン2」の計算)

アナログ電圧の読み取り

read_adc関数で、ADS1015からデータを取得します。引数には、ADS1015上のアナログ入力ピンの番号(A0~A3)、ゲインの番号を設定します。

    # ADS1015からデータを取得します
    data = ads.read_adc( ads1015_pin, gain=GAIN)

引数 内容 入力
1 ADS1015上のアナログ入力ピン(A0~A3)の番号 0~3を指定します
2 ゲインの番号を指定します。 2/3, 1,2,4,8,16を指定します
戻り値 読み取った電圧値(0~4095)が返ります ——-

※ 複数のピンを使用している場合は、ピン番号を変えて再度関数を呼び出してください。

電圧値への変換

ADS1015から取得したデータ(0~4095)を、実際の電圧値に変換します。

前述の計算で「ゲイン1」の時の「1単位の電圧(0.002V)」を計算済みなので、掛け算して実際の電圧値に変換します。

    # 取得データから電圧を計算します
    volt = data * UNIT

    print("受信データ:" + str(data))
    print("電圧      :" + "{:.3f}".format(volt))

※ “{:.3f}”.format() は、少数点第三位までを表示する指定です。

まとめ

RaspberryPi でPythonを使って、ADC(アナログ-デジタル変換)を行う方法について解説しました。参考になればうれしいです。

UdemyにRaspberryPiの講座があります

実はUdemyで『RaspberryPi』『Pico』『Arduino』の基礎/実践講座が見れます。無料もあるので「動画で学びたい」「本は読み尽くした」という方は以下のリンクをご覧ください。

⇒ RaspberryPiの講座一覧はこちら

以下の記事で、RaspberryPi・RaspberryPi Picoのおすすめ講座3選も解説しています。

RaspberryPiでPWMを使おう

このブログではRaspberryPiで「PWM」を使う方法についても解説しています。

興味のある方はこちらの記事もご覧ください。

応援・要望お待ちしてます

ブログを見ていて「この辺を詳しく知りたい」「このライブラリの使い方を知りたい」「こんなことで困ってる」...etc があれば、コメント・問い合わせ・Twitterで教えてください。質問・ご要望に合わせて解説記事を作ります。

ブログを気に入っていただけたり、「応援してもいいよ」という方がいたら、ブログやSNSでの紹介をお願いします。 あたたかい応援は、中の人の更新の大きな励みになります。

ABOUT ME
えす
現役のソフトウェアエンジニアです。 C++ C# Python を使ってます。10年ちょい設計/開発部門にいましたが、今はQAエンジニアっぽいことをしています。

COMMENT

メールアドレスが公開されることはありません。