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