Wall of code to follow. I had to get creative to use the two display packs with just the one frame buffer. There isn’t enough memory space for two frame buffers.
What I do is write to the buffer display 1 only, update the display, then clear the buffer. Then write to it for display 2 only, update the display, then clear the buffer. wash, rinse and repeat.
import time
import st7789
from machine import ADC, Pin
from pimoroni_i2c import PimoroniI2C
from breakout_bme280 import BreakoutBME280
from breakout_bme68x import BreakoutBME68X
from breakout_ltr559 import BreakoutLTR559
from breakout_rtc import BreakoutRTC
vsys = ADC(29)
charging = Pin(24, Pin.IN)
conversion_factor = 3 * 3.3 / 65535
full_battery = 4.2
empty_battery = 2.8
frame_buffer = bytearray(240 * 320 * 2)
display1 = st7789.ST7789(width=240, height=320, buffer=frame_buffer, slot=0)
display2 = st7789.ST7789(width=240, height=320, buffer=frame_buffer, slot=1)
display1.set_backlight(1.0)
display2.set_backlight(1.0)
i2c = PimoroniI2C(sda=(4), scl=(5))
bme_out = BreakoutBME68X(i2c)
bme_in = BreakoutBME280(i2c,0x77)
ltr = BreakoutLTR559(i2c)
rtc = BreakoutRTC(i2c)
rtc.set_backup_switchover_mode(1)
rtc.set_24_hour()
rtc.update_time()
min_temp_in = None
max_temp_in = None
min_temp_out = None
max_temp_out = None
min_press_out = None
max_press_out = None
start_time = time.time()
rtc.enable_periodic_update_interrupt(True)
while True:
if rtc.read_periodic_update_interrupt_flag():
rtc.clear_periodic_update_interrupt_flag()
if rtc.update_time():
rtc_date = rtc.string_date()
rtc_time = rtc.string_time()
time_elapsed = time.time() - start_time
# read the sensors
temp_in, press_in, hum_in = bme_in.read()
temp_out, press_out, hum_out, gas_resistance, status, gas_index, meas_index = bme_out.read()
# convert pressure to mb
pressuremb = press_out / 100
# header
display1.set_pen(255, 255, 255)
display1.text("indoor", 15, 0, 240, 2)
display1.text("outdoor", 140, 0, 240, 2)
display1.text("temperature", 25, 20, 240, 3)
display1.text("min", 95, 78, 240, 3)
display1.text("max", 92, 100, 240, 3)
display1.text("humidity", 50, 130, 240, 3)
display1.text("pressure", 50, 200, 240, 3)
# indoor temperature
temp_in = round(temp_in)
if temp_in < 0:
display1.set_pen(255, 255, 255)
elif 0 <= temp_in < 12:
display1.set_pen(0, 0, 255)
elif 12 <= temp_in < 17:
display1.set_pen(255, 255, 0)
elif 17 <= temp_in < 25:
display1.set_pen(0, 255, 0)
elif 25 <= temp_in < 30:
display1.set_pen(255, 140, 0)
elif temp_in >= 30:
display1.set_pen(255, 0, 0)
else:
display1.set_pen(0, 0, 0)
display1.text('{:.0f}'.format(temp_in) + '`c', 15, 45, 240, 4)
# outdoor temperature
temp_out = round(temp_out)
if temp_out < 0:
display1.set_pen(255, 255, 255)
elif 0 <= temp_out < 12:
display1.set_pen(0, 0, 255)
elif 12 <= temp_out < 17:
display1.set_pen(255, 255, 0)
elif 17 <= temp_out < 25:
display1.set_pen(0, 255, 0)
elif 25 <= temp_out < 30:
display1.set_pen(255, 140, 0)
elif temp_out >= 30:
display1.set_pen(255, 0, 0)
else:
display1.set_pen(0, 0, 0)
display1.text('{:.0f}'.format(temp_out) + '`c', 160, 45, 240, 4)
# indoor min max temperature readings
if time_elapsed > 5:
if min_temp_in is not None and max_temp_in is not None:
if temp_in < min_temp_in:
min_temp_in = int(temp_in)
elif temp_in > max_temp_in:
max_temp_in = int(temp_in)
else:
min_temp_in = int(temp_in)
max_temp_in = int(temp_in)
if min_temp_in is not None and max_temp_in is not None:
min_string_in = ('{:.0f}'.format(min_temp_in))
max_string_in = ('{:.0f}'.format(max_temp_in))
else:
min_string_in = ""
max_string_in = ""
if min_temp_in is not None and max_temp_in is not None:
if min_temp_in < 0: # very cold
display1.set_pen(255, 255, 255)
elif 0 <= min_temp_in < 12: # cold
display1.set_pen(0, 0, 255)
elif 12 <= min_temp_in < 17: # cool
display1.set_pen(255, 255, 0)
elif 17 <= min_temp_in < 25: # warm
display1.set_pen(0, 255, 0)
elif 25 <= min_temp_in < 30: # hot
display1.set_pen(255, 140, 0)
elif min_temp_in >= 30: # very hot
display1.set_pen(255, 0, 0)
else:
display.set_pen(0, 0, 0)
display1.text(min_string_in, 25, 78, 240, 3)
if max_temp_in < 0: # very cold
display1.set_pen(255, 255, 255)
elif 0 <= max_temp_in < 12: # cold
display1.set_pen(0, 0, 255)
elif 12 <= max_temp_in < 17: # cool
display1.set_pen(255, 255, 0)
elif 17 <= max_temp_in < 25: # warm
display1.set_pen(0, 255, 0)
elif 25 <= max_temp_in < 30: # hot
display1.set_pen(255, 140, 0)
elif max_temp_in >= 30: # very hot
display1.set_pen(255, 0, 0)
else:
display1.set_pen(0, 0, 0)
display1.text(max_string_in, 25, 100, 240, 3)
# outdoor min max temperature readings
if time_elapsed > 5:
if min_temp_out is not None and max_temp_out is not None:
if temp_out < min_temp_out:
min_temp_out = int(temp_out)
elif temp_out > max_temp_out:
max_temp_out = int(temp_out)
else:
min_temp_out = int(temp_out)
max_temp_out = int(temp_out)
if min_temp_out is not None and max_temp_out is not None:
min_string_out = ('{:.0f}'.format(min_temp_out))
max_string_out = ('{:.0f}'.format(max_temp_out))
else:
min_string_out = ""
max_string_out = ""
if min_temp_out is not None and max_temp_out is not None:
if min_temp_out < 0: # very cold
display1.set_pen(255, 255, 255)
elif 0 <= min_temp_out < 12: # cold
display1.set_pen(0, 0, 255)
elif 12 <= min_temp_out < 17: # cool
display1.set_pen(255, 255, 0)
elif 17 <= min_temp_out < 25: # warm
display1.set_pen(0, 255, 0)
elif 25 <= min_temp_out < 30: # hot
display1.set_pen(255, 140, 0)
elif min_temp_out >= 30: # very hot
display1.set_pen(255, 0, 0)
else:
display1.set_pen(0, 0, 0)
display1.text(min_string_out, 180, 78, 240, 3)
#max_temp_out = round(max_temp_out)
if max_temp_out < 0: # very cold
display1.set_pen(255, 255, 255)
elif 0 <= max_temp_out < 12: # cold
display1.set_pen(0, 0, 255)
elif 12 <= max_temp_out < 17: # cool
display1.set_pen(255, 255, 0)
elif 17 <= max_temp_out < 25: # warm
display1.set_pen(0, 255, 0)
elif 25 <= max_temp_out < 30: # hot
display1.set_pen(255, 140, 0)
elif max_temp_out >= 30: # very hot
display1.set_pen(255, 0, 0)
else:
display1.set_pen(0, 0, 0)
display1.text(max_string_out, 180, 100, 240, 3)
# indoor humidity
if hum_in < 30:
display1.set_pen(255, 140, 0)
elif 30 <= hum_in < 61:
display1.set_pen(0, 255, 0)
elif 61 <= hum_in < 81:
display1.set_pen(255, 255, 0)
elif hum_in >= 81:
display1.set_pen(255, 0, 0)
else:
display1.set_pen(0, 0, 0)
#display1.text((int(hum_in)), 20, 80, 240, 3)
display1.text('{:.0f}'.format(hum_in) + '%', 10, 160, 240, 4)
# outdoor humidity
if hum_out < 30:
display1.set_pen(255, 140, 0)
elif 30 <= hum_out < 61:
display1.set_pen(0, 255, 0)
elif 61 <= hum_out < 81:
display1.set_pen(255, 255, 0)
elif hum_out >= 81:
display1.set_pen(255, 0, 0)
else:
display1.set_pen(0, 0, 0)
#display1.text((int(hum_in)), 20, 80, 240, 3)
display1.text('{:.0f}'.format(hum_out) + '%', 160, 160, 240, 4)
# outddor pressure reading on display 2
if pressuremb < 982:
display1.set_pen(255, 0, 0)
display1.text('{:.0f}'.format(pressuremb) + 'mb', 50, 230, 240, 4)
display1.text("very low", 30, 265, 240, 4)
elif 982 <= pressuremb < 1004:
display1.set_pen(255, 255, 0)
display1.text('{:.0f}'.format(pressuremb) + 'mb', 50, 230, 240, 4)
display1.text("low", 80, 265, 240, 4)
elif 1004 <= pressuremb < 1026:
display1.set_pen(0, 255, 0)
display1.text('{:.0f}'.format(pressuremb) + 'mb', 55, 230, 240, 4)
display1.text("unsetled", 30, 265, 240, 4)
elif 1026 <= pressuremb < 1048:
display1.set_pen(0, 0, 255)
display1.text('{:.0f}'.format(pressuremb) + 'mb', 50, 230, 240, 4)
display1.text("high", 35, 265, 240, 4)
elif pressuremb >= 1048:
display1.set_pen(255, 140, 0)
display1.text('{:.0f}'.format(pressuremb) + 'mb', 50, 230, 240, 4)
display1.text("very high", 20, 265, 240, 4)
else:
display1.set_pen(0, 0, 0)
display1.text('{:.0f}'.format(pressuremb) + 'mb', 50, 230, 240, 4)
display1.text("", 25, 265, 240, 4)
# battery state
voltage = vsys.read_u16() * conversion_factor
percentage = 100 * ((voltage - empty_battery) / (full_battery - empty_battery))
if percentage > 100:
percentage = 100.00
if charging.value() == 1: # if it's plugged into USB power...
display1.set_pen(0, 255, 0)
display1.text("Battery", 5, 300, 240, 3)
#display1.text("ON", 180, 280, 240, 3)
display1.text('{:.0f}%'.format(percentage), 155, 300, 240, 3)
#display1.text('{:.1f}v'.format(voltage), 155, 300, 240, 3)
#display1.text("MAINS", 155, 300, 240, 3)
display1.set_backlight(1.0)
display2.set_backlight(1.0)
else: # if not, display the battery stats
display1.set_pen(255, 255, 0)
display1.text("Battery", 5, 300, 240, 3)
#display1.text("ON", 180, 280, 240, 3)
display1.text('{:.0f}%'.format(percentage), 155, 300, 240, 3)
#display1.text("Batt", 155, 300, 240, 3)
display1.set_backlight(0.5)
display2.set_backlight(0.5)
#display2.set_led(125,0,0)
# time to update display 1
display1.update()
display1.set_pen(0, 0, 0)
display1.clear()
# header
display2.set_pen(255, 255, 255)
display2.text("rain fall", 50, 130, 240, 3)
display2.text("wind", 80, 200, 240, 3)
display2.text("@", 100, 230, 240, 4)
display2.set_pen(255, 255, 255)
hours = rtc.get_hours()
minutes = rtc.get_minutes()
display2.text(rtc.string_date(), 70, 30, 240, 2)
#display2.text(f"{hours:02}:{minutes:02}", 190, 0, 320, 3)
if hours <12:
display2.text(f"{hours:2}:{minutes:02}:am", 50, 0, 240, 4)
elif hours == 12:
display2.text(f"{hours:2}:{minutes:02}:pm", 60, 0, 240, 4)
elif hours >12:
hours = hours - 12
display2.text(f"{hours:2}:{minutes:02}:pm", 60, 0, 240, 4)
reading = ltr.get_reading()
light = reading[BreakoutLTR559.LUX]
display2.set_pen(0, 255, 0)
display2.text("sun", 10, 50, 240, 4)
#Convert light level in lux to descriptive value.
if light < 50:
display2.text("dark", 120, 50, 240, 4)
elif 50 <= light < 100:
display2.text("dim", 110, 50, 240, 4)
elif 100 <= light < 500:
display2.text("light", 110, 50, 240, 4)
elif light >= 500:
display2.text("bright", 110, 50, 240, 4)
# UV Index
display2.set_pen(0, 255, 0)
display2.text("UV:", 15, 80, 240, 4)
display2.text("??", 140, 80, 240, 4)
# percipitaion
display2.set_pen(0, 255, 0)
display2.text("??" + 'mm', 10, 160, 240, 3)
display2.text("??" + 'mm/h', 120, 160, 240, 3)
# wind
display2.set_pen(0, 255, 0)
display2.text("??", 50, 230, 240, 4)
display2.text("??", 150, 230, 240, 4)
display2.text("??", 100, 265, 240, 4)
# display2.set_pen(255, 255, 255)
# display2.text("wind:", 0, 190, 240, 3)
# display2.text("NE", 80, 190, 240, 3)
# wind direction
# display2.set_pen(255, 255, 255)
# display2.text("36 km/h", 130, 190, 240, 3)
# battery state
voltage = vsys.read_u16() * conversion_factor
percentage = 100 * ((voltage - empty_battery) / (full_battery - empty_battery))
if percentage > 100:
percentage = 100.00
if charging.value() == 1: # if it's plugged into USB power...
display2.set_pen(0, 255, 0)
display2.text("Battery", 5, 300, 240, 3)
#display2.text("ON", 180, 280, 240, 3)
#display2.text('{:.1f}v'.format(voltage), 155, 300, 240, 3)
display2.text('{:.0f}%'.format(percentage), 155, 300, 240, 3)
#display2.text("MAINS", 155, 300, 240, 3)
else: # if not, display the battery stats
display2.set_pen(255, 255, 0)
display2.text("Battery", 5, 300, 240, 3)
#display2.text("ON", 180, 280, 240, 3)
display2.text('{:.0f}%'.format(percentage), 155, 300, 240, 3)
#display2.text("Batt", 155, 300, 240, 3)
# update display 2
display2.update()
display2.set_pen(0, 0, 0)
display2.clear()
time.sleep(1.0)