ラズパイに接続したセンサーが固まる原因は

ラズパイに接続したセンサーが固まる原因は
Page content

はじめに

自宅の室内環境を測定するために、ラズパイ (Raspberry Pi Zero WHとRaspberry Pi 4) に各種センサー (CO2濃度・温度・湿度・大気圧) を接続して日々運用しています。

今回は、ラズパイZeroに接続しているセンターのひとつ、温湿度・気圧センサーのBME280が、何かの拍子に固まっていた問題を解決した話です。実際のラズパイZeroセットの様子は次の写真のとおりです。全てむき出しの状態。

問題発生の状況とタイミング

状況

温湿度・気圧センサーBME280へアクセスして測定値を取得するPythonスクリプト (オリジナルはこれ) が、あるタイミングで、次のようにOSError: [Errno 121] Remote I/O errorで異常終了するようになり、それ以降、このPythonスクリプトを実行する度に異常終了します。

ラズパイの再起動やシャットダウンのみではBME280アクセスは復活せず、電源供給をいったん断って再度起動すると復活します。

root@raspi0:~# ./bme280_json.py
Traceback (most recent call last):
File "./bme280_json.py", line 147, in <module>
	setup()
File "./bme280_json.py", line 143, in setup
	writeReg(0xF2,ctrl_hum_reg)
File "./bme280_json.py", line 20, in writeReg
	bus.write_byte_data(i2c_address,reg_address,data)
File "/usr/local/lib/python3.7/dist-packages/smbus2/smbus2.py", line 455, in write_byte_data
	ioctl(self.fd, I2C_SMBUS, msg)
OSError: [Errno 121] Remote I/O error

発生タイミング

ラズパイのそばに置いているデスクファンの電源をOFFしたとき。(ONのときも可能性はある)

当初は、何かの熱暴走の可能性を考えていました。また、なぜか“日々の在宅業務を終えるタイミング”と関係していそうな雰囲気もありました。しかし、私が椅子から立ち上がるときなどの振動とは全く関係はなくて、たとえば仕事の終わりにノートPC冷却用のデスクファンを操作し、その電源をOFFにしたタイミング以降に、BME280の異変が発生することが多いと先日やっと気づいた次第。

山善 扇風機 デスクファン ロータリースイッチ 風量2段階調節 ホワイト YDS-N121(W)

山善 扇風機 デスクファン ロータリースイッチ 風量2段階調節 ホワイト YDS-N121(W)

山善(YAMAZEN)

問題の原因と対策

原因・被疑箇所

問題の発生タイミングから、何らかの電気的なノイズがBME280の動作異常の原因だと予想できます。家のコンセントのACライン経由でノイズが入り込むのか、他の線が空中のノイズを拾っているのか。特に測定機器は持っていないので可能な範囲で、デスクファンの電源のON/OFFを繰り返しながら下記のようにいろいろ試すと、

  1. ラズパイをAC電源から切り離してバッテリー駆動しても発生頻度の変化は感じ取れず (電源供給USBケーブルはまだ変更せず)
  2. I2C通信のボーレートをデフォルトの100kHzから10kHzに落としても発生頻度の変化は感じ取れず (変更方法はこちら)
  3. 電源供給USBケーブルを別のものに交換すると発生頻度が下がるようだ

被疑箇所として最も可能性が高いのは、ラズパイZeroに電源供給しているUSBケーブルだと分かりました。

対策

そこで対策として、手持ちのものから耐ノイズ性が最も高そうなUSBケーブルを探し、さらにおまじないでフェライトコアを取り付けて、これを電源供給に使うことにしました。電源供給USBケーブルとデスクファンの距離も離しておきましょう。

  • NG: 下記写真の黒色USBケーブル (長さ1.5m, 柔らかめ, 100均で購入)
  • Better: 下記写真の銀色USBケーブル+フェライトコア (長さ1.75m, 硬めで中に編組シールドが見える, 古いUSBハブの付属品)

まとめ

「ラズパイに接続したセンサーの動作異常の原因は、そばに置いた機器の100V電源操作で飛んでいる放射ノイズ」という仮説を、すぐに想像できなかったことが悔しいです (笑)。

機器の相互作用によるこのような現象を、IoT時代には、特に物を自作する場合には意外だと思っちゃいけないのかもしれません。ケーブル配線と機器間の距離を考慮したり、ケーブルの編組シールドといった、普遍的な電磁波対策は常に有効ということで、肝に銘じておきます。

エレコム DH-AMB12 AVケーブル 音楽伝送 A-microBケーブル USB2.0 1.2m

エレコム DH-AMB12 AVケーブル 音楽伝送 A-microBケーブル USB2.0 1.2m

エレコム

Raspberry Pi Zero W - ヘッダー ハンダ付け済み - ラズベリー・パイ ゼロ W ワイヤレス

Raspberry Pi Zero W - ヘッダー ハンダ付け済み - ラズベリー・パイ ゼロ W ワイヤレス

Raspberry Pi

スイッチサイエンス BME280温度/湿度/気圧センサモジュール SSCI-022361

スイッチサイエンス BME280温度/湿度/気圧センサモジュール SSCI-022361

スイッチサイエンス

参考情報) i2c_baudrateの変更方法

ラズパイでの、I2C通信のボーレートi2c_baudrateの変更方法について。次の機種・OSの組み合わせで確認しました。

  • 機種: Raspberry Pi Zero WH
  • OS: Raspberry Pi OS (Raspbian GNU/Linux 10 (buster))
  1. 変更前の値を確認する (100000はデフォルト値)
$ printf "%d\n" 0x$(xxd -ps /sys/class/i2c-adapter/i2c-1/of_node/clock-frequency)
100000
  1. /boot/config.txtを編集してdtparam=i2c_baudrate=10000を追記する
$ diff -up /boot/config.txt.original /boot/config.txt
--- /boot/config.txt.original	2021-02-23 11:44:22.000000000 +0900
+++ /boot/config.txt	2021-08-19 19:39:56.000000000 +0900
@@ -64,3 +64,6 @@ max_framebuffers=2
[all]
#dtoverlay=vc4-fkms-v3d
enable_uart=1
+
+# CUSTOM
+dtparam=i2c_baudrate=10000
  1. ラズパイを再起動する
  2. 値が設定通りに変更されているかを確認する
$ printf "%d\n" 0x$(xxd -ps /sys/class/i2c-adapter/i2c-1/of_node/clock-frequency)
10000

参考リンク