rpi-rgb-led-matrix icon indicating copy to clipboard operation
rpi-rgb-led-matrix copied to clipboard

Updating matrix panels from a flask app

Open targettadams opened this issue 2 years ago • 1 comments
trafficstars

I am using a raspberry pi 4 with six 32x16 outdoor p10 matrix panels. They are being used as part of a sports scoreboard (cricket).

To interface with the board, I am trying to build a very simple RESTful API using flask. It is just a post method which takes in a string that essentially specifies what score to display on a particular panel.

I am having problems getting the displays to work properly when they are part of the flask app. Standalone, they work fine (I can display and update numbers to all panels with no issues whatsoever).

The issue is a little difficult to describe, so I'll use some pictures. Anyone have any ideas of how I could get it to work properly?

  1. When I start the web service, the 'OVERS' panel will display '0' 1

  2. Then I send a post request to update the number to '33.2' 2

  3. All good it seems ... but after a small amount of time (variable, but of the order of a few seconds), the number fades away back to '0' with a residual ghosted outline of '33.2' 3

(Actually, even in 2) you can make out a ghosted outline of the original '0').

I don't think there is anything too controversial with my code (not a seasoned python programmer btw).

Here is the flask app:

from scoreboard import Scoreboard
from flask import Flask, request

app = Flask(__name__)

scoreboard = Scoreboard()
scoreboard.display() # Default display

def update_scoreboard_display(requestJson):
    requestData = requestJson['data']
    scoreType = requestData[0:3]
    scoreData = requestData[3:]
    updateScoreboard = True
    if scoreType == "OVB":
        scoreboard.setOversBowled(float(scoreData))
    if updateScoreboard:
        scoreboard.display()

@app.route('/scoreboard', methods=['POST'])
def get_scoreboard_data():
    requestJson = request.get_json()
    update_scoreboard_display(requestJson)
    return '', 200

if __name__ == '__main__':
    app.run(host='0.0.0.0', port='80', debug=True)

And here is some of my scoreboard code. I have omitted the utility code which translates which pixels to switch on for which number. Essentially, each number maps to a set of pixels which should be switched on, this is implemented in the loop in the 'display' method. My panel options are shown in the constructor.

from scoreboardUtils import ScoreboardArray, ScoreboardArrayController
from rgbmatrix import RGBMatrix, RGBMatrixOptions

class Scoreboard(object):
    def __init__(self):
        self.values = [0, 0.0, 0, 0, 0, 0]

        options = options = RGBMatrixOptions()

        options.rows = 16
        options.cols = 32
        options.chain_length = 6
        options.parallel = 1
        options.row_address_type = 0
        options.multiplexing = 8
        options.pwm_bits = 1
        options.brightness = 100
        options.hardware_mapping = "adafruit-hat"
        options.pwm_lsb_nanoseconds = 1300 # Default was 130
        options.led_rgb_sequence = "RGB"
        options.pixel_mapper_config = ""
        options.panel_type = ""
        options.gpio_slowdown = 4
        options.drop_privileges = False
        #options.daemon = 0
        #options.show_refresh_rate = True

        self.matrix = RGBMatrix(options = options)

        digitStrokeInPixels = 2
        self.controller = ScoreboardArrayController(options.cols, options.rows, digitStrokeInPixels)

    def setOversBowled(self, oversBowled):
        self.values[1] = oversBowled

    def display(self):
        decimalSizeInPixels = 2
        margin = 2
        rightMargin = 2
        offset_canvas = self.matrix.CreateFrameCanvas()
        for i in range(len(self.values)):
            scoreboardArray = ScoreboardArray(self.values[i], True if (i == 1) else False, decimalSizeInPixels, self.controller, margin, 0.5*rightMargin if (i == 1) else rightMargin)
            for x in range(i*self.controller.arrayWidth, (i+1)*self.controller.arrayWidth):
                for y in range(0, self.matrix.height):
                    if (scoreboardArray.IsDigitPixel(y,x-i*self.controller.arrayWidth)):
                        offset_canvas.SetPixel(x,y,255,255,255)
        offset_canvas = self.matrix.SwapOnVSync(offset_canvas)

targettadams avatar Apr 24 '23 13:04 targettadams

flask runs multiple threads simultaneously. You might need to disable multithreading or rework the application. Suggest stackoverflow for this question instead of this repo

combs avatar May 07 '23 23:05 combs