improved logging with timestamps (instead of print)
[EVA-2020-02-2.git] / examples / all-in-one-no-pm.py
... / ...
CommitLineData
1#!/usr/bin/env python
2
3import time
4import colorsys
5import os
6import sys
7import ST7735
8import ltr559
9
10from bme280 import BME280
11from enviroplus import gas
12from subprocess import PIPE, Popen
13from PIL import Image
14from PIL import ImageDraw
15from PIL import ImageFont
16import logging
17
18logging.basicConfig(
19 format='%(asctime)s.%(msecs)03d %(levelname)-8s %(message)s',
20 level=logging.INFO,
21 datefmt='%Y-%m-%d %H:%M:%S')
22
23logging.info("""all-in-one.py - Displays readings from all of Enviro plus' sensors
24Press Ctrl+C to exit!
25""")
26
27# BME280 temperature/pressure/humidity sensor
28bme280 = BME280()
29
30# Create ST7735 LCD display class
31st7735 = 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
41st7735.begin()
42
43WIDTH = st7735.width
44HEIGHT = st7735.height
45
46# Set up canvas and font
47img = Image.new('RGB', (WIDTH, HEIGHT), color=(0, 0, 0))
48draw = ImageDraw.Draw(img)
49path = os.path.dirname(os.path.realpath(__file__))
50font = ImageFont.truetype(path + "/fonts/Asap/Asap-Bold.ttf", 20)
51
52message = ""
53
54# The position of the top bar
55top_pos = 25
56
57
58# Displays data and text on the 0.96" LCD
59def 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
86def 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
94factor = 0.8
95
96cpu_temps = [get_cpu_temperature()] * 5
97
98delay = 0.5 # Debounce the proximity tap
99mode = 0 # The starting mode
100last_page = 0
101light = 1
102
103# Create a values dict to store the data
104variables = ["temperature",
105 "pressure",
106 "humidity",
107 "light",
108 "oxidised",
109 "reduced",
110 "nh3"]
111
112values = {}
113
114for v in variables:
115 values[v] = [1] * WIDTH
116
117# The main loop
118try:
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
183except KeyboardInterrupt:
184 sys.exit(0)