PyModbusを使ってUSB-RS485変換アダプタ通してModbus対応温湿度センサーの値を取得する

PymodbusとUSB-RS485変換アダプタを使ってModbus RTU対応の機器から情報を取得してみます。


# 使っている機器
## Raspberry Pi
使っているのはラズパイ4です。

## 温湿度センサ
**KKmoonRS485温度湿度 トランスミッタ RS485 Modbus-RTU データ ロガー 無線 温度 センサ 温度湿度モニタ**
「RS485 Modbus」でAmazonで検索すると一番上に出てくるこちらのセンサー使っています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116068/ea813822-b3bf-4585-51b9-797b5174f052.png)
https://www.amazon.co.jp/dp/B07KS3WJRM/

仕様も引用しておきます。

|項目|内容|
|:--|:--|
|電源範囲|DC8V〜48V（正と負の極性を区別せず、極性を逆にすることもできます）|
|温度測定範囲|-40℃〜125℃|
|湿度測定範囲|0〜100％RH|
|測定精度と分解能|温度：±0.3℃、0.1℃湿度：±3.0％、0.1RH|
|応答時間|2秒|
|シリアルボーレート|1200,2400,4800,9600（2桁のダイヤルスイッチ）、デフォルトの9600|
|バイトフォーマット|8データビット、1ストップビット、チェック不要|
|通信アドレス|1〜63（6桁のダイヤルスイッチ）、デフォルト1|

## 変換アダプタ
こちらの変換アダプタ使ってUSB-RS485の変換をします。
**WINGONEER USB 2.0 to RS485シリアルコンバータアダプタCP2104 SN75176 FUSE + TVS， FT232よりも安定した二重保護**

https://www.amazon.co.jp/gp/product/B01N3LM0PU/

# 使っているライブラリ「PyModbus」

https://github.com/riptideio/pymodbus

以下で簡単にインストールできます。

```
pip install pymodbus
```


# 配線
USBアダプタを使った構成なのでとてもシンプルです。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116068/b19eee5a-c100-85b1-dcd0-ec660723e9ba.png)
電源がDC8V〜48Vと大きめなので気をつけてください。上の写真でセンサーが赤く光っていると思いますが電源足りてないと光りません。極性は気にしないで大丈夫です。

RS485のA、Bを合わせて配線します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116068/955371a2-942c-e059-93be-47eca3b963b6.png)

以下の写真のように、この温湿度計はプラスマイナス逆でも動きます。（逆でも動くかのテストの時の写真でした・・）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116068/a6de8c9f-3bb8-0e45-13db-8469475941c1.png)


USBアダプタを差したときに、どのデバイスで認識されたか確認しておきます。USBに差した直後にdmesg見るとわかりやすいです。以下のログみると `ttyUSB0` であることがわかります。

```sh
$ dmesg | tail -n 5
[ 7533.026509] usb 1-1.3: Product: CP2104 USB to UART Bridge Controller
[ 7533.026524] usb 1-1.3: Manufacturer: Silicon Labs
[ 7533.026538] usb 1-1.3: SerialNumber: 00868CDA
[ 7533.032198] cp210x 1-1.3:1.0: cp210x converter detected
[ 7533.042672] usb 1-1.3: cp210x converter now attached to ttyUSB0
$ ls /dev/ttyUSB0
/dev/ttyUSB0
```


# PyModbusを使って取得してみる
PyModbusを使うと以下のように簡単に温度と湿度を取得できます。


```python
from pymodbus.client import ModbusSerialClient

client = ModbusSerialClient(baudrate=9600, port="/dev/ttyUSB0", method="rtu")
if client.connect():
  res = client.read_holding_registers(address=0, count=2, unit=1)
  temperature = res.registers[0]/10
  print(f"Temperature:\t{temperature} ˚C")
  humidity  = res.registers[1]/10
  print(f"Humidity:\t{humidity} %")
  client.close()
```

以下少しだけ説明します。

portにはUSB差した時にLinuxで認識されたデバイスを指定します。baudrateは上記の仕様の表にあるとおり調整可能ですが、デフォルトでは9600なのでそれを指定します。

```python
ModbusSerialClient(baudrate=9600, port="/dev/ttyUSB0", method="rtu")
```

ここでSocket通信がオープンされます。

```python
if client.connect():
```

例えば以下のようにconnectした後、 `client.socket` に対してModbusの命令を直接投げることも可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116068/137b90c3-1230-ea47-42bb-11c8a6c771b2.png)


# 実行してみる
以下のように温度と湿度が取得できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116068/90b2500c-d463-a64b-8c74-1eac7492918b.png)



# 参考にした記事

同様の構成をGolangで実装していて周辺の内容も書いてくださっています。

https://future-architect.github.io/articles/20200803/


今回はRS485のUSB変換装置を使いましたが、前にGPIO経由でやった時の記事です。実は見た目は一緒ですが別物の温湿度センサーを使っています。

https://yomon.hatenablog.com/entry/2020/09/raspberry_pi_gpio_modbus