Loading README.md +9 −6 Original line number Diff line number Diff line Loading @@ -46,12 +46,14 @@ port = softuart.setup(9600, 2, 1) port:on("data", 10, uart_callback) function uart_callback(data) local pm25i, pm25d, pm10i, pm10d = sds011.parse_frame(data) if pm25i ~= nil then -- pm25i/pm10i contain the integer part (i.e., PM2.5 / PM10 value in µg/m³) -- pm25d/pm10d contain the decimal/fractional part (i.e., PM2.5 / PM10 fraction in .1 µg/m³, range 0 .. 9) 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 -- invalid checksum or non-data frame (i.e., acknowledgment of a write command) -- sds011.work_period has been updated after using sds011.set_work_period end end end ``` Loading @@ -68,6 +70,7 @@ Currently, the following commands are supported * 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; does not change it * period == 0: continuous operation (about one measurement per second) * 0 < *period* ≤ 30: about one measurement every *period* minutes; fan turned off in-between Loading init.lua +12 −6 Original line number Diff line number Diff line Loading @@ -25,12 +25,13 @@ end function setup_client() print("Connected") gpio.write(ledpin, 1) port = softuart.setup(9600, 2, 1) port:on("data", 10, uart_callback) publishing_mqtt = true mqttclient:publish(mqtt_prefix .. "/state", "online", 0, 1, function(client) publishing_mqtt = false port:write(sds011.set_work_period(nil)) end) port = softuart.setup(9600, 2, 1) port:on("data", 10, uart_callback) end function connect_mqtt() Loading @@ -55,8 +56,7 @@ function connect_wifi() end function uart_callback(data) local pm25i, pm25f, pm10i, pm10f = sds011.parse_frame(data) if pm25i == nil then if not sds011.parse_frame(data) then print("Invalid or data-less SDS011 frame") return end Loading @@ -64,8 +64,14 @@ function uart_callback(data) if sds011.work_period > 0 then work_period = string.format("%d min", sds011.work_period) end local json_str = string.format('{"pm2_5_ugm3": %d.%d, "pm10_ugm3": %d.%d, "rssi_dbm": %d, "period": "%s"}', pm25i, pm25f, pm10i, pm10f, wifi.sta.getrssi(), work_period) local influx_str = string.format("pm2_5_ugm3=%d.%d,pm10_ugm3=%d.%d", pm25i, pm25f, pm10i, pm10f) local json_str = string.format('{"rssi_dbm":%d,"period":"%s"', wifi.sta.getrssi(), work_period) if sds011.pm2_5i ~= nil then json_str = string.format('%s,"pm2_5_ugm3":%d.%d,"pm10_ugm3":%d.%d', json_str, sds011.pm2_5i, sds011.pm2_5f, sds011.pm10i, sds011.pm10f) local influx_str = string.format("pm2_5_ugm3=%d.%d,pm10_ugm3=%d.%d", sds011.pm2_5i, sds011.pm2_5f, sds011.pm10i, sds011.pm10f) end json_str = json_str .. '}' if not publishing_mqtt then watchdog:start(true) publishing_mqtt = true Loading sds011.lua +23 −8 Original line number Diff line number Diff line Loading @@ -55,23 +55,38 @@ end function sds011.set_work_period(period) -- period == 0 : continuous operation, about one measurement per second -- period > 0 : about one measurement every <period> minutes, fan is turned off in-between if period < 0 or period > 30 then if period ~= nil and (period < 0 or period > 30) then return end sds011.work_period = period local cmd = string.char(c_head, c_id, c_workperiod, c_write, period) local op = c_write if period == nil then op = c_read period = 0 end local cmd = string.char(c_head, c_id, c_workperiod, op, period) cmd = cmd .. string.char(0, 0, 0, 0, 0, 0, 0, 0, 0, 0) return sds011.finish_cmd(cmd) end function sds011.parse_frame(data) local header, command, pm25l, pm25h, pm10l, pm10h, id1, id2, sum, tail = struct.unpack("BBBBBBBBBB", data) if header ~= c_head or command ~= 0xc0 or (pm25l + pm25h + pm10l + pm10h + id1 + id2) % 256 ~= sum or tail ~= c_tail then return nil if header ~= c_head or (pm25l + pm25h + pm10l + pm10h + id1 + id2) % 256 ~= sum or tail ~= c_tail then return false end if command == 0xc0 then local pm25 = pm25h * 256 + pm25l local pm10 = pm10h * 256 + pm10l sds011.pm2_5i = pm25 / 10 sds011.pm2_5f = pm25 % 10 sds011.pm10i = pm10 / 10 sds011.pm10f = pm10 % 10 return true end if command == 0xc5 then sds011.work_period = pm10l return true end pm25 = pm25h * 256 + pm25l pm10 = pm10h * 256 + pm10l return pm25 / 10, pm25 % 10, pm10 / 10, pm10 % 10 return false end return sds011 Loading
README.md +9 −6 Original line number Diff line number Diff line Loading @@ -46,12 +46,14 @@ port = softuart.setup(9600, 2, 1) port:on("data", 10, uart_callback) function uart_callback(data) local pm25i, pm25d, pm10i, pm10d = sds011.parse_frame(data) if pm25i ~= nil then -- pm25i/pm10i contain the integer part (i.e., PM2.5 / PM10 value in µg/m³) -- pm25d/pm10d contain the decimal/fractional part (i.e., PM2.5 / PM10 fraction in .1 µg/m³, range 0 .. 9) 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 -- invalid checksum or non-data frame (i.e., acknowledgment of a write command) -- sds011.work_period has been updated after using sds011.set_work_period end end end ``` Loading @@ -68,6 +70,7 @@ Currently, the following commands are supported * 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; does not change it * period == 0: continuous operation (about one measurement per second) * 0 < *period* ≤ 30: about one measurement every *period* minutes; fan turned off in-between Loading
init.lua +12 −6 Original line number Diff line number Diff line Loading @@ -25,12 +25,13 @@ end function setup_client() print("Connected") gpio.write(ledpin, 1) port = softuart.setup(9600, 2, 1) port:on("data", 10, uart_callback) publishing_mqtt = true mqttclient:publish(mqtt_prefix .. "/state", "online", 0, 1, function(client) publishing_mqtt = false port:write(sds011.set_work_period(nil)) end) port = softuart.setup(9600, 2, 1) port:on("data", 10, uart_callback) end function connect_mqtt() Loading @@ -55,8 +56,7 @@ function connect_wifi() end function uart_callback(data) local pm25i, pm25f, pm10i, pm10f = sds011.parse_frame(data) if pm25i == nil then if not sds011.parse_frame(data) then print("Invalid or data-less SDS011 frame") return end Loading @@ -64,8 +64,14 @@ function uart_callback(data) if sds011.work_period > 0 then work_period = string.format("%d min", sds011.work_period) end local json_str = string.format('{"pm2_5_ugm3": %d.%d, "pm10_ugm3": %d.%d, "rssi_dbm": %d, "period": "%s"}', pm25i, pm25f, pm10i, pm10f, wifi.sta.getrssi(), work_period) local influx_str = string.format("pm2_5_ugm3=%d.%d,pm10_ugm3=%d.%d", pm25i, pm25f, pm10i, pm10f) local json_str = string.format('{"rssi_dbm":%d,"period":"%s"', wifi.sta.getrssi(), work_period) if sds011.pm2_5i ~= nil then json_str = string.format('%s,"pm2_5_ugm3":%d.%d,"pm10_ugm3":%d.%d', json_str, sds011.pm2_5i, sds011.pm2_5f, sds011.pm10i, sds011.pm10f) local influx_str = string.format("pm2_5_ugm3=%d.%d,pm10_ugm3=%d.%d", sds011.pm2_5i, sds011.pm2_5f, sds011.pm10i, sds011.pm10f) end json_str = json_str .. '}' if not publishing_mqtt then watchdog:start(true) publishing_mqtt = true Loading
sds011.lua +23 −8 Original line number Diff line number Diff line Loading @@ -55,23 +55,38 @@ end function sds011.set_work_period(period) -- period == 0 : continuous operation, about one measurement per second -- period > 0 : about one measurement every <period> minutes, fan is turned off in-between if period < 0 or period > 30 then if period ~= nil and (period < 0 or period > 30) then return end sds011.work_period = period local cmd = string.char(c_head, c_id, c_workperiod, c_write, period) local op = c_write if period == nil then op = c_read period = 0 end local cmd = string.char(c_head, c_id, c_workperiod, op, period) cmd = cmd .. string.char(0, 0, 0, 0, 0, 0, 0, 0, 0, 0) return sds011.finish_cmd(cmd) end function sds011.parse_frame(data) local header, command, pm25l, pm25h, pm10l, pm10h, id1, id2, sum, tail = struct.unpack("BBBBBBBBBB", data) if header ~= c_head or command ~= 0xc0 or (pm25l + pm25h + pm10l + pm10h + id1 + id2) % 256 ~= sum or tail ~= c_tail then return nil if header ~= c_head or (pm25l + pm25h + pm10l + pm10h + id1 + id2) % 256 ~= sum or tail ~= c_tail then return false end if command == 0xc0 then local pm25 = pm25h * 256 + pm25l local pm10 = pm10h * 256 + pm10l sds011.pm2_5i = pm25 / 10 sds011.pm2_5f = pm25 % 10 sds011.pm10i = pm10 / 10 sds011.pm10f = pm10 % 10 return true end if command == 0xc5 then sds011.work_period = pm10l return true end pm25 = pm25h * 256 + pm25l pm10 = pm10h * 256 + pm10l return pm25 / 10, pm25 % 10, pm10 / 10, pm10 % 10 return false end return sds011