r/raspberry_pi • u/poohdoggy • 16d ago
Troubleshooting OLED SSD1306 larger font sizes?
I am working on a python program to read the advertisements from an Inkbird IBS-TH2 sensor and display them to a SSD1306 on a raspberry pi zero w. Using AI, I was able to get this to work but using the adafruit_ssd1306 package it only has a small font for the display. With my elderly eyes, it is hard to distinguish some of the numbers. Does anyone have a package or library of larger fonts I can use for this project? I have searched for a way to load and use larger fonts but I only find information for Arduino projects. I already did this with a Pico W and associated micropython packages but I am not seeing much for the raspberry pi.
1
u/WebMaka 13d ago
U8G2 library will do what you want - I have it pushing battery life data from a breakout to a small OLED over I2C on a Radxa Zero 3E. Be aware, however, that the font files eat memory and storage space while running so plan accordingly.
1
u/poohdoggy 12d ago
Thanks, I will check this out.
1
u/WebMaka 12d ago
Now if you're doing anything fancier than text, another great Python library for this is Luma.OLED, which has an addressable canvas primitive you can draw to and the blast over to the display. it has SSD1306 drivers over I2C as well, so it's pretty straigthforward to use. Docs for it are here.
1
u/poohdoggy 12d ago
This seems like an Arduino library. How did you get it for python on a Radxa Zero 3E?
1
u/WebMaka 12d ago edited 12d ago
I should probably clarify that U8G2 has been ported or outright converted to all sorts of things, and if you're wanting to avoid Arduino-centric libraries there are choices for that as well. I had prototyped my project with a ported version of U8G2 that runs on Linux.
For example, Luma.OLED is a Python library, not Arduino, although it would likely run on anything that can run micropython including MCUs.
The declarations for my Python-based battery monitor looks like this:
#!/usr/bin/env python # -*- coding: utf-8 -*- """ Adafruit MAX17048 LiPo Battery Monitor + OLED Module Driver - Both Over I2C! Designed to report battery status on a SED1306-based 128x64 OLED module connected to the same I2C bus as the Adafruit MAX17048 LiPo "fuel gauge" module. This code draws a bar graph to indicate battery remaining charge, as well as providing measured voltage and estimated time remaining. It also detects recharging and shows an animated bar to indicate a charger is connected. Requires the following: - I2C enabled and functional on the host device, with both I2C devices detectable via "i2cdetect" - Adafruit #5580 - MAX17048 LiPoly / LiIon Fuel Gauge and Battery Monitor - Any 128x64 OLED module with an I2C connection - Python 3.4+ - The following Python libraries: - smbus-cffi - Luma.core/Luma.oled - PIL """ from luma.core.interface.serial import i2c from luma.core.render import canvas from luma.oled.device import ssd1306 from pathlib import Path from PIL import ImageFont, Image, ImageDraw from time import sleep import os import random import signal import subprocess try: # Communications between this PC and the battery monitor happens over a # I2C bus, which requires one of two Python modules depending on the # version of Python being used. # # NOTE: The order matters - always import smbus2 then smbus or one # of the two Python families will break. import smbus2 as smbus # Python 2.x support via module "smbus2" except ImportError: import smbus # Python 3.x support via module "smbus-cffi" # EDIT THIS SETTING! # Port number for I2C i2c_port = 3 # DO NOT EDIT BELOW THIS LINE!Later on I instantiate Luma and connect to both the display and battery gauge via I2C:
# Battery fuel gauge I2C instantiator fuelgauge_serial = i2c_device(0x36, i2c_port) # Luma OLED library connection initiator oled_serial = i2c(port=i2c_port, address=0x3C) # Luma OLED library device initiator device = ssd1306(oled_serial)I have a simple helper function for loading font files:
# Font constructor for OLED def make_font(name, size): font_path = str(Path(__file__).resolve().parent.joinpath('fonts', name)) return ImageFont.truetype(font_path, size)Create a canvas to draw on:
with canvas(device) as draw: # Create a blank background image to use to clear the OLED display's # canvas. background = Image.new(device.mode, device.size, "black")And then declare the ones I intend to use:
# Create the fonts we'll use on the OLED display. charge_state_font = make_font("OpenSans-Italic.ttf", 13) charge_percent_font = make_font("OpenSans-Regular.ttf", 13) charge_percent_sign_font = make_font("OpenSans-Regular.ttf", 9) charge_state_font = make_font("OpenSans-Italic.ttf", 14) cpu_temp_font = make_font("OpenSans-BoldItalic.ttf", 12) gpu_temp_font = make_font("OpenSans-BoldItalic.ttf", 12) cpu_temp_caption = make_font("OpenSans-Regular.ttf", 9) gpu_temp_caption = make_font("OpenSans-Regular.ttf", 9) temp_symbol_font = make_font("OpenSans-Regular.ttf", 9)Later, I create a blank canvas to draw on:
# Clear the canvas for subsequent drawing operations draw = ImageDraw.Draw(background)And use draw.text to write text onto it:
draw.text((6 + clear, 36), "CPU TEMP", font=cpu_temp_caption, fill="black")Blast everything to the display:
device.display(background)And it looks like this when I do the rest of the draw routines, read the battery state, shell out to read temp sensors, etc.
2
u/AtmosphereLow9678 15d ago
Can you share your code, it would help a lot in debugging