はじめに
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)の半分の電圧が入力されるようにしています。
ピン番号 | 内容 | 備考 |
1 | 3V3 power | 回路への電源供給です |
3 | SDA | I2Cの通信線です |
5 | SCL | I2Cの通信線です |
6 | Ground | 回路のグラウンドです。 |
RaspberryPi本体で「I2C通信が有効化」されていることを前提にしています。初めてI2Cを使う方は、RaspberryPiのデスクトップから設定を行ってください。
ピンアサイン
※ RaspberryPi 公式のGitHubより引用
使用する部品
今回の回路では、以下の部品を使用します。
RaspberryPi 4 (8GBモデル)
スイッチやLEDをつなげて使うなら、価格が下がった「RaspberryPi4」がおすすめです。
A/D変換基板
今回使い方を解説するA/D変換基板です。
ブレッドボード
国内サンハヤト製のブレッドボードです。少々堅めの指し心地ですが、海外製と違ってピン穴の番号がすべて印刷されており、品質も高いのでおすすめです。
ジャンプワイヤ (オス-メス タイプ)
RaspberryPiで使う場合は、以下のオスーメスタイプがおすすめです。
エネループ
使い捨ての乾電池もいいですが、エネループなら4本充電時の電気代が約1円。モーター・ポンプなどの電池が消耗しやすい実験・工作におすすめです。
※ はじめて使う方は充電器とのセットがおすすめです
電池ボックス
電源に使用する乾電池用のボックスとスナップです。記事では単4を使っていますが、容量の大きい単3タイプをお勧めします。単3でも単4でも電圧は変わりません。
抵抗
お手持ちのもので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の設定を行います。前述した接続方法と同じピンを使う場合は、以下の一行で、設定(バス番号・アドレスの指定)が行えます。
※ 固定の設定(バス番号: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(アナログ-デジタル変換)を行う方法について解説しました。参考になればうれしいです。
おすすめ書籍
MicroPythonのプログラミングガイドブックがついに登場!
「MicroPython」の専門書がついに発売になりました!
この一冊で、MicroPythonの言語仕様から、プログラミングの仕方までが、”ガッツリ”学べます!
別言語を使っている人や、これからマイコンを始める(工学系の)学生を対象としているので「初心者向け」ではありません。しかし、「自前のライブラリの作成」が目標なので、これ一冊で「ガッツリ」とMicroPythonを学びたい人におすすめの内容となっています。
全ての内容はここでは紹介しきれないので、詳細は以下からご覧ください。目次だけでも”ガッツリ”なのが確認できると思います。
質問・要望 大歓迎です
「こんな解説記事作って」「こんなことがしたいけど、〇〇で困ってる」など、コメント欄で教えてください。 質問・要望に、中の人ができる限り対応します。
使えたよ・設定できたよの一言コメントも大歓迎。気軽に足跡を残してみてください。記事を紹介したい方はブログ、SNSにバシバシ貼ってもらってOKです。
[…] Tech and Investment | RaspberryPiでA/D変換する方法【Adafurit ADS1015】 はじめに RaspberryPi でPythonを使って、ADC(アナログ-デジタル変換)を行う方法について解 […]
非常にわかりやすい記事をありがとうございます。
質問なのですが、抵抗で分圧したのは短絡を防止するためと考えて良いのでしょうか。
また、とても素人質問で恐縮ですが、ADS1015を用いて他の電源回路の電圧測定はできるのでしょうか(GNDが違うので難しいのではないかと感じています)
Rocketさん
コメントありがとうございます、えすです。
お褒めいただきありがとうございます。
分圧は3.3Vの電圧をそのまま取得してもつまらないので、半分に変化させるために行っています。
(ボリューム等を使った方が、分かりやすかったかもですね)
電源回路については、GNDが別(共通化できない)となると難しいかもしれません。
電気回路はあまり得意ではないので、お力になれずすみません。