Trying to get scrolling text on the Piicodev OLED display

Ok, here’s the code I’m using to scroll text. It works by removing the first character of the text string and redrawing the display each iteration.

from PiicoDev_SSD1306 import *
display = create_PiicoDev_SSD1306()

def scroll_text(text, x, y):
	for i in range(len(text) + 1):
		display.fill(0)
		display.text(text, x, y, 1)
		display.show()
		text = text [1:]

scroll_text('This is some text scrolling across the display!', 1, 1)

My problem is that I can’t get it to scroll at a consistent rate - it will start scrolling quickly, slow down a bit, then speed up a little. I can slow down the scrolling rate by inserting a sleep command at the end of the for loop, but the problem persists, no matter what values I use for sleep. Any ideas? Thanks!

EDIT: I’m using a Raspberry Pi 4B with the Piicodev HAT adapter.

3 Likes

Awesome work @Steven!
As for making the scroll rate consistent, i wonder if this would work:
You could gate the call to show() with a non-blocking delay like this:

from time import ticks_ms

now = ticks_ms()
last = now
period = 1000 # milliseconds. The event loop period

while True:
    now = ticks_ms()
    if now - last > period: # event scheduler
        display.show()
        last = now
        print("tick")

The smbus package that drives i2c communications seems to be pretty inconsistent with how it handles transactions. In some far-flung future we might look into porting PiicoDev_Unified.py to use pigpio for I2C comms - apparently it might help

3 Likes

Awesome work Steven!
Without seeing what else you have happening on the Pi I imagine the I2C updates themselves are sporadic.

Also its worth noting that the Pi and micro:bit ports dont have the framebuf module like the Pico does so will run a bit slower (dont worry, an update is due!)

Liam

2 Likes

I would guess that this line is a string copy. If so, then it would likely account for the slowdown after a time, as memory gets fragmented. If you instead print a substring at postion i then you will avoid the copy.
How to Substring a String in Python (freecodecamp.org)

3 Likes

Hi Steven
Indeed the scrolling is not uniform and goes into a race towards the end. If you are using python on a Raspberry Pi 4B see if this works. I kept your original code adding 3 lines to incorporate a variable sleep to compensate for the changing processing time. I also used Jeff105671’s suggestion to use substrings. The variable “delay” sets the character scroll time in fractions of a second. Note you cannot make the delay too low because sleep() cannot be negative. It is interesting to print the sleep time which increases markedly towards the end of the scroll to slow it down. I still have the perception it races towards the end although perhaps it is an illusion.

from PiicoDev_SSD1306 import *
from time import sleep, process_time
display = create_PiicoDev_SSD1306()
delay = 0.25 # delay in fractions of a second

def scroll_text(text, x, y):
    for i in range(len(text) + 1):
        start = process_time()
        display.fill(0)
        display.text(text[i:], x, y, 1)
        display.show()
        sleep (delay - (process_time() - start))
        
scroll_text('This is some text scrolling across the display!', 1, 1)
3 Likes

Thank you everyone for your replies. Those suggestions did help, but only marginally. I still had big problems where the text would slow down mid-scroll, and accelerate towards the end (@Fractal, you’re definitely not imagining it!). Through trial and error combining your suggestions, I could get smooth scrolling but only at a rate of > 2 seconds.

In the end, I managed to get consistent scrolling at high speeds by bumping up the I2C core to 1MHz.

In /boot/config.txt, add dtparam=i2c_baudrate=1000000.

Found this solution in Adafruit’s PiOLED (a similar I2C display) documentation.

Hope this won’t damage any of my Piicodev modules.

2 Likes

Hi Steven
I measured the max time in the loop at 0.19 secs and was able to run the scrolling at 0.2 secs per character without any mods. I am wondering if there is some issue with your pi for it to run slow. I double checked my code and I am at a loss to understand why it does not give the same character rate from beginning to end of scrolling.

2 Likes

Not sure why this is the case either. Unfortunately, I don’t know enough about how the hardware works to come up with a theory. For what it’s worth, I do have 6 other Piicodev modules attached but I’m not sure if this would change anything.

That said, I’m glad I found a solution.

2 Likes

Hi Steven and all those that are interested!

I just popped through a PR on the OLED repo: Print() scrolling text by LiamHowell · Pull Request #4 · CoreElectronics/CE-PiicoDev-SSD1306-MicroPython-Module · GitHub

This adds the function print() each subsequent call it bumps the last line of text upwards much like the Python terminal.

I’ve been testing on the Pico, inside the examples folder there’s an example of which I recorded 0.03 seconds per print
image

Might be useful as a benchmark for different controllers? (Note you’ll have to chang the import from utime to time on the Pi)

Any and all feedback+suggestions welcome :smiley:

4 Likes

Awesome! :smiley: We’ll evaluate the PR and deploy changes ASAP!
Nice work :clap:

2 Likes

Awesome @Liam120347 and thanks @Michael!

1 Like