Commit | Line | Data |
---|---|---|
d7b32dab SM |
1 | #!/usr/bin/env python |
2 | ||
3 | import time | |
4 | import colorsys | |
5 | import os | |
6 | import sys | |
7 | import ST7735 | |
8 | import ltr559 | |
9 | ||
10 | from bme280 import BME280 | |
11 | from pms5003 import PMS5003 | |
12 | from enviroplus import gas | |
13 | from PIL import Image | |
14 | from PIL import ImageDraw | |
15 | from PIL import ImageFont | |
16 | ||
17 | print("""all-in-one.py - Displays readings from all of Enviro plus' sensors | |
18 | ||
19 | Press Ctrl+C to exit! | |
20 | ||
21 | """) | |
22 | ||
23 | # BME280 temperature/pressure/humidity sensor | |
24 | bme280 = BME280() | |
25 | ||
26 | # PMS5003 particulate sensor | |
27 | pms5003 = PMS5003() | |
28 | ||
29 | # Create ST7735 LCD display class | |
30 | st7735 = ST7735.ST7735( | |
31 | port=0, | |
32 | cs=1, | |
33 | dc=9, | |
34 | backlight=12, | |
35 | rotation=270, | |
36 | spi_speed_hz=10000000 | |
37 | ) | |
38 | ||
39 | # Initialize display | |
40 | st7735.begin() | |
41 | ||
42 | WIDTH = st7735.width | |
43 | HEIGHT = st7735.height | |
44 | ||
45 | # Set up canvas and font | |
46 | img = Image.new('RGB', (WIDTH, HEIGHT), color=(0, 0, 0)) | |
47 | draw = ImageDraw.Draw(img) | |
48 | path = os.path.dirname(os.path.realpath(__file__)) | |
49 | font = ImageFont.truetype(path + "/fonts/Asap/Asap-Bold.ttf", 20) | |
50 | ||
51 | message = "" | |
52 | ||
53 | # The position of the top bar | |
54 | top_pos = 25 | |
55 | ||
56 | # Displays data and text on the 0.96" LCD | |
57 | def display_text(variable, data, unit): | |
58 | # Maintain length of list | |
59 | values[variable] = values[variable][1:] + [data] | |
60 | # Scale the values for the variable between 0 and 1 | |
61 | colours = [(v - min(values[variable]) + 1) / (max(values[variable]) - min(values[variable]) + 1) for v in values[variable]] | |
62 | # Format the variable name and value | |
63 | message = "{}: {:.1f} {}".format(variable[:4], data, unit) | |
64 | print(message) | |
65 | draw.rectangle((0, 0, WIDTH, HEIGHT), (255, 255, 255)) | |
66 | for i in range(len(colours)): | |
67 | # Convert the values to colours from red to blue | |
68 | colour = (1.0 - colours[i]) * 0.6 | |
69 | r, g, b = [int(x * 255.0) for x in colorsys.hsv_to_rgb(colour, 1.0, 1.0)] | |
70 | # Draw a 1-pixel wide rectangle of colour | |
71 | draw.rectangle((i, top_pos, i+1, HEIGHT), (r, g, b)) | |
72 | # Draw a line graph in black | |
73 | line_y = HEIGHT - (top_pos + (colours[i] * (HEIGHT - top_pos))) + top_pos | |
74 | draw.rectangle((i, line_y, i+1, line_y+1), (0, 0, 0)) | |
75 | # Write the text at the top in black | |
76 | draw.text((0, 0), message, font=font, fill=(0, 0, 0)) | |
77 | st7735.display(img) | |
78 | ||
79 | delay = 0.5 # Debounce the proximity tap | |
80 | mode = 0 # The starting mode | |
81 | last_page = 0 | |
82 | light = 1 | |
83 | ||
84 | # Create a values dict to store the data | |
85 | variables = ["temperature", | |
86 | "pressure", | |
87 | "humidity", | |
88 | "light", | |
89 | "oxidised", | |
90 | "reduced", | |
91 | "nh3", | |
92 | "pm1", | |
93 | "pm25", | |
94 | "pm10"] | |
95 | ||
96 | values = {} | |
97 | ||
98 | for v in variables: | |
99 | values[v] = [1] * WIDTH | |
100 | ||
101 | # The main loop | |
102 | try: | |
103 | while True: | |
104 | proximity = ltr559.get_proximity() | |
105 | ||
106 | # If the proximity crosses the threshold, toggle the mode | |
107 | if proximity > 1500 and time.time() - last_page > delay: | |
108 | mode += 1 | |
109 | mode %= len(variables) | |
110 | last_page = time.time() | |
111 | ||
112 | # One mode for each variable | |
113 | if mode == 0: | |
114 | variable = "temperature" | |
115 | unit = "C" | |
116 | data = bme280.get_temperature() | |
117 | display_text(variable, data, unit) | |
118 | ||
119 | if mode == 1: | |
120 | variable = "pressure" | |
121 | unit = "hPa" | |
122 | data = bme280.get_pressure() | |
123 | display_text(variable, data, unit) | |
124 | ||
125 | if mode == 2: | |
126 | variable = "humidity" | |
127 | unit = "%" | |
128 | data = bme280.get_humidity() | |
129 | display_text(variable, data, unit) | |
130 | ||
131 | if mode == 3: | |
132 | variable = "light" | |
133 | unit = "Lux" | |
134 | if proximity < 10: | |
135 | data = ltr559.get_lux() | |
136 | else: | |
137 | data = 1 | |
138 | display_text(variable, data, unit) | |
139 | ||
140 | if mode == 4: | |
141 | variable = "oxidised" | |
142 | unit = "kO" | |
143 | data = gas.read_all() | |
144 | data = data.oxidising / 1000 | |
145 | display_text(variable, data, unit) | |
146 | ||
147 | if mode == 5: | |
148 | variable = "reduced" | |
149 | unit = "kO" | |
150 | data = gas.read_all() | |
151 | data = data.reducing / 1000 | |
152 | display_text(variable, data, unit) | |
153 | ||
154 | if mode == 6: | |
155 | variable = "nh3" | |
156 | unit = "kO" | |
157 | data = gas.read_all() | |
158 | data = data.nh3 / 1000 | |
159 | display_text(variable, data, unit) | |
160 | ||
161 | if mode == 7: | |
162 | variable = "pm1" | |
163 | unit = "ug/m3" | |
164 | data = pms5003.read() | |
165 | data = data.pm_ug_per_m3(1.0) | |
166 | display_text(variable, data, unit) | |
167 | ||
168 | if mode == 8: | |
169 | variable = "pm25" | |
170 | unit = "ug/m3" | |
171 | data = pms5003.read() | |
172 | data = data.pm_ug_per_m3(2.5) | |
173 | display_text(variable, data, unit) | |
174 | ||
175 | if mode == 9: | |
176 | variable = "pm10" | |
177 | unit = "g/m3" | |
178 | data = pms5003.read() | |
179 | data = data.pm_ug_per_m3(10) | |
180 | display_text(variable, data, unit) | |
181 | ||
182 | # Exit cleanly | |
183 | except KeyboardInterrupt: | |
184 | sys.exit(0) |