= INA226を使用した簡易電圧モニタ = 某所で、1-5V程度の出力電圧を監視したいとの依頼があったので、BBBでEPICS内蔵の簡易電圧モニタを作成することになった。[[br]] 電圧の測定は、I2C通信ができるモジュールやIC、Serial通信が可能なテスタなどが候補に挙がった。[[br]] || モジュール || 測定範囲[V] || bit数 || || BBB内蔵 || 0 ~ 1.8 || 12 || || Arduino uno || 0 ~ 5 || 10 || || [https://www.switch-science.com/catalog/1138/ Adafruit ADS1115] || 0 ~ VDD || 16 || || [https://strawberry-linux.com/catalog/items?code=12031 INA226 I2Cディジタル電流・電圧・電力計モジュール] || 0~36 || 16(15) || || [http://akizukidenshi.com/catalog/g/gK-08018/ MCP3425] || VSS-0.3 ~ VDD+0.3 || 16 || 今回の目標としては * 安く作ること * テスタやPLCのADCモジュール、マルチメーター等は使えない * 分解能は12bit以上 * スピードは考慮しない としたので、 * [https://www.switch-science.com/catalog/1138/ Adafruit ADS1115] * [https://strawberry-linux.com/catalog/items?code=12031 INA226 I2Cディジタル電流・電圧・電力計モジュール] * [http://akizukidenshi.com/catalog/g/gK-08018/ MCP3425] が候補となった。 == I2C 接続試験 == 始めに通信が簡単そうな[https://strawberry-linux.com/catalog/items?code=12031 INA226 I2Cディジタル電流・電圧・電力計モジュール]で実験してみた。 ブレッドボードにINA226モジュールを差し、4.7kΩのプルアップ抵抗をSCL,SDAに接続、電源は3.3Vを接続した。モジュールのI2Cアドレスは0x40になるように設定。[[br]] BBBとはI2C-2(P9-19,P9-20)にSCL,SDAをそれぞれ接続した。[[br]] BBBのI2C用のコマンドで確認。[[br]]入力した電圧は、VCC(3.3V) {{{ root@beaglebone:~# i2cdetect -y -r 2 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: 40 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- UU UU UU UU -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- -- root@beaglebone:~# i2cget -y 2 0x40 0x02 w 0x720a }}} 0x720aはリトルエンディアンなので、LSB,HSBを反転。(0x0a72 -> 2674)[[br]] 2674 x 1.25[mV] = 3342.5[mV][[br]] テスタで読んだ値が3.35Vなので正しそう。[[br]] その後、[http://akizukidenshi.com/catalog/g/gK-08018/ MCP3425]も試してみたが、レジスタを読むだけでなく、RDYビットを設定したりしないといけないらしいので、今回は[https://strawberry-linux.com/catalog/items?code=12031 INA226 I2Cディジタル電流・電圧・電力計モジュール]を使うことにした。 == 基板作成 == 基板は、秋月の[http://akizukidenshi.com/catalog/g/gP-07190/ BeagleBone・ユニバーサルプロトケープ]に[https://strawberry-linux.com/catalog/items?code=12031 INA226 I2Cディジタル電流・電圧・電力計モジュール]を載せて、LEMOコネクタから電圧を入力するようにした。[[br]] いつも問題になるケースは、[http://akizukidenshi.com/catalog/g/gP-07749/ BeagleBone Blck用ケース]を加工して使うことにした。 最終的に、[attachment:bbb_tinyVoltMeter.pdf 回路図]は [[Image(bbb_tinyVoltMeter.png,300)]] このようにしました。[[br]] ただ、コネクタとモジュール基板を上面に実装するとケースの蓋に当たってしまうので裏面に実装した。 == 実装写真 == 実装基板とケースはこんな感じで。[[br]] スペースとしては2chまでは実装できそう。[[br]] [[Image(IMG_0202.JPG,300)]] [[Image(IMG_0203.JPG,300)]] [[Image(IMG_0204.JPG,300)]] [[Image(IMG_0205.JPG,300)]] == IOC == IOCはdrvAsynI2Cを使って電圧レジスタを読み込むだけのお手軽仕様で。[[br]] レジスタマップ等のチップの仕様は[http://www.ti.com/lit/ds/symlink/ina226.pdf TI INA226]から。[[br]] とりあえず、積算時間、平均回数はデフォルトのまま変えないで、BusVoltageレジスタを読み込むだけのIOCを作成。[[br]] INA226 で通常測定で使用するレジスタは以下のようになっている。詳しくは[http://www.ti.com/lit/ds/symlink/ina226.pdf datesheet]を参照。 || POINTER(HEX) || ADDRESS || POWER-ON RESET(HEX) || TYPE || || 00h || Configuration Register || 4127 || R/W || || 01h || Shunt Voltage Register || 0000 || R || || 02h || Bus Voltage Register || 0000 || R || || 03h || Power Register || 0000 || R || || 04h || Current Register || 0000 || R || === configure/RELEASE === RELEASEファイルは、使用するドライバサポートを追加。 {{{ ASYN = $(EPICS_BASE)/../modules/soft/asyn/4-31 STREAM = $(EPICS_BASE)/../modules/soft/stream/2.7.7_I2C DRVASYNI2C = $(EPICS_BASE)/../modules/instruments/bbb/drvAsynI2C }}} I2Cを使うので対応したものを設定。 === protocol file === プロトコルファイルはdrvAsynI2Cの例題にあったものをコピーして使用。 {{{ Terminator = ""; LockTimeout = 500; ReplyTimeout = 100; ReadTimeout = 100; WriteTimeout = 100; MaxInput = 2; ExtraInput = Error; RdReg { out ${1} ${2}; in "%02r"; } WtReg { out ${1} ${2} "%02r"; } }}} 始めは、実験時にi2cgetで取得できたように、リトルエンディアンのデータが出力されるかと思ったが、データは普通の値として取得できたので、エンディアン変換等の後処理をする必要はなかった。 === Db file === DBファイルは、streamdeviceでレジスタを読み込んで、電圧変換するだけ。[[br]] 一応、configurationレジスタの設定も作成してあるが、いまのところ使っていない。 {{{ record(longin, "$(USER):INA226:BUS_VOLT:GET:RAW") { field(DESC, "INA226 bus registor read") field(DTYP, "stream") field(INP, "@INA226.proto RdReg($(I2C_ADDR),2) $(BUS)") field(SCAN, "$(SCAN)") field(FLNK, "$(USER):INA226:BUS_VOLT:GET") } record(calc, "$(USER):INA226:BUS_VOLT:GET") { field(DESC, "convert voltage") field(INPA, "$(USER):INA226:BUS_VOLT:GET:RAW") field(CALC, "A*0.001*1.25") field(EGU, "V") field(PREC, "3") } ################################################# # # bit 0~2: operate mode # 3~5: shunt voltage conversion time # 6~8: bus voltage conversion time # 9~11: averaging mode # 12~14: reserved # 15: config reset # record(longout, "$(USER):INA226:CONF_REG:SET") { field(DESC, "Set config registor") field(DTYP, "stream") field(OUT, "@INA226.proto WtReg($(I2C_ADDR),0) $(BUS)") } }}} === src/Makefile === src/MakefileにDBDとlibを設定する。 {{{ # Include dbd files from all support applications: presSens_DBD += asyn.dbd presSens_DBD += stream.dbd presSens_DBD += drvAsynI2C.dbd # Add all the support libraries needed by this IOC presSens_LIBS += asyn presSens_LIBS += stream presSens_LIBS += drvAsynI2C }}} === st.cmd === st.cmdは、送信先のデバイスを{{{drvAsynI2CConfigure}}}にするだけで、いつものstreamdeviceと時と同じ。 {{{ #!../../bin/linux-arm/presSens ## You may have to change presSens to something else ## everywhere it appears in this file < envPaths epicsEnvSet("STREAM_PROTOCOL_PATH", ".:../../presSensApp/Db") cd "${TOP}" ## Register all support components dbLoadDatabase "dbd/presSens.dbd" presSens_registerRecordDeviceDriver pdbbase drvAsynI2CConfigure("I2C","/dev/i2c-2",1) ## Load record instances dbLoadRecords("db/INA226.db","USER=PFaVA:test,I2C_ADDR=0x40,SCAN=1 second,BUS=I2C") cd "${TOP}/iocBoot/${IOC}" iocInit #var streamDebug 1 #asynSetTraceMask( "I2C", 0, -1 ) #asynSetTraceIOMask( "I2C", 0, -1 ) }}} === 実行 === make後にst.cmdを実行するが、I2Cデバイスへのアクセスは通常はrootでしか許可されていないので、IOCの起動はrootで実行する必要がある。[[br]] もしくは専用のユーザーを作成し、I2Cデバイスへのアクセスを許可する設定をするしかないが、今回はrootで実行する。 IOCを起動後、cagetしてみる。[[br]] 入力電圧は、3.3V電源。[[br]] {{{ beaglebone:/opt/epics/app/presSens> caget PFaVA:test:INA226:BUS_VOLT:GET PFaVA:test:INA226:BUS_VOLT:GET:RAW PFaVA:test:INA226:BUS_VOLT:GET 3.36625 PFaVA:test:INA226:BUS_VOLT:GET:RAW 2693 }}} テスタの読み値で3.37Vなのでほぼ同じ。