Raspberry Pi Pico and SGP40 air quality sensor micropython example

In this article we connect an SGP40 air quality sensor to our Raspberry Pi Pico

The SGP40 is Sensirion’s new digital VOC (volatile organic compounds) sensor designed for easy integration into air purifiers or demand-controlled ventilation.

SGP40 is Sensirion’s new digital VOC (volatile organic compounds) sensor designed for easy integration into air treatment devices and air quality monitors.

Based on Sensirion’s CMOSens® Technology, the SGP40 offers a complete sensor system on a single chip and features a digital I²C interface, a temperature-controlled micro-hotplate and a humidity-compensated indoor air quality signal.

In combination with Sensirion’s powerful VOC Algorithm, the sensor signal can be directly used to evaluate indoor air quality

Parts Required

I used a Pico sense hat which has 4 sensors

Name Link
Pico Raspberry Pi Pico Development Board
SGP40

SGP40 SGP30 Air Quality Sensor Digital

Raspberry Pi Pico with Pico Sense HAT Multi Sensor Humidity, Air Quality, Color, Pressure Sensor Sense HAT for Pico with Inbuilt 1.14” LCD Display
Connecting cables Aliexpress product link

Lysee 3D Printer Parts & Accessories – AHT20 Temperature and Humidity Sensor Module DHT11 Upgrade I2C XD Humidity Sensor Probe – (Color: Green)

Ebay link

 

Schematic/Connection

I used a sense hat from sb components which simply plugs into your Pico, you could also use a sensor

This is a suggested layout if you would go down the sensor route. The code uses pins GP6 and 7 for I2C

Code Example

I used Thonny and this example is written in Micropython

The first part is a library for the bme280

You need to upload this to your Raspberry Pi Pico

Go to File > Save as…
Select the Raspberry Pi Pico
Name your file as bme280.py and press the OK button
And that’s it. The library was uploaded to your board. To make sure that it was uploaded successfully, go to File > Save as… and select the Raspberry Pi Pico device. Your file should be listed there:
After uploading the library to your board, you can use the library in your code by importing the library.

from machine import I2C
import utime
import struct
import math

