10 from bme280
import BME280
11 from pms5003
import PMS5003
12 from enviroplus
import gas
13 from subprocess
import PIPE
, Popen
15 from PIL
import ImageDraw
16 from PIL
import ImageFont
18 print("""all-in-one.py - Displays readings from all of Enviro plus' sensors
24 # BME280 temperature/pressure/humidity sensor
27 # PMS5003 particulate sensor
30 # Create ST7735 LCD display class
31 st7735
= ST7735
.ST7735(
44 HEIGHT
= st7735
.height
46 # Set up canvas and font
47 img
= Image
.new('RGB', (WIDTH
, HEIGHT
), color
=(0, 0, 0))
48 draw
= ImageDraw
.Draw(img
)
49 path
= os
.path
.dirname(os
.path
.realpath(__file__
))
50 font
= ImageFont
.truetype(path
+ "/fonts/Asap/Asap-Bold.ttf", 20)
54 # The position of the top bar
58 # Displays data and text on the 0.96" LCD
59 def 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
)
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
,
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
)))\
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))
85 # Get the temperature of the CPU for compensation
86 def get_cpu_temperature():
87 process
= Popen(['vcgencmd', 'measure_temp'], stdout
=PIPE
, universal_newlines
=True)
88 output
, _error
= process
.communicate()
89 output
= output
.decode()
90 return float(output
[output
.index('=') + 1:output
.rindex("'")])
93 # Tuning factor for compensation. Decrease this number to adjust the
94 # temperature down, and increase to adjust up
99 delay
= 0.5 # Debounce the proximity tap
100 mode
= 0 # The starting mode
104 # Create a values dict to store the data
105 variables
= ["temperature",
119 values
[v
] = [1] * WIDTH
124 proximity
= ltr559
.get_proximity()
126 # If the proximity crosses the threshold, toggle the mode
127 if proximity
> 1500 and time
.time() - last_page
> delay
:
129 mode
%= len(variables
)
130 last_page
= time
.time()
132 # One mode for each variable
134 variable
= "temperature"
136 cpu_temp
= get_cpu_temperature()
137 # Smooth out with some averaging to decrease jitter
138 cpu_temps
= cpu_temps
[1:] + [cpu_temp
]
139 avg_cpu_temp
= sum(cpu_temps
) / float(len(cpu_temps
))
140 raw_temp
= bme280
.get_temperature()
141 data
= raw_temp
- ((avg_cpu_temp
- raw_temp
) / factor
)
142 display_text(variable
, data
, unit
)
145 variable
= "pressure"
147 data
= bme280
.get_pressure()
148 display_text(variable
, data
, unit
)
151 variable
= "humidity"
153 data
= bme280
.get_humidity()
154 display_text(variable
, data
, unit
)
160 data
= ltr559
.get_lux()
163 display_text(variable
, data
, unit
)
166 variable
= "oxidised"
168 data
= gas
.read_all()
169 data
= data
.oxidising
/ 1000
170 display_text(variable
, data
, unit
)
175 data
= gas
.read_all()
176 data
= data
.reducing
/ 1000
177 display_text(variable
, data
, unit
)
182 data
= gas
.read_all()
183 data
= data
.nh3
/ 1000
184 display_text(variable
, data
, unit
)
189 data
= pms5003
.read()
190 data
= data
.pm_ug_per_m3(1.0)
191 display_text(variable
, data
, unit
)
196 data
= pms5003
.read()
197 data
= data
.pm_ug_per_m3(2.5)
198 display_text(variable
, data
, unit
)
203 data
= pms5003
.read()
204 data
= data
.pm_ug_per_m3(10)
205 display_text(variable
, data
, unit
)
208 except KeyboardInterrupt: