マイクロビット(e_53)MCP4725 D/A変換(1)
MCP4725 D/A (I2C)
Microchip社のMCP4725をmicro:bitで使ってみました。※thonny-microbitのMicroPythonを使っています。
「MCP4725」は分解能12bitのD/Aコンバータです。I2C通信で制御します。EEPROMも内臓しています。
I2Cの周波数は標準100kHz、Fast400kHz、High-Speed3.4MHzとあります。micro:bitで使うので標準100kHzになります。(micro:bitに搭載されているI2Cデバイスの地磁気センサーMAG3110、加速度センサMMA865が100kHzで動作しているため)
外観
MCP4725モジュールHW-315の外観写真です。右はピンヘッダを半田付けした状態です。(以後はMCP4725と記載します)
接続例
MCP4725の電源電圧は2.7V~5.5Vなのでmicro:bitと接続できます。その際のD/A変換出力は3.3Vが最大になります。
D/A変換出力をmicro:bitで測定するために、MCP4725の出力端子からmicro:bitのpin0に接続しています。pin0のモードはアナログ入力にします。
※micro:bitのピン配置図は「https://tech.microbit.org/hardware/edgeconnector/」からの引用です。
実体接続した写真です。
ちなみにI2Cデバイスのスレーブアドレスは簡単にわかります。96(0x60)がMCP4725のアドレスになります。
>>> from microbit import *
>>> i2c.scan()
[14, 29, 96]
>>> hex(96)
'0x60'
ちなみに、14(0xe)がMAG3110(地磁気センサー)、29(0x1d)がMMA8653(加速度センサー)です。
READ COMMAND
DAC registerとEEPROMのデータを読込んでみようと思います。
データは下図のように格納されています。読込むデータは2nd~6th byteの5バイトです。
2nd byteは現在の設定値です。RDY/BSY(ready/busy/Write EEPROM status)やPOR(power on reset)、PD1、PD0(power down mode)が分かります。
3-4th byteはDACレジスタ値です。
5-6th byteはEEPROMの値です。PDモードも含んでいます。
※詳細はMCP4725のデーターシートを参照ください。
micro:bitで読込むには
i2c.read(MCP4725のアドレス,5)
で読込みます。これが下図の1st byte(Read Command)です。
※ Microchip Technology MCP4725のデータシートから抜粋
スクリプト
データ読み込みのスクリプトは以下のようにしました。
mcp4725_read_b0.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from microbit import *
# i2c.init(freq=100000, sda=pin20, scl=pin19)
# MCP4725 slave-add hex(96)='0x60'
adr_dac=0x60
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.read(adr_dac,5)
# 2nd 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 PD2 str
print('<2nd byte>')
print('RDY/BSY POR=',by2_rdpo, 'PD1 PD0=', by2_pd10)
# 3nd 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,4nd byte 8+4bit>')
print('Register Data=', reg_dat,hex(int(reg_dat)) )
# 5nd byte r_dat[3] 6nd byte r_dat[4]
by5_pd10=r_digit(r_dat[3])[1:3]
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-6nd byte PD, 4+8bit>')
print('PD1 PD0=', by5_pd10, 'EEPROM Data=', rom_dat, hex(int(rom_dat)) )
read_DAC()
関数
r_digit(dat)はdat(int)値を’0’で埋めた8文字にしています。例えば以下のようになります。
>>> r_digit(0x06)
'00000110'
>>> r_digit(0b0110)
'00000110'
読込だ各byteをr_digit()に送って8文字データに変更して必要な部分をスライスして抜き出しています。
必要に応じて文字を加算しています。
実行結果
%Run mcp4725_read_b0.py
<2nd byte>
RDY/BSY POR= 11 PD1 PD0= 00
<3,4nd byte 8+4bit>
Register Data= 0b100000000000 0x800
<5-6nd byte PD, 4+8bit>
PD1 PD0= 00 EEPROM Data= 0b100000000000 0x800
>>>
出荷時にはEEPROM Dataは0b100000000000(0x800)になっています。そのため電源電圧の1/2(Vcc/2)が出力されます。
Write Commands
D/A変換するデータを書込んでその出力値をmicro:bitのpin0で読込んでみます。
MCP4725の書込みは下図のようになっています。
2nd byteのC2,C1,C0でレジスタだけ、EEPROMと両方に書込みを設定できます。まだPD1,PD0でPower のモードが設定できます。通常(0,0)で出力します。(0,1)なら1.0kΩ、(1,0)なら100kΩ、(1,1)なら500kΩで接地します。待機電力が軽減されるようです。
micro:bitで書込むには
書込むデータを
buf=bytearray(3)として
i2c.write(MCP4725のアドレス,buf)
で書込みます。これが下図の1st byte(Device Addressing)です。
繰返しての書込みは2nd-4byteを繰返します。
例えばbuf=bytearray(3の倍数)として、相当のデータを与えて書込みます。
※詳細はMCP4725のデーターシートを参照ください。
※ Microchip Technology MCP4725のデータシートから抜粋
スクリプト
データ書込みのスクリプトは以下のようにしました。
mcp4725_write_b0.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from microbit import *
# i2c.init(freq=100000, sda=pin20, scl=pin19)
# MCP4725 100kHz:standard_mode
adr_dac=0x60 # MCP4725 address hex(96)='0x60'
VDD=3200 # mV micro:bitの電源電圧をテスターで測定すると3200mVでした
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'):# value 出力mV
# 設定できるのは4095/4096*VDD まで hex(4095)'0xfff' 12bit(4096)
s_dat=int(value/VDD*4096) # 出力したい電圧に応じたデジタル値に
print('set mv =',value)
w_dat=w_digt(s_dat) # str w_digtへ送って'0'で埋めた12文字にする
buf=bytearray(3) # I2C write bytedata
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
i2c.write(adr_dac,buf) # bufを送信
return buf
write_DAC(1500,cmd='010', pd='00') # 出力したい電圧 1500mv,コマンドモード,パワーダウンモード
pin0.set_pull(pin0.NO_PULL) # pin0をNO_PULLにしておく
r_out=pin0.read_analog()*VDD/1024 # pin0でアナログ値を読む 分解能8bit
print('pin0 mv=',int(r_out)) # micro:bit測定値
関数
write_DAC(value,cmd=’010′, pd=’00’)
value:アナログ出力電圧値(mV)、cmd=’010′:書込むモード(’010’ならレジスタだけ、’011’ならEEPROMと両方)、パワーダウンモードを設定します。
実行結果(1)
>>> %Run mcp4725_write_b0.py
set mv = 1500
pin0 mv= 1525
micro:bitビットで測定した値は少しズレました。分解能の差異かも知れません。ちなみに、テスターで測定した出力は1515mVでした。
Power Down モード以下のように’01’で実行して見ます。
write_DAC(1500,cmd=’010′, pd=’01’)
実行結果(2)
>>> %Run mcp4725_write_b0.py
set mv = 1500
w_dat= 100000000000
write_buf_data= bytearray(b'b\x80\x00')
pin0 mv= 11 # power down動作されている
先の読込み(mcp4725_read_b0.py)を確認して見ます。分かりやすいように、VDD=750mVにしました。
mcp4725_write_b0.py
write_DAC(750,cmd=’010′, pd=’00’)で実行した後、設定を読込みしてみます。
実行結果(3)
>>> %Run mcp4725_write_b0.py
set mv = 750
w_dat= 010000000000
write_buf_data= bytearray(b'@@\x00')
pin0 mv= 773
>>> %Run mcp4725_read_b0.py
<2nd byte>
RDY/BSY POR= 11 PD1 PD0= 00
<3,4nd byte 8+4bit>
Register Data= 0b010000000000 0x400 #レジスタに書込まれた
<5-6nd byte PD, 4+8bit>
PD1 PD0= 00 EEPROM Data= 0b100000000000 0x800 #EEPROMには書込みされてない
write_DAC(750,cmd=’011′, pd=’00’)で実行した後、設定を読込みしてみます。
実行結果(4)
>>> %Run mcp4725_write_b0.py
set mv = 750
w_dat= 010000000000
write_buf_data= bytearray(b'`@\x00')
pin0 mv= 773
>>> %Run mcp4725_read_b0.py
<2nd byte>
RDY/BSY POR= 11 PD1 PD0= 00
<3,4nd byte 8+4bit>
Register Data= 0b010000000000 0x400 #レジスタに書込まれた
<5-6nd byte PD, 4+8bit>
PD1 PD0= 00 EEPROM Data= 0b010000000000 0x400 #EEPROMに書込まれた
<h3<まとめ
micro:bitでMCP4725モジュールHW-315を使ったD/A変換を確認しました。Read Command、Write Commandの動作を確認しました。