離れた場所の〇〇が測りたい その3 温湿度センサSHT31

 I2Cインターフェースのデバイスはとても便利に使えます。Inter-Integrated Circuit の名称のとおり、プリント基板内の距離ぐらいしか配線長を延ばせません。TTLレベルのRS-232CをUARTと呼ぶのが一般的ですが、このインターフェースであれば、数mの距離を通信できます。1対1の通信なので、拡張性は高くありません。

I2Cインターフェースのセンサが多く入手できるので

 I2CをUARTに変換できるデバイス、たとえばSC16IS750がありますが、ここではマイコンを使います。マイコンもプログラミングが簡単なほうがよいので、MicroPythonを利用します。MicroPythonはWikiPediaによれば2013年に開発された最近の言語です。Python3の処理系で、importするライブラリはpythonで書かれたものやコンパイルされた .mpyを利用します。

 いろいろなマイコン・ボードで動作しますが、安価に入手できたAdafruitのTrinket M0を利用します。Adafruitでは、MicroPythonをCircuitPythonと呼びます。形状はコンパクトで、ピンヘッダは10ピンだけです。したがって、利用できるI/Oは多くありません。電源以外には、Rx/TxのUARTとSCL/SDAのI2Cの2種類がプリント基板上にシルク印刷されています。ピンには複数の機能が割り当てられているので、GPIO、アナログ入力、SPI、I2S、割り込みが利用できます。

 Trinket M0にはUSBコネクタが用意されており、PCとつないでプログラムを開発します。PCにつないだとき、CIRCUIYPYというストレージが見えます。このルートにmain.pyがあれば、電源が入るもしくはリセットされると実行されます。libフォルダにはライブラリを保存します。このストレージは59kバイトしかないので、購入時に入っていたWindows7のドライバは不要なら削除して空き容量を増やしておきます。

 ファームウエアは3.0.1をインストールしました。

専用のエディタmu

 python3のプログラムはテキスト・エディタがあれば記述できます。ファイル名をmain.pyで保存します。muというエディタがあるのでインストールします。ソース・コード・エリアとシリアルモニタが合体しているので使いやすいです。

温湿度センサはSHT31を利用

 Adafruitのライブラリをダウンロードしますが、大きすぎてすべてをCIRCUIYPYのフォルダにコピーできません。August 30, 2018 auto-releaseからadafruit-circuitpython-bundle-3.x-mpy-20180830.zipをダウンロードし、解凍したのち、adafruit_sht31d.mpyadafruit_bus_device(フォルダごと)の二つを、CIRCUIYPYのlibフォルダに入れます。

SHT31との接続

 電源とI2C信号の4本を配線します。

 CircuitPython I2Cの解説ページにあるI2Cデバイスを探し出すプログラムを動かします。

# CircuitPython demo - I2C scan

import time
import board
import busio

i2c = busio.I2C(board.SCL, board.SDA)

while not i2c.try_lock():
pass

while True:
print("I2C addresses found:", [hex(device_address)
for device_address in i2c.scan()])
time.sleep(2)

 実行結果です。SHT31のデフォルト・スレーブ・アドレス0x44を表示しました。

 つづいて、SHT31のライブラリを利用します。温度や湿度の値などは、こちらのページの記述を参考にしました。

import time
import board
import busio
import adafruit_sht31d

i2c = busio.I2C(board.SCL, board.SDA)
i2c.unlock()
sensor = adafruit_sht31d.SHT31D(i2c)
while True:
print("Temp:", sensor.temperature)
print("Humidity: %0.1f %%" % sensor.relative_humidity)
time.sleep(1.0)

 実行結果です。妥当な値を表示しているのでうまく動いているようです。指をセンサに近づけると湿度が急に変化しました。

Arduino UNOへシリアルで送信する

 Trinket M0にはRx/Txのシリアル通信のピンが出ているので、ここからArduino UNOのソフトウェア・シリアル通信でArduinoへデータを受け渡しをします。UARTの通信は標準ライブラリに入っているようです。digitalioをimportすれば使えます。記述方法は、こちらのMicroPythonページCircuitPython UART Serialページを参照しました。

import time
import board
import busio
import adafruit_sht31d
import digitalio

uart = busio.UART(board.TX, board.RX, baudrate=9600)
i2c = busio.I2C(board.SCL, board.SDA)
i2c.unlock()
sensor = adafruit_sht31d.SHT31D(i2c)

# Use the object to print the sensor readings
while True:
print("Temp:", sensor.temperature)
uart.write(str(sensor.temperature)+" ")
print("Humidity: %0.1f %%" % sensor.relative_humidity)
uart.write(str(sensor.relative_humidity)+"\n")
time.sleep(1.0)

 実行結果です。

 

 接続です。動作はしますが、このままではTrinket M0は3.3VなのでI/Oポートの電圧が高くなって、ICの内部が壊れるかもしれません。

 (※)初出時、レベル・シフトを入れずに公開しました。申し訳ございません。

 抵抗分割によるレベル・シフト回路を入れます。

 R1=1.2k、R2=2.2kの値で電圧を分割しました。Trinket M0で使われているAtmel SAM D21EのI/O電圧の最大値はVdd+0.3Vなので、3.6Vを超えてはなりません。3.4V程度なので、収まっています。Rx信号のほうはノイズのピークが4Vを超えています。こちらは信号は出ていないので、接続しないことで解決できます。R1とR2の値を調整して、もっと低い電圧に抑えるようにもできます。

 

 Arduino UNOのスケッチです。Software Serial Exampleのページのスケッチを利用しました。

#include <SoftwareSerial.h>
SoftwareSerial mySerial(10, 11); // RX, TX

void setup() {
Serial.begin(9600);
Serial.println("Goodnight moon!");
mySerial.begin(9600);
}

void loop() { // run over and over
if (mySerial.available()) {
Serial.write(mySerial.read());
}
}

 実行結果です。

前へ

SpresenseでLチカから始める (9) Wireライブラリ SHT31

次へ

ディジタル・ポテンショメータ (2) TPL0501