From a3352b1d8e3fe2fd3992142358013120791c4464 Mon Sep 17 00:00:00 2001 From: Daniel Friesel Date: Sun, 29 May 2022 11:03:38 +0200 Subject: Add work/sleep query option and state tracking variable --- README.md | 42 ++++++++++++++++++++++++++++++++---------- sds011.lua | 28 ++++++++++++++++++++-------- 2 files changed, 52 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index f7e8505..e9741ab 100644 --- a/README.md +++ b/README.md @@ -47,36 +47,58 @@ port:on("data", 10, uart_callback) function uart_callback(data) if sds011.parse_frame(data) then - -- PM values or work period have been updated if sds011.pm2_5i ~= nil then -- pm2_5i/pm10i contain the integer part (i.e., PM2.5 / PM10 value in µg/m³) - -- pm2_5d/pm10d contain the decimal/fractional part (i.e., PM2.5 / PM10 fraction in .1 µg/m³, range 0 .. 9) - else - -- sds011.work_period has been updated after using sds011.set_work_period + -- pm2_5f/pm10f contain the decimal/fractional part (i.e., PM2.5 / PM10 fraction in .1 µg/m³, range 0 .. 9) end end end ``` -## SDS011 Configuration API +## SDS011 API If desired, **sds011.lua** can be used to configure the SDS011 sensor. -Currently, the following commands are supported + +### Commands * `port:write(sds011.set_report_mode(active))` * active == nil: request current mode; do not change it. The mode can be read from `sds011.active_mode` after a few milliseconds. * active == true: periodically report PM2.5 and PM10 values via UART * active == false: only report PM2.5 and PM10 values when queried -* `port:write(sds011.sleep(sleep))` - * sleep == true: put sensor into sleep mode. - The fan is turned off, no further measurements are performed. - * sleep == false: wake up sensor * `port:write(sds011.set_work_period(period))` * period == nil: request current work period; do not change it. The work period can be read from `sds011.work_period` after a few milliseconds. * period == 0: continuous operation (about one measurement per second) * 0 < *period* ≤ 30: about one measurement every *period* minutes; fan turned off in-between +* `port:write(sds011.sleep(sleep))` + * sleep == nil: query current sleep mode; do not change it. + The mode can be read from `sds011.working` after a few milliseconds; do + not trust its value before that. + Background: SDS011 sensors only respond to a sleep mode query when they are + not in sleep mode. To handle this, the driver sets `sds011.working = false` + when running the query, and reverts it to `sds011.working = true` only if + it receives an appropriate response. + * sleep == true: put sensor into sleep mode. + The fan is turned off, no further measurements are performed. In this mode, + `port:write(sds011.sleep(false))` is the only command accepted by the + device. + * sleep == false: wake up sensor +* `port:write(sds011.query())`: Query PM2.5 and PM10 values in passive mode. + data is available after a few milliseconds. + +### Variables + +* `sds011.active_mode` + * true: the sensor automatically reports readings + * false: the sensor only reports readings when queried +* `sds011.work_period` + * 0: perform one reading measurement every second + * otherwise: number of minutes between measurements +* `sds011.working` + * true: the sensor is enabled + * false: the sensor is in sleep mode +* `sds011.pm2_5i`, `sds011.pm2_5f`, `sds011.pm10i`, `sds011.pm10f`: see Usage ## Application Example diff --git a/sds011.lua b/sds011.lua index 44b965b..06cd5ac 100644 --- a/sds011.lua +++ b/sds011.lua @@ -18,8 +18,9 @@ local c_sleep = 0x00 local c_work = 0x01 local c_workperiod = 0x08 -sds011.work_period = nil sds011.active_mode = nil +sds011.work_period = nil +sds011.working = nil function sds011.finish_cmd(cmd) cmd = cmd .. string.char(0xff, 0xff) @@ -46,18 +47,22 @@ function sds011.set_report_mode(active) elseif active then cmd = c_active end - local cmd = string.char(c_head, c_id, c_report_mode, op, cmd) + cmd = string.char(c_head, c_id, c_report_mode, op, cmd) cmd = cmd .. string.char(0, 0, 0, 0, 0, 0, 0, 0, 0, 0) return sds011.finish_cmd(cmd) end -function sds011.sleep(sleep) - local cmd = string.char(c_head, c_id, c_sleepcmd, c_write) - if sleep then - cmd = cmd .. string.char(c_sleep) - else - cmd = cmd .. string.char(c_work) +function sds011.set_sleep(sleep) + local op = c_write + local cmd = c_work + if sleep == nil then + -- if the device is sleeping, it will not respond to a query + sds011.working = false + op = c_read + elseif sleep then + cmd = c_sleep end + cmd = string.char(c_head, c_id, c_sleepcmd, op, cmd) cmd = cmd .. string.char(0, 0, 0, 0, 0, 0, 0, 0, 0, 0) return sds011.finish_cmd(cmd) end @@ -94,6 +99,13 @@ function sds011.parse_frame(data) elseif command == 0xc5 and pm25l == 0x02 then sds011.active_mode = pm10l == 0 return true + elseif command == 0xc5 and pm25l == 0x06 then + if pm25h == 0 or pm10l == 1 then + sds011.working = true + else + sds011.working = false + end + return true elseif command == 0xc5 and pm25l == 0x08 then sds011.work_period = pm10l return true -- cgit v1.2.3