Shrinking an IP address to fit on the PCD8544 Nokia 5110 style LCD - MicroPython Example

LCD status displays can really simplify troubleshooting IoT devices.  I need to know the IP address of the device. and MDNS doesn't always work for me.  I could log into my router to find the IPs of my devices but it is simpler to add a cheap display and log the IP address on the display. 

I have a pile of cheap Nokia-style modules that are 84 pixels x 48 pixels. The Adafruit Python driver defaults to a 5x8 font which results in 6x10 dot character spacing. 5 lines at 10 pixels tall is more than 48 pixels but we don't need the last two padding rows because there is nothing below them. That turns out to be 14 characters on the 5110-style LCD.  IP addresses can be 15 characters if all 5 octets are 3 decimal digits. This means it is possible to lose the last character of an IP address as shown below.

The separator characters don't need to be full fixed-width characters. We know they can be smaller than the digits used for the IP address octets.  The function down below renders the "." characters as narrow graphics in between the octets.

The top two rows demonstrate the default text behavior.  The 2nd row from the bottom shows how the text lays out if we compress the width of periods ".".

Click to expand


Test Program

This code can be found on GitHub. There is a small block of LCD initialization code

spi = busio.SPI(board.SCK, MOSI=board.MOSI)
dc = digitalio.DigitalInOut(board.D6) # data/command
cs = digitalio.DigitalInOut(board.D5) # Chip select
reset = digitalio.DigitalInOut(board.D9) # reset
display = adafruit_pcd8544.PCD8544(spi, dc, cs, reset)
display.contrast = 60

This test program exercises our function by displaying a full 12-digit IP address: 888.888.888.888.  Our test program is verifying the rendering and does not care if the address is an actual valid IP address.

# compress the width needed by putting a blank space instead of "."
display.text('IP Address', 0, char_height*0, 1)
# can be too wide for screen
#display.text(, 0, 10, 1)
our_address =
display_ip_compressed(display, our_address, char_height*1)
# demo lines
display.text("Comp vs Trunc",0,char_height*2,1)
display_ip_compressed(display, "888.888.888.888",char_height*3)

The driver calls our re-usable IP address to render.  See the line in bold.

A reusable function that renders IP addresses

This function renders an IP address with compressed spacing for the "." separator characters.  You can just copy and paste this into your MicroPython or CircuitPython program.

# 5x8 - font
# 6x10 - pad one on the side and two on the bottom
# 5 lines of txt is 50 pixels or 48 because we don't need to pad last row
char_width = 6
char_height = 10
#  TODO do font size math to make this work on other displays
def display_ip_compressed(display, our_address, y_position):
  writes out an IP address replacing 6 pixels wide '.' character with 4p pixels wide 2x2 square
  Nokia display is 84x48 = 14 characters wide = 84 pixels
  An IP address can be 3*4+3 = 15 characters
  Each character is 6 (5+1) wide.  3 characters are 18 plus a dot is 24 wide
  Each character is 10 (8+2) tall
  display.text("              ",0,y_position,1) # erase the line
  display.rect((char_width*3)+(4*0)+1, y_position+(char_height-5), 2,2,1)
  display.rect((char_width*6)+(4*1)+1, y_position+(char_height-5), 2,2,1)
  display.rect((char_width*9)+(4*2)+1, y_position+(char_height-5), 2,2,1)

  if (our_address):
    our_octets = str(our_address).split(".")
    display.text(our_octets[0], (char_width*0)+(4*0), y_position, 1)
    display.text(our_octets[1], (char_width*3)+(4*1), y_position, 1)
    display.text(our_octets[2], (char_width*6)+(4*2), y_position, 1)
    display.text(our_octets[3], (char_width*9)+(4*3), y_position, 1)

The Seeed XIAO ESP32 C3

The display is significantly larger than the device it is attached to. The XIAO has 11 pins. The LCD uses5 fo those. I usually add an LED for status but do I really need it with a display?



2023 01


Popular posts from this blog

Understanding your WSL2 RAM and swap - Changing the default 50%-25%

Installing the RNDIS driver on Windows 11 to use USB Raspberry Pi as network attached

DNS for Azure Point to Site (P2S) VPN - getting the internal IPs