Below code includes SCD41, going to run it for a while.
Decided to use rv3028 with pi 4 instead, and a GPS breakout I have yet to buy.
If I could edit the post title to include SCD41, that would be nice.
p.s. with below code, pico will run froze after a while because of memory, I will adjust to use less list function and revisit.
# universal
import utime
import jpegdec
# setup breakout garden base
from pimoroni_i2c import PimoroniI2C
PINS_BREAKOUT_GARDEN = {"sda": 4, "scl": 5}
i2c = PimoroniI2C(**PINS_BREAKOUT_GARDEN)
# setup 1.54” square breakout LCD
# https://github.com/pimoroni/pimoroni-pico/tree/main/micropython/modules/picographics#drawing-text
import picographics
from picographics import PicoGraphics, DISPLAY_LCD_240X240, PEN_RGB332
display = PicoGraphics(display=DISPLAY_LCD_240X240, rotate=0, pen_type=PEN_RGB332)
display.set_backlight(0.5)
# define colors
black = display.create_pen(000, 000, 000)
lightblue = display.create_pen(000, 236, 255)
green = display.create_pen(000, 255, 000)
red = display.create_pen(255, 000, 000)
grey = display.create_pen(120, 120, 120)
orange = display.create_pen(255, 140, 000)
violet = display.create_pen(255, 000, 255)
yellow = display.create_pen(255, 255, 000)
white = display.create_pen(255, 255, 255)
# setup SCD41 breakout sensor
import breakout_scd41
breakout_scd41.init(i2c)
breakout_scd41.start()
# setup BME688 breakout sensor (i2c address= 0x77?)
from breakout_bme68x import BreakoutBME68X
bme688 = BreakoutBME68X(i2c)
# BME688 declear list section start
# air quality: IAQ indoor air quality index, calculated by Bosch software BSEC library
# air temperature: -40 .. 85cel
# air pressure : 300 .. 1100hPa
# air humidity : 0 .. 100%
# VOC values in the air (volatile organic compounds)
# declear a list with initial number -41 and 86
# bme688 temperature sensor range is -40 to 85
bme688_temperature_list = [-41,86]
# declear a list with initial number -1 and 101
# bme688 humidity sensor range is 0 - 100
bme688_humidity_list=[-1,101]
#declear a list with initial number 299 and 1101
# bme688 pressure sensor range is 300 to 1100
bme688_pressure_list = [299,1101]
# BME688 declear list section end
# SCD41 declear list section start
# CO2 measurement range 0 .. 40,000ppm
# measurment accuracy range 400 .. 5,000ppm
# Humidity measurement range 0% .. 100%RH
# Temperature measurement range -10 .. 60C
# scd41 temperature sensor range is -10 to 60
scd41_temperature_list = [-11,61]
# scd41 humidity sensor range is 0 to 100%
scd41_humidity_list = [-1,101]
#scd41 co2 sensor measurement accuracy is 400 to 5000ppm
scd41_co2_list = [399,5001]
# SCD41 declear list section end
#
while True:
# sensors reading. Factory stated gas_index and meas_index will be zero.
temperature, pressure, humidity, gas_resistance, status, gas_index, meas_index = bme688.read()
# Temperature
# collect and sort
bme688_temperature_list.append(temperature)
bme688_temperature_list.sort()
# pick the 2nd and before last
bme688_temp_min = bme688_temperature_list[1]
bme688_temp_max = bme688_temperature_list[-2]
#remove duplicate so the list does not grow to infinite
bme688_temperature_list= list(set(bme688_temperature_list))
# Celsius to Fahrenheit
bme688_temperature_f = temperature * 1.8 + 32
# Humidity
bme688_humidity_list.append(humidity)
bme688_humidity_list.sort()
bme688_humidity_min = bme688_humidity_list[1]
bme688_humidity_max = bme688_humidity_list[-2]
bme688_humidity_list = list(set(bme688_humidity_list))
# Pressure
bme688_pressure_list.append(pressure)
bme688_pressure_list.sort()
bme688_pressure_min = bme688_pressure_list[1]
bme688_pressure_max = bme688_pressure_list[-2]
bme688_pressure_list = list(set(bme688_pressure_list))
# convert pressure (Pa) to other unit
# read function return value in Pa
# sensor value in hPa
bme688_pressure_psi = ( pressure * 0.0145038 ) / 100
#bme688_pressure_min = ( bme688_pressure_min * 0.0145038) / 100
#bme688_pressure_max = ( bme688_pressure_max * 0.0145038) / 100
# Display
# font select bitmap6 bitmap8 bitmap14_outline sans gothic cursive serif_italic serif
display.set_font("serif")
# C degree @coordinate x=1 y=30
display.set_pen(white)
display.text('{:.1f}'.format(temperature) , 1, 30,240,2)
# @ coordinate x=5 y=65
display.text('{:.1f}'.format(bme688_temp_min), 5, 65,240,1)
# @coordinate x=95 y=65
display.text('{:.1f}'.format(bme688_temp_max) ,95 ,65,240,1)
# F degree @coordinate x=155 y=30
display.set_pen(yellow)
display.text('{:.0f}'.format(bme688_temperature_f) ,155,30,240,2)
# Humidity @coordinate x=1 y=105
display.set_pen(lightblue)
display.text('{:.1f}'.format(humidity) ,1,105,240,2)
# @coordinate x=5 y=140
display.text('{:.1f}'.format(bme688_humidity_min) ,5,140,240,1)
# @coordinate x=95 y=140
display.text('{:.1f}'.format(bme688_humidity_max) ,95,140,240,1)
# Pressure @coordinate x=5 y=180
display.set_pen(orange)
display.text('{:.1f}'.format(bme688_pressure_psi) ,5, 180,240,2)
# @coordinate x=5 y=215
#display.text('{:.1f}'.format(bme688_pressure_min) ,5,215,240,1)
# @coordinate x=95 y=215
#display.text('{:.1f}'.format(bme688_pressure_max) ,95,215,240,1)
# Gas @coordinate x=135 y=115
display.set_pen(violet)
display.text('{:.0f}'.format(gas_resistance) ,135, 115,240,1)
# Status @coordinate x=165 y=175
display.set_pen(green)
display.text('{:.0f}'.format(status) ,165,175,240,1)
# display refresh
display.update()
utime.sleep(5)
display.set_pen(black)
display.clear()
# BME688 Section end
# SCD41 Section start
#if breakout_scd41.ready():
scd41_co2,scd41_temperature,scd41_humidity = breakout_scd41.measure()
# Temperature
# collect and sort
scd41_temperature_list.append(scd41_temperature)
scd41_temperature_list.sort()
# pick the 2nd and before last
scd41_temp_min = scd41_temperature_list[1]
scd41_temp_max = scd41_temperature_list[-2]
#remove duplicate so the list does not grow to infinite
scd41_temperature_list= list(set(scd41_temperature_list))
# Humidity
# collect and sort
scd41_humidity_list.append(scd41_humidity)
scd41_humidity_list.sort()
# pick the 2nd and before last
scd41_humidity_min = scd41_humidity_list[1]
scd41_humidity_max = scd41_humidity_list[-2]
#remove duplicate so the list does not grow to infinite
scd41_humidity_list= list(set(scd41_humidity_list))
# co2
# collect and sort
scd41_co2_list.append(scd41_co2)
scd41_co2_list.sort()
# pick the 2nd and before last
scd41_co2_min = scd41_co2_list[1]
scd41_co2_max = scd41_co2_list[-2]
#remove duplicate so the list does not grow to infinite
scd41_co2_list= list(set(scd41_co2_list))
# Display
# font select bitmap6 bitmap8 bitmap14_outline sans gothic cursive serif_italic serif
display.set_font("serif")
# C degree @coordinate x=1 y=30
display.set_pen(white)
display.text('{:.1f}'.format(scd41_temperature) ,1, 30,240,2)
# @ coordinate x=5 y=65
display.text('{:.1f}'.format(scd41_temp_min), 5, 65,240,1)
# @coordinate x=95 y=65
display.text('{:.1f}'.format(scd41_temp_max) ,95 ,65,240,1)
# Humidity @coordinate x=1 y=105
display.set_pen(lightblue)
display.text('{:.1f}'.format(scd41_humidity) ,1,105,240,2)
# @coordinate x=5 y=140
display.text('{:.1f}'.format(scd41_humidity_min) ,5,140,240,1)
# @coordinate x=95 y=140
display.text('{:.1f}'.format(scd41_humidity_max) ,95,140,240,1)
# co2 @coordinate x=5 y=180
display.set_pen(violet)
display.text('{:.0f}'.format(scd41_co2) ,1,180,240,2)
# @coordinate x=5 y=215
display.text('{:.0f}'.format(scd41_co2_min) ,5,215,240,1)
# @coordinate x=95 y=215
display.text('{:.0f}'.format(scd41_co2_max) ,115,215,240,1)
# display refresh
display.update()
utime.sleep(5)
display.set_pen(black)
display.clear()
# SCD41 Section end