rpi-rgb-led-matrix
rpi-rgb-led-matrix copied to clipboard
Is it possible to stop and resume the RGBmatrix updater thread?
I have a scenario where most of the time the LED matrix will be blank, but it can be worken up via a USB serial command to display something and the go back to sleep.
Is it possible to stop and later restart the RGBmatrix updater thread? I tried making it public so that I could access the Stop() and Run() methods, but I think I misunderstand the object model, as it seems that the updater thread is not a complete class at the point of declaration.
Any pointers anyone can offer would be greatly appreciated. The main motivation here is just to save CPU cycles and hence keep the system temperature down.
Hi. Thanks for your extended comment and ideas. I understand how the HUB75 interface works - however, putting aside all of the pros and cons of using a Raspberry Pi, another application processor with an OS, an MCU, an FPGA / CPLD, it should be possible to pause the data output thread and keep the display in a blank state, given that you can clock out zero for all of the pixels in the current frame (in fact, just doing so for the current row is sufficient, as that is the only part of the display being actively driven). You can then send no further data until required by ending the thread, hence reducing power consumption.
So far I just haven't worked out a structure to correctly expose this functionality due to the way that the classes involved are structured (being incomplete at definition) and was hoping that either someone else has done this or might be able to point me in the right direction to implement this feature and submit a pull request.
Have there been any updates regarding this issue?
I have a scenario where most of the time the LED matrix will be blank
I have exactly the same scenario: besides the matrix display I installed a push button to the Pi, and upon a push (which would happen ca. 5 times a day), I want the matrix to operate for about 10 minutes.
First it was unexpected to see the CPU usage stay up at 75% even after clearing the display, and that I cannot properly close or deallocate the matrix object. After some research this is not suprising after all, and the documentation even tells about it in the limitations section:
The system needs constant CPU to update the display. Using the DMA controller was considered but after extensive experiments dropped due to its slow speed..
Fortunately, it is not so hard to overcome this: just use a separate process for the LED matrix handling, and another one for controlling the former. I am using the Python 3 bindings on a Pi 3B+, and the following code stub seems to work well using the multiprocessing standard lib (aimed for controlling Python functions as separate processes), but I guess I could also use the more general subprocess lib (aimed for controlling any shell-executable process). Probably I lose some speed and response time but in my case it's not a problem.
# matrix.py
import signal
import sys
import time
from typing import Optional
from rgbmatrix import RGBMatrix, FrameCanvas
# I put the matrix state into a module-wide variable so that functions can work on it
STATE: Optional[tuple[RGBMatrix, FrameCanvas]] = None
def init() -> tuple[RGBMatrix, FrameCanvas]:
"""Initialize the matrix and canvas"""
matrix = RGBMatrix(options=...)
return matrix, matrix.CreateFrameCanvas()
def loop(matrix: RGBMatrix, canvas: FrameCanvas) -> None:
"""Display loop: refresh the matrix"""
while True:
canvas.Clear()
draw_something(canvas)
canvas = matrix.SwapOnVSync(canvas)
time.sleep(...)
def cleanup(signum: int, frame):
"""Catch termination signal, clear the matrix, and exit"""
matrix, canvas = STATE
canvas.Clear()
matrix.SwapOnVSync(canvas)
sys.exit(0)
def run() -> None:
"""Tell the process to do cleanup when terminating, initialize and run the loop"""
global STATE
STATE = init()
signal.signal(signal.SIGINT, cleanup)
signal.signal(signal.SIGTERM, cleanup)
loop(*STATE)
# main.py
from multiprocessing import Process
from matrix import run
# This code can be put into a loop checking a button, or something else...
if __name__ == "__main__":
# Fire up the matrix
process = Process(target=run)
process.start()
# Now the display loop is running, CPU usage at 75%
wait_some_time_or_do_something()
# Send a SIGTERM to the process, and it will execute the cleanup function
process.terminate()
# Now the display is blank, CPU usage down :-)