MicroPython(ESP8266)を使用して、I2Cで接続できるADS1115を使用して、電圧の測定を行ってみました。

使用するADS1115は、16BitA/Dコンバータで、4つのシングルエンド入力または2つの差動入力、およびプログラムブルコンパレータを使用できます。

今回は、シングルエンド入力または2つの差動入力を使用して、電圧の測定に挑戦したいと思います。

ADS1115は、基板に実装されたものを使用しました。
KKHMF ADS1115(amazon 他)

ESP8266とADS1115との回路図は下記のとおりです。

A0~A3までのアナログ入力は、1KΩの抵抗を並列および直列に接続して、500Ω、1KΩ、2KΩ、3KΩで抵抗分割しています。電源電圧は 3.3Vです。

thonnyとシリアル通信するためには、回路図には図示していませんが、IO15(6pin)を10KΩでGnd(プルダウン)に接続する必要があります。
および、IO2(7pin)、IO0(8pin)は内部でプルアップされていますが、必要であれば10KΩでVCC(3.3V)に接続してください。

MicroPythonのプログラムは下記のようになりました。
開発環境は前回の「MicroPython(ESP8266)に萌えたい。ESP-WROOM-02でLちか。」を参照してください

まずは、I2Cのpinを決めます。ESP8266ではソフトウェアI2Cになっているので、任意のpinを指定できます。
ここでは、SCL=IO14(3pin)、SDA=IO12(4pin)に設定しました。
必要な、ライブラリーとI2Cの初期を行います。

#	MicroPython ADS1115 readding
#
#   SCL = IO14(3pin)
#   SDA = IO12(4pin)
#   I2C address =0x48 (addr open) 

from machine import Pin, I2C

import utime

i2c=I2C(scl=Pin(14),sda=Pin(12),freq=400000)

I2CのADS1115のアドレスは、0x48(ADDR(5pin)は無接続)

極性表示のpolarityを設定します。polarity_data = 0で+表示、polarity_data = でー表示になります。

必要なバッファーを設定します。
configレジスター用に3バイト、conversion_addr用に1バイト、conversionレジスタ用に2バイト用意します。
また、configレジスターの定義をします。

最後にlsbサイズの定義をします。

polarity=['+','-']
polarity_data = 0

config_buff=bytearray(3)
conversion_addr_buff=bytearray(1)
conversion_buff=bytearray(2)

#Address Pointer Register
conversion_reg = 0x00
config_reg = 0x01

#config Register
# input(Differential)
ain0_ain1 = 0b0000_0000
ain0_ain3 = 0b0001_0000
ain1_ain3 = 0b0010_0000
ain2_ain3 = 0b0011_0000
# input(Single-ended)
ain0_gnd = 0b0100_0000
ain1_gnd = 0b0101_0000
ain2_gnd = 0b0110_0000
ain3_gnd = 0b0111_0000
# gain amplifier
v6144 = 0b0000_0000
v4064 = 0b0000_0010
v2048 = 0b0000_0100
v1024 = 0b0000_0110
v0512 = 0b0000_1000
v0256 = 0b0000_1010
v0256 = 0b0000_1100
v0256 = 0b0000_1110

# data rate
sps8 = 0b0000_0000
sps16 = 0b0010_0000
sps32 = 0b0100_0000
sps64 = 0b0110_0000
sps128 = 0b1000_0000
sps250 = 0b1010_0000
sps475 = 0b1100_0000
sps860 = 0b1110_0000

lsb_size=[187.5,125.0,62.5,31.25,15.625,7.8125,7.8125,7.8125]

今回は、ユーザー定義関数を作成しました。
関数名は、ads1115_readで引数として、入力端子、入力電圧範囲、レートです。
戻り値として、極性と測定した値を返します。

print文で、極性、測定したデータをmVで表示します。

polarity_data,data= ads1115_read(ain0_gnd ,v4064,sps128)    
print("ain0_gnd=",polarity[polarity_data],data /1000,"mV")

作成したユーザー定義関数ads1115_readは下記のとおりです。
一部コメント文がありますが、確認用に残してあります。

config_buffを設定します。
config_buff[0]はconfigレジスターを指定します。0x01になります。
config_buff[1]は初期設定値0x81と入力端子、入力電圧範囲のorを取ります。
config_buff[2]は初期設定値0x03とレートのorを取ります。

i2c.writeto関数で、I2Cアドレスおよびconfigバッファーを指定して、書き込みします。

conversionレジスターから測定値を読み出す準備をします
conversion_addr_buff[0]にconversion_reg(0x00)を指定します。
20ms後にi2c.writeto関数でI2Cアドレスとconversion_buff[0]つまり0x00を指定して、書き込みします。

i2c.readfrom_into関数でI2Cアドレスおよびconversionバッファーを読み込みます。

読みこまれたconversion_buff[0]のbit7は極性となっていますので、IF文で0x80でandを取って検査します。

マイナスの場合は、polarity_data=1をセットした後、conversion_buff[0]を左8ビットシフトし、conversion_buff[1]とorをとり、0xffffでandを取ったのちbit反転します。

プラスの場合は、polarity_data=0をセットした後、conversion_buff[0]を左8ビットシフトし、conversion_buff[1]とorをとり、0x7fffでandを取ります。

16bit生データに、LSBの係数をかけます。

戻り値として、極性と測定データ(μV)を返します。

def ads1115_read(input_ads,gain,rate):
#     utime.sleep_ms(10)
    config_buff[0] = config_reg
    config_buff[1] = 0x81 | input_ads | gain 
    config_buff[2] = 0x03 | rate 
    
#    print(config_buff[0])
#    print(config_buff[1])
#    print(config_buff[2])
    
    conversion_addr_buff[0] = conversion_reg

    i2c.writeto(i2c_addr,config_buff)
    utime.sleep_ms(20)
#    i2c.readfrom_into(i2c_addr,conversion_buff)
#    print("buff0=",conversion_buff[0])
#    print("buff1=",conversion_buff[1])    
    
    
    i2c.writeto(i2c_addr,conversion_addr_buff)
#    conversion_buff=i2c.readfrom(i2c_addr,2)
    i2c.readfrom_into(i2c_addr,conversion_buff)
#    print("buff0=",conversion_buff[0])
#    print("buff1=",conversion_buff[1])
    
    if (conversion_buff[0] & 0x80):
        polarity_data=1
        data16bit = ~(((conversion_buff[0]  << 8) | conversion_buff[1])) & 0xffff
#        print("-data16bit=",bin(data16bit))
#        print("-data16bit=",hex(data16bit))
#        print("-data16bit=",data16bit)
    else:
        polarity_data=0
        data16bit=(((conversion_buff[0]  << 8) | conversion_buff[1])) & 0x7fff
#    print("+data16bit=",data16bit)
#    print(polarity[polarity_data])
#    print("data16bit=",data16bit)
#    print(lsb_size[gain >> 1])
    data = data16bit * (lsb_size[gain >> 1])
    
    return polarity_data,data

実際に測定した結果は下記のとおりです。(内はテスタで測定した結果です)

MicroPython v1.20.0 on 2023-04-26; ESP module with ESP8266
Type "help()" for more information.
>>> %Run -c $EDITOR_CONTENT
ain0_gnd= + 252.25 mV
ain1_gnd= + 754.5 mV
ain2_gnd= + 1763.75 mV
ain3_gnd= + 3278.88 mV
ain0_ain1= - 502.125 mV
ain0_ain3= - 3026.38 mV
ain1_ain3= - 2524.13 mV
ain2_ain3= - 1514.5 mV
>>> 

ain0_gnd= + 252.25 mV  (0.252V)
ain1_gnd= + 754.5 mV   (0.753V)
ain2_gnd= + 1763.75 mV  (1.760V)
ain3_gnd= + 3278.88 mV  (3.279V)
ain0_ain1= - 502.125 mV  (-0.503V)
ain0_ain3= - 3026.38 mV  (-3.026V)
ain1_ain3= - 2524.13 mV  (-2.523V)
ain2_ain3= - 1514.5 mV  (-1.514V)

全体のブログラムは下記のとおりです。

#	MicroPython ADS1115 readding
#
#   SCL = IO14(4pin)
#   SDA = IO12(3pin)
#   I2C address =0x48 (addr open) 

from machine import Pin, I2C

import utime

i2c=I2C(scl=Pin(14),sda=Pin(12),freq=400000)

i2c_addr= 0x48

polarity=['+','-']
polarity_data = 0

config_buff=bytearray(3)
conversion_addr_buff=bytearray(1)
conversion_buff=bytearray(2)

#Address Pointer Register
conversion_reg = 0x00
config_reg = 0x01

#config Register
# input(Differential)
ain0_ain1 = 0b0000_0000
ain0_ain3 = 0b0001_0000
ain1_ain3 = 0b0010_0000
ain2_ain3 = 0b0011_0000
# input(Single-ended)
ain0_gnd = 0b0100_0000
ain1_gnd = 0b0101_0000
ain2_gnd = 0b0110_0000
ain3_gnd = 0b0111_0000
# gain amplifier
v6144 = 0b0000_0000
v4064 = 0b0000_0010
v2048 = 0b0000_0100
v1024 = 0b0000_0110
v0512 = 0b0000_1000
v0256 = 0b0000_1010
v0256 = 0b0000_1100
v0256 = 0b0000_1110

# data rate
sps8 = 0b0000_0000
sps16 = 0b0010_0000
sps32 = 0b0100_0000
sps64 = 0b0110_0000
sps128 = 0b1000_0000
sps250 = 0b1010_0000
sps475 = 0b1100_0000
sps860 = 0b1110_0000

lsb_size=[187.5,125.0,62.5,31.25,15.625,7.8125,7.8125,7.8125]

def ads1115_read(input_ads,gain,rate):
#     utime.sleep_ms(10)
    config_buff[0] = config_reg
    config_buff[1] = 0x81 | input_ads | gain 
    config_buff[2] = 0x03 | rate 
    
#    print(config_buff[0])
#    print(config_buff[1])
#    print(config_buff[2])
    
    conversion_addr_buff[0] = conversion_reg

    i2c.writeto(i2c_addr,config_buff)
    utime.sleep_ms(20)
#    i2c.readfrom_into(i2c_addr,conversion_buff)
#    print("buff0=",conversion_buff[0])
#    print("buff1=",conversion_buff[1])    
    
    
    i2c.writeto(i2c_addr,conversion_addr_buff)
#    conversion_buff=i2c.readfrom(i2c_addr,2)
    i2c.readfrom_into(i2c_addr,conversion_buff)
#    print("buff0=",conversion_buff[0])
#    print("buff1=",conversion_buff[1])
    
    if (conversion_buff[0] & 0x80):
        polarity_data=1
        data16bit = ~(((conversion_buff[0]  << 8) | conversion_buff[1])) & 0xffff
#        print("-data16bit=",bin(data16bit))
#        print("-data16bit=",hex(data16bit))
#        print("-data16bit=",data16bit)
    else:
        polarity_data=0
        data16bit=(((conversion_buff[0]  << 8) | conversion_buff[1])) & 0x7fff
#    print("+data16bit=",data16bit)
#    print(polarity[polarity_data])
#    print("data16bit=",data16bit)
#    print(lsb_size[gain >> 1])
    data = data16bit * (lsb_size[gain >> 1])
    
    return polarity_data,data

polarity_data,data= ads1115_read(ain0_gnd ,v4064,sps128)    
print("ain0_gnd=",polarity[polarity_data],data /1000,"mV")

polarity_data,data= ads1115_read(ain1_gnd ,v4064,sps128)
print("ain1_gnd=",polarity[polarity_data],data /1000,"mV")

polarity_data,data= ads1115_read(ain2_gnd ,v4064,sps128)
print("ain2_gnd=",polarity[polarity_data],data /1000,"mV")

polarity_data,data= ads1115_read(ain3_gnd ,v4064,sps128)
print("ain3_gnd=",polarity[polarity_data],data /1000,"mV")


polarity_data,data= ads1115_read(ain0_ain1,v4064,sps128)
print("ain0_ain1=",polarity[polarity_data],data /1000,"mV")

polarity_data,data= ads1115_read(ain0_ain3,v4064,sps128)
print("ain0_ain3=",polarity[polarity_data],data /1000,"mV")

polarity_data,data= ads1115_read(ain1_ain3,v4064,sps128)
print("ain1_ain3=",polarity[polarity_data],data /1000,"mV")

polarity_data,data= ads1115_read(ain2_ain3,v4064,sps128)
print("ain2_ain3=",polarity[polarity_data],data /1000,"mV")

おすすめの記事