[HN Gopher] SSD1306 display drivers and font rendering
___________________________________________________________________
SSD1306 display drivers and font rendering
Author : todsacerdoti
Score : 45 points
Date : 2025-04-14 17:08 UTC (5 hours ago)
(HTM) web link (subalpinecircuits.com)
(TXT) w3m dump (subalpinecircuits.com)
| kaycebasques wrote:
| I really love the SSD1306 for its educational value. If you've
| bought a sensor kit for Arduino or ESP32 or Pico or whatever,
| chances are decent that you already have an SSD1306 lying around.
| There's so much example code for it. And the datasheet was pretty
| easy to grok IMO. My first exposure to it was in the pico-
| examples repo: https://github.com/raspberrypi/pico-
| examples/tree/master/i2c...
|
| There's a few Rust libraries for it, too. And it's supported in
| Wokwi! https://wokwi.com/projects/425067706980448257
| hadlock wrote:
| I love the SSD1306 simply because a simple arduino can drive it
| at ~150fps making for some _really_ smooth graphics. 1 bit per
| pixel monochrome OLED means it 's got a tiny frame-buffer, and
| you can drive it ridiculously fast especially over SPI. It's
| really great for stuff like realtime gauges etc.
| 4gotunameagain wrote:
| That's one of the biggest shaving the yak tangents I've seen.
|
| Love it.
| foldr wrote:
| It's generally quite easy to use these over I2C without a driver.
| You can crib the sequence of initialization commands from the
| example code supplied by the manufacturer (or loads of examples
| on GitHub), and then the commands to draw to the screen are
| pretty straightforward. The chip has its own display RAM, so you
| don't need to worry about redrawing every time the display
| refreshes or anything as low-level as that.
| grmnygrmny2 wrote:
| Interesting! That could be good way to boost the speeds here
| for sure, as I'm still pushing out a full framebuffer out with
| every update and am not usually updating the whole screen.
| arghwhat wrote:
| Go for the SPI version, which is the same chip but just s
| different breakout board.
|
| Many ESP32's can only do 400kHz I2C, whereas their SPI peripheral
| can often do 80 MHz or more (although you wouldn't want to go
| _that_ fast here). 400kHz sort of works, but if you also want to
| handle other I2C devices it can easily become a problem.
| grmnygrmny2 wrote:
| (author here) I've been pondering this, yeah. I'm currently
| sharing the I2C bus with a DAC and that's working alright, but
| the refresh rate issue is enough to make me consider SPI. I
| know the SPI peripheral supports DMA as well, and the I2C one
| doesn't (sort of? I know there's "async" transmit now but can't
| tell if that's really doing DMA)
| arghwhat wrote:
| The I2C peripheral is DMA - a write just queues an operation
| descriptor in a hardware FIFO, and interrupts fire whenever
| something exciting happens or the FIFO is drained. The
| synchronous implementation is just blocking on a condition
| set by the interrupt handler.
|
| But this is exactly the kind of thing the SPI peripheral is
| meant for. This cannot be said for the I2C peripheral, with
| its measly fast mode support.
|
| Depending on the chip and your usecase, you might also want
| to use I2S for your DAC.
| grmnygrmny2 wrote:
| Ah! That makes sense, thanks!
|
| And yes, the audio data runs over I2S - the chip I'm using
| just uses I2C for control.
| generj wrote:
| I2C is nice because it is (with Adafruit and Sparkfun's Stemma
| QT/Qwiik) literally plug and play for beginners, with a wide
| variety of sensors available.
|
| Plus not needing to dedicate a control pin per device added to
| the bus. Though of course if data throughout is an issue SPI is
| better than I2C.
| arghwhat wrote:
| I2C is fine for sensors and other low-bandwidth devices, but
| inappropriate for displays and other high-bandwidth devices.
|
| When used with those kits, you'd use the QWIIC/whatever
| connector for all the sensors and other low-bandwidth things
| like I2C is meant for, while the display would be connected
| with SPI.
|
| (I2C isn't more plug and play than SPI though, and a
| preterminated plug shouldn't be a big deal.)
| hadlock wrote:
| If you're going to do I2C just get an LCD display. This OLED
| can be driven at 150fps by simple devices like an ardunio
| which is where it really shines - super crisp, high contrast,
| smoove as buttah graphics for realtime readouts etc. OLED
| over SPI is really visually impressive stuff and effectively
| 0 latency. Using the SSD1306 for static displays over I2C is
| almost a crime.
| generj wrote:
| This display is the modern 16x2 display for hardware hackers:
| cheap and versatile.
|
| One of my favorite hacks is running this display over HDMI [0].
|
| Note that it's possible to refresh it at higher rates by using
| partial refreshes. Or even higher to 150 fps [1].
|
| [0] https://hackaday.com/2022/04/01/making-your-own-
| technically-...
|
| [1] https://hackaday.com/2018/05/08/push-it-to-the-limit-
| ssd1306...
| analog31 wrote:
| I switched from 16x2 to SSD1306 because the latter runs on 3.3
| V, and is thus more friendly to battery power.
| mikeInAlaska wrote:
| Here's a rust version i made with bitmapped fonts for both i2c
| and SPI https://github.com/scopenews/minimalSSD1306driver/ I was
| running this on my pi as a demo.
|
| I normally work with C++ on esp32 for these little displays, and
| in there I use a screen buffer for partial refreshes which makes
| them very fast !!
| grmnygrmny2 wrote:
| That's very cool - I definitely gotta work on adding partial
| refreshes. Thanks for sharing!
| Graziano_M wrote:
| To embed a binary in esp-idf I believe you need something like:
| create_resources(${CMAKE_CURRENT_LIST_DIR}/../../binaries/RAM_APP
| ${CMAKE_BINARY_DIR}/binaries.c) set_property(SOURCE
| ${CMAKE_BINARY_DIR}/binaries.c PROPERTY GENERATED 1)
|
| Or using `EMBED_FILES`
|
| I just happened to be looking at this very thing today that had
| to do this: https://github.com/espressif/esp-serial-
| flasher/blob/master/...
| grmnygrmny2 wrote:
| Amazing! Thank you!
| qwe----3 wrote:
| The SH1106 (1.3 inch) is a better option now. You can get them
| for 1.50$ on aliexpress sometimes
| atVelocet wrote:
| There is also https://github.com/pioarduino/platform-espressif32
| which allows one to use _Arduino > 3.2_ and _IDF > 5.4_. If you
| use _PlatformIO_ put this into your _platformio.ini_
| [espressif32] ; PLATFORM platform = espressif32
| board_build.embed_txtfiles = folder/file.ext ; embed null-
| terminated file(s)
|
| Also have a look at
| https://docs.platformio.org/en/latest/platforms/espressif32.....
| peteforde wrote:
| I really love the u8g2 library, but unfortunately I love my
| SSD1327 OLED even more. It supports 16-tone greyscale (which u8g2
| cannot do) allowing 80s/90s video game style image dithering.
|
| Getting up and running with lvgl was honestly kind of brutal, but
| now that it's done, I am generally happy with it. As you
| determined, it's much more of a UI toolkit than u8g2; the sort of
| thing designed with fancy thermostats and smart watches in mind.
| u8g2 has a menu toolkit but it is pretty narrow in scope.
|
| I am planning on releasing a bare bones IDF-SDK v5.4 + lvgl 9.x +
| SSD1327 starter project soon so that I can hopefully save future
| travelers some pain.
| kevin_thibedeau wrote:
| LVGL works better on slow displays with internal video memory if
| you minimize the vertical height of widgets. That allows the
| library to update smaller strips of the display as widgets are
| redrawn.
| bmink wrote:
| I'm actually working on code for esp-idf / SSD1309 right now, a
| little bigger than the 1306. I went through a similar arc as OP.
|
| I was actually surprised / disappointed by the poor quality of
| the drivers out there. If you instrument and log the bytes u8g2
| sends to the device and how the buffer is sent, you see it's
| pretty messy, inefficient and hacky. Seems like everyone
| copy+pasting everyone else's code, without understanding fully.
|
| So in the end I just decided to draw into a local buffer and then
| send that buffer in one single transaction to the display.
|
| Once you figure out the data sheet it's actually very easy to
| program these displays. For example, to test any SSDxxxx display,
| you need to send all of two bytes: 0xaf (display on), 0xa5 (all
| pixels on)
|
| I am now looking at SSD1322, which is both grayscale and has
| enough internal RAM for two buffers for even smoother drawing
| (write into a non-displayed region of the RAM and then change the
| display offset)
| grmnygrmny2 wrote:
| I discovered the same thing with u8g2, and digging through the
| abstraction layers it felt like improving it was going to be
| impossible. Sending a single transaction with a framebuffer is
| so much simpler and faster.
|
| SSD1322 looks great and might be something I look at for the
| future..
| userbinator wrote:
| It's worth noting that the controllers for these small displays
| and their instruction sets have a common lineage that goes back
| to the 90s --- the SSD1306's looks very much like the Epson
| S1D15300 series, for example. From a quick search, other
| controllers with a similar instruction set are ST7565 and UC1601.
___________________________________________________________________
(page generated 2025-04-14 23:00 UTC)