class SGP40:

    class NotFoundException(Exception):
        pass

    class NotSupportedException(Exception):
        pass

    class CRCException(Exception):
        pass

    MEASUREMENT_RAW = 0x260f
    MEASUREMENT_TEST = 0x280e
    HEATER_OFF = 0x3615
    RESET = 0x0006

    GET_SERIAL_ID = 0x3682
    GET_FEATURESET = 0x202f

    # Generated using
    # crc_table = []
    # for crc in range(256):
    #     for crc_bit in range(8):
    #         if crc & 0x80:
    #             crc = (crc << 1) ^ CRC8_POLYNOMIAL;
    #         else:
    #             crc = (crc << 1);
    #         crc = crc%256
    #     crc_table.append(crc)

    CRC_TABLE = [
        0, 49, 98, 83, 196, 245, 166, 151, 185, 136, 219, 234, 125, 76, 31, 46,
        67, 114, 33, 16, 135, 182, 229, 212, 250, 203, 152, 169, 62, 15, 92, 109,
        134, 183, 228, 213, 66, 115, 32, 17, 63, 14, 93, 108, 251, 202, 153, 168,
        197, 244, 167, 150, 1, 48, 99, 82, 124, 77, 30, 47, 184, 137, 218, 235,
        61, 12, 95, 110, 249, 200, 155, 170, 132, 181, 230, 215, 64, 113, 34, 19,
        126, 79, 28, 45, 186, 139, 216, 233, 199, 246, 165, 148, 3, 50, 97, 80,
        187, 138, 217, 232, 127, 78, 29, 44, 2, 51, 96, 81, 198, 247, 164, 149,
        248, 201, 154, 171, 60, 13, 94, 111, 65, 112, 35, 18, 133, 180, 231, 214,
        122, 75, 24, 41, 190, 143, 220, 237, 195, 242, 161, 144, 7, 54, 101, 84,
        57, 8, 91, 106, 253, 204, 159, 174, 128, 177, 226, 211, 68, 117, 38, 23,
        252, 205, 158, 175, 56, 9, 90, 107, 69, 116, 39, 22, 129, 176, 227, 210,
        191, 142, 221, 236, 123, 74, 25, 40, 6, 55, 100, 85, 194, 243, 160, 145,
        71, 118, 37, 20, 131, 178, 225, 208, 254, 207, 156, 173, 58, 11, 88, 105,
        4, 53, 102, 87, 192, 241, 162, 147, 189, 140, 223, 238, 121, 72, 27, 42,
        193, 240, 163, 146, 5, 52, 103, 86, 120, 73, 26, 43, 188, 141, 222, 239,
        130, 179, 224, 209, 70, 119, 36, 21, 59, 10, 89, 104, 255, 206, 157, 172
        ]

    def __init__(self, i2c, addr=0x59):
        self.i2c = i2c
        self.addr = addr
        if not addr in i2c.scan():
            raise self.NotFoundException

    def measure_raw(self, humidity=50, temperature=25):
        paramh = struct.pack(">H", math.ceil(humidity * 0xffff / 100))
        crch = self.__crc(paramh[0], paramh[1])
        paramt = struct.pack(">H", math.ceil((temperature + 45) * 0xffff / 175))
        crct = self.__crc(paramt[0], paramt[1])
        data = paramh + bytes([crch]) + paramt + bytes([crct])
        self.i2c.writeto_mem(self.addr, self.MEASUREMENT_RAW, data, addrsize=16)
        utime.sleep_ms(30)
        raw = self.i2c.readfrom(self.addr, 3)
        self.__check_crc(raw)
        return struct.unpack('>H', raw[:2])[0]

    def measure_test(self):
        raw = self.__read_bytes(self.MEASUREMENT_TEST, 3, 250000)
        self.__check_crc(raw)
        return struct.unpack('>H', raw[:2])[0]

    def reset(self):
        self.__write_command(self.RESET)

    def heater_off(self):
        self.__write_command(self.HEATER_OFF)

    def get_serial_id(self):
        data = self.__read_bytes(self.GET_SERIAL_ID, 6, 500)
        return data

    def __write_command(self, cmd):
        bcmd = struct.pack('>H', cmd)
        self.i2c.writeto(self.addr, bcmd)

    def __read_bytes(self, cmd, count, pause):
        self.__write_command(cmd)
        utime.sleep_us(pause)
        return self.i2c.readfrom(self.addr, count)

    def __check_crc(self, arr):
        assert (len(arr) == 3)
        if self.__crc(arr[0], arr[1]) != arr[2]:
            raise self.CRCException

    def __crc(self, msb, lsb):
        crc = 0xff
        crc ^= msb
        crc = self.CRC_TABLE[crc]
        if lsb is not None:
            crc ^= lsb
            crc = self.CRC_TABLE[crc]
        return crc

You can download from the bottom of this article

Now we need to use these functions

After uploading the library to the Raspberry Pi Pico, copy the following code to the main.py.

This will print the air quality as a raw value into the shell every 5 seconds

from machine import Pin, I2C
from time import sleep
from sgp40 import SGP40

i2c = I2C(1,scl=Pin(7), sda=Pin(6), freq=40000)#all sensor connected through I2C

while True:
  air_quality = SGP40(i2c, 0x59)
  Air_quality = air_quality.measure_raw()
  print("Air quality = ",Air_quality)

  sleep(5)

 

Output

Here is what I saw in Thonny REPL window

>>> %Run -c $EDITOR_CONTENT
Air quality = 65182
Air quality = 24107
Air quality = 24855
Air quality = 25286

Links

sgp40

Related posts

A Raspberry Pi Pico and KY-001 Temperature Sensor

A Raspberry Pi Pico and KY-006 Passive Buzzer

A Raspberry Pi Pico and KY-012 Active Buzzer

This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish. Read More