Font size increase for OLED Display Module SSD1306

Hey Allan,

Just wanted to touch base really quickly - where were you up to with this?(the thought of doing this work twice would be painful)
I’ve got a project where I would also like to use some larger numbers and thought of spinning up a could of small functions to draw specific characters like you requested:

I’ll keep you posted :smiley:

Bumping the topic: while the excellent team at Core works on a cleaner implementation I’ve botched together something that allows for scaling much like parametric CAD.

2 Likes

Thanks very much putting that code together. After a bit of thought, I’m more inclined to work with…

I have no idea how font files work, but I can easily generate text files like the following (for example) “5.DAT”
image

If I have a temperature (say) “+12.34C” I can:

FOR each line
FOR each characters in the string,
call up the appropriate character “.DAT” file and
FOR each line/column in the DAT file, with the appropriate character offset, set the relevant pixels in the frame buffer.
RINSE and REPEAT

[incidentally, How do you indent text in this forum?]

The key element is:

Not too fussed about the speed because it’s a temperature reading which should be varying only slowly (in my case anyway), and we do a screen update only when the entire process is finished. Not particularly elegant either, but it’s simple. Fault finding is relatively straightforward. And updates/correction/alternatives to the font/DAT files can be done with a text editor. Or in my case an Excel spreadsheet using conditional formatting to manually construct DAT file source data for each character.

The hold-up is that I have no idea how to open a file and read the data in micro-python. And zero experience using a Pi . I’m working on it.

In the meantime, if someone wants to put some code together, I’m quite happy to generate the DAT files…

Cheers,
ALH

1 Like

Hi Allan,

The blit method (mentioned in the Factory) more or less does the overlaying method, though is only included in framebuf.

In Micropython the font is stored as a long hex array: https://github.com/micropython/micropython/blob/master/extmod/font_petme128_8x8.h
This tool lets you build, visualise and text hex strings: LED Matrix Tool

Though the underlying code isn’t there to scale and load the fonts.

Id definitely check out a guide on using file readers, the Makerverse micro SD adapter. Makerverse Micro SD Adapter - MicroPython Guide and Data Logging - Tutorial Australia

