-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsps30_test.py
151 lines (130 loc) · 4.31 KB
/
sps30_test.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# SPDX-FileCopyrightText: 2021 Kevin J. Walters
# SPDX-License-Identifier: MIT
"""
Test program for Sensirion SPS30 device putting it through its paces using i2c.
SPS30 running 2.2 firmware appears to take around one second to change into the
requested mode for data type. Any read in that time will be in the previous format
causing bad data or CRC errors!
Reminder: SPS30 interface select pin needs to be connected to ground for i2c mode.
"""
# pylint: disable=unused-import
import time
import board
import busio
from adafruit_sps30.i2c import SPS30_I2C
DELAYS = (5.0, 2.0, 1.0, 0.1, 0.0, 0.0)
DEF_READS = len(DELAYS)
PM_PREFIXES = ("pm10", "pm25", "pm40", "pm100")
TEST_VERSION = "1.2"
def some_reads(sps, num=DEF_READS):
"""Read and print out some values from the sensor which could be
integers or floating-point values."""
output_header = True
last_idx = min(len(DELAYS), num) - 1
for idx in range(last_idx + 1):
data = sps.read()
if output_header:
print("PM1\tPM2.5\tPM4\tPM10")
output_header = False
# print(data)
print("{}\t{}\t{}\t{}".format(*[data[pm + " standard"] for pm in PM_PREFIXES]))
if idx != last_idx:
time.sleep(DELAYS[idx])
# Just for last value
print("ALL for last read")
for field in sps.FIELD_NAMES:
print("{:s}: {}".format(field, data[field]))
print()
print("Reminder: tps units are different between integer and floating-point modes")
# Bogus data / bogus CRC errors for around one second after mode change are
# inhibited by default mode_change_delay=1.5 in SPS30_I2C constructor
# measured at 0.98 seconds, 1.5 is more conservative value
print()
# To allow a human to grab the serial console
# after a power up to capture the data
print("Sleeping for 20 seconds")
time.sleep(20)
# SPS30 works up to 100kHz
print("BEGIN TEST sps30_test version", TEST_VERSION)
i2c = busio.I2C(board.SCL, board.SDA, frequency=100_000)
print("Creating SPS30_I2C defaults")
sps30_int = SPS30_I2C(i2c, fp_mode=False)
fw_ver = sps30_int.firmware_version
print("Firmware version: {:d}.{:d}".format(fw_ver[0], fw_ver[1]))
print("Six reads in integer mode")
some_reads(sps30_int)
del sps30_int
print("Creating SPS30_I2C fp_mode=True")
sps30_fp = SPS30_I2C(i2c, fp_mode=True)
print("Six reads in default floating-point mode")
start_t = time.monotonic()
readstart_t = start_t
fails = 0
exception = None
for attempts in range(30):
try:
readstart_t = time.monotonic()
some_reads(sps30_fp)
break
except RuntimeError as ex:
exception = ex
fails += 1
time.sleep(0.050)
if fails:
print("Number of exceptions:", fails)
print("Last exception:", repr(exception))
print("Time to good read:", readstart_t - start_t)
print("Stop and wait 10 seconds")
sps30_fp.stop()
print("Start and wait for data to become available")
sps30_fp.start()
start_t = time.monotonic()
while True:
now_t = time.monotonic()
got_data = sps30_fp.data_available
if got_data or now_t - start_t > 30.0:
break
print("Time since start: ", now_t - start_t)
print("Data available:", got_data)
print("Six more reads")
some_reads(sps30_fp)
print("Reset (goes to idle mode)")
sps30_fp.reset()
print("Start")
sps30_fp.start()
print("Six reads after reset+start")
some_reads(sps30_fp)
print("Stop / Sleep / 10 second pause / Wake-up / Start")
sps30_fp.stop()
sps30_fp.sleep()
time.sleep(5)
got_data = False
try:
got_data = sps30_fp.data_available
if got_data:
print("Data available during sleep mode: BAD BAD BAD!")
except OSError:
# this seems to happen in sleep mode
# OSError: [Errno 19] Unsupported operation
pass
time.sleep(5)
sps30_fp.wakeup() # transitions back to "Idle" mode
sps30_fp.start() # needed to return to "Measurement" mode
print("Six reads after wakeup and start")
some_reads(sps30_fp)
print("Six more reads after wakeup and start")
some_reads(sps30_fp)
# data sheet implies this takes 10 seconds but more like 14
print("Fan clean (the speed up is audible)")
sps30_fp.clean(wait=4)
for _ in range(2 * (10 - 4 + 15)):
cleaning = bool(sps30_fp.read_status_register() & sps30_fp.STATUS_FAN_CLEANING)
print("c" if cleaning else ".", end="")
if not cleaning:
break
time.sleep(0.5)
print()
print("Six reads after clean")
some_reads(sps30_fp)
print("END TEST")
time.sleep(6)