要旨
Node.jsでmodbus-serialを使用し、Raspberry PiからCO2センサにmodbusのシリアル通信を行なった。
背景
在宅勤務が始まり、換気環境がオフィスより劣る自宅で最高のパフォーマンスを出すためにCO2濃度管理が必要不可欠!
などと論理武装し、一般人が買える最高性能っぽいCO2センサSenseair Sunriseを購入。
しかし、Raspberry PiのIC2接続で読み出すことに挫折(ArduinoのIC2は成功)。
1年ほど積んでいたCO2センサをUARTにより使用することを試みるのであった。
事前準備
ホストにRaspberry Pi Zero Wを用いたので、以下の工程を事前に行っています。
- Raspberry Piのセットアップ
- シリアル通信の有効化
- Node.jsのインストール
配線
ホストであるRaspberry PiからSenseair Sunriseに配線しました。
詳細は公式データシートを参照してください。
No | Sunrise | Raspberry Pi | 使用機能 |
---|---|---|---|
1 | GND | GND P6 | グラウンド |
2 | VBB | 3.3V P1 | センサ電源 |
3 | VDDIO | 3.3V P1 | I/O電源 |
4 | RxD/SDA | TXD P8 (GPIO14) | UART receive input |
5 | TxD/SCL | RXD P10 (GPIO15) | UART transmit output |
6 | COMSEL | - | HIGH: UART(floating可) |
7 | nRDY | - | 電圧 |
8 | DVCC | - | 内部電源出力 |
9 | EN | 3.3V P1 | HIGH: Enable(稼働) |
コード
node moduleのmodbus-serialを使用しています。
インストールは以下のコマンドです。
npm install modbus-serial
modbus-serialのライブラリのexamplesを参考に作成しています。
公式データシート[Modbus on Senseair Sunrise TDE5514]の該当項番を値のコメントに記載しています。
他のセンサを使用される方は設定値の変更が必要です。
正常動作の動作確認以外は行っていないので、参考程度でお願いします。
const ModbusRTU = require('modbus-serial')
let client
const serialPort = '/dev/serial0'
const repeatCount = 10
const sleepMilliseconds = 1000
const networkErrors = [
'ESOCKETTIMEDOUT',
'ETIMEDOUT',
'ECONNRESET',
'ECONNREFUSED',
'EHOSTUNREACH',
'ENETRESET',
'ECONNABORTED',
'ENETUNREACH',
'ENOTCONN',
'ESHUTDOWN',
'EHOSTDOWN',
'ENETDOWN',
'EWOULDBLOCK',
'EAGAIN'
]
const connect = () => {
client = new ModbusRTU()
// 2.1 Modbus settings -> Default slave address
client.setID(104)
// 1.2 Bus timing -> Response time-out
client.setTimeout(180)
}
const reconnect = () => {
console.warn('reconnect!')
client.close()
connect()
}
const run = async () => {
for (let i = 0; i < repeatCount; i++) {
try {
const result = await getCo2AndTemperature()
console.log(result != null ? result : 'Error!')
await sleep(sleepMilliseconds)
} catch (e) {
console.error(e)
}
}
// 無限ループ
// setImmediate(() => {
// run();
// })
}
const getCo2AndTemperature = async () => {
try {
if (!client.isOpen) {
// 2.1 Modbus settings
await client.connectRTUBuffered(serialPort, {
baudRate: 9600,
parity: 'none',
dataBits: 8,
stopBits: 1
})
}
// Table 1:Input Registers(IR)
// IR4 0x03 CO2 Value Filtered Pressure Compensated [ppm]
// IR5 0x04 Temperature [℃×100]
const response = await client.readInputRegisters(3, 2)
return {
co2: response.data[0],
temperature: response.data[1]
}
} catch (e) {
console.error(e)
if (e.errno && networkErrors.includes) reconnect()
}
}
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms))
const main = async () => {
connect()
await run()
client.close()
}
main()
終わり
CO2センサの値読み取りに成功したので、次は以下を考えています。
- Cloud DBにCO2濃度をPOST
- ブラウザで閲覧可能なサイト作成