Raspberry Pi PR

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より引用

使用する部品

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

RaspberryPi 4 (8GBモデル)

解説はRaspberryPi 「2」 ですが、今買うなら、性能が大幅アップした「4」がおすすめです。 後継機なのでピンアサインは同一で、解説と同じように使えます。

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(アナログ-デジタル変換)を行う方法について解説しました。参考になればうれしいです。

お知らせ

今月号のInterfaceは『仕事のChatGPT』!

今週号の日経Interfaceは「仕事のChatGPT」。
イントロとして、ChatGPTをはじめとした大規模言語モデル(LLM)の現在や、エンジニア向け生成AIの活用法。その後の内容で、ChatGPTを使ったPythonでゲームの作り方や生成AIを使ったシステムの製作例が学べます。

全ての内容はここでは紹介しきれないので、詳細は以下のAmazonページをご覧ください。

5月25日発売です。

CQ出版
¥1,430 (2024/04/25 12:53時点 | Amazon調べ)

質問・要望 大歓迎です

「こんな解説記事作って」「こんなことがしたいけど、〇〇で困ってる」など、コメント欄で教えてください。 質問・要望に、中の人ができる限り対応します。

使えたよ・設定できたよの一言コメントも大歓迎。気軽に足跡を残してみてください。記事を紹介したい方はブログ、SNSにバシバシ貼ってもらってOKです。

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

POSTED COMMENT

  1. […] Tech and Investment | RaspberryPiでA/D変換する方法【Adafurit ADS1015】 はじめに RaspberryPi でPythonを使って、ADC(アナログ-デジタル変換)を行う方法について解 […]

  2. Rocket より:

    非常にわかりやすい記事をありがとうございます。

    質問なのですが、抵抗で分圧したのは短絡を防止するためと考えて良いのでしょうか。

    また、とても素人質問で恐縮ですが、ADS1015を用いて他の電源回路の電圧測定はできるのでしょうか(GNDが違うので難しいのではないかと感じています)

    • えす より:

      Rocketさん

      コメントありがとうございます、えすです。

      お褒めいただきありがとうございます。
      分圧は3.3Vの電圧をそのまま取得してもつまらないので、半分に変化させるために行っています。
      (ボリューム等を使った方が、分かりやすかったかもですね)

      電源回路については、GNDが別(共通化できない)となると難しいかもしれません。
      電気回路はあまり得意ではないので、お力になれずすみません。

ADC(ADS1015)を使ってRaspberry Piでアナログ信号を取り込む方法 | Murasan Lab へ返信する コメントをキャンセル

メールアドレスが公開されることはありません。 が付いている欄は必須項目です