Merge pull request #54 from spincrisis/patch-1
[EVA-2020-02-2.git] / examples / all-in-one-no-pm.py
CommitLineData
20442c9a 1#!/usr/bin/env python3
c96f1398
TF
2
3import time
4import colorsys
5import os
6import sys
7import ST7735
bca04496
PH
8try:
9 # Transitional fix for breaking change in LTR559
10 from ltr559 import LTR559
11 ltr559 = LTR559()
12except ImportError:
13 import ltr559
c96f1398
TF
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
20442c9a 21from fonts.ttf import RobotoMedium as UserFont
10b73e18 22import logging
c96f1398 23
10b73e18
CM
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
c96f1398
TF
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__))
20442c9a 56font_size = 20
bde38401 57font = ImageFont.truetype(UserFont, font_size)
c96f1398
TF
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)
10b73e18 74 logging.info(message)
c96f1398
TF
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():
e2d010e2 94 process = Popen(['vcgencmd', 'measure_temp'], stdout=PIPE, universal_newlines=True)
c96f1398
TF
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
20442c9a 101factor = 2.25
c96f1398 102
27156d25 103cpu_temps = [get_cpu_temperature()] * 5
c96f1398
TF
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:
69294f3c 137 # variable = "temperature"
c96f1398
TF
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)
69294f3c 145 display_text(variables[mode], data, unit)
c96f1398
TF
146
147 if mode == 1:
69294f3c 148 # variable = "pressure"
c96f1398
TF
149 unit = "hPa"
150 data = bme280.get_pressure()
69294f3c 151 display_text(variables[mode], data, unit)
c96f1398
TF
152
153 if mode == 2:
69294f3c 154 # variable = "humidity"
c96f1398
TF
155 unit = "%"
156 data = bme280.get_humidity()
69294f3c 157 display_text(variables[mode], data, unit)
c96f1398
TF
158
159 if mode == 3:
69294f3c 160 # variable = "light"
c96f1398
TF
161 unit = "Lux"
162 if proximity < 10:
163 data = ltr559.get_lux()
164 else:
165 data = 1
69294f3c 166 display_text(variables[mode], data, unit)
c96f1398
TF
167
168 if mode == 4:
69294f3c 169 # variable = "oxidised"
c96f1398
TF
170 unit = "kO"
171 data = gas.read_all()
172 data = data.oxidising / 1000
69294f3c 173 display_text(variables[mode], data, unit)
c96f1398
TF
174
175 if mode == 5:
69294f3c 176 # variable = "reduced"
c96f1398
TF
177 unit = "kO"
178 data = gas.read_all()
179 data = data.reducing / 1000
69294f3c 180 display_text(variables[mode], data, unit)
c96f1398
TF
181
182 if mode == 6:
69294f3c 183 # variable = "nh3"
c96f1398
TF
184 unit = "kO"
185 data = gas.read_all()
186 data = data.nh3 / 1000
69294f3c 187 display_text(variables[mode], data, unit)
c96f1398
TF
188
189# Exit cleanly
190except KeyboardInterrupt:
191 sys.exit(0)