use generic variables; handle pms5003.ReadTimeoutError
[EVA-2020-02-2.git] / examples / all-in-one-no-pm.py
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 enviroplus import gas
12 from subprocess import PIPE, Popen
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 Press Ctrl+C to exit!
19 """)
20
21 # BME280 temperature/pressure/humidity sensor
22 bme280 = BME280()
23
24 # Create ST7735 LCD display class
25 st7735 = ST7735.ST7735(
26 port=0,
27 cs=1,
28 dc=9,
29 backlight=12,
30 rotation=270,
31 spi_speed_hz=10000000
32 )
33
34 # Initialize display
35 st7735.begin()
36
37 WIDTH = st7735.width
38 HEIGHT = st7735.height
39
40 # Set up canvas and font
41 img = Image.new('RGB', (WIDTH, HEIGHT), color=(0, 0, 0))
42 draw = ImageDraw.Draw(img)
43 path = os.path.dirname(os.path.realpath(__file__))
44 font = ImageFont.truetype(path + "/fonts/Asap/Asap-Bold.ttf", 20)
45
46 message = ""
47
48 # The position of the top bar
49 top_pos = 25
50
51
52 # Displays data and text on the 0.96" LCD
53 def display_text(variable, data, unit):
54 # Maintain length of list
55 values[variable] = values[variable][1:] + [data]
56 # Scale the values for the variable between 0 and 1
57 colours = [(v - min(values[variable]) + 1) / (max(values[variable])
58 - min(values[variable]) + 1) for v in values[variable]]
59 # Format the variable name and value
60 message = "{}: {:.1f} {}".format(variable[:4], data, unit)
61 print(message)
62 draw.rectangle((0, 0, WIDTH, HEIGHT), (255, 255, 255))
63 for i in range(len(colours)):
64 # Convert the values to colours from red to blue
65 colour = (1.0 - colours[i]) * 0.6
66 r, g, b = [int(x * 255.0) for x in colorsys.hsv_to_rgb(colour,
67 1.0, 1.0)]
68 # Draw a 1-pixel wide rectangle of colour
69 draw.rectangle((i, top_pos, i+1, HEIGHT), (r, g, b))
70 # Draw a line graph in black
71 line_y = HEIGHT - (top_pos + (colours[i] * (HEIGHT - top_pos)))\
72 + top_pos
73 draw.rectangle((i, line_y, i+1, line_y+1), (0, 0, 0))
74 # Write the text at the top in black
75 draw.text((0, 0), message, font=font, fill=(0, 0, 0))
76 st7735.display(img)
77
78
79 # Get the temperature of the CPU for compensation
80 def get_cpu_temperature():
81 process = Popen(['vcgencmd', 'measure_temp'], stdout=PIPE, universal_newlines=True)
82 output, _error = process.communicate()
83 return float(output[output.index('=') + 1:output.rindex("'")])
84
85
86 # Tuning factor for compensation. Decrease this number to adjust the
87 # temperature down, and increase to adjust up
88 factor = 0.8
89
90 cpu_temps = [get_cpu_temperature()] * 5
91
92 delay = 0.5 # Debounce the proximity tap
93 mode = 0 # The starting mode
94 last_page = 0
95 light = 1
96
97 # Create a values dict to store the data
98 variables = ["temperature",
99 "pressure",
100 "humidity",
101 "light",
102 "oxidised",
103 "reduced",
104 "nh3"]
105
106 values = {}
107
108 for v in variables:
109 values[v] = [1] * WIDTH
110
111 # The main loop
112 try:
113 while True:
114 proximity = ltr559.get_proximity()
115
116 # If the proximity crosses the threshold, toggle the mode
117 if proximity > 1500 and time.time() - last_page > delay:
118 mode += 1
119 mode %= len(variables)
120 last_page = time.time()
121
122 # One mode for each variable
123 if mode == 0:
124 variable = "temperature"
125 unit = "C"
126 cpu_temp = get_cpu_temperature()
127 # Smooth out with some averaging to decrease jitter
128 cpu_temps = cpu_temps[1:] + [cpu_temp]
129 avg_cpu_temp = sum(cpu_temps) / float(len(cpu_temps))
130 raw_temp = bme280.get_temperature()
131 data = raw_temp - ((avg_cpu_temp - raw_temp) / factor)
132 display_text(variable, data, unit)
133
134 if mode == 1:
135 variable = "pressure"
136 unit = "hPa"
137 data = bme280.get_pressure()
138 display_text(variable, data, unit)
139
140 if mode == 2:
141 variable = "humidity"
142 unit = "%"
143 data = bme280.get_humidity()
144 display_text(variable, data, unit)
145
146 if mode == 3:
147 variable = "light"
148 unit = "Lux"
149 if proximity < 10:
150 data = ltr559.get_lux()
151 else:
152 data = 1
153 display_text(variable, data, unit)
154
155 if mode == 4:
156 variable = "oxidised"
157 unit = "kO"
158 data = gas.read_all()
159 data = data.oxidising / 1000
160 display_text(variable, data, unit)
161
162 if mode == 5:
163 variable = "reduced"
164 unit = "kO"
165 data = gas.read_all()
166 data = data.reducing / 1000
167 display_text(variable, data, unit)
168
169 if mode == 6:
170 variable = "nh3"
171 unit = "kO"
172 data = gas.read_all()
173 data = data.nh3 / 1000
174 display_text(variable, data, unit)
175
176 # Exit cleanly
177 except KeyboardInterrupt:
178 sys.exit(0)