Uart read,write and wiring with CO2 sensor

We are connecting a CO2 sensor with the RJ12 connector.
RJ12 Connector only gives us 4 pins that are required for this sensor, but we are missing 2 pins.

The pins that we don’t get from RJ12 connector are the signal and en_vbb pins. Can we connect them to the board? How and which ones?

The imp that we are using is the battery powered sensor node which uses imp003

Datasheet of CO2 sensor:
Manual of CO2 sensor:

Here is the snippet of the code:
local LP = hardware.uartFG;
local state = 1
hardware.pinY.configure(DIGITAL_OUT, state);
hardware.pinS.configure(DIGITAL_OUT, state);

LP.configure(9600, 8, PARITY_NONE, 2, NO_CTSRTS);

Not sure how to read/write from the sensor after reading the manual.

Please help out.


So here, the wiring I would suggest would be:

  • GND on sensor to GND on imp (pin 4 on the RJ12)

  • VBB shorted to EN_VBB connected to 3V3 on imp (pin 5 on the RJ12). There’s no need to use the sensor’s shutdown mode as the imp has a power switch integrated.

  • TXD on sensor to RXD on imp (pin 6 on the RJ12)

  • RXD on sensor to TXD on imp (pin 1 on the RJ12)

  • RDY to the 1wire line on the imp (pin 3 on the RJ12)

  • Connect VCAP to 3V3 on the imp; I would put at least 220uF on there (right at the sensor itself) to help with the current peak during a reading. A supercap shouldn’t be necessary but I would recommend using the Energizer Lithium AAs here as they are better with high current than alkalines.

Luckily, the RDY signal (which is useful) is open drain so can be connected to the 1wire line. After powering up the imp you can wait for pinM to go low which indicates the sensor is ready for commands.

See the “standard RDY polling” flow in the datasheet

1 Like

We are following the arduino project below.
We are able to get the first read down and but then the subsequent read is not working. We tried different ways. Any help would be appreciate!

I have also attached the loop function below.

function loop(){
imp.wakeup(10, loop);
if (first_loop == 0) {

	sendRequest(simpleWriteCommand, 4, false);
	first_loop = 1; 
	counter = 0;
    sendRequest(write_to_0x20, 4, false);
sendRequest(simpleReadCommand, 37, true); 
local crc_result;
local aBlob = blob();
for(local i = 0; i < 35; i++){
    aBlob.writen(response[i], 'b');
crc_result = CRC16.calculate(aBlob);
local  crc_result_h = crc_result & 0xff; 
server.log("crc h: " + crc_result_h); 
local crc_result_l = (crc_result >> 8) & 0xff; 
server.log("crc l: " + crc_result_l); 

if ((response[35] != crc_result_h) && (response[36] == crc_result_l)) { 
    server.log("! ! !  CRC Sensor and Calulated Do NOT MATCH"); 
}else {
    server.log("CRC Sensor and Calulated MATCH"); 
  	imp.sleep(20);// wait 20 seconds befoe next sensor read 
  	server.log("rdy now LOW, an active LOW signal.  Low means READY."); 
    transmit_packet[0] = 0xfe; // 
    transmit_packet[1] = 0x41; //Write to LP8 ModBus command 
    transmit_packet[2] = 0x0; // Address H 
    transmit_packet[3] = 0x80; //address L 
    transmit_packet[4] = 0x19;//number of bytes = 0x0080 thru 0x0099 - decimal = 25
    transmit_packet[5] = 0x20; //INCLUDING calculation control byte 
	for (local i = 6; i < 31; i++) { 
        transmit_packet[i] = response[i-3]; 
    server.log("transmit_packets: ");
    // Now compute new CRC of all data in transmit_packet[]: 
    //crc_result = ModRTU_CRC(transmit_packet, (6+23)); // Function call to calculate CRC  37=0 to 36 
    local aBlob = blob(31);
    local bBlob = blob(39);
    for(local i = 0; i < 29; i++){
        aBlob[i] = transmit_packet[i];

    crc_result = CRC16.calculate(aBlob);
    local  crc_result_h = crc_result & 0xff; 
    server.log("crc h: " + crc_result_h); 
    local crc_result_l = (crc_result >> 8) & 0xff; 
    server.log("crc l: " + crc_result_l);
    bBlob[37] = crc_result_h;
    bBlob[38] = crc_result_l;
 	// Send transmit_packet[] to LP8 
 	sendRequest(bBlob, 4, false); // send 38 bytes total, expect 4 byte response 
	server.log("\n ****** transmit_packet sent to LP8 RAM ******."); 
	server.log("Sensor response:"); 


I don’t see any reading in the code you posted?

Thanks for the quick reply, following is the reading code.

function sendRequest(command, n, read)


for (local i = 0; i < n; i++)
response[i] =;
server.log(“response[” + i + "] = " + response[i]);
if(n == 37){
local decimal = 256 * response[29] + response[30];
server.log("CO2: " + decimal);

function simpleWrite(command){
local timeout = 0;
while ( == 1) {
if (timeout > 10){
server.log(“waiting for rdy to go low”);
server.log(“rdy now LOW, an active LOW signal. Low means READY.”);

function waitRead(command){
local timeout = 0;
while ( == 0) {
if (timeout > 10){
server.log(“waiting for rdy to go HIGH”);
server.log(“rdy now HIGH, an active HIGH signal. HIGH means READ.”);

So, here I’m particularly concerned about the way you’re reading the packet.

The read() command does not block - so if all the data has not arrived yet, you’ll get -1 back from this and I would suspect that your buffer appears to have some of them in there (though they’ll appear as 255 in your logging as you’re reading them back out of the buffer).

Would that summarize what you’re seeing? If so, the hacky way to work around this would be to just put a long delay before reading, to ensure the whole response has been received, but the real answer is to process the bytes individually as they come in with a state machine.

Also, waitRead will essentially just wait for 0.1s as there is no delay in the loop; I’m guessing you’re trying to wait for up to 1s? (same for simpleWrite).

I’ve also just started with the LP8. I wasn’t too impressed by the Arduino code in their docs so I pretty much started from scratch. The problem I’m running into is that I’m not getting any response from the LP8 … at all. I’ve checked out my connections and all seems good. The LP8 RDY pin never goes high. If I force it high and send out a request on ModBus, I get no reply.

//set up serial bus ====
LP8 <- hardware.uartWJ
LP8.configure(9600, 8, PARITY_NONE, 2, TIMING_ENABLED , LP8_answer)

//config pins ====
LP8_rdy <- hardware.pinT
LP8_en <- hardware.pinP
LP8_rset <- hardware.pinS


Turns out that the reset pin is not used by the LP8 and the enable pin is not needed (as per Hugo’s comment)

Checked to make sure my the LP8 RxD goes to PinW and TxD to PinJ. The LP8 RDY pin goes to PinT. I used the TIMING_ENABLED in the uart config because imp docs seemed to indicate it was necessary for ModBus.