ゲインアンプ付きA/Dコンバータ(SX8725C)を用いた簡易地震計の製作 1 (製作編)

# デモ用の地震計を作りたい
![th_DSC_3648.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/88076/70b08db0-6965-319c-f8a6-d0445601e322.png)

PGAの調整によってノイズ問題が解決した結果は下記参照
[ゲインアンプ付きA/Dコンバータ(SX8725C)を用いた簡易地震計の製作 2（ノイズ対策）](https://qiita.com/pirotan628/items/f2a7f535399d787e03a8)


# はじめに
手元に4.5Hzっぽい昔のジオフォンがあり、デモンストレーション用に利用しようと思った。しかしデモのために本格的なロガーを用意する金銭的なアテがなく、またあっても持ち歩きが面倒。

小型のデバイスを自作できないかと考えたものの、アンプ部分の製作が目的の日時に間に合わせられる自信がない。何か安くて楽な方法は無いかと部品屋で検索していると、下記のモジュールを見つけた。

# SX8725C

SX8725Cは内部に可変ゲインアンプを搭載したA/Dコンバータで、出力が微小電圧のセンサーをそのまま接続して計測可能なモジュール。

差動入力が可能なアンプを製作する手間が省けるので、手軽に使えることがメリット。マルツからMSX8725CというDIP化モジュールが販売されているため利用した。

https://www.marutsu.co.jp/pc/i/243036/
https://www.marutsu.co.jp/select/list/detail.php?id=491

[DIP基板回路図（マルツ）](https://www.marutsu.co.jp/contents/shop/marutsu/datasheet/0000000200325769.pdf)
[SX8725C データシート](https://pdf1.alldatasheet.jp/datasheet-pdf/view/408960/SEMTECH/SX8725C.html)

# 製作

今度は SX8725C の利用例をネットで探し始め、下記の記事を参照した。

[5ドル！ラズパイ・ゼロ（Raspberry pi Zero）でIoT　(34)　A-Dコンバータの利用9　SX8725C](https://www.denshi.club/pc/raspi/5raspberry-pi-zeroiot10a-d7ltc2450-2.html)

ネットで見つかるほぼ唯一の日本語の記事だが、初心者が利用するに十分な内容でまとめられている。

マイコンには RaspberryPi-Pico を採用し、MSX8725C に付属の説明書を参考に回路を接続した。デモではPCに接続して波形表示することになるため、電圧をシリアルで受信できれば十分。できるだけ小型かつSDカードのトラブルの心配も無いことが大きなメリット。おそらくArduinoでも問題ないだろう。

使い回しの基板で汚いが、現在はこのボードでテスト中。
![SX8725C_circuit_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/88076/11a28186-ccef-9e79-8285-f26e65b50ea3.png)


- ジオフォンのダンピング係数が不明であるため、シャント抵抗を変えられるようにソケットで対応することにした。

- 一部のノイズ源が特定できずセンサー側にコモンモードチョークコイルを入れた状態の写真だが、あまり効果はなかった。地震計の特性に影響が出る可能性があるため、外した方が良いかもしれない。

- 基板の差動入力用の配線は平行だと周辺のノイズを拾ったため、ツイストに変更した。こちらは効果あり。

レジスタの設定は 16bit, 差動入力, ゲインアンプ使用(Pga:x1, Pga3:127/12), 5[V]給電, 電源電圧リファレンス といったものを選択した。

動作にはMicroPythonを使い、記事末尾のコードを走らせている。ほとんど紹介記事のプログラムそのまま。

```regist.py
# Define values
ValACCfg0 = b'\x1E' #30   #0b00011110
ValACCfg1 = b'\xFF' #255  #0b11111111
ValACCfg2 = b'\x00' #0    #0b00000000
ValACCfg3 = b'\x7F' #127  #0b01111111 #PGA1x1 PGA3 127/12
ValACCfg4 = b'\x00' #0    #0b00000000
ValACCfg5 = b'\x02' #2    #0b00000010 #diff, VBATT
ValMode   = b'\x88' #132  #0b10000100 #pump off
```

# 実験
縦軸：[mV]
横軸：10 [msec]
1. センサ入力端子を開放した状態
![スクリーンショット 2022-11-10 9.33.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/88076/ff04afb6-ada2-b239-3cba-77823efcbee6.png)

1. センサ入力に負荷（シャント抵抗）のみ繋いだ状態
![スクリーンショット 2022-11-10 9.32.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/88076/acae769f-64cc-021f-a5b3-14f2fe6c88a2.png)

1. 地震計を接続した状態
![スクリーンショット 2022-11-10 9.34.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/88076/69f1ae34-ebc2-e018-324a-e97144411cb0.png)

1. 地震計に振動を与えた場合
![スクリーンショット 2022-11-10 9.35.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/88076/b890d57b-1b1a-427a-ea3b-0a6d3be456e2.png)

計測は概ねうまくできているようだが、気になる点がいくつか。

- 開放時の発振。地震計を接続しても若干残っている。1Hzくらいって何だろうか。

- 致命的に問題なのがスパイクノイズである。

目下スパイクのノイズ源を探しているが、Raspberry Pi pico の[昇降圧コンバータが悪さをしている](http://radiopench.blog96.fc2.com/blog-entry-1200.html?sp)のであれば電源供給から見直さないといけない。最悪、Arduinoに乗り換えも検討することになるかも。

## MicroPython コード

観測の現場で良く使われてきたサンプリング100Hzを目指して割り込み処理を行うことにした。
ただし、A/Dが間に合っているのかまだ未確認。シリアルには一応100サンプル/秒来ていることが確認できた。

```SX8725C.py
import utime
import machine

led = machine.Pin(25, machine.Pin.OUT)
timer = machine.Timer()

i2c_bus_number  = 0
i2c_sda=machine.Pin(0)
i2c_scl=machine.Pin(1)
i2c=machine.I2C(i2c_bus_number,sda=i2c_sda, scl=i2c_scl, freq=100000)

#if we use only one i2c device, this code is useful to find the address.
addrlist = i2c.scan()
print( "address is :" + str(hex(addrlist[0])) )

addr = addrlist[0]
#addr = 0x48  # Default address of SX8725C
i2c_address = addr

#Vref = 1.22  # for internal refernce
Vref = 5.00   # for Vbatt reference
conversion_factor = Vref / (65535)
zero_shift = -98


# Define registers
RegACOutLsb = 0x50
RegACOutMsb = 0x51
RegACCfg0 = 0x52
RegACCfg1 = 0x53
RegACCfg2 = 0x54
RegACCfg3 = 0x55
RegACCfg4 = 0x56
RegACCfg5 = 0x57
RegMode   = 0x70

# Define values
ValACCfg0 = b'\x1E' #30   #0b00011110
ValACCfg1 = b'\xFF' #255  #0b11111111
ValACCfg2 = b'\x00' #0    #0b00000000
ValACCfg3 = b'\x7F' #127  #0b01111111 #127/12
ValACCfg4 = b'\x00' #0    #0b00000000
ValACCfg5 = b'\x02' #2    #0b00000010 #diff, VBATT
ValMode   = b'\x88' #132  #0b10000100 #pump off

reglist = []
reglist = list(range(0x50, 0x50+8))
reglist.append(0x70)

# --- Check default values (not required) ---
data=[]
for reg in reglist:
    readdata = i2c.readfrom_mem(addr,reg,1)
    data.append(int.from_bytes(readdata,'big'))
print(data)
#--------------------------------------------

#init
i2c.writeto_mem(addr,RegACCfg0,ValACCfg0)
i2c.writeto_mem(addr,RegACCfg1,ValACCfg1)
i2c.writeto_mem(addr,RegACCfg2,ValACCfg2)
i2c.writeto_mem(addr,RegACCfg3,ValACCfg3)
i2c.writeto_mem(addr,RegACCfg4,ValACCfg4)
i2c.writeto_mem(addr,RegACCfg5,ValACCfg5)
i2c.writeto_mem(addr,RegMode,ValMode) 

# --- Check current values (not required) ---
data=[]
for reg in reglist:
    readdata = i2c.readfrom_mem(addr,reg,1)
    data.append(int.from_bytes(readdata,'big'))
print(data)
#--------------------------------------------


def sign16(x):
    return ( -(x & 32768) | (x & 32767) );

#main
def readdata(timer):
    data = []
    for reg in (RegACOutLsb, RegACOutMsb):
        readdata = i2c.readfrom_mem(addr,reg,1)
        data.append(int.from_bytes(readdata,'big'))
    data16 = (data[1]<<8 | data[0])

    dataDiff = sign16(int(hex(data16),16))
    mVol = 1000 * dataDiff * conversion_factor
    var = "{:0=+12.4f}".format(mVol + zero_shift)
    print (var)

led.value(1)
timer.init(freq=100, mode=machine.Timer.PERIODIC, callback=readdata)

```