SparkFun Qwiic Alphanumeric Flickering

First project using a Raspberry Pi 5, four SparkFun Qwiic Alphanumeric displays and the Qwiic Shim. The project reads UDP data and shows it on the four displays. The data is from a scoreboard on our network and is picking up home/away score, period and the time. (Note: Hockey timing… minutes : seconds . tenths mm:ss.d are being displayed. Yes, it’s updating every tenth of a second when there clock is running. When the clock is stopped, the data is only refreshed once a second.)

Unfortunately, the displays flicker with each print. There’s no clear statement to blank it out from the previous data.

Is there any way to get the displays to stop flickering?

Here’s my code:

from __future__ import print_function
import socket
import qwiic_alphanumeric
import time
import sys

# UDP configuration
UDP_IP = "0.0.0.0"  # Listen on all available interfaces
UDP_PORT = 7698
TARGET_IP = "192.168.56.224"

# Create a socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind((UDP_IP, UDP_PORT))



def run_example():

    print("\nSparkFun Qwiic Alphanumeric - Example 9: Multi Display")
    my_display = qwiic_alphanumeric.QwiicAlphanumeric()

    if my_display.begin(0x70, 0x71, 0x72, 0x73) == False:
        print("\nThe Qwiic Alhanumerics aren't connected to the system. Please check your connection", \
            file=sys.stderr)
        return

    print("\nQwiic Alphanumerics ready!")
    
    my_display.set_brightness(5)
    
    while True:
        data, addr = sock.recvfrom(1024)  # Buffer size is 1024 bytes
        
#        print(f"Listening for UDP packets on port {UDP_PORT}...")
                
            # Filter packets by sender's IP
        if addr[0] == TARGET_IP:
            # Extract the relevant positions (176-183 excluding 178 and 182)
            if len(data) > 217:  # Ensure data is long enough
                filtered_data = (
                    data[176:181]
                )
                filtered_data_71 = (
                    data[182:183]
                )
                filtered_data_per = (
                    data[208:209]
                )
                filtered_data_home = (
                    data[210:212]
                )
                filtered_data_away = (
                    data[214:216]
                )
                
                # Convert the filtered data to a string (for display purposes)
                filtered_string = ''.join(chr(x) for x in filtered_data)
                filtered_string_71 = ''.join(chr(x) for x in filtered_data_71)
                filtered_string_per = ''.join(chr(x) for x in filtered_data_per)
                filtered_string_home = ''.join(chr(x) for x in filtered_data_home)
                filtered_string_away = ''.join(chr(x) for x in filtered_data_away)
                
                # Display the filtered data on the alphanumeric display
                print(f"Displaying: {filtered_string}.{filtered_string_71} Per: {filtered_string_per} A:{filtered_string_away} H:{filtered_string_home}")
                my_display.print(filtered_string_71 + " P" + filtered_string_per + filtered_string + " H" + filtered_string_home + " A" + filtered_string_away)  # Write new text
                my_display.colon_on_single(4)
                my_display.colon_on_single(3)
    #            display0.decimal_on()
    #            display1.decimal_on()
    #            display3.decimal_on()
            else:
                print(f"Received short packet from {TARGET_IP}. Ignoring.")

if __name__ == '__main__':
    try:
        run_example()
    except (KeyboardInterrupt, SystemExit) as exErr:
        print("\nScoreboard")
        sys.exit(0)

You could try only updating the changed segments and implement a buffer:

class DisplayBuffer:
    def __init__(self):
        self.buffer = [""] * 4  # Assuming 4 displays

    def update(self, new_data):
        changes = []
        for i, (old, new) in enumerate(zip(self.buffer, new_data)):
            if old != new:
                changes.append((i, new))
                self.buffer[i] = new
        return changes

display_buffer = DisplayBuffer()

# Inside your main loop:
def update_display(my_display, new_data):
    changes = display_buffer.update(new_data)
    for position, value in changes:
        my_display.print(value, position)  # Assuming print method can target specific positions

# In your main loop:
new_display_data = [
    filtered_string_71 + " P" + filtered_string_per,
    filtered_string[:4],  # Assuming 4 characters per display
    "H" + filtered_string_home,
    "A" + filtered_string_away
]
update_display(my_display, new_display_data)
my_display.colon_on_single(4)
my_display.colon_on_single(3)

If that doesn’t fix it, it also might help to clear the display before writing the new data. Something like:

from __future__ import print_function
import socket
import qwiic_alphanumeric
import time
import sys

# UDP configuration
UDP_IP = "0.0.0.0"  # Listen on all available interfaces
UDP_PORT = 7698
TARGET_IP = "192.168.56.224"

# Create a socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind((UDP_IP, UDP_PORT))

def run_example():
    print("\nSparkFun Qwiic Alphanumeric - Hockey Scoreboard Display")
    my_display = qwiic_alphanumeric.QwiicAlphanumeric()

    if my_display.begin(0x70, 0x71, 0x72, 0x73) == False:
        print("\nThe Qwiic Alhanumerics aren't connected to the system. Please check your connection", \
            file=sys.stderr)
        return

    print("\nQwiic Alphanumerics ready!")
    
    # Set initial brightness
    my_display.set_brightness(5)
    
    while True:
        try:
            data, addr = sock.recvfrom(1024)  # Buffer size is 1024 bytes
            
            # Filter packets by sender's IP
            if addr[0] == TARGET_IP:
                # Ensure data is long enough
                if len(data) > 217:
                    # Extract relevant data
                    filtered_data = (data[176:181])
                    filtered_data_71 = (data[182:183])
                    filtered_data_per = (data[208:209])
                    filtered_data_home = (data[210:212])
                    filtered_data_away = (data[214:216])
                    
                    # Convert filtered data to strings
                    filtered_string = ''.join(chr(x) for x in filtered_data)
                    filtered_string_71 = ''.join(chr(x) for x in filtered_data_71)
                    filtered_string_per = ''.join(chr(x) for x in filtered_data_per)
                    filtered_string_home = ''.join(chr(x) for x in filtered_data_home)
                    filtered_string_away = ''.join(chr(x) for x in filtered_data_away)
                    
                    # Print debug information
                    print(f"Displaying: {filtered_string}.{filtered_string_71} Per: {filtered_string_per} A:{filtered_string_away} H:{filtered_string_home}")
                    
                    # Clear the entire display before writing new data
                    my_display.clear()
                    
                    # Write new text
                    display_text = filtered_string_71 + " P" + filtered_string_per + filtered_string + " H" + filtered_string_home + " A" + filtered_string_away
                    my_display.print(display_text)
                    
                    # Turn on colons
                    my_display.colon_on_single(4)
                    my_display.colon_on_single(3)
                else:
                    print(f"Received short packet from {TARGET_IP}. Ignoring.")
        
        except Exception as e:
            print(f"An error occurred: {e}")
            # Optional: add a small delay to prevent rapid error loops
            time.sleep(0.1)

if __name__ == '__main__':
    try:
        run_example()
    except (KeyboardInterrupt, SystemExit):
        print("\nScoreboard display stopped.")
        sys.exit(0)

Thanks for the suggestions!

The second code didn’t change the flicker.

The first suggestion returned the following error:

Traceback (most recent call last):
File “”, line 109, in
File “”, line 96, in run_example
File “”, line 87, in update_display
TypeError: QwiicAlphanumeric.print() takes 2 positional arguments but 3 were given

Line 87 was: my_display.print(value, position)

I actually tried something like that but it looks like I can’t address a specific character position (as your comment indicated).