8 # Transitional fix for breaking change in LTR559
9 from ltr559
import LTR559
14 from bme280
import BME280
15 from pms5003
import PMS5003
, ReadTimeoutError
as pmsReadTimeoutError
16 from enviroplus
import gas
17 from subprocess
import PIPE
, Popen
19 from PIL
import ImageDraw
20 from PIL
import ImageFont
21 from fonts
.ttf
import RobotoMedium
as UserFont
25 format
='%(asctime)s.%(msecs)03d %(levelname)-8s %(message)s',
27 datefmt
='%Y-%m-%d %H:%M:%S')
29 logging
.info("""all-in-one.py - Displays readings from all of Enviro plus' sensors
35 # BME280 temperature/pressure/humidity sensor
38 # PMS5003 particulate sensor
41 # Create ST7735 LCD display class
42 st7735
= ST7735
.ST7735(
55 HEIGHT
= st7735
.height
57 # Set up canvas and font
58 img
= Image
.new('RGB', (WIDTH
, HEIGHT
), color
=(0, 0, 0))
59 draw
= ImageDraw
.Draw(img
)
61 font
= ImageFont
.truetype(UserFont
, font_size
)
65 # The position of the top bar
69 # Displays data and text on the 0.96" LCD
70 def display_text(variable
, data
, unit
):
71 # Maintain length of list
72 values
[variable
] = values
[variable
][1:] + [data
]
73 # Scale the values for the variable between 0 and 1
74 vmin
= min(values
[variable
])
75 vmax
= max(values
[variable
])
76 colours
= [(v
- vmin
+ 1) / (vmax
- vmin
+ 1) for v
in values
[variable
]]
77 # Format the variable name and value
78 message
= "{}: {:.1f} {}".format(variable
[:4], data
, unit
)
80 draw
.rectangle((0, 0, WIDTH
, HEIGHT
), (255, 255, 255))
81 for i
in range(len(colours
)):
82 # Convert the values to colours from red to blue
83 colour
= (1.0 - colours
[i
]) * 0.6
84 r
, g
, b
= [int(x
* 255.0) for x
in colorsys
.hsv_to_rgb(colour
, 1.0, 1.0)]
85 # Draw a 1-pixel wide rectangle of colour
86 draw
.rectangle((i
, top_pos
, i
+ 1, HEIGHT
), (r
, g
, b
))
87 # Draw a line graph in black
88 line_y
= HEIGHT
- (top_pos
+ (colours
[i
] * (HEIGHT
- top_pos
))) + top_pos
89 draw
.rectangle((i
, line_y
, i
+ 1, line_y
+ 1), (0, 0, 0))
90 # Write the text at the top in black
91 draw
.text((0, 0), message
, font
=font
, fill
=(0, 0, 0))
95 # Get the temperature of the CPU for compensation
96 def get_cpu_temperature():
97 process
= Popen(['vcgencmd', 'measure_temp'], stdout
=PIPE
, universal_newlines
=True)
98 output
, _error
= process
.communicate()
99 return float(output
[output
.index('=') + 1:output
.rindex("'")])
102 # Tuning factor for compensation. Decrease this number to adjust the
103 # temperature down, and increase to adjust up
106 cpu_temps
= [get_cpu_temperature()] * 5
108 delay
= 0.5 # Debounce the proximity tap
109 mode
= 0 # The starting mode
113 # Create a values dict to store the data
114 variables
= ["temperature",
128 values
[v
] = [1] * WIDTH
133 proximity
= ltr559
.get_proximity()
135 # If the proximity crosses the threshold, toggle the mode
136 if proximity
> 1500 and time
.time() - last_page
> delay
:
138 mode
%= len(variables
)
139 last_page
= time
.time()
141 # One mode for each variable
143 # variable = "temperature"
145 cpu_temp
= get_cpu_temperature()
146 # Smooth out with some averaging to decrease jitter
147 cpu_temps
= cpu_temps
[1:] + [cpu_temp
]
148 avg_cpu_temp
= sum(cpu_temps
) / float(len(cpu_temps
))
149 raw_temp
= bme280
.get_temperature()
150 data
= raw_temp
- ((avg_cpu_temp
- raw_temp
) / factor
)
151 display_text(variables
[mode
], data
, unit
)
154 # variable = "pressure"
156 data
= bme280
.get_pressure()
157 display_text(variables
[mode
], data
, unit
)
160 # variable = "humidity"
162 data
= bme280
.get_humidity()
163 display_text(variables
[mode
], data
, unit
)
169 data
= ltr559
.get_lux()
172 display_text(variables
[mode
], data
, unit
)
175 # variable = "oxidised"
177 data
= gas
.read_all()
178 data
= data
.oxidising
/ 1000
179 display_text(variables
[mode
], data
, unit
)
182 # variable = "reduced"
184 data
= gas
.read_all()
185 data
= data
.reducing
/ 1000
186 display_text(variables
[mode
], data
, unit
)
191 data
= gas
.read_all()
192 data
= data
.nh3
/ 1000
193 display_text(variables
[mode
], data
, unit
)
199 data
= pms5003
.read()
200 except pmsReadTimeoutError
:
201 logging
.warn("Failed to read PMS5003")
203 data
= float(data
.pm_ug_per_m3(1.0))
204 display_text(variables
[mode
], data
, unit
)
210 data
= pms5003
.read()
211 except pmsReadTimeoutError
:
212 logging
.warn("Failed to read PMS5003")
214 data
= float(data
.pm_ug_per_m3(2.5))
215 display_text(variables
[mode
], data
, unit
)
221 data
= pms5003
.read()
222 except pmsReadTimeoutError
:
223 logging
.warn("Failed to read PMS5003")
225 data
= float(data
.pm_ug_per_m3(10))
226 display_text(variables
[mode
], data
, unit
)
229 except KeyboardInterrupt: