Raspberry Pi Pico(d_09)MCP4725 DAコンバータ
MCP4725 HW-315 (I2C)
MCP4725は分解能12bitのD/Aコンバータです。I2C通信で制御します。Raspberry Pi PicoでMCP4725搭載のHW-315モジュールを使ってみました。
I2Cの周波数は標準100kHz、Fast400kHz、High-Speed3.4MHzとあります。標準の100kHzで動作を確認しました。
※micro:bitの記事e_54からRaspberry Pi Picoで使えるように追記、修正等をしました。
外観
MCP4725モジュールHW-315の外観写真です。(以後はMCP4725と記載します。)
接続例
MCP4725の電源電圧は2.7V~5.5VなのでRaspberry Pi Picoと接続できます。その際のD/A変換出力は3.3Vが最大になります。
I2C通信にはI2C1のSDA(GP10)SCL(GP11)を使いました。
D/A変換出力をRaspberry Pi Picoで測定するために、MCP4725の出力端子からRaspberry Pi PicoのADC2(GP28)に接続しています。
接続出来たらI2Cデバイスのスレーブアドレスを調べてみます。
ThonnyのShellで確認しました。
MCP4725のスレーブアドレスは以下のように96(0x60)でした。
>>> from machine import I2C,Pin
>>> i2c=I2C(1, scl=Pin(11), sda=Pin(10), freq=100_000)
>>> i2c.scan()
[96] #0x60
MCP4725の説明
データシートから抜粋してMCP4725の説明します。※詳細はMCP4725のデーターシートを参照ください。
(#印の行は下方のスクリプトに対応する部分です。adrはMCP4725のアドレスです。)
POWER-DOWN
POWER-DOWNモードがあります。レジスタのPD1、PD0ビット値でモード変更できます。
D/A変換する時はNormalMode(0、0)です。他は各抵抗値が負荷になる省電力状態です。
※MCP4725のデータシートから抜粋
Read
MCP4725の読込みは下図のようになっています。
I2CでReadすると2nd~6th byteの5bytesのデータが返ります。
# r_dat=i2c.readfrom(adr,5)
2nd byteにはEEPROM Write Status POR(Power-On-Reset)とPOWER-DOWN MODEのデータがあります。
# by2_rdpo=r_digit(r_dat[0])[0:2] (RDY/BSY POR)
# by2_pd10=r_digit(r_dat[0])[5:7] (PD1 PD0)
3rd byteの8bitと4th byte+上位4bitの12bitがDACデータになります。
# by3_da=r_digit(r_dat[1])
# by4_da=r_digit(r_dat[2])[0:4]
# reg_dat=’0b’+by3_da + by4_da (DAC Resister 12bit Data)
※MCP4725のデータシートから抜粋
Write
MCP4725の書込みは下図のようになっています。
書込むデータをbuf=bytearray(3)として、
i2c.writeto(adr,buf)
で書込みます。
繰返しての書込みは2nd-4byteを繰返します。
例えばbuf=bytearray(3の倍数)として、相当のデータを与えて書込みます。
※MCP4725のデータシートから抜粋
2nd byte(buf[0])のC2,C1,C0の値によって、レジスタだけに書込む(0,1,0)、EEPROMにも書込む(0,1,1)を設定できます。まだPD1、PD0でPower のモードが設定できます。通常(0,0)で出力します。(0,1)なら1.0kΩ、(1,0)なら100kΩ、(1,1)なら500kΩで接地します。待機電力が軽減されるようです。
#buf[0]=int(‘0b’+ cmd +’00’+pd +’0’)
出力させたい電圧値を12bitデータに変換した値に変換します。
#w_dat=w_digt(s_dat)
変換した値の上位8bitを3rd byte(buf[1])に、
#buf[1]=int(‘0b’+ w_dat[0:8])
下4bitを4th byte(buf[2])の上位4bitに設定します。
#buf[2]=int(‘0b’+ w_dat[8:12]) << 4
スクリプト
MCP4725のスクリプトは以下のようにしました。
※開発環境はThonnyです。ThonnyでMicroPythonをRaspberry Pi Pico with RP2040にインストールして使っています。
pico_mcp4725_test_01b.py
#!/usr/bin/env python
# -*- coding: utf-8 -*
from machine import I2C,Pin,ADC
import time
# MCP4725 12-Bit Digital-to-Analog Converter with EEPROM Memory
i2c = I2C(1, scl=Pin(11), sda=Pin(10), freq=100_000)
adr=0x60 # slave address hex(96)='0x60'
VDD=3300 #3300mV
def r_digit(dat): # int
dat=bin(dat) # str
value='0'*(8-len(dat[2:])) + dat[2:] # str
return value
def read_DAC():
# read 5bytes
r_dat=i2c.readfrom(adr,5)
# 2 byte r_dat[0]
by2_rdpo=r_digit(r_dat[0])[0:2] #RDY/BSY POR str
by2_pd10=r_digit(r_dat[0])[5:7] #PD1 PD0 str
print('<2 byte>')
print('|RDY/BSY|POR|=',by2_rdpo, '|PD1|PD0|=', by2_pd10)
# 3 byte r_dat[1] 4nd byte r_dat[2]
by3_da=r_digit(r_dat[1])
by4_da=r_digit(r_dat[2])[0:4]
reg_dat='0b'+by3_da + by4_da # DAC Resister 12bit Data str
print('<3-4 byte 12bit>')
print('Register_Data=', reg_dat,hex(int(reg_dat)) )
# 5 byte r_dat[3] 6nd byte r_dat[4] EEPROM Data
by5_pd10=r_digit(r_dat[3])[1:3] #PD1 PD0
by5_da=r_digit(r_dat[3])[4:8]
by6_da=r_digit(r_dat[4])
rom_dat='0b'+by5_da + by6_da # DAC EEPROM 12bit Data str
print('<5-6 byte PD, 12bit>')
print('|PD1|PD0|=', by5_pd10)
print('EEPROM_Data=', rom_dat, hex(int(rom_dat)))
return #r_dat
def w_digt(dat): # int
dat=bin(dat) # str
value='0'*(12-len(dat[2:])) + dat[2:] # str '0'埋12文字
return value
def write_DAC(value,cmd='010', pd='00'):
# write cmd '010' DAC-Regi '011'DAC-Regi+EEPROM
# 設定できるのは4095/4096*VDD まで hex(4095)'0xfff'
s_dat=int(value/VDD*4096)
#print('value=',value,'s_dat(0d,0x)=',s_dat, hex(s_dat))
print('set mv =',value)
w_dat=w_digt(s_dat) #str
#print('w_dat=',w_dat)
buf=bytearray(3) # I2C write data
buf[0]=int('0b'+ cmd +'00'+pd +'0') # command PowerDown
# DAC no Data wo 8bit 4bit ni bunkai site set suru
buf[1]=int('0b'+ w_dat[0:8]) # D11-D4 8bit
buf[2]=int('0b'+ w_dat[8:12]) << 4 # D3-D0 4bit 4 shift-up
#print('write_buf_data=',buf)
i2c.writeto(adr,buf)
#EEPROM Write Time typ 25msec max 50msec
if cmd=='011':
time.sleep_ms(50)
return buf
## example
# MCP4725 Write Data 出力値等の設定
write_DAC(VDD/2,cmd='010', pd='00')
# MCP4725 OUT DataをADC2で測定
adc=ADC(Pin(28))
val=adc.read_u16()*(VDD/2**16)
print('Vout mv=',val)
print('')
# MCP4725 Read Data データの読出し
read_DAC()
関数
(1)write_DAC(value,cmd=’010′, pd=’00’)
出力電圧等を設定します。
value:アナログ出力電圧値(mV)
cmd:書込むモード(’010’ならレジスタだけ、’011’ならEEPROMと両方
pd:パワーダウンモードを設定します。
(2)read_DAC()
レジスタ、EEPROMのデータ読出します。
実行結果
OutputをVDD/2(1650mV)で実行してみました。
write_DAC(VDD/2,cmd=’010′, pd=’00’)
結果は以下のようになりました。※Thonnyのshellに表示されます。
>>> %Run -c $EDITOR_CONTENT
set mv = 1650.0 # 設定値 3300/2 mv
Vout mv= 1660.071 # ADCで読んだ値 だいたい合ってる。
<2 byte> # EEPROM Status,Current Setting DAC
|RDY/BSY|POR|= 11 |PD1|PD0|= 00 # PDはD/Aモード
<3-4 byte 12bit>
Register_Data= 0b100000000000 0x800 # 12bitの値
<5-6 byte PD, 12bit> # EEPROM Data
|PD1|PD0|= 00 # PDはD/Aモード
EEPROM_Data= 0b100000000000 0x800 # 12bitの値(初期は0.5*VDD)
>>>
次に、OutputをVDD/3(1100mV)にして見ました。
write_DAC(VDD/3,cmd=’010′, pd=’00’)
set mv = 1100.0
Vout mv= 1108.04
<2 byte>
|RDY/BSY|POR|= 11 |PD1|PD0|= 00
<3-4 byte 12bit>
Register_Data= 0b010101010101 0x555 # VDD/3値の12bitデータに
<5-6 byte PD, 12bit>
|PD1|PD0|= 00
EEPROM_Data= 0b100000000000 0x800 # cmd='010'なのでEEPROM値は無変化
EEPROMにもデータ書込む、パワーダウンを設定して実行してみます。
write_DAC(VDD/3,cmd=’011′, pd=’01’)
>>> %Run -c $EDITOR_CONTENT
set mv = 1100.0
Vout mv= 9.667969 # パワーダウン状態(1kΩ)
<2 byte>
|RDY/BSY|POR|= 11 |PD1|PD0|= 01
<3-4 byte 12bit>
Register_Data= 0b010101010101 0x555 # VDD/3値の12bitデータに
<5-6 byte PD, 12bit>
|PD1|PD0|= 01
EEPROM_Data= 0b010101010101 0x555 # EEPROMにも12bitデータ書込み
>>>
まとめ
Raspberry Pi PicoでMCP4725を使ってD/A変換ができました。