SDS011 - mjdeventer/AQ-JDMB GitHub Wiki
Table of contents
Serial UART protocol
Number Byte | Name | Content |
---|---|---|
0 | msg header | AA |
1 | Command No | C0 |
2 | Data 1 | PM2.5 low byte |
3 | Data 2 | PM2.5 high byte |
4 | Data 3 | PM10 low byte |
5 | Data 4 | PM10 high byte |
6 | Data 5 | ID byte 1 |
7 | Data 6 | ID byte 2 |
8 | Checksum | Check-sum |
9 | msg tail | AB |
Interfacing via Python3
the sensor always talks, i.e. there is no poll command
thus we need to identify the start and end character [AA] and [AB] to make sure we get a full data delivery from the sensor
here a Python3 code (modified from geoffwatts, and dhaeb)
import serial, time, struct
ser = serial.Serial()
ser.port = "/dev/ttyUSB0" # Set this to your serial port, e.g. "com3" on windows or "/dev/ttyUSB0" on linux, depending on which number of com you are using, check hardware manager
ser.baudrate = 9600
ser.open()
ser.flushInput()
byte, lastbyte = "\x00", b'\xab' #the actual start byte is \xc0, here byte is just a pre-allocation
while True:
byte = ser.read(size=1); #print(byte)
# We got a valid packet header when following is true:
if byte == b'\xc0' and lastbyte == b'\xab':
sentence = ser.read(size=8) # Read 8 more bytes
readings = struct.unpack('<hhxxcc',sentence) # Decode the packet - little endian, 2 shorts for pm2.5 and pm10, 2 reserved bytes, checksum, message tail
pm_25 = readings[0]/10
pm_10 = readings[1]/10
# ignoring the checksum and message tail
print("PM 2.5:",pm_25,"μg/m^3 PM 10:",pm_10,"μg/m^3")
lastbyte = readings[3]`#the last byte needs to be b'\xab' if a full data string has been received ``
Readout function
It is useful to define the SDS011 readout as a function to trigger in a Data Acquisition loop for live plotting and storing the data
import struct, serial, time
def getsds011(comport):
"""Opens COM to SDS011 and returns 1 data touple of PM25 and PM10
input - string of the comport the SDS011 is connected to
output - a 1x2 toubple with [0] entry being pm25 and [1] being pm10"""
portflagsds011 = True
ser = serial.Serial()
ser.port = comport # Set this to your serial port
ser.baudrate = 9600
ser.open()
ser.flushInput()
byte, lastbyte = "\x00", b'\xab'
while portflagsds011== True:
#lastbyte = byte
byte = ser.read(size=1); #print(byte)
# We got a valid packet header
if byte == b'\xc0' and lastbyte == b'\xab':
#if lastbyte == "\x00" and byte == b'\xaa':
sentence = ser.read(size=8) # Read 8 more bytes
readings = struct.unpack('<hhxxcc',sentence) # Decode the packet - little endian, 2 shorts for pm2.5 and pm10, 2 reserved bytes, checksum, message tail
pm_25 = readings[0]/10
pm_10 = readings[1]/10
# ignoring the checksum and message tail
print("PM 2.5:",pm_25,"μg/m^3 PM 10:",pm_10,"μg/m^3")
lastbyte = readings[3]
del readings
portflagsds011 = False
#ser.flushInput()
ser.close()
return pm_25, pm_10