CircuitPython 10行プログラミング (5) SPI
Trinket M0マイコン・ボードとCircuitPythonを使って、SPIバスにつながるセンサを利用します。基板の裏にはSPI関連のシルク印刷はありません。
SPIバスは、マスタのデータ出力はMOSI(Master Out Slave In)、センサなどのデバイスからの出力はMISO(Master In Slave Out)で受けます。MISOを使わないデバイスもあります。データはSCK(クロック)に従ってやり取りをします。マスタは、データを受け取るときにもマスタがクロックを出さないといけないので、ダミー・データを送ることがあります。
つながるデバイスを選択するためにCS(チップ・セレクト、SSとか呼ばれることもある)が必要です。このTrinket M0マイコン・ボードでは、ディジタル出力用にD0とD1が空いているので、このどちらかを使うことになりそうです。
次の図は、表面から見た端子です。
●センサは熱電対+MAX31855
SPIバスのインターフェースをもつ熱電対のセンサ・デバイスMAX31855Kを使います。熱電対はK型ですから、測定温度範囲は-200~+1350℃です。Adafruitのブレーク・アウト・ボードは5Vから3.3VへのレギュレータICとレベル変換回路を搭載しているので、5Vと3.3Vのどちらのマイコンにもつなげられます。
接続です。
Trinket M0 表面シルク |
MAX31855のシルク |
---|---|
0(D0) | CS |
2(MISO) | DO |
3(SCK) | CLK |
USB | Vin |
GND | GND |
MAX31855の温度データは32ビットあります。14ビット(D31~D18)が熱電対の冷接点温度補償済みのデータで、12ビット(D15~D4)がIC内部の温度データです。どちらも2の補数形式で入っています。32ビット・データの中には、断線情報などのフラグも含まれているので、実用的なプログラムでは、それらを活用します。
ビット | D31 | D30 | ... | D18 | D17 | D16 | D15 | D14 | ... | D4 | D3 | D2 | D1 | D0 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
値 | 符号 | MSB | LSB | 予約 | 1=フォルト | 符号 | MSB | LSB | 予約 | 1=Vccへのショート | 1=GNDへのショート | 1=オープン |
●ライブラリbusio
busioの中のSPIデバイス・クラスでは、最初にピンの設定します。
busio.SPI(クロック・ピン, MOSI=ピン, MISO=ピン) |
を使います。I2Cと同様に、バスをロックしたうえで利用します。
spi.configure(baudrate=5000000, phase=0, polarity=0) |
baudrateは転送速度をHzで指定します。MAX31855は最大5MHzです。SPIの信号は、クロックのどの部分のデータを読み取るかをphaseとpolarityの組み合わせで指定します。ほとんどのデバイスはともに0です。
Tinket M0マイコン・ボードのCPUは12MHzまでの転送速度に対応しています。
次のプログラムは、正の値だけを扱っています。
チップ・セレクトCSはデフォルトHIGHです。なので、最初にD0端子を出力に設定して、直後にHIGHにします。SPIバスの転送シーケンスは、CSがLOWになってから始まります。CSを明示的にLOWにしたうえで、spi.readinto(result)で読み出します。読み出したらCSをHIGHに戻します。
転送時に必要なクロックは、Arduino IDEのWireライブラリのようにユーザが作らなくてもよいようです。
from board import *
import digitalio
from busio import SPI
cs = digitalio.DigitalInOut(D0)
cs.direction = digitalio.Direction.OUTPUT
cs.value = 1
spi = SPI(D3, MISO=D2)
result = bytearray(4)
while not spi.try_lock():
pass
spi.configure(baudrate=5000000, phase=0, polarity=0)
cs.value = 0
spi.readinto(result)
cs.value = 1
# print(result)
Temp14 = ((result[0] << 8 | result[1]) >> 2) * 0.25
Temp12 = ((result[2] << 8 | result[3]) >> 4) * 0.0625
print(Temp14, Temp12)
●MAX31855のライブラリ
CircuitPythonのライブラリは、前回のSi7021と同じく、最新版のライブラリをダウンロードします。adafruit-circuitpython-bundle-3.x-mpy-20190202.zipを解凍して、adafruit_max31855.mpyとadafruit_bus_deviceフォルダを、CIRCUIYPYドライブの中にlibの名前のフォルダを作って入れます。
前回、adafruit_si7021.mpyを入れたままなので、今のフォルダは、次のような構成です。
ファイルの容量は47Kバイト中35.5Kバイトの空きがありますが、余裕があるわけではありません。Windows7のドライバが入っていたフォルダは不要なので消しました。
ダウンロードした中のexampleフォルダにあるmax31855_simpletest.pyをMuに読み込みます。CSがD5端子になっているのでD0に変更して保存します。実行中の様子です。途中、センサの先端を指でつまみました。反応は素早いですね。
華氏は不要なので整理しました。
from time import sleep
from board import *
from busio import SPI
import digitalio
import adafruit_max31855
spi = SPI(SCK, MOSI=MOSI, MISO=MISO)
cs = digitalio.DigitalInOut(D0)
max31855 = adafruit_max31855.MAX31855(spi, cs)
while True:
tempC = max31855.temperature
print('Temperature: %0.1f C'% tempC)
sleep(2.0)