Font size increase for OLED Display Module SSD1306

guys,
is there an easy way to increase the font size on the OLED display? Have pity on those that are getting old, or wear glasses. Or both. Please.

I’ve got the temperature readings working, but try to read the displays a little awkward.

Cheers,
Allan H

4 Likes

Update

A superb and flexible solution is presented later in this thread. Jump to the reply.


Hi @Allan153090 - this is something that’s bugged me for a while and would really increase PiicoDev’s accessibility.

In short - truly variable font sizes are kinda… hard - but it should be pretty straightforward to deploy an integer scaling to the font, ie. double or triple the size. Hopefully, that level of functionality is enough for most makers’ needs.

We’ll hit this today and I’ll update you here with our progress.

4 Likes

Ok so my initial enthusiasm has been nipped a bit - our PiicoDev OLED class depends on a built-in framebuffer for Pico which has a fixed font size (see image). This may take a little longer than anticipated.

This is definitely something that has come up in the MicroPython project before, see this GitHub issue.

@James46717 has done some great projects with the PiicoDev OLED where they drive the display with a custom image file for each number displayed. See their relay timer project.

Obviously, it would be preferred to scale the font internally, but that’s something that is beyond MicroPyton at the moment. I’ll continue digging and see if we can work something out internally.

6 Likes

Thank you for having a look at the problem. The searching I did last night didn’t turn up an easy solution. Twice the size should be fine.

It’s a little time-consuming, but the only practical approach I could think of was to define a function that returned a bitmap for each digit. And then (for example) parse a temperature reading (e.g. 23.4) into three individual function calls to return the bitmaps in order. Plus fiddling with the decimal place and append degrees Celsius on the end. Add then positioning on the screen.

Which is not a particularly elegant or general approach. Given that I only need indoor and outdoor temperatures here in Adelaide (post-climate change apocalypse say -10°C to +50°C) it will do the job.

Can you think of any simpler workarounds for my particular use case?

Cheers,
Allan H.

3 Likes

Simpler? Not really… You would have to hand-make the framebuffer like we do for the micro:bit or RPi
The following is the text method we use for micro:bit / pi. It loads the font file and draws the characters. You would have to redefine the framebuffer for Pico (assuming you’re using that) and add a size argument to this method. You can see that everything is working in blocks of 8. This is what would be scaled by the size parameter.
This is what I was initially going to try, before I rediscovered that the Pico’s framebuf class is pre-baked by MicroPython.

def text(self, text, x, y, c=1):
    fontFile = open("font-pet-me-128.dat", "rb")
    font = bytearray(fontFile.read())
    for text_index in range(0, len(text)):
         ind = 0
         for col in range(8):
            fontDataPixelValues = font[(ord(text[text_index])-32)*8 + col]
            #ind = text_index * 8 + x * 8 + y * 128 + col
            for i in range(0,7):
                if fontDataPixelValues & 1 << i != 0:
                    x_coordinate = x + col + text_index * 8
                    y_coordinate = y+i
                    if x_coordinate < WIDTH and y_coordinate < HEIGHT:
                        self.pixel(x_coordinate, y_coordinate, c)
4 Likes

bear with me while I familiarise myself with how a bitmap is displayed…

2 Likes

turns out I know nothing about libraries either. Google found the following link

Can any aspect of the adafruit arduino ssd1306 library approach be adopted?

1 Like

Adafruit use the same idea discussed above - scaling the font in integer multiples. The library linked is compiled for Arduino which means it doesn’t have the same challenges we face for unifying functionality for Pico, RPi, micro:bit (and others in the future!)

You could definitely achieve this, it would require dropping the MicroPython framebuf class used in PiicoDev_SSD1306.py and making your own. Not exactly for the faint-hearted but it’s what’s outlined in my previous reply.

3 Likes

Michael,
thank you very much for going to the trouble of detailing than explanation above. I’m currently looking at “PiicoDev_SSD1306.py” (… “Ported by Peter Johnston at Core Electronics October 2021…”) from James46717 via Simple Relay Timer - Tutorial Australia.

I didn’t realise the inner workings of the frame buffer was such a pain.

I think the key though is your last statement “challenges we face for unifying functionality…”. That’s the really hard bit. All I can say is, keep up the good work!

As for my specific use case - I might put that challenge on hold for the moment.

Cheers,
Allan H

3 Likes

I’m very keen to see what could be achieved by manipulating bitmaps programatically. Of course, the challenge would be to maintain cross-platform compatibility.

An alternative is the Adafruit PiOLED HAT for RPi which allows custom fonts and text sizes out of the box. Not sure if it could be made to work alongside my Piicodev setup as the Piicodev adapter occupies my GPIO.

3 Likes

Stephen,
I had a look at the enormous amount of coding required as per Usage | Adafruit PiOLED - 128x32 Mini OLED for Raspberry Pi | Adafruit Learning System and put it in the too hard basket for the moment.

That’s the really nice thing about the Core Piicodev system - most of that complexity is hidden. It just works.

ALH

That’s the really nice thing about the Core Piicodev system - most of that complexity is hidden. It just works.

Completely agree. You can get your code done super-quick.

To prove that it is possible there is:

which is a working example. Which recommends:

ALH

2 Likes

The limitation of small font size was raised last January and it seems has not been solved. At the time the only solution I could see was to load graphic images. These are 128 x 64 pixel Portable Bitmap Image (PBM) files. If you only wanted say the numbers 0 - 9 it would be feasible to load one of ten PBM files created in Photoshop. But if you wanted a signed temperature in deg celsius this method obviously fails. To illustrate I have a test.pbm file but it will not upload. To create a PBM file on demand you would need the netpbmfile python library

but this is hardly an efficient or elegant solution.
I am presently using the OLED display in a weather station. It is also useful for displaying results when prototyping. It would be really nice to have a display which was not such a strain on the eyes. Is there any other hardware available?

1 Like

Hey Allan,

What kind of characters were you looking to display? Some rudimentary numbers should be easy to put together using lines and arcs.
@James46717 has some really interesting code in this topic: Pi Pico Smart Watering System Controller - #4 by James46717

While the excellent team at Core look at getting fonts larger it might be a good place to start!

1 Like

Liam,
Michael has flagged the work that @James46717 work in this area. It’s taken me two days to do some reading and get my head around all the information in the posts above.

Summing up where we are so far (refer to posts above for Michael’s technical descriptions):

  1. The problem (as Michael pointed out earlier) is that in the micropython SSD1306 display implementation, text is limited to 8 x 8 pixels. (framebuf — frame buffer manipulation — MicroPython 1.18 documentation)

  2. Use case: Require temperature and humidity display in a larger font. Say -10.0 °C to +50.0 °C and 10% to 90% RH. Just need numbers (0-9) and some symbols (+,-,.,°C, %RH) . A total of 15 characters distinct required.

  3. Jim’s code displays a larger font by parsing the required string into individual characters. It then manually constructs each character using the requisite number of lines (micropython primitives).

Key element of Jim’s code (paraphrased) (Broad description which omits the offsets required to correctly position the character on the display). Which is something I can work with.

image

  1. What I had in mind was a process of fiddling with the pixels in the frame buffer. Is it possible to could convert a letter in a particular font to a (say) 16 x 16 bit-map / set of pixels. And then “place/overlay” the pixels/bits In the appropriate locations in the frame buffer (/memory locations),?

Or to borrow and reinterpret Michael’s description “hand make the frame buffer” ?

image

rinse and repeat until entire string has the appropriate pixels fiddled. And then display the frame buffer.

It’s got a very simplistic appeal. But forget any ideas of making this approach general or suitable for a wide range of platforms or displays. Strictly a one-off for a SSD1306 controller and a 128 x 64 display.

Any ideas anyone? Is this vaguely possible? Or am I just being cheerfully optimistic out of ignorance? Happy to accept advice from someone who knows what they’re doing. Although I suspect I know what the answer is…

  1. At this stage, the most practical approach is to follow that in item # 3. I’ll let everyone know how it goes . Nothing happens quickly around here.

ALH

1 Like

Hi Allan,

With a combo of James’s work, a bit of your time and the arc and circle functions (linked below), you should be able to collapse the functions used and add some of the basic characters. (having it scale nicely might be a bit harder)

Definitely - the FrameBuffer.pixel(x, y[, c]) command lets you set a single pixels value to on or off. A tool like this should speed things up!

Code for arcs and circles:

Documentation: GitHub - CoreElectronics/CE-PiicoDev-SSD1306-MicroPython-Module: CE-PiicoDev-SSD1306-MicroPython-Module

1 Like

A few years back I used this OLED: https://www.waveshare.com/wiki/0.96inch_OLED_(A)
It is based on SSD1306. I installed the necessary arduino library from the wiki page.

I used the following function to make the text size smaller or bigger:
static void SSD1331_char(unsigned char x, unsigned char y, char acsii, char size, char mode, unsigned short hwColor)
My tutorial is in my native language but the photos and code may help you understand how I did it.
https://blog.techshopbd.com/tds-মিটার/

2 Likes

Hey everyone! We featured this forum topic in this week’s episode of The Factory - our fortnightly engineering catchup.

There’s some great ideas being thrown around for case-specific solutions. I’ve seen projects where people define numbers out of drawn lines, or use the .blit() method to overlay bitmap images.
I think the most accessible solution for the most people is the Pull Request that we discuss in the video. It should be pretty trivial to support font scaling within the framebuf class natively. If you’d like to see this feature get implemented into MicroPython then perhaps add your support to the PR - its a pretty simple one and perhaps just hasn’t garnered enough attention.


With all that being said, this is still an open source project - your ideas and code contributions are welcome! If you think you’ve come up with something that makes PiicoDev even just a little :pinching_hand: bit better then open an issue or PR on the GitHub repo!

4 Likes

Looks like I’m going to be busy for the next few weekends…

1 Like