My Inky Phat clock - refresh speed question

I just received my Inky pHat and Pi Zero WH and put it together to make a clock. I run an NTP server on another Raspberry Pi so the idea was that I could have a physically small clock with a good display that would keep time but would sync with the NTP Pi on a regular basis.

I cobbled together some code, tested the Inky and came to the conclusion that I would need to display text in black as red takes a little too long to refresh. Needless to say the tech is great and it works really well. The simple Python script gets fired by crontab every minute and updates the display.

Now, my issue/problem is that although the Inky refreshes in about 15 seconds, the script takes around 25 seconds to run. This is my code segment for localtime, where it refreshes from the Zero’s own clock:

def LocalTime():
    Row1 = strftime('%a %d %b')   
    Row2 = strftime('%H:%M %z')   
    Row3 = 'Local Time ' + strftime('%Z')
    inkyphat.text((x, 2),  Row1, inkyphat.BLACK, font=font)
    inkyphat.text((x, 38), Row2, inkyphat.BLACK, font=font)
    inkyphat.text((x, 80), Row3, inkyphat.BLACK, font=smallfont)
    inkyphat.show()
    sys.exit

Any ideas how I can speed this up, or is 25 seconds a realistic time for this setup?

I’d also like to know this. I’m trying to put together a display which shows real-time visitors to my website but it takes about 8 seconds to refresh the screen (even when not using red).

Is it possible to speed this up at all or only refresh a portion of the screen?

Generally speaking, if you need to update more than once every few minutes then you’re using the wrong display technology.

It’s not possible to make the display refresh any faster while maintaining the same level of image quality/repeatability, and it also runs the risk of damaging the display so we tend to stick well within the visual quality/speed limits.

If you want to know more than you ever might want to know about this, I’d recommend watching: https://www.youtube.com/watch?v=MsbiO8EAsGw

1 Like

Thanks Gadgetoid!

I actually watched the video and can now understand the problem. Needless to say, it’s an amazing piece of tech especially bearing in mind the price. I’l keep running mine as a 1-minute update clock and by the time it’s worn out I’m sure the new improved version will be in stock :)

Using the ideas put forward in Ben Krasnow’s YouTube video and other hacks, I’ve managed to get my InkyPhat to run with a refresh rate of around 1.5Hz, sufficient to display a clock updating every second. This only works when displaying just black and white pixels and, as mentioned already in this thread, risks degrading the display. (I run the clean.py script supplied with the Inky Python package periodically to minimise burn-in.)

The hacks I’ve been using are:

  1. A stripped-down LUT. After a bit of experimenting, I’ve found that this one gives pretty good results except perhaps for very thin white lines on a black background:

         'black': [
         # Phase 0     Phase 1     Phase 2     Phase 3     Phase 4     Phase 5     Phase 6
         # A B C D     A B C D     A B C D     A B C D     A B C D     A B C D     A B C D
         0b01010000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000,  # LUT0 - Black
         0b01100000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000,  # LUT1 - White
         0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000,  # IGNORE
         0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000,  # LUT3 - Red
         0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000,  # LUT4 - VCOM
    
         # Duration            |  Repeat
         # A   B     C     D   |
        24,   24,    0,    0,     1,   # 0 Clear to black, then go to final voltage
         0,    0,    0,    0,     0,   # 1
         0,    0,    0,    0,     0,   # 2
         0,    0,    0,    0,     0,   # 3
         0,    0,    0,    0,     0,   # 4
         0,    0,    0,    0,     0,   # 5
         0,    0,    0,    0,     0,   # 6
         ],
    
  2. Since I know I’ll be updating the display constantly, there is no point powering down the display after an update operation. Keeping the display powered up also means that the display initialisation (including LUT loading) only needs to be performed once at startup.

  3. If the display is not being powered down after each update, it is more efficient to check that the display’s BUSY status has cleared before performing a screen update rather than waiting for BUSY to go low after each update. This frees up the application to work on preparing the next frame to be displayed in parallel with the display being updated.

  4. Since I only using black and and white pixels when doing continuous high-speed display refreshes, there is no need to write to the SSD1675A chip’s “RED” RAM every frame. This can be initialised with zeros just once at startup.

  5. I set the max SPI speed to 20MHz, not 488kHz. The SSD1675A can handle up to 20MHz and the PI’s SPI i/f up to 125MHz.

A more radical approach, which avoids flicker during the screen update and possibly reduces the burn-in risk, is to take a differential approach to updating, i.e. re-define the use of the LUT’s and SSD1675A’s display RAM as follows:

  • Set LUT0 to null
  • Set LUT1 to a sequence which turns a pixel known already to be black, to white
  • Set LUT2 to a sequence which turns a pixel known already to be white, to black
  • For pixels which are to be unchanged from one frame to the next, set their BW and RED RAM entries to 0 (so they use LUT0)
  • For pixels which are to be changed from black to white in the next frame, set their BW RAM entry to 1 and RED RAM entry to 0 (so they use LUT1)
  • For pixels which are to be changed from white to black in the next frame, set their BW RAM entry to 0 and RED RAM entry to 1 (so they use LUT2)

I’ve uploaded my hacked version of the inky library here and my version using differential frame updating here.

To use, create a display by calling the function inky_fast.InkyPHATFast(“black”) or inky_delta.InkyPHATDelta(“black”) rather than Inky.InkyPHAT(colour) and then call the method show_stay_awake() rather than show() on the display object.