Close

From Breadboard to Protoboard

A project log for BLEifying a Honeywell PM Sensor

The Honeywell PMS transmits data via UART; if you wanted to get data you need wires. Adding BLE means it can just advertise data wirelessly.

parasquidparasquid 08/14/2020 at 19:210 Comments

Having confirmed that all components are working (it was good that I breadboarded first; it turned out a previous cable I was using didn't have all the wires in continuity so I had to replace it) it's time to cook something up with a protoboard.

Magnet wire has recently been my go-to for point to point wiring, because it looks neat and is relatively easy to work with. This magnet wire has the insulation that burns off with a drop of solder.

And here are our actors. The star of the show is the MDBt42Q breakout board running Espruino. I opted to use some make header pins as some sort of nest for the sensor to keep in in place, while giving a bit of room underneath for various connectors.

Fully assembled, all components fit almost within the protoboard itself. I opted to mount the breakout sideways so as not to obstruct the sensor fan's airflow.

And here's a quick test of the current consumption. According to the USB tester, the whole thing consumes about 80mA at 5v (the sensor requires 5v and has a Vout for 3v3 which I'm using to power the MDBT42Q) when running at the default once-a-second-reading mode.

I also remembered why I initially shelved this project from before: the serial output isn't very clean since the 32-byte packet length isn't sent all at once, and can sometimes even contain stray bytes in the middle which forces you to do buffering of the stream. Fortunately Javascript is a high enough level language to prototype with, so I think I finally got a stream parser that I'm happy with:

var s = new Serial();
s.setup(9600,{rx: D15, tx: D14});

let buffer = '';
const header = String.fromCharCode(0x42) + String.fromCharCode(0x4d);

s.on('data', function (data) {
  buffer = buffer + data;
  if(buffer.length < 32) {
    // get at least 32 bytes
  } else  {
    // find header and discard any previous bytes in buffer
    const index = buffer.indexOf(header);
    if(index != -1) { // found the header
      buffer = buffer.substr(index); // discard previous bytes until header
      if(buffer.length >= 32) {
        buffer = buffer.substr(0, 32);  // get a complete packet
        const arrayBuffer = E.toArrayBuffer(buffer);
        const dataView = new DataView(arrayBuffer);
        console.log({
          header: dataView.getInt16(0),
          length: dataView.getUint8(3), // only get LSB
          pm25: dataView.getUint8(7), // only get LSB
          pm10: dataView.getUint8(9), // only get LSB
          checksum: dataView.getUint16(30),
        });
        digitalPulse(LED, true, 100);
        buffer = buffer.substr(32); // set buffer to leftover bytes
      }
    } else { // header not found
    }
  }
});

I'm running a battery test right now to see how long it would last on a continuous draw (worst case scenario). Depending on the results, I might add instructions to get the sensor to sleep and only do a reading for five seconds a minute, and/or add some sort of energy gathering device like a solar panel or an induction coil to help charge the battery.

Discussions