Merge branch 'topshed-master'
[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)
82 output, _error = process.communicate()
83 output = output.decode()
84 return float(output[output.index('=') + 1:output.rindex("'")])
85
86
87 # Tuning factor for compensation. Decrease this number to adjust the
88 # temperature down, and increase to adjust up
89 factor = 0.8
90
91 cpu_temps = [0] * 5
92
93 delay = 0.5 # Debounce the proximity tap
94 mode = 0 # The starting mode
95 last_page = 0
96 light = 1
97
98 # Create a values dict to store the data
99 variables = ["temperature",
100 "pressure",
101 "humidity",
102 "light",
103 "oxidised",
104 "reduced",
105 "nh3"]
106
107 values = {}
108
109 for v in variables:
110 values[v] = [1] * WIDTH
111
112 # The main loop
113 try:
114 while True:
115 proximity = ltr559.get_proximity()
116
117 # If the proximity crosses the threshold, toggle the mode
118 if proximity > 1500 and time.time() - last_page > delay:
119 mode += 1
120 mode %= len(variables)
121 last_page = time.time()
122
123 # One mode for each variable
124 if mode == 0:
125 variable = "temperature"
126 unit = "C"
127 cpu_temp = get_cpu_temperature()
128 # Smooth out with some averaging to decrease jitter
129 cpu_temps = cpu_temps[1:] + [cpu_temp]
130 avg_cpu_temp = sum(cpu_temps) / float(len(cpu_temps))
131 raw_temp = bme280.get_temperature()
132 data = raw_temp - ((avg_cpu_temp - raw_temp) / factor)
133 display_text(variable, data, unit)
134
135 if mode == 1:
136 variable = "pressure"
137 unit = "hPa"
138 data = bme280.get_pressure()
139 display_text(variable, data, unit)
140
141 if mode == 2:
142 variable = "humidity"
143 unit = "%"
144 data = bme280.get_humidity()
145 display_text(variable, data, unit)
146
147 if mode == 3:
148 variable = "light"
149 unit = "Lux"
150 if proximity < 10:
151 data = ltr559.get_lux()
152 else:
153 data = 1
154 display_text(variable, data, unit)
155
156 if mode == 4:
157 variable = "oxidised"
158 unit = "kO"
159 data = gas.read_all()
160 data = data.oxidising / 1000
161 display_text(variable, data, unit)
162
163 if mode == 5:
164 variable = "reduced"
165 unit = "kO"
166 data = gas.read_all()
167 data = data.reducing / 1000
168 display_text(variable, data, unit)
169
170 if mode == 6:
171 variable = "nh3"
172 unit = "kO"
173 data = gas.read_all()
174 data = data.nh3 / 1000
175 display_text(variable, data, unit)
176
177 # Exit cleanly
178 except KeyboardInterrupt:
179 sys.exit(0)