Shop OBEX P1 Docs P2 Docs Learn Events
flt2int: CO2 sensor conversion — Parallax Forums

flt2int: CO2 sensor conversion

Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
edited 2021-12-04 07:26 in Propeller 1

I've been evaluating the Sensirion SCD30 CO2 sensor lately. It's a handy little unit that senses CO2 concentration, local temperature, and relative humidity. My reason for doing this is to replace the COZIR 0-20% sensor that I've been working with, with something to operate in a less CO2-concentrated environment, suitable for monitoring CO2 in classrooms. This is being done in conjunction with mentoring a high-school student's senior project.

The results I was getting from this sensor were initially very puzzling -- until I read further in the datasheet. The results are in 32-bit floating point! Who does that? Anyway, I invoked the machinery of the Float32 module, and the results made more sense.

But why bring a WMD like Float32 to a knife fight when all you need to do is round floating-point numbers to integer form? So I endeavored to do the conversion in a short Spin routine:

PRI flt2int(flt, scale) | sign, exp

  if (flt == 0.0)
    return 0
  sign := flt >> 31
  exp := flt >> 23 & $ff - 149
  result := (((flt & $7fffff | $800000) * scale) + 1) >> 1
  if (exp < 0)
    result >>= -exp
  elseif (exp > 0)
    result <<= exp
  if (sign)

It does rounding, and it works for my application. The scale argument is there so I can read temperature in tenths of a degree, rather than being rounded to the nearest degree. I just set scale to 10.

I neglected to deal with the NaN stuff, since it doesn't come in to play here. Besides, what's NaN in integer form? $8000_0000?



  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2021-12-05 06:24

    How'd this end up in the P2 forum? Moderators, please move it to P1. Thx.



    Thanks! -P.

  • Nice, Phil!
    I wrote a driver for these too, and thought the same about the float data. Sensirion makes some really nice stuff but they do some bizarre things! Between the float output, the clunky clock requirements spec (datasheet says 100kHz max, but 50kHz max is recommended), and the clock stretching needed in unusual places...their chips can be so fussy to get working properly.
    I used a derivative of FloatString in mine for the conversion method. It's not as heavy as it'd initially sound, as long as OpenSpin or Eric's FlexSpin are used (since they eliminate any code that isn't actually used), but it's nice to have a lone, concise conversion method like that.


  • evanhevanh Posts: 14,835

    A quick squiz at the datasheet only and I note the I2C serial pins are also UART serial pins. I suspect UART was the target market originally, with I2C subsequently added. Probably via internal bit-bashing.

    Of note is direct support of Modbus protocol. That's intended for industrial use with no added microcontroller. I can see lab-coats and LabView on the other end of that cable. IEEE floats suits them just fine.

  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2021-12-04 22:26

    Attached is an archive that includes a demo program, my much-abbreviated driver for the SCD30, and an I2C driver that includes the necessary accommodation for clock stretching. Note that both SDA and SCL need pull-ups.

    A properly commented and boiler-plated version will be posted later.

    Also, the module's self-heating gives inaccurate temperature readings. There's a way to compensate built into the module. However, for compensating the CO2 concentration for temperature, it's better to use the uncompensated temperature, since that will be the temperature of the sample chamber. Moreover, any temperature compensation built into the unit will be inaccurate from power-up, since it takes awhile for the self-heating to equilibrate. For this reason, it's better to incorporate an external temperature sensor, like the One-Wire DS18B20, for an accurate ambient temperature reading.


Sign In or Register to comment.