A Newxie display is a modern take on the classic Nixie tube aesthetic. It is a 135 wide x 240 tall TFT display with double pins on the bottom for mechanical stability - see the product page link below.Â
What's a good use for a Newxie display? How about an analog thermometer - you know, the old-school type with a glass tube with red alcohol inside that rises as the temperature rises. Let's build it!Â
Original Idea
I've been working of building a weather information center using a Fruit Jam and the AdafruitIO Weather Power-up. AdafruitIO provides over 300 hyper local weather data elements updated every 20 minutes. Using it is like drinking from a fire hose, and most boards can only handle a few data points due to memory constraints. The Fruit Jam changed all that - with a 640x480 display and tons of memory, I can now display pages and pages of weather data.Â
Once I had the horsepower to show more than just text, I started thinking about more expressive ways to visualize the data. I thought that a classic thermometer would be an ideal way to display temperature data. As an added bonus, by adding a narrow stripe inside the main body, I can show a second temperature, such as the "feels like" temperature. Here is how it came out:
On page 1 of the Fruit Jam Weather Center (I'm up to 10 pages so far) it shows current weather data. The thermometer sits vertically along the right edge, with bold tick marks and a clean red column that rises with the temperature. It shows degrees Fahrenheit for the left scale, degrees Celsius on the right side, and freezing is marked in red.
The graphic was built using rounded rectangles from the adafruit_display_shapes library for the outlines and indicators, lines from display_shapes for the tic marks, and bitmap_fonts for the numbers. When all was said and done, there ended up being a lot of display elements to create this seemingly simple graphic.Â
After all that work let's make it reusable...
With a little effort I converted the text into a separate helper library. The first hurdle was that not all displays are as large as the Fruit Jam. The original was 440 px high but to be reusable it needs to be scalable. Likewise if it isn't going to be as tall I'd also want to be able to customize the min/max values. Ultimately the goal was to make most of the elements customizable. After several iterations I with AI's help, got it working well enough to try it on a different display.Â
I had a "multi-board" where I have a Feather RP2350 connected to a 240x320 display, an RTC module, a TLV320 DAC, etc., that I've been using to try things out. So, I added an SPA06-003 temperature breakout and added the thermometer graphic:
Â
Â
For the most part it worked quite well, and by trying it on a completely different display I was able to tweak a couple of issues that came up. For the multi-board I changed the colors to match the existing design, narrowed the temperature scale, and resized the thermometer to fit on the display. One interesting thing is that since I didn't have two different temperatures to display, I just set the color of the second temperature scale to red and update both temperatures to the same value. You'll also note that in this use the minimum temperature is above freezing, so the freezing temperature isn't shown. Proof of concept - check! Ready to try a new display.Â
How About a Round Display
Here's a 240 round TFT with the thermometer graphic - this rotates between two pages of a watch face and the thermometer.
On to the Newxie Display
Gather the parts
There are few components for this project, and the assembly is straightforward. There is some soldering adding pins to the board, assembling the board and connecting it up. The star of the show is the Newxie display:
For the board I used a Feather ESP32 v2 as I wanted to use wifi:
For getting the local temperature I used a SPA06-003 breakout along with a short STEMMA cable:
For a build plate I used a Feather Tripler.
Assembly
- Solder the header pins on to your Feather board
- Solder on one set of female headers to plug the Feather board in to the tripler
- Solder on a 2x header for the Newxie (I used a 2x14 but any 2x at least 7 will work) in the prototyping area in the empty space.
- Wire up the Newxie pins to the Feather pins as follows:
- V+ to 3.3v on the board (labeled "3V")
- G to Ground on the board (labeled "GND")
- CL to spi clock on the board (labeled "SCK")
- DA to spi data on the board (labeled "MO")
- CS to D15 on the board (labeled "15")
- DC to D32 on the board (labeled "32")
- you can leave BL unconnected
- Plug in the SPA06-003 breakout board STEMMA connector to the STEMMA port on the board with the STEMMA cable.
Refer to the Learn Guides for the Newxie (Pinouts | Adafruit 1.14" 240x135 Color Newxie TFT Display | Adafruit Learning System) and the Feather board (Overview | Adafruit ESP32 Feather V2 | Adafruit Learning System) for the main components.
Get Ready to Code
You will first need to install CircuitPython on the board. The particular Feather I chose (ESP32 v2) does not show up as a USB drive like on some boards. Follow the instructions in the Learn Guide to install CircuitPython and understand editing programs using Web Workflow. I always use the most recent beta version of CircuitPython (I like living on the bleeding edge...)
Once you have installed CircuitPython you will need to install several libraries from the bundle to your board. Specifically, you will need:
- adafruit_requests required by other libraries
- adafruit_connection_manager used for wifi connectivity
- adafruit_io used to set the time
- adafruit_st7789Â used to set up the Newxie display
- adafruit_bitmap_font used for fonts used on the display
- adafruit_display_text used to create text labels
- adafruit_display_shapes used to create the graphical components
- adafruit_spa06_003Â used for the temperature breakout board
You will also need to create a /fonts/ folder and add some fonts of different sizes. I created a number of pcf font files from the Calibri font on my PC following the instructions in this Learn Guide: Overview | Custom Fonts for CircuitPython Displays | Adafruit Learning System
Create the thermometer.py Helper Library
You will need a file named thermometer.py in your \lib\ folder which is the helper library for this thermometer display element. In your editor create a new file named 'thermometer.py' and save it in your /lib/ folder. Copy the code from the following code file into this file and save:
# SPDX-FileCopyrightText: Copyright (c) 2025 Dana Kamp
#
# SPDX-License-Identifier: MIT
import math
import displayio
from adafruit_display_shapes.rect import Rect
from adafruit_display_shapes.roundrect import RoundRect
from adafruit_display_shapes.circle import Circle
from adafruit_display_shapes.line import Line
from adafruit_display_text.bitmap_label import Label
class Thermometer:
"""Reusable thermometer graphic with update method for actual/apparent temps.
Builds a displayio.Group containing the frame, outline, bulb, tick marks,
labels, and two fills (actual in red, apparent in white). Use ``update`` to
redraw the fills at new temperatures.
> Copy thermometer.py into the lib folder.
> anchor_point is the top-left corner of the thermometer graphic. Default is
(550, 0). Adjust as needed to fit your display.
The default graphic is sizeed 100 px wide by 440 px high. The scale runs
from temp_min (default 0F) to temp_max (default 100F). Each degree is
represented by px_per_degree pixels (default 4), so the scale height is
px_per_degree * (temp_max - temp_min) pixels high.
Default min/max temperature is 0-100°F. You can adjust temp_min and temp_max
to fit your expected temperature range. If you set px_per_degree to None,
the scale will stretch to fill the full 400px height between the top and
bottom of the thermometer graphic.
Colors can be customized by passing a dictionary of color values (0xRRGGBB)
for any of these keys:
"frame", "bg", "outline", "bulb_outline", "bulb_fill",
"tick_major", "tick_minor", "tick_c", "tick_c_zero", "freezing_tick",
"fill_actual", "fill_apparent", "fill_placeholder",
"label_f", "label_c"
If omitted, defaults will be used.
from thermometer import Thermometer
therm = Thermometer(
anchor=(550, 0),
display=display,
tick_font=font15,
therm = Thermometer(
temp_min=20,
temp_max=80, # scale stretches to fill
# px_per_degree=None # implied; leave it out to auto-fill
frame_height=320, # optional shrink total height from detault 440 if needed
frame_width=80, # optional
scale_margin_top=8, # optional
scale_margin_bottom=22, # optional
colors={
"frame": 0x001122,
"outline": 0xFFFFFF,
"bulb_fill": 0x00FF00,
"fill_actual": 0x00CCFF,
"fill_apparent": 0xFFFF00,
"tick_major": 0xEEEEEE,
"label_f": 0xFFAA00,
},
)
group.append(therm.group) where you want it layered.
> Call
therm.update(current_temp, apparent_temp) whenever new data arrives.
"""
def __init__(
self,
anchor=(550, 0),
*,
display=None,
colors=None,
tick_font=None,
px_per_degree=None,
temp_min=0,
temp_max=100,
frame_height=440,
frame_width=100,
scale_margin_top=10,
scale_margin_bottom=30,
log_fn=None,
initial_temp=50,
):
self.anchor = anchor
self.display = display
self.tick_font = tick_font
self.temp_min = temp_min
self.temp_max = temp_max
self.frame_height = frame_height
self.frame_width = frame_width
self.scale_margin_top = scale_margin_top
self.scale_margin_bottom = scale_margin_bottom
self.log = log_fn or (lambda msg: None)
# Core geometry: frame is 100x440 by default with a scale that fills the
# available vertical space between the top and bottom margins. If
# px_per_degree is not provided, it is derived so the given temp range
# fills the entire scale height (e.g., 20-80°F will stretch to the full
# height). Reduce frame_height if your display is shorter than 440 px.
self.scale_height_px = max(
1, self.frame_height - self.scale_margin_top - self.scale_margin_bottom
)
self.px_per_degree = (
px_per_degree
if px_per_degree is not None
else self.scale_height_px / max(1, (self.temp_max - self.temp_min))
)
self.colors = {
"frame": 0x000066,
"bg": 0x000066,
"outline": 0xFFFFFF,
"bulb_outline": 0xFFFFFF,
"bulb_fill": 0xFF0000,
"tick_major": 0xFFFFFF,
"tick_minor": 0xFFFFFF,
"tick_c": 0xAAAAFF,
"tick_c_zero": 0xFF0000,
"freezing_tick": 0xFF0000,
"fill_actual": 0xFF0000,
"fill_apparent": 0xFFFFFF,
"fill_placeholder": 0x000066,
"label_f": 0xFFFFFF,
"label_c": 0xAAAAFF,
}
if colors:
self.colors.update(colors)
self.group = displayio.Group()
self._build_static_parts()
self._append_fills(initial_temp, initial_temp, placeholder=True)
# --- public API -----------------------------------------------------
def update(self, temperature, apparent_temperature):
"""Update the thermometer fills based on current and apparent temps."""
temp = self._parse_temp(temperature, default=50)
app = self._parse_temp(apparent_temperature, default=temp)
if temp < self.temp_min:
temp = self.temp_min
if temp > self.temp_max:
temp = self.temp_max
if app < self.temp_min:
app = self.temp_min
if app > self.temp_max:
app = self.temp_max
if self.display:
self.display.auto_refresh = False
try:
self._pop_fills()
self._append_fills(temp, app, placeholder=False)
self.log(
f"Thermometer updated - actual: {temp}F, apparent: {app}F"
)
finally:
if self.display:
self.display.auto_refresh = True
# --- internals ------------------------------------------------------
def _build_static_parts(self):
x, y = self.anchor
self.top_y = y + self.scale_margin_top
self.bottom_y = self.top_y + self.scale_height_px
# Background frame and outline
frame_fill = self.colors.get("bg", self.colors["frame"])
frame = Rect(x, y, self.frame_width, self.frame_height, fill=frame_fill)
outline = RoundRect(
x=x + 40,
y=self.top_y,
width=20,
height=self.scale_height_px,
r=10,
outline=self.colors["outline"],
stroke=1,
)
bulb = Circle(
x + 50,
y + self.frame_height - (self.scale_margin_bottom + 10),
15,
outline=self.colors["bulb_outline"],
fill=self.colors["bulb_fill"],
stroke=1,
)
self.group.append(frame)
self.group.append(outline)
self.group.append(bulb)
self._build_ticks(x, y)
self._build_labels(x)
def _build_ticks(self, x, y):
# Fahrenheit ticks (respect the configured min/max range)
start_major = int(math.ceil(self.temp_min / 10.0) * 10)
for temp in range(start_major, self.temp_max + 1, 10):
y_pos = self._temp_to_y(temp)
self.group.append(
Line(x + 30, y_pos, x + 40, y_pos, color=self.colors["tick_major"])
)
start_minor = int(math.ceil((self.temp_min - 5) / 10.0) * 10 + 5)
for temp in range(start_minor, self.temp_max, 10):
if temp < self.temp_min:
continue
y_pos = self._temp_to_y(temp)
self.group.append(
Line(x + 35, y_pos, x + 40, y_pos, color=self.colors["tick_minor"])
)
# Freezing tick (32F) only if in range
if self.temp_min <= 32 <= self.temp_max:
freezing_y = self._temp_to_y(32)
self.group.append(
Line(x + 30, freezing_y, x + 40, freezing_y, color=self.colors["freezing_tick"])
)
# Celsius ticks (-10 to 35) filtered to range
for c_temp in (-10, 0, 10, 20, 30):
f_temp = self._c_to_f(c_temp)
if not (self.temp_min <= f_temp <= self.temp_max):
continue
y_pos = self._temp_to_y(f_temp)
color = self.colors["tick_c_zero"] if c_temp == 0 else self.colors["tick_c"]
self.group.append(Line(x + 60, y_pos, x + 65, y_pos, color=color))
for c_temp in (-5, 5, 15, 25, 35):
f_temp = self._c_to_f(c_temp)
if not (self.temp_min <= f_temp <= self.temp_max):
continue
y_pos = self._temp_to_y(f_temp)
self.group.append(Line(x + 60, y_pos, x + 65, y_pos, color=self.colors["tick_c"]))
def _build_labels(self, x):
if not self.tick_font:
return
# Fahrenheit labels (right-justified on the left side of the graphic)
start_major = int(math.ceil(self.temp_min / 10.0) * 10)
for temp in range(start_major, self.temp_max + 1, 10):
y_pos = self._temp_to_y(temp) - 4
self.group.append(
Label(
self.tick_font,
text=str(temp),
anchor_point=(1.0, 0.5),
anchored_position=(x + 20, y_pos),
color=self.colors["label_f"],
)
)
# Celsius labels (left-justified on the right side)
for c_temp in (-10, -5, 0, 5, 10, 15, 20, 25, 30, 35):
f_temp = self._c_to_f(c_temp)
if not (self.temp_min <= f_temp <= self.temp_max):
continue
y_pos = self._temp_to_y(f_temp) - 3
color = self.colors["tick_c_zero"] if c_temp == 0 else self.colors["label_c"]
self.group.append(
Label(
self.tick_font,
text=str(c_temp),
anchor_point=(0.0, 0.5),
anchored_position=(x + 70, y_pos),
color=color,
)
)
def _append_fills(self, temp, app_temp, *, placeholder):
actual_fill_x = self.anchor[0] + 42
apparent_fill_x = self.anchor[0] + 48
actual_height, actual_y = self._height_and_y(temp)
apparent_height, apparent_y = self._height_and_y(app_temp)
actual_radius = min(7, actual_height // 2) if actual_height > 0 else 0
app_radius = min(2, apparent_height // 2) if apparent_height > 0 else 0
actual_color = (
self.colors["fill_placeholder"] if placeholder else self.colors["fill_actual"]
)
app_color = (
self.colors["fill_placeholder"] if placeholder else self.colors["fill_apparent"]
)
actual_rect = RoundRect(
x=actual_fill_x,
y=actual_y,
width=15,
height=max(1, actual_height),
r=actual_radius,
fill=actual_color,
)
apparent_rect = RoundRect(
x=apparent_fill_x,
y=apparent_y,
width=4,
height=max(1, apparent_height),
r=app_radius,
fill=app_color,
)
self.group.append(actual_rect)
self.group.append(apparent_rect)
def _pop_fills(self):
if len(self.group) >= 2:
self.group.pop()
self.group.pop()
def _parse_temp(self, value, default):
try:
txt = str(value).replace("°F", "").replace("°", "").strip()
return float(txt)
except Exception:
return float(default)
def _height_and_y(self, temp):
delta = temp - self.temp_min
height = int(delta * self.px_per_degree)
y_pos = self.bottom_y - height
return height, y_pos
def _temp_to_y(self, temp_f):
delta = temp_f - self.temp_min
return int(self.bottom_y - delta * self.px_per_degree)
@staticmethod
def _c_to_f(temp_c):
return temp_c * 9 / 5 + 32
Create your settings.toml file
You will need to update the settings.toml file on your board (by default the CircuitPython installation adds an empty settings.toml file. The set-up process also gives you a chance to add in your wifi data so that may already be in your file.). You will need your WiFi credentials as well as an AdafruitIO userID and key. These are available free from the Adafruit website:Â Get Started with Adafruit IO | Welcome to Adafruit IO | Adafruit Learning System.
The items needed in your settings.toml file include:
CIRCUITPY_WIFI_SSID = "***Enter your wifi SSD here***" CIRCUITPY_WIFI_PASSWORD = "***Enter your wifi pawword here***" CIRCUITPY_WEB_API_PASSWORD="***Enter your password used to access your board on Web Workflow***" CIRCUITPY_WEB_API_PORT=80 AIO_USERNAME = "***Enter your AdafruitIO username***" AIO_KEY = "***Enter your AdafruitIO key***"
Note that in the above code you need to replace the starred placeholder information between the quotes with your own information. The settings.toml file needs to be saved in the root directory of your board.
On to code.py
I am going to go through code snippets to explain the process flow. The complete code for this project in included at the end of this article.Â
Set up the display
To set up the display we use:
displayio.release_displays() spi = board.SPI() cs = board.D15 dc = board.D32 display_bus = fourwire.FourWire(spi, command=dc, chip_select=cs, reset=None) display = ST7789(display_bus, rotation=180, width=135, height=240, rowstart=40, colstart=53)
Connect to WiFi and AdafruitIO
Next we run code to connect to WiFi and prepare to get the time from AdafruitIO to set the RTC.
aio_username = os.getenv('AIO_USERNAME')
aio_key = os.getenv('AIO_KEY')
wifi_ssid = os.getenv('CIRCUITPY_WIFI_SSID')
wifi_pw = os.getenv('CIRCUITPY_WIFI_PASSWORD')
timezone = os.getenv('TIMEZONE')
wifi.radio.connect(wifi_ssid, wifi_pw)
print("Connected as: ", wifi.radio.ipv4_address)
pool = adafruit_connection_manager.get_radio_socketpool(wifi.radio)
ssl_context = adafruit_connection_manager.get_radio_ssl_context(wifi.radio)
requests = adafruit_requests.Session(pool, ssl_context)
io = IO_HTTP(aio_username, aio_key, requests)
We start by getting our credentials from the settings.toml file and putting them into variables for easy access. Next we run commands to establish the WiFi connection and establish a connection to AdafruitIO.
Set the time
We call 'set_clock()' function to set the time, then call the 'get_time()' and 'get_date()' to confirm our settings. These are functions defined at the top of code.py after the import statements:
def set_clock():
try:
now = time.struct_time(io.receive_time(timezone))
r = rtc.RTC()
r.datetime = time.struct_time((now.tm_year, now.tm_mon, now.tm_mday, now.tm_hour, now.tm_min, now.tm_sec, 1, -1, -1))
except Exception as e:
print("Failed to set RTC: ", e)
def get_time():
r = rtc.RTC()
now = r.datetime
hour = now.tm_hour
period = "am"
if hour > 11:
period = "pm"
if hour > 12:
hour = hour - 12
if hour == 0:
hour = 12
return f"{hour:01d}:{now.tm_min:02d} {period}"
def get_date():
r = rtc.RTC()
now = r.datetime
return f"{now.tm_mon:1}/{now.tm_mday:2}/{now.tm_year}"
i2c = board.STEMMA_I2C() spa = SPA06_003.over_i2c(i2c) time.sleep(2) print(spa.temperature, c2f(spa.temperature), spa.pressure + ELE_CORR)
Note that we first have to set up the i2c bus which is simple with the STEMMA port. We then use the library to establish the device. I added a 2 second sleep to give the breakout time to stabilize. We then print out the current device readings. Since the SPA06-00 reports temperature in Celsius we need a conversion to Fahrenheit, hence another function at the top of the file:Â
def c2f(c):
return (c * 9/5) + 32
Note too that the SPA06-003 reports local atmospheric pressure whereas the common usage needs to convert to standard sea level. I have a constant at the top of the file 'ELE_CORR' = 11.2 which is the correction needed for my elevation above sea level. I found this factor with an internet search. Realistically there is a fairly complex calculation, but you can get a simple approximation which is what I am using. Be sure you are using the correct units (you want hPa).Â
Add the Display Elements:
Basically, there are three display elements - the background color (rectangle), the thermometer graphic and the rotating text at the bottom for time and readings.Â
First, we set up the display group then add the elements and define our fonts (you will need your own fonts and change the code to name the appropriately). Then we add a rectangle the display width and height. Next, we add the thermometer at the top and in the center of the display, and then the bottom text label centered. Once then element is created then they need to be appended to the splash group.Â
Finally, we use therm.update() to set the initial readings for the thermometer graphic. therm.update() is looking for two arguments - temperatures in °F. Since we only have one temperature (the output of the SPA06-003), we use it twice. Since the colors of both are the same (red) it appears on the graphic as a single reading.Â
splash = displayio.Group()
display.root_group = splash
display_background = Rect(0, 0, display.width, display.height, fill=0x000088)
splash.append(display_background)
font17 = bitmap_font.load_font("/fonts/Calibri-17.pcf")
font23 = bitmap_font.load_font("/fonts/Calibri-23.pcf")
dh = display.height
tw=display.width - 40
therm = Thermometer(
anchor=(20,5),
display=display,
tick_font=font17,
frame_height=display.height - 20,
frame_width=tw,
temp_min=50,
temp_max=90,
scale_margin_top = 10,
colors={
"bg": 0x000088,
"fill_apparent": 0xFF0000,
}
)
splash.append(therm.group)
bottom_label = label.Label(font23, text=f"{c2f(spa.temperature):.1f} °F", anchored_position = (display.width//2, 220), anchor_point = (0.5, 0.0))
splash.append(bottom_label)
therm.update(int(c2f(spa.temperature)),int(c2f(spa.temperature)))
The while loop
For the while loop we use a non-blocking approach with time.monotonic(). In the loop we do a couple of things:
- Every ten seconds (or whatever the UPDATE_INTERVAL is set to) we cycle through the rotating text at the bottom of the display
- If displaying the time or date, we get the current time and date from the RTC and update the display with the appropriate function.
- If displaying a temperature, we request the current temperature from the SPA06-003, update the text at the bottom as well as update the graphic value
- If displaying the pressure, we request the current pressure, adjust to sea level and update the text
- If we have gone through 400 cycles, we go out and reset the clock. At 10 second interval this is about an hour - there is no need to do this more often than that.Â
Further Refinements
Since we can show two different temperatures, one addition would be to get the outside temperature from the AdafruitIO weather API. Another improvement would be to redesign the layout and create a 3D printed case to make this a more finished project. What other ideas do you have?
Full Code
import time
import board
import rtc
import displayio
import os
import ssl
import fourwire
import wifi
import adafruit_requests
import adafruit_connection_manager
from adafruit_io.adafruit_io import IO_HTTP
from adafruit_st7789 import ST7789
from adafruit_bitmap_font import bitmap_font
from adafruit_display_text import label
from adafruit_display_shapes.rect import Rect
from thermometer import Thermometer
from adafruit_spa06_003 import SPA06_003
ELE_CORR = 11.2
UPDATE_INTERVAL = 10
def c2f(c):
return (c * 9/5) + 32
def set_clock():
try:
now = time.struct_time(io.receive_time(timezone))
r = rtc.RTC()
r.datetime = time.struct_time((now.tm_year, now.tm_mon, now.tm_mday, now.tm_hour, now.tm_min, now.tm_sec, 1, -1, -1))
except Exception as e:
print("Failed to set RTC: ", e)
def get_time():
r = rtc.RTC()
now = r.datetime
hour = now.tm_hour
period = "am"
if hour > 11:
period = "pm"
if hour > 12:
hour = hour - 12
if hour == 0:
hour = 12
return f"{hour:01d}:{now.tm_min:02d} {period}"
def get_date():
r = rtc.RTC()
now = r.datetime
return f"{now.tm_mon:1}/{now.tm_mday:2}/{now.tm_year}"
displayio.release_displays()
spi = board.SPI()
cs = board.D15
dc = board.D32
display_bus = fourwire.FourWire(spi, command=dc, chip_select=cs, reset=None)
display = ST7789(display_bus, rotation=180, width=135, height=240, rowstart=40, colstart=53)
aio_username = os.getenv('AIO_USERNAME')
aio_key = os.getenv('AIO_KEY')
wifi_ssid = os.getenv('CIRCUITPY_WIFI_SSID')
wifi_pw = os.getenv('CIRCUITPY_WIFI_PASSWORD')
timezone = os.getenv('TIMEZONE')
wifi.radio.connect(wifi_ssid, wifi_pw)
print("Connected as: ", wifi.radio.ipv4_address)
pool = adafruit_connection_manager.get_radio_socketpool(wifi.radio)
ssl_context = adafruit_connection_manager.get_radio_ssl_context(wifi.radio)
requests = adafruit_requests.Session(pool, ssl_context)
io = IO_HTTP(aio_username, aio_key, requests)
set_clock()
print(get_time(), " ", get_date())
i2c = board.STEMMA_I2C()
spa = SPA06_003.over_i2c(i2c)
time.sleep(2)
print(spa.temperature, c2f(spa.temperature), spa.pressure + ELE_CORR)
splash = displayio.Group()
display.root_group = splash
display_background = Rect(0, 0, display.width, display.height, fill=0x000088)
splash.append(display_background)
font17 = bitmap_font.load_font("/fonts/Calibri-17.pcf")
font23 = bitmap_font.load_font("/fonts/Calibri-23.pcf")
dh = display.height
tw=display.width - 40
therm = Thermometer(
anchor=(20,5),
display=display,
tick_font=font17,
frame_height=display.height - 20,
frame_width=tw,
temp_min=50,
temp_max=90,
scale_margin_top = 10,
colors={
"bg": 0x000088,
"fill_apparent": 0xFF0000,
}
)
splash.append(therm.group)
bottom_label = label.Label(font23, text=f"{c2f(spa.temperature):.1f} °F", anchored_position = (display.width//2, 220), anchor_point = (0.5, 0.0))
splash.append(bottom_label)
therm.update(int(c2f(spa.temperature)),int(c2f(spa.temperature)))
next_cycle = time.monotonic() + UPDATE_INTERVAL
time_cycle = time.monotonic() + UPDATE_INTERVAL * 400
cycle = 1
while True:
if time.monotonic() > time_cycle:
time_cycle = time.monotonic() + UPDATE_INTERVAL * 400
try:
set_clock()
except Exception as e:
print("Error setting time: ", e)
if cycle == 5:
cycle = 0
if time.monotonic() > next_cycle:
next_cycle = time.monotonic() + UPDATE_INTERVAL
cycle = cycle + 1
temp_c = None
pressure_hpa = None
if cycle in (3, 4, 5):
temp_c = spa.temperature
pressure_hpa = spa.pressure + ELE_CORR
if cycle == 1:
bottom_label.color = 0xFF88FF
bottom_label.text = get_time()
elif cycle == 2:
bottom_label.color = 0x55FF55
bottom_label.text = get_date()
elif cycle == 3:
bottom_label.color = 0xFFFFFF
t = c2f(temp_c)
ft = f"{t:.1f} °F"
therm.update(t,t)
bottom_label.text = ft
elif cycle == 4:
bottom_label.color = 0xFFFF00
ft = f"{temp_c:.1f} °C"
bottom_label.text = ft
elif cycle == 5:
bottom_label.color = 0x00FF00
bottom_label.text = f"{pressure_hpa:.1f} hPa"
else:
pass
time.sleep(.1)
This page (Newxie Digital to Analog Thermometer) was last updated on January 02, 2026.
Text editor powered by tinymce.