-
-
Save kadamski/92653913a53baf9dd1a8 to your computer and use it in GitHub Desktop.
| #!/usr/bin/python | |
| # coding=utf-8 | |
| # "DATASHEET": http://cl.ly/ekot | |
| from __future__ import print_function | |
| import serial, struct, sys, time | |
| DEBUG = 1 | |
| CMD_MODE = 2 | |
| CMD_QUERY_DATA = 4 | |
| CMD_DEVICE_ID = 5 | |
| CMD_SLEEP = 6 | |
| CMD_FIRMWARE = 7 | |
| CMD_WORKING_PERIOD = 8 | |
| MODE_ACTIVE = 0 | |
| MODE_QUERY = 1 | |
| ser = serial.Serial() | |
| ser.port = sys.argv[1] | |
| ser.baudrate = 9600 | |
| ser.open() | |
| ser.flushInput() | |
| byte, data = 0, "" | |
| def dump(d, prefix=''): | |
| print(prefix + ' '.join(x.encode('hex') for x in d)) | |
| def construct_command(cmd, data=[]): | |
| assert len(data) <= 12 | |
| data += [0,]*(12-len(data)) | |
| checksum = (sum(data)+cmd-2)%256 | |
| ret = "\xaa\xb4" + chr(cmd) | |
| ret += ''.join(chr(x) for x in data) | |
| ret += "\xff\xff" + chr(checksum) + "\xab" | |
| if DEBUG: | |
| dump(ret, '> ') | |
| return ret | |
| def process_data(d): | |
| r = struct.unpack('<HHxxBB', d[2:]) | |
| pm25 = r[0]/10.0 | |
| pm10 = r[1]/10.0 | |
| checksum = sum(ord(v) for v in d[2:8])%256 | |
| print("PM 2.5: {} μg/m^3 PM 10: {} μg/m^3 CRC={}".format(pm25, pm10, "OK" if (checksum==r[2] and r[3]==0xab) else "NOK")) | |
| def process_version(d): | |
| r = struct.unpack('<BBBHBB', d[3:]) | |
| checksum = sum(ord(v) for v in d[2:8])%256 | |
| print("Y: {}, M: {}, D: {}, ID: {}, CRC={}".format(r[0], r[1], r[2], hex(r[3]), "OK" if (checksum==r[4] and r[5]==0xab) else "NOK")) | |
| def read_response(): | |
| byte = 0 | |
| while byte != "\xaa": | |
| byte = ser.read(size=1) | |
| d = ser.read(size=9) | |
| if DEBUG: | |
| dump(d, '< ') | |
| return byte + d | |
| def cmd_set_mode(mode=MODE_QUERY): | |
| ser.write(construct_command(CMD_MODE, [0x1, mode])) | |
| read_response() | |
| def cmd_query_data(): | |
| ser.write(construct_command(CMD_QUERY_DATA)) | |
| d = read_response() | |
| if d[1] == "\xc0": | |
| process_data(d) | |
| def cmd_set_sleep(sleep=1): | |
| mode = 0 if sleep else 1 | |
| ser.write(construct_command(CMD_SLEEP, [0x1, mode])) | |
| read_response() | |
| def cmd_set_working_period(period): | |
| ser.write(construct_command(CMD_WORKING_PERIOD, [0x1, period])) | |
| read_response() | |
| def cmd_firmware_ver(): | |
| ser.write(construct_command(CMD_FIRMWARE)) | |
| d = read_response() | |
| process_version(d) | |
| def cmd_set_id(id): | |
| id_h = (id>>8) % 256 | |
| id_l = id % 256 | |
| ser.write(construct_command(CMD_DEVICE_ID, [0]*10+[id_l, id_h])) | |
| read_response() | |
| if __name__ == "__main__": | |
| cmd_set_sleep(0) | |
| cmd_set_mode(1); | |
| cmd_firmware_ver() | |
| time.sleep(3) | |
| cmd_query_data(); | |
| cmd_set_mode(0); | |
| cmd_set_sleep() |
Wicked, also check the /var/log/syslog file or dmesg, i remember low voltage warnings in one of them when I was doing too much with my weak 5v supply
It's been running in the backyard since yesterday evening, 0 hits on 'voltage' issues it seems. Ever since then it has measured 10 times with 1 second intervals, put the SDS011 to sleep for about 5 minutes, wake up and measure again. So I am still optimistic this works ;-)
Pics of the enclosure you can find here. Currently using a standard weatherproof junction box which was always my entention for the outdoor enclosure.
Remco
What needs to change in the code if I would not use Sensor Hat?
@alokvermaiitr what you mean by Sensor Hat?
For those still having the issue where it maxes out, I wrote some new code which seems to work past the 20,000 mark https://github.com/FaisalAhmed123/Nova-PM2.5-Sensor-Reading-Interpreter/blob/main/main.py

Wicked, also check the /var/log/syslog file or dmesg, i remember low voltage warnings in one of them when I was doing too much with my weak 5v supply