I’m not entirely certain that its possible, the forum’s text input uses markdown so you can bullet items with - or * but screenshots are probably easier (or comment them like code with ``` at the start and end

Thanks of those links. This may take a while. Now might be a good time to learn some basic linux skills.
ALH

An interesting discussion.
The bitmap and line drawing methods I used are very limited, but they resulted in a quick solution and low memory usage. When I first started I wanted to develop a font driver, the ability to use existing font files to display characters. I soon found it was beyond my programming skills.

The RPi Pico has a limited memory which is already half used by Micro Python. Adafruits version takes up even more memory space. The RP2040 can support up to 16MB of off chip memory, the Pico has only 2MB. Price, space consideration ??? If version 2 of the Pico is ever produced I would like to see it with the full 16MB.

The PiicoDev OLED module is a great product, I have yet to use it on anything other than the Pico. I am pretty sure a RPi Zero 2 would be able to run scalable fonts. I have done this with an Adafruit OLED and their drivers.

An alternative using the Pico would be to throwaway Micropython and use the Arduino IDE to develop C++ code. I soon gave up this idea because Thonny and Micropython are just too easy to use.

Some thoughts.
Cheers
Jim

1 Like

I guess this has not really progressed with a solution after noting the date of the last post.

I have just purchased the SSD1306 & BME280 and it was so simple with a few lines to get the display showing the temp and humidity.

Not exactly sure on how to do a PR, but will figure it out. Not confident that it would make any difference though.

Love the PiicoDev system.

2 Likes

Hi David,

There were some strides on this subject. If you check out some of James’s projects a bitmap method was used from memory.

I think the topic fizzled out since there were lots of ideas but none seemed to be super scalable or were too project specific.

128x64 isn’t also a lot of pixels to play with, Pimoroni have a better implementation but they also use much larger displays in most of their products. i.e. the Badger

1 Like

I developed a library that produces 3 lines of 8 characters, easy to read from a distance.
It simply uses line drawing to make the characters. The library draws upper case, numeric and a few special characters. I have used it successfully in a number of projects.

Include these files.
Modified PiicoDev Library. PiicoDev_SSD1306_Large.py

##################################################################################################
# Modified from git hub library used by SSD1306_Large Text routines ****
##################################################################################################
# Sends data to the Core Electronics PiicoDev OLED SSD1306 Display
# Ported by Peter Johnston at Core Electronics October 2021
# Original Repos:
# 2021-09-12:
# https://github.com/micropython/micropython/blob/master/drivers/display/ssd1306.py
# 2021-08-01:
# https://github.com/fizban99/microbit_ssd1306/blob/master/ssd1306_text.py
# 2021-07-15:
# https://github.com/adafruit/Adafruit_Python_SSD1306/blob/master/Adafruit_SSD1306/SSD1306.py

# 2021 OCT 14 - Initial release
# 2022 JAN 04 - Remove dependency on PIL module.  Improve compatibility with pbm files.

# 2022 FEB 26 - Removed MicroBit and Linux routines to make smaller file

_SET_CONTRAST = 0x81
_SET_ENTIRE_ON = 0xA4
_SET_NORM_INV = 0xA6
_SET_DISP = 0xAE
_SET_MEM_ADDR = 0x20
_SET_COL_ADDR = 0x21
_SET_PAGE_ADDR = 0x22
_SET_DISP_START_LINE = 0x40
_SET_SEG_REMAP = 0xA0
_SET_MUX_RATIO = 0xA8
_SET_IREF_SELECT = 0xAD
_SET_COM_OUT_DIR = 0xC0
_SET_DISP_OFFSET = 0xD3
_SET_COM_PIN_CFG = 0xDA
_SET_DISP_CLK_DIV = 0xD5
_SET_PRECHARGE = 0xD9
_SET_VCOM_DESEL = 0xDB
_SET_CHARGE_PUMP = 0x8D
WIDTH = 128
HEIGHT = 64

from PiicoDev_Unified import *
from math import cos,sin,radians
import framebuf
    
class PiicoDev_SSD1306(framebuf.FrameBuffer):
    def init_display(self):
        self.width = WIDTH
        self.height = HEIGHT
        self.pages = HEIGHT // 8
        self.buffer = bytearray(self.pages * WIDTH)
        for cmd in (
            _SET_DISP,  # display off
            # address setting
            _SET_MEM_ADDR,
            0x00,  # horizontal
            # resolution and layout
            _SET_DISP_START_LINE,  # start at line 0
            _SET_SEG_REMAP | 0x01,  # column addr 127 mapped to SEG0
            _SET_MUX_RATIO,
            HEIGHT - 1,
            _SET_COM_OUT_DIR | 0x08,  # scan from COM[N] to COM0
            _SET_DISP_OFFSET,
            0x00,
            _SET_COM_PIN_CFG,
            0x12,
            # timing and driving scheme
            _SET_DISP_CLK_DIV,
            0x80,
            _SET_PRECHARGE,
            0xF1,
            _SET_VCOM_DESEL,
            0x30,  # 0.83*Vcc
            # display
            _SET_CONTRAST,
            0xFF,# maximum
            _SET_ENTIRE_ON,  # output follows RAM contents
            _SET_NORM_INV,  # not inverted
            _SET_IREF_SELECT,
            0x30,  # enable internal IREF during display on
            # charge pump
            _SET_CHARGE_PUMP,
            0x14,
            _SET_DISP | 0x01,  # display on
        ):  # on
            self.write_cmd(cmd)

    def poweroff(self):
        self.write_cmd(_SET_DISP)

    def poweron(self):
        self.write_cmd(_SET_DISP | 0x01)

    def setContrast(self, contrast):
        self.write_cmd(_SET_CONTRAST)
        self.write_cmd(contrast)

    def invert(self, invert):
        self.write_cmd(_SET_NORM_INV | (invert & 1))

    def rotate(self, rotate):
        self.write_cmd(_SET_COM_OUT_DIR | ((rotate & 1) << 3))
        self.write_cmd(_SET_SEG_REMAP | (rotate & 1))

    def show(self):
        x0 = 0
        x1 = WIDTH - 1
        self.write_cmd(_SET_COL_ADDR)
        self.write_cmd(x0)
        self.write_cmd(x1)
        self.write_cmd(_SET_PAGE_ADDR)
        self.write_cmd(0)
        self.write_cmd(self.pages - 1)
        self.write_data(self.buffer)
        
    def write_cmd(self, cmd):
        try:
            self.i2c.writeto_mem(self.addr, int.from_bytes(b'\x80','big'), bytes([cmd]))
            self.comms_err = False
        except:
            print(i2c_err_str.format(self.addr))
            self.comms_err = True
            
    def write_data(self, buf):
        try:
            self.write_list[1] = buf
            self.i2c.writeto_mem(self.addr, int.from_bytes(self.write_list[0],'big'), self.write_list[1])
            self.comms_err = False
        except:
            print(i2c_err_str.format(self.addr))
            self.comms_err = True
            
    def circ(self,x,y,r,t=1,c=1):
        for i in range(x-r,x+r+1):
            for j in range(y-r,y+r+1):
                if t==1:
                    if((i-x)**2 + (j-y)**2 < r**2):
                        self.pixel(i,j,1)
                else:
                    if((i-x)**2 + (j-y)**2 < r**2) and ((i-x)**2 + (j-y)**2 >= (r-r*t-1)**2):
                        self.pixel(i,j,c)
                   
    def arc(self,x,y,r,stAng,enAng,t=0,c=1):
        for i in range(r*(1-t)-1,r):
            for ta in range(stAng,enAng,1):
                X = int(i*cos(radians(ta))+ x)
                Y = int(i*sin(radians(ta))+ y)
                self.pixel(X,Y,c)
            
    def load_pbm(self, filename, c):
        with open(filename, 'rb') as f:
            line = f.readline()
            if line.startswith(b'P4') is False:
                print('Not a valid pbm P4 file')
                return
            line = f.readline()
            while line.startswith(b'#') is True:
                line = f.readline()
            data_piicodev = bytearray(f.read())
        for byte in range(WIDTH // 8 * HEIGHT):
            for bit in range(8):
                if data_piicodev[byte] & 1 << bit != 0:
                    x_coordinate = ((8-bit) + (byte * 8)) % WIDTH
                    y_coordinate = byte * 8 // WIDTH
                    if x_coordinate < WIDTH and y_coordinate < HEIGHT:
                        self.pixel(x_coordinate, y_coordinate, c)
                        
    class graph2D:
        def __init__(self, originX = 0, originY = HEIGHT-1, width = WIDTH, height = HEIGHT, minValue=0, maxValue=255, c = 1, bars = False):
            self.minValue = minValue
            self.maxValue = maxValue
            self.originX = originX
            self.originY = originY
            self.width = width
            self.height = height
            self.c = c
            self.m = (1-height)/(maxValue-minValue)
            self.offset = originY-self.m*minValue
            self.bars = bars
            self.data = []

    def updateGraph2D(self, graph, value):
        graph.data.insert(0,value)
        if len(graph.data) > graph.width:
            graph.data.pop()
        x = graph.originX+graph.width-1
        m = graph.c
        for value in graph.data:
            y = round(graph.m*value + graph.offset)
            if graph.bars == True:
                for idx in range(y, graph.originY+1):
                    if x >= graph.originX and x < graph.originX+graph.width and idx <= graph.originY and idx > graph.originY-graph.height:
                        self.pixel(x,idx, m)
            else:
                if x >= graph.originX and x < graph.originX+graph.width and y <= graph.originY and y > graph.originY-graph.height:
                    self.pixel(x,y, m)
            x -= 1

class PiicoDev_SSD1306_MicroPython(PiicoDev_SSD1306):
    def __init__(self, bus=None, freq=None, sda=None, scl=None, addr=0x3C):
        self.i2c = create_unified_i2c(bus=bus, freq=freq, sda=sda, scl=scl)
        self.addr = addr
        self.temp = bytearray(2)
        self.write_list = [b'\x40', None]  # Co=0, D/C#=1
        self.init_display()
        super().__init__(self.buffer, WIDTH, HEIGHT, framebuf.MONO_VLSB)
        self.fill(0)
        self.show()
        
def create_PiicoDev_SSD1306(addr=0x3C,bus=None, freq=None, sda=None, scl=None):
    return PiicoDev_SSD1306_MicroPython(addr=addr, bus=bus, freq=freq, sda=sda, scl=scl)

Library to draw characters SSD1306_Large.py

################################
# Large Font on SSD1306 OLED
#
# 3 lines of 8 characters each
################################

from PiicoDev_SSD1306_Large import *

class SSD1306_8x3():
    def __init__(self):
        self.oled = create_PiicoDev_SSD1306()

    def display(self, text, p):
#        print(posArray[0][0])
        for i in range (len(text)):
            x=p[i][0]
            y=p[i][1]
            if text[i]=="A" or text[i]=="a":
                self.oled.line(x+1,y+15,x+5,y+1,1)
                self.oled.line(x+5,y+1,x+10,y+15,1)
                self.oled.line(x+3,y+11,x+8,y+11,1)
            elif text[i]=="B" or text[i]=="b":
                self.oled.line(x+1,y+15,x+1,y+1,1)
                self.oled.line(x+1,y+1,x+6,y+1,1)
                self.oled.line(x+6,y+1,x+8,y+3,1)
                self.oled.line(x+8,y+3,x+8,y+4,1)
                self.oled.line(x+8,y+4,x+6,y+7,1)
                self.oled.line(x+5,y+7,x+1,y+7,1)
                self.oled.line(x+6,y+7,x+9,y+10,1)
                self.oled.line(x+9,y+10,x+9,y+12,1)
                self.oled.line(x+9,y+12,x+6,y+15,1)
                self.oled.line(x+6,y+15,x+1,y+15,1)
            elif text[i]=="C" or text[i]=="c":
                self.oled.line(x+10,y+2,x+9,y+1,1)
                self.oled.line(x+9,y+1,x+4,y+1,1)
                self.oled.line(x+4,y+1,x+2,y+3,1)
                self.oled.line(x+2,y+3,x+1,y+7,1)
                self.oled.line(x+1,y+7,x+1,y+12,1)
                self.oled.line(x+1,y+12,x+4,y+15,1)
                self.oled.line(x+4,y+15,x+8,y+15,1)
                self.oled.line(x+8,y+15,x+10,y+13,1)
            elif text[i]=="D" or text[i]=="d":
                self.oled.line(x+1,y+15,x+1,y+1,1)
                self.oled.line(x+1,y+1,x+6,y+1,1)
                self.oled.line(x+6,y+1,x+9,y+3,1)
                self.oled.line(x+9,y+3,x+9,y+12,1)
                self.oled.line(x+9,y+12,x+6,y+15,1)
                self.oled.line(x+6,y+15,x+1,y+15,1)
            elif text[i]=="E" or text[i]=="e":
                self.oled.line(x+1,y+15,x+1,y+1,1)
                self.oled.line(x+1,y+1,x+9,y+1,1)
                self.oled.line(x+1,y+7,x+7,y+7,1)
                self.oled.line(x+1,y+15,x+9,y+15,1)
            elif text[i]=="F" or text[i]=="f":
                self.oled.line(x+1,y+15,x+1,y+1,1)
                self.oled.line(x+1,y+1,x+9,y+1,1)
                self.oled.line(x+1,y+7,x+6,y+7,1)
            elif text[i]=="G" or text[i]=="g":
                self.oled.line(x+9,y+2,x+8,y+1,1)
                self.oled.line(x+8,y+1,x+4,y+1,1)
                self.oled.line(x+4,y+1,x+2,y+3,1)
                self.oled.line(x+2,y+3,x+1,y+7,1)
                self.oled.line(x+1,y+7,x+1,y+12,1)
                self.oled.line(x+1,y+12,x+4,y+15,1)
                self.oled.line(x+4,y+15,x+8,y+15,1)
                self.oled.line(x+8,y+15,x+10,y+13,1)
                self.oled.line(x+10,y+13,x+10,y+9,1)
                self.oled.line(x+10,y+9,x+6,y+9,1)    
            elif text[i]=="H" or text[i]=="h":
                self.oled.line(x+1,y+15,x+1,y+1,1)
                self.oled.line(x+1,y+7,x+9,y+7,1)
                self.oled.line(x+9,y+15,x+9,y+1,1)
            elif text[i]=="I" or text[i]=="i":
                self.oled.line(x+1,y+1,x+9,y+1,1)
                self.oled.line(x+1,y+15,x+9,y+15,1)
                self.oled.line(x+5,y+15,x+5,y+1,1)
            elif text[i]=="J" or text[i]=="j":
                self.oled.line(x+9,y+1,x+9,y+10,1)
                self.oled.line(x+9,y+10,x+7,y+15,1)
                self.oled.line(x+7,y+15,x+3,y+15,1)
                self.oled.line(x+3,y+15,x+1,y+10,1)
            elif text[i]=="K" or text[i]=="k":
                self.oled.line(x+1,y+15,x+1,y+1,1)
                self.oled.line(x+1,y+9,x+8,y+1,1)
                self.oled.line(x+4,y+7,x+9,y+15,1)
            elif text[i]=="L" or text[i]=="l":
                self.oled.line(x+1,y+15,x+1,y+1,1)
                self.oled.line(x+1,y+15,x+9,y+15,1)
            elif text[i]=="M" or text[i]=="m":
                self.oled.line(x+1,y+15,x+1,y+1,1)
                self.oled.line(x+1,y+1,x+5,y+7,1)
                self.oled.line(x+9,y+1,x+5,y+7,1)
                self.oled.line(x+9,y+15,x+9,y+1,1)
            elif text[i]=="N" or text[i]=="n":
                self.oled.line(x+1,y+15,x+1,y+1,1)
                self.oled.line(x+1,y+1,x+9,y+15,1)
                self.oled.line(x+9,y+15,x+9,y+1,1)
            elif text[i]=="O" or text[i]=="o":
                self.oled.line(x+10,y+5,x+8,y+1,1)
                self.oled.line(x+8,y+1,x+4,y+1,1)
                self.oled.line(x+4,y+1,x+2,y+3,1)
                self.oled.line(x+2,y+3,x+1,y+7,1)
                self.oled.line(x+1,y+7,x+1,y+12,1)
                self.oled.line(x+1,y+12,x+4,y+15,1)
                self.oled.line(x+4,y+15,x+7,y+15,1)
                self.oled.line(x+7,y+15,x+10,y+12,1)
                self.oled.line(x+10,y+12,x+10,y+5,1)
            elif text[i]=="P" or text[i]=="p":
                self.oled.line(x+1,y+15,x+1,y+1,1)
                self.oled.line(x+1,y+1,x+7,y+1,1)
                self.oled.line(x+7,y+1,x+9,y+4,1)
                self.oled.line(x+9,y+4,x+9,y+6,1)
                self.oled.line(x+9,y+6, x+6,y+9,1)
                self.oled.line(x+5,y+9,x+1,y+9,1)
            elif text[i]=="Q" or text[i]=="q":
                self.oled.line(x+10,y+5,x+8,y+1,1)
                self.oled.line(x+8,y+1,x+4,y+1,1)
                self.oled.line(x+4,y+1,x+2,y+3,1)
                self.oled.line(x+2,y+3,x+1,y+7,1)
                self.oled.line(x+1,y+7,x+1,y+12,1)
                self.oled.line(x+1,y+12,x+4,y+15,1)
                self.oled.line(x+4,y+15,x+7,y+15,1)
                self.oled.line(x+7,y+15,x+10,y+12,1)
                self.oled.line(x+10,y+12,x+10,y+5,1)
                self.oled.line(x+6,y+10,x+10,y+15,1)
            elif text[i]=="R" or text[i]=="r":
                self.oled.line(x+1,y+15,x+1,y+1,1)
                self.oled.line(x+1,y+1,x+7,y+1,1)
                self.oled.line(x+7,y+1,x+9,y+4,1)
                self.oled.line(x+9,y+4,x+9,y+6,1)
                self.oled.line(x+9,y+6, x+6,y+9,1)
                self.oled.line(x+5,y+9,x+1,y+9,1)
                self.oled.line(x+5,y+9,x+9,y+15,1)
            elif text[i]=="S" or text[i]=="s":
                self.oled.line(x+9,y+2,x+7,y+1,1)
                self.oled.line(x+7,y+1,x+3,y+1,1)
                self.oled.line(x+3,y+1,x+2,y+2,1)
                self.oled.line(x+3,y+1,x+2,y+2,1)    
                self.oled.line(x+2,y+2,x+1,y+5,1)
                self.oled.line(x+1,y+5,x+5,y+7,1)
                self.oled.line(x+5,y+7,x+9,y+8,1)
                self.oled.line(x+9,y+8,x+10,y+11,1)
                self.oled.line(x+10,y+11,x+10,y+13,1)
                self.oled.line(x+10,y+13,x+7,y+15,1)
                self.oled.line(x+7,y+15,x+4,y+15,1)
                self.oled.line(x+4,y+15,x+1,y+13,1)
            elif text[i]=="T" or text[i]=="t":
                self.oled.line(x+5,y+15,x+5,y+1,1)
                self.oled.line(x+1,y+1,x+9,y+1,1)
            elif text[i]=="U" or text[i]=="u":
                self.oled.line(x+1,y+1,x+1,y+13,1)
                self.oled.line(x+1,y+13,x+3,y+15,1)
                self.oled.line(x+3,y+15,x+7,y+15,1)
                self.oled.line(x+7,y+15,x+9,y+13,1)
                self.oled.line(x+9,y+13,x+9,y+1,1)
            elif text[i]=="V" or text[i]=="v":
                self.oled.line(x+1,y+1,x+5,y+15,1)
                self.oled.line(x+5,y+15,x+9,y+1,1)
            elif text[i]=="W" or text[i]=="w":
                self.oled.line(x+1,y+1,x+3,y+15,1)
                self.oled.line(x+3,y+15,x+5,y+8,1)
                self.oled.line(x+5,y+8,x+8,y+15,1)
                self.oled.line(x+8,y+15,x+10,y+1,1)
            elif text[i]=="X" or text[i]=="x":
                self.oled.line(x+1,y+1,x+9,y+15,1)
                self.oled.line(x+9,y+1,x+1,y+15,1)
            elif text[i]=="Y" or text[i]=="y":
                self.oled.line(x+5,y+15,x+5,y+7,1)
                self.oled.line(x+5,y+7,x+1,y+1,1)
                self.oled.line(x+5,y+7,x+10,y+1,1)
            elif text[i]=="Z" or text[i]=="z":
                self.oled.line(x+1,y+1,x+9,y+1,1)
                self.oled.line(x+1,y+15,x+9,y+1,1)
                self.oled.line(x+1,y+15,x+9,y+15,1)
            elif text[i]==".":
                self.oled.line(x+1,y+14,x+2,y+14,1)
                self.oled.line(x+1,y+15,x+2,y+15,1)
            elif text[i]=="!":
                self.oled.line(x+1,y+14,x+1,y+15,1)
                self.oled.line(x+1,y+1,x+1,y+10,1)
            elif text[i]=="?":
                self.oled.line(x+5,y+14,x+6,y+14,1)
                self.oled.line(x+5,y+15,x+6,y+15,1)
                self.oled.line(x+5,y+10,x+5,y+8,1)
                self.oled.line(x+5,y+8,x+8,y+6,1)
                self.oled.line(x+8,y+6,x+9,y+2,1)
                self.oled.line(x+8,y+1,x+4,y+1,1)
            elif text[i]=="/":
                self.oled.line(x+9,y+1,x+1,y+15,1)
            elif text[i]==":":
                self.oled.line(x+1,y+14,x+2,y+14,1)
                self.oled.line(x+1,y+15,x+2,y+15,1)
                self.oled.line(x+1,y+6,x+2,y+6,1)
                self.oled.line(x+1,y+5,x+2,y+5,1)
            elif text[i]==",":
                self.oled.line(x+1,y+13,x+1,y+14,1)
                self.oled.line(x+2,y+13,x+2,y+17,1)
                self.oled.line(x+1,y+17,x+2,y+17,1)
            elif text[i]=="&":
                self.oled.line(x+4,y+7,x+2,y+5,1)
                self.oled.line(x+2,y+5,x+2,y+3,1)
                self.oled.line(x+2,y+3,x+3,y+2,1)
                self.oled.line(x+3,y+2,x+4,y+1,1)
                self.oled.line(x+4,y+1,x+6,y+1,1)
                self.oled.line(x+6,y+1,x+7,y+2,1)
                self.oled.line(x+7,y+2,x+8,y+3,1)
                self.oled.line(x+8,y+3,x+8,y+4,1)
                self.oled.line(x+8,y+4,x+6,y+6,1)
                self.oled.line(x+6,y+6,x+1,y+10,1)
                self.oled.line(x+1,y+10,x+1,y+13,1)
                self.oled.line(x+1,y+13,x+3,y+15,1)
                self.oled.line(x+3,y+15,x+6,y+15,1)
                self.oled.line(x+6,y+15,x+9,y+9,1)
                self.oled.line(x+4,y+8,x+10,y+15,1)
            elif text[i]=="+":
                self.oled.line(x+5,y+5,x+5,y+11,1)
                self.oled.line(x+2,y+8,x+8,y+8,1)
            elif text[i]=="-":
                self.oled.line(x+2,y+8,x+8,y+8,1)
            elif text[i]=="=":
                self.oled.line(x+2,y+6,x+8,y+6,1)
                self.oled.line(x+2,y+9,x+8,y+9,1)
            elif text[i]=="0":
                self.oled.line(x+10,y+5,x+8,y+1,1)
                self.oled.line(x+8,y+1,x+4,y+1,1)
                self.oled.line(x+4,y+1,x+2,y+3,1)
                self.oled.line(x+2,y+3,x+1,y+7,1)
                self.oled.line(x+1,y+7,x+1,y+12,1)
                self.oled.line(x+1,y+12,x+4,y+15,1)
                self.oled.line(x+4,y+15,x+7,y+15,1)
                self.oled.line(x+7,y+15,x+10,y+12,1)
                self.oled.line(x+10,y+12,x+10,y+5,1)
                self.oled.line(x+9,y+4,x+2,y+12,1)
            elif text[i]=="1":
                self.oled.line(x+5,y+15,x+5,y+1,1)
                self.oled.line(x+5,y+1,x+2,y+3,1)
            elif text[i]=="2":
                self.oled.line(x+1,y+3,x+2,y+1,1)
                self.oled.line(x+2,y+1,x+7,y+1,1)    
                self.oled.line(x+7,y+1,x+9,y+3,1)
                self.oled.line(x+9,y+3,x+9,y+6,1)
                self.oled.line(x+9,y+6,x+2,y+13,1)
                self.oled.line(x+2,y+13,x+1,y+15,1)
                self.oled.line(x+1,y+15,x+10,y+15,1)
            elif text[i]=="3":
                self.oled.line(x+1,y+3,x+2,y+1,1)
                self.oled.line(x+2,y+1,x+7,y+1,1)    
                self.oled.line(x+7,y+1,x+9,y+3,1)
                self.oled.line(x+9,y+3,x+9,y+5,1)
                self.oled.line(x+9,y+5,x+7,y+7,1)
                self.oled.line(x+7,y+7,x+4,y+7,1)    
                self.oled.line(x+7,y+8,x+9,y+9,1)
                self.oled.line(x+9,y+9,x+9,y+12,1)
                self.oled.line(x+9,y+12,x+7,y+15,1)
                self.oled.line(x+7,y+15,x+3,y+15,1)
                self.oled.line(x+3,y+15,x+1,y+13,1)    
            elif text[i]=="4":
                self.oled.line(x+8,y+1,x+8,y+15,1)
                self.oled.line(x+1,y+1,x+1,y+7,1)
                self.oled.line(x+1,y+7,x+9,y+7,1)
            elif text[i]=="5":
                self.oled.line(x+9,y+1,x+1,y+1,1)
                self.oled.line(x+1,y+1,x+1,y+7,1)
                self.oled.line(x+7,y+7,x+1,y+7,1)    
                self.oled.line(x+7,y+8,x+9,y+9,1)
                self.oled.line(x+9,y+9,x+9,y+12,1)
                self.oled.line(x+9,y+12,x+7,y+15,1)
                self.oled.line(x+7,y+15,x+3,y+15,1)
                self.oled.line(x+3,y+15,x+1,y+13,1)
            elif text[i]=="6":
                self.oled.line(x+10,y+3,x+8,y+1,1)
                self.oled.line(x+8,y+1,x+4,y+1,1)
                self.oled.line(x+4,y+1,x+2,y+3,1)
                self.oled.line(x+2,y+3,x+1,y+7,1)
                self.oled.line(x+1,y+7,x+1,y+12,1)
                self.oled.line(x+1,y+12,x+4,y+15,1)
                self.oled.line(x+4,y+15,x+7,y+15,1)
                self.oled.line(x+7,y+15,x+10,y+13,1)
                self.oled.line(x+10,y+13,x+10,y+9,1)
                self.oled.line(x+10,y+9,x+8,y+7,1)
                self.oled.line(x+8,y+7,x+4,y+7,1)
                self.oled.line(x+4,y+7,x+2,y+9,1)
            elif text[i]=="7":
                self.oled.line(x+1,y+1,x+10,y+1,1)
                self.oled.line(x+10,y+1,x+3,y+15,1)
            elif text[i]=="8":
                self.oled.line(x+4,y+7,x+2,y+5,1)
                self.oled.line(x+2,y+5,x+2,y+3,1)
                self.oled.line(x+2,y+3,x+3,y+2,1)
                self.oled.line(x+3,y+2,x+4,y+1,1)
                self.oled.line(x+4,y+1,x+6,y+1,1)
                self.oled.line(x+6,y+1,x+7,y+2,1)
                self.oled.line(x+7,y+2,x+8,y+3,1)
                self.oled.line(x+8,y+3,x+8,y+5,1)
                self.oled.line(x+8,y+5,x+6,y+7,1)
                self.oled.line(x+1,y+10,x+1,y+13,1)
                self.oled.line(x+1,y+13,x+3,y+15,1)
                self.oled.line(x+3,y+15,x+7,y+15,1)
                self.oled.line(x+7,y+15,x+9,y+13,1)
                self.oled.line(x+9,y+13,x+9,y+10,1)
                self.oled.line(x+9,y+10,x+6,y+7,1)
                self.oled.line(x+6,y+7,x+4,y+7,1)
                self.oled.line(x+4,y+7,x+2,y+9,1)
            elif text[i]=="9":
                self.oled.line(x+10,y+6,x+8,y+8,1)
                self.oled.line(x+8,y+8,x+3,y+8,1)
                self.oled.line(x+3,y+8,x+1,y+5,1)
                self.oled.line(x+1,y+5,x+1,y+3,1)
                self.oled.line(x+1,y+3,x+3,y+1,1)
                self.oled.line(x+3,y+1,x+8,y+1,1)
                self.oled.line(x+8,y+1,x+10,y+3,1)
                self.oled.line(x+10,y+3,x+10,y+10,1)
                self.oled.line(x+10,y+10,x+9,y+13,1)
                self.oled.line(x+9,y+13,x+7,y+15,1)
                self.oled.line(x+7,y+15,x+3,y+15,1)
                self.oled.line(x+3,y+15,x+1,y+13,1)
            elif text[i]==" ":
                self.oled.fill_rect(x, y, 14, 21, 0)
                pass
        return

    def line1(self, line1text):
        self.display(line1text, [(0,0), (15,0), (30,0), (45,0), (60,0), (75,0), (90,0), (105,0)])
        return

    def line2(self, line2text):
        self.display(line2text, [(0,22),(15,22),(30,22),(45,22),(60,22),(75,22),(90,22),(105,22)])
        return

    def line3(self, line3text):
        self.display(line3text, [(0,44),(15,44),(30,44),(45,44),(60,44),(75,44),(90,44),(105,44)])
        return
    
    def draw_pixel(self, x, y):
        self.oled.pixel(x,y,1)
#        self.oled.show()
        
    def draw_line(self, x1, y1, x2, y2):
        self.oled.line(x1,y1,x2,y2,1)
#        self.oled.show()

    def Clear(self):
        self.oled.fill(0)
        self.oled.show()
        return

    def Show(self):
        self.oled.show()
        return
    
"""
def wrap(string):
    if len(string)> 8:
        spaceArray = []
        cut1 = 23
        cut2 = 23
        cut3 = 23
        for character in range (len(string)):
            if string[character] == " ":
                spaceArray.append(character)
        for i in range (len(spaceArray)):    
            if spaceArray[i] < 8 :
                cut1= spaceArray[i]
                #cut[0]=space
            
            if 8 < spaceArray[i] < 16 :
                cut2=spaceArray[i]
               
            if 16 < spaceArray[i] < 24 :
                cut3=spaceArray[i]
              
        line1(string[0:(cut1)])
        line2(string[(cut1+1):(cut2)])
        line3(string[(cut2+1):(cut3)])
        
    else:
        line1(string)
    #line2(line2text)
    #line3(line3text)
    return
"""

How to use library.

from SSD1306_Large import SSD1306_8x3

display = SSD1306_8x3()
display.Clear()
display.line1('ABCDEFGH')
display.line2('01234567')
display.line3(',!?/:+-=')
display.Show()

Regards
Jim

2 Likes

We actually have a stellar contribution called Packed Font which is captured in our PiicoDev Community Contributions article. I regret that we didn’t drop a link into this thread - but here it is anyhow.

some screenshots:

This is a great and lightweight alternative :smiley: nice one Jim

3 Likes

Thanks Jim and Michael for this update.

This will help getting my small temp / humidity project viewable for a family member whose eyesight isn’t the best. The next challenge will be to put it all together with a LiPo in a nice wooden casing.

Cheers

3 Likes

Hi all, one small extra problem that I cannot figure out, the running of the Packed Font gives …unknown file format as per the attached screen shot.


Tried with and without the .pf file type, but no joy.
Any thoughts appreciated.
Cheers

1 Like

This is what I get when the files are loaded without the .pf extension.

I must be doing something wrong, but not sure. Maybe a complete reload may be the answer.
Regards

1 Like

Solved :slightly_smiling_face: Had corrupted image files.

2 Likes