Adds mqtt example (#68)
[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
be4d0fc9
PH
70 vmin = min(values[variable])
71 vmax = max(values[variable])
72 colours = [(v - vmin + 1) / (vmax - vmin + 1) for v in values[variable]]
c96f1398
TF
73 # Format the variable name and value
74 message = "{}: {:.1f} {}".format(variable[:4], data, unit)
10b73e18 75 logging.info(message)
c96f1398
TF
76 draw.rectangle((0, 0, WIDTH, HEIGHT), (255, 255, 255))
77 for i in range(len(colours)):
78 # Convert the values to colours from red to blue
79 colour = (1.0 - colours[i]) * 0.6
be4d0fc9 80 r, g, b = [int(x * 255.0) for x in colorsys.hsv_to_rgb(colour, 1.0, 1.0)]
c96f1398 81 # Draw a 1-pixel wide rectangle of colour
be4d0fc9 82 draw.rectangle((i, top_pos, i + 1, HEIGHT), (r, g, b))
c96f1398 83 # Draw a line graph in black
be4d0fc9
PH
84 line_y = HEIGHT - (top_pos + (colours[i] * (HEIGHT - top_pos))) + top_pos
85 draw.rectangle((i, line_y, i + 1, line_y + 1), (0, 0, 0))
c96f1398
TF
86 # Write the text at the top in black
87 draw.text((0, 0), message, font=font, fill=(0, 0, 0))
88 st7735.display(img)
89
90
91# Get the temperature of the CPU for compensation
92def get_cpu_temperature():
e2d010e2 93 process = Popen(['vcgencmd', 'measure_temp'], stdout=PIPE, universal_newlines=True)
c96f1398
TF
94 output, _error = process.communicate()
95 return float(output[output.index('=') + 1:output.rindex("'")])
96
97
98# Tuning factor for compensation. Decrease this number to adjust the
99# temperature down, and increase to adjust up
20442c9a 100factor = 2.25
c96f1398 101
27156d25 102cpu_temps = [get_cpu_temperature()] * 5
c96f1398
TF
103
104delay = 0.5 # Debounce the proximity tap
105mode = 0 # The starting mode
106last_page = 0
107light = 1
108
109# Create a values dict to store the data
110variables = ["temperature",
111 "pressure",
112 "humidity",
113 "light",
114 "oxidised",
115 "reduced",
116 "nh3"]
117
118values = {}
119
120for v in variables:
121 values[v] = [1] * WIDTH
122
123# The main loop
124try:
125 while True:
126 proximity = ltr559.get_proximity()
127
128 # If the proximity crosses the threshold, toggle the mode
129 if proximity > 1500 and time.time() - last_page > delay:
130 mode += 1
131 mode %= len(variables)
132 last_page = time.time()
133
134 # One mode for each variable
135 if mode == 0:
69294f3c 136 # variable = "temperature"
c96f1398
TF
137 unit = "C"
138 cpu_temp = get_cpu_temperature()
139 # Smooth out with some averaging to decrease jitter
140 cpu_temps = cpu_temps[1:] + [cpu_temp]
141 avg_cpu_temp = sum(cpu_temps) / float(len(cpu_temps))
142 raw_temp = bme280.get_temperature()
143 data = raw_temp - ((avg_cpu_temp - raw_temp) / factor)
69294f3c 144 display_text(variables[mode], data, unit)
c96f1398
TF
145
146 if mode == 1:
69294f3c 147 # variable = "pressure"
c96f1398
TF
148 unit = "hPa"
149 data = bme280.get_pressure()
69294f3c 150 display_text(variables[mode], data, unit)
c96f1398
TF
151
152 if mode == 2:
69294f3c 153 # variable = "humidity"
c96f1398
TF
154 unit = "%"
155 data = bme280.get_humidity()
69294f3c 156 display_text(variables[mode], data, unit)
c96f1398
TF
157
158 if mode == 3:
69294f3c 159 # variable = "light"
c96f1398
TF
160 unit = "Lux"
161 if proximity < 10:
162 data = ltr559.get_lux()
163 else:
164 data = 1
69294f3c 165 display_text(variables[mode], data, unit)
c96f1398
TF
166
167 if mode == 4:
69294f3c 168 # variable = "oxidised"
c96f1398
TF
169 unit = "kO"
170 data = gas.read_all()
171 data = data.oxidising / 1000
69294f3c 172 display_text(variables[mode], data, unit)
c96f1398
TF
173
174 if mode == 5:
69294f3c 175 # variable = "reduced"
c96f1398
TF
176 unit = "kO"
177 data = gas.read_all()
178 data = data.reducing / 1000
69294f3c 179 display_text(variables[mode], data, unit)
c96f1398
TF
180
181 if mode == 6:
69294f3c 182 # variable = "nh3"
c96f1398
TF
183 unit = "kO"
184 data = gas.read_all()
185 data = data.nh3 / 1000
69294f3c 186 display_text(variables[mode], data, unit)
c96f1398
TF
187
188# Exit cleanly
189except KeyboardInterrupt:
190 sys.exit(0)