CircuitPython 10行プログラミング (7) 1-Wire

 Tinket M0マイコン・ボードとCircuitPythonを使って、1-Wireにつながる温度センサDS18B20を利用します。名前のとおり信号線は1本で、電源とGNDを含めて3本の接続で遠距離通信ができます。いろいろなデバイスがつながりますが、温度センサのDS18B20が最もポピュラです。デフォルトで12ビットの分解能をもっており、測定温度範囲は-55~+125℃です。

シリアル通信

 デバイスには固有の64ビットのROMデータが記録され読み出せるので、複数のデバイスを3本のラインにパラレルに接続できます。

 通信は、最初にリセットを、固有のROMデータを問い合わせます(0xf0)。読み出しは0x33です。固有のROMデータを指定した後、温度の変換を要求します。
 データシートによれば、温度の変換要求はConverT(0x44)を送ります。温度データはScrachpadの最初の2バイトに収録されています。読み出しは0xbeです。最初のバイトは下位8ビット、次のバイトは上位の3ビットと符号です。符号はbit3~bit7まで同じ値がコピーされています。データは2の補数形式です。
 パワーオン・リセット時には下位バイトに0x50、上位バイトに0x05が入っています。85℃です。
 Scrachpadの最後の9バイトはCRCです。

接続

 D0に信号を、3VへVdd、GNDにはGNDを接続しました。信号とVddの間には4.7kΩの抵抗をつなぎます。

Adafruitのライブラリ

 前記のように大変複雑な通信手順です。CircuitPythonには1-Wireのライブラリがありますが、ピンの指定と、ビットのタイミングを取るだけのものです。

import busio
import board

onewire = busio.OneWire(board.D0)
print(onewire.read_bit())

 もう一つAdafruit OneWire ライブラリがあります。こちらはROMコードを読み出すところまでサポートしています。

import board
from adafruit_onewire.bus import OneWireBus

ow_bus = OneWireBus(board.D0)
devices = ow_bus.scan()

for d in devices:
print("ROM={}\tFamily=0x{:02x}".format(d.rom, d.family_code))

 結果は、

ROM=bytearray(b'(\xff\xa4h\x84\x16\x043') Family=0x28

でした。

 ここで利用する温度センサDS18B20用にもライブラリがあります。1-Wireのライブラリと組み合わせて使います。

# Simple demo of printing the temperature from the first found DS18x20 sensor every second.
# Author: Tony DiCola
import time
import board
from adafruit_onewire.bus import OneWireBus
from adafruit_ds18x20 import DS18X20

# Initialize one-wire bus on board pin D5.
ow_bus = OneWireBus(board.D0)
# Scan for sensors and grab the first one found.
ds18 = DS18X20(ow_bus, ow_bus.scan()[0])
# Main loop to print the temperature every second.
while True:
print('Temperature: {0:0.3f}C'.format(ds18.temperature))
time.sleep(1.0)

 実行結果です。

 Adafruitのライブラリは、CIRCUIYPYドライブの中のlibへ入れます。ダウンロードは前回と同じです。今回追加したのはadafruit_onewireフォルダとadafruit_ds18x20.mpyの二つです。