CircuitPython 10行プログラミング Step2 (6) ロードセル+ADS1220
A-DコンバータADS1220は4チャネルの入力をもち、熱電対、白金測温抵抗体、ブリッジ回路などに便利な電流発生機能を内蔵しています。白金測温抵抗体を使った温度の測定は、こちらの記事で取り上げました。
◆5ドル!ラズパイ・ゼロ(Raspberry pi Zero)でIoT (47) アナログ温度センサ5 白金抵抗体、ADS1220 |
このA-Dコンバータを使って、ロードセルのブリッジ回路の電圧を読み出します。
●ADS1220のおもなスペック
- 動作電圧 2.853~5.5V
- 分解能 24ビット
- 入力 シングルエンド;4チャネル。差動;2チャネル。レファレンス入力が2チャネル。
- 電流源 二つ、プログラマブル
- 基準電圧源 内蔵、外部可
- インターフェース SPI+DRDY
- アンプ PGA(最大128倍)
- サンプリング・レート 最大2000SPS
SPIのインターフェースでは、チップ・セレクト信号CSをHIGHからLOWにすると、A-D変換が開始されます。変換が完了するとSPI信号とは関係ないADS1220固有の信号DRDYがLOW-HIGHになり、実際のデータがMOSI端子から出てきます。
●ロードセル
入手した「ロードセル シングルポイント(ビーム型) SC133 20kG」のおもな仕様は次の2点です。
- 定格容量;20kg
- 定格出力;1mV/V
ロードセルにはひずみゲージが貼ってあり、ブリッジ回路で構成されています。電圧5Vかけると、最大荷重20kgのときの出力電圧は5mVです。印加する電圧が異なれば、補正します。
●接続
ロードセルの端子名とケーブルの色は、次のとおりです。
赤色;EXC+
黒色;EXC-
緑色;SIG+
白色;SIG-
回路図は、データシートのFigure 82. Resistive Bridge Measurementをそのまま利用しました。ブリッジ回路とA-Dコンバータの入力部分に入っているフィルタの定数は、白金測温抵抗体の解説部分に書かれている定数に近い値を流用しました。
マイコン・ボードの信号ピンは次のとおりです。
D50;MISO(ADS1220のDinへ)
D51;MOSI(ADS1220のDoutへ)
D52;SCLK
D53;CS
●レジスタ類
リセットは0x06もしくは0x07です。
設定を書き込むレジスタは0x4xです。コンフィギュレーション・レジスタ0は0x40、コンフィギュレーション・レジスタ1は0x44、コンフィギュレーション・レジスタ2は0x48、コンフィギュレーション・レジスタ3は0x4cです。
データシートのTable 26. Register Settingsに従い、下記の設定にします。
◆コンフィギュレーション・レジスタ0(オフセット= 0x00)[リセット時= 0x00] 0x3e AIN P = AIN1、AIN N = AIN2、ゲイン= 128、PGAイネーブル ◆コンフィギュレーション・レジスタ1(オフセット= 0x00)[リセット時= 0x00] 0x04 DR = 20 SPS、通常モード、連続変換モード ◆コンフィギュレーション・レジスタ2(オフセット= 0x00)[リセット時= 0x00] 0x98 外部リファレンス(REFP1、REFN1)、50Hzと60Hzの同時除去、PSW=1 ◆コンフィギュレーション・レジスタ3(オフセット= 0x00)[リセット時= 0x00] 0x00 IDACは使用しない |
データの読み出しコマンドは0x1xです。0x10を使います。データは3バイトで構成されていて、最上位、上位、最下位の順で読み出せます。
●プログラム
最初にリセット、次に四つのコンフィギュレーション・レジスタを書き込みます。連続変換を指定しているので、その後、while文で3バイト分のデータの読み出しを行います。
from board import *
import digitalio
from busio import SPI
import time
cs = digitalio.DigitalInOut(D53)
cs.direction = digitalio.Direction.OUTPUT
cs.value = 1
spi = SPI(SCK, MISO=MISO, MOSI=MOSI)
def writeCommand(x):
cs.value = 0
time.sleep(0.05)
spi.write(x)
cs.value = 1
time.sleep(0.1)
def readADC():
cs.value = 0
result = bytearray(3)
spi.readinto(result, write_value=0x10)
cs.value = 1
Volts = result[0] << 16 | result[1] << 8 | result[2]
# print(result[0], result[1], result[2])
return(Volts)
while not spi.try_lock():
pass
spi.configure(baudrate=500000, phase=1, polarity=0)
writeCommand(bytes([0x06])) # reset
writeCommand(bytes([0x40, 0x3e])) # configregistor0
writeCommand(bytes([0x44, 0x04])) # configregistor1
writeCommand(bytes([0x48, 0x98])) # configregistor2
writeCommand(bytes([0x4c, 0x00])) # configregistor3
g = 0
readADC()
offset = readADC()
print("offset", offset)
time.sleep(2)
while 1:
result = readADC()
print("readADC=", result)
print("offset=", offset)
g = (result-offset+ 0xffffff) # * scale
if g < 10000:
print("weight=", g)
time.sleep(2)
このときの波形をADALM2000のロジック・アナライザの機能を使って観測します。プロトコルはSPIです。MOSIがマイコンからA-Dコンバータへ送っているデータです。0x10、0x10、0x10ですが、一部データが化けています。
マイコンが受け取っているMISOが変換データです。
DIO4がDRDY信号です。CS信号は画面の左側(見えていない)でHIGH-LOWに変化しています。DRDYはHIGH-LOW-HIGHと変化しています。LOW-HIGHに同期してデータの転送が始まります。
実行中の様子です。128gほどのおもりを載せたときの様子です。約1/5の重量が表示されています。
重さのgにscaleを掛けて、実際のおもさを出します。実際は、重さのわかっているものを載せ、scaleを算出しました。5.12とすれば、100~500gでほぼ正しい値を表示するようになりました。
本来なら、内蔵のアンプPGAのゲイン128や分解能2^23、ブリッジの印加電圧などを使ってスケールを計算すべきなのですが、5に近い値を導けませんでした。
同じロードセルを使ったHX711の記事で、重さはg単位が表示できましたが、この記事で表示できる重さは約10g単位の分解能しか得られていないように思われます。ブリッジへの印加電圧など、調整できるところもあるので、分解能は高められるかもしれません。