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