Skip to content

Instantly share code, notes, and snippets.

@ati
Last active December 10, 2015 01:38
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ati/4360766 to your computer and use it in GitHub Desktop.
Save ati/4360766 to your computer and use it in GitHub Desktop.
Electric imp code for K30 CO2 sensor communication using RS-232 protocol
//K30 CO2 sensor interface
// using RS-232 communication
/*
250 - 350 ppm – background (normal) outdoor air level
350- 1,000 ppm - typical level found in occupied spaces with good air exchange.
1,000 – 2,000 ppm - level associated with complaints of drowsiness and poor air.
2,000 – 5,000 ppm – level associated with headaches, sleepiness, and stagnant, stale, stuffy air.
Poor concentration, loss of attention, increased heart rate
and slight nausea may also be present.
>5,000 ppm – this indicates unusual air conditions where high levels of other gases could also be present.
Toxicity or oxygen deprivation could occur. This is the permissible exposure limit
for daily workplace exposures.
>40,000 ppm - this level is immediately harmful due to oxygen deprivation.
source: http://www.dhs.wisconsin.gov/eh/chemfs/fs/carbondioxide.htm
*/
local k30_response = [];
local co2_value = 0;
local output = OutputPort("CO2", "number");
/*
We read CO2 value from IR4 using “Read input registers” (function code 04).
Hence, Starting address will be 0x0003 (register number-1) and Quantity of registers 0x0001.
CRC calculated to 0xC5D5 is sent with low byte first.
source: "modbus on co2 engine" pdf
*/
const co2_read_request = "\xfe\x04\x00\x03\x00\x01\xd5\xc5";
const co2_response_length = 7;
const poll_period = 10.0; // seconds
function join(a, sep)
{
local res = "";
foreach(i,v in a)
{
if (i > 0) { res += sep; }
res += v.tostring();
}
return res;
}
function k30_setup()
{
hardware.uart12.configure(9600, 8, PARITY_NONE, 1, NO_CTSRTS);
}
// can't pass parameters for imp.wakeup
function k30_inner_poll()
{
return k30_poll(false);
}
// main receiver loop. currently receives data in 7-bytes frames (co2 read mode)
function k30_poll(do_reset)
{
if (do_reset) { k30_response = []; }
local byte = hardware.uart12.read();
while (byte >= 0)
{
k30_response.push(byte);
byte = hardware.uart12.read();
}
if (k30_response.len() >= co2_response_length)
{
local current_co2 = (k30_response[3]<<8) + k30_response[4]
// server.show(join(k30_response, ":"));
server.show(current_co2)
output.set(current_co2)
}
else
{
imp.wakeup(0.01, k30_inner_poll);
}
}
function k30_ping()
{
hardware.uart12.write(co2_read_request);
imp.sleep(0.02);
k30_poll(true);
// server.log(time());
imp.wakeup(poll_period, k30_ping);
}
imp.configure("K30 sensor RS232 logger", [], [output]);
k30_setup();
k30_ping();
// end of code
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment