Slow LED Matrix pixel drawing (1px/s) due to Serial.readStringUntil('\n')

Hello! I am using an Arduino Mega control a 32x32 RGB LED matrix panel. A Python script is sending individual pixel data to serial port. It works fine, but it's drawing one pixel per second (not ideal for 1024 pixels!).

I measured time for getData() and parseData() for each pixel and it looks like getData is taking ~1000ms so this is what's causing the drawing rate of 1px/s. I know that Serial.readStringUntil('\n') times out after 1000ms by default, but each line of pixel data being sent to serial port terminates with \n, so why is Serial.readStringUntil('\n') waiting for 1s before it continues? I'd appreciate any help making me see my mistake here. Thanks!

Arduino:

#include <RGBmatrixPanel.h>

#define CLK 11 
#define OE   9
#define LAT 10
#define A   A0
#define B   A1
#define C   A2
#define D   A3
#define MAX_LENGTH 18

RGBmatrixPanel matrix(A, B, C, D, CLK, LAT, OE, false);
const char delim[] = ",()";
char dataIn[MAX_LENGTH];
char tmp[MAX_LENGTH];

void setup() 
{
  Serial.begin(115200);
  matrix.begin();
}

void loop()
{
  if (Serial.available() > 0) 
  {
    char c = Serial.read();
    if (c == 'S') // start
    {
      Serial.write('S');
      unsigned int px = 0;
      while (px < 1024) // 1024 pixels
      {
        Serial.println(micros());
        getData();
        Serial.println(micros());
        parseData();
        Serial.println(micros());
        px++;
        Serial.write('S');
        Serial.println(' ');
      }
      matrix.updateDisplay(); 
    }
  }
}

void getData() 
{
  dataIn[0] = '\0';
  tmp[0] = '\0';
  String dataString = Serial.readStringUntil('\n');
  dataString.toCharArray(dataIn, sizeof(dataIn));
}

void parseData() 
{
  int i = 0;
  int j = 0;
  int r = 0;  
  int g = 0;
  int b = 0;
  strcpy(tmp, dataIn);
  char * data;

  data = strtok(tmp, delim);
  i = atoi(data);
  
  data = strtok(NULL, delim);
  j = atoi(data); 

  data = strtok(NULL, delim);
  r = atoi(data); 

  data = strtok(NULL,delim);
  g = atoi(data); 

  data = strtok(NULL, delim);
  b = atoi(data); 

  matrix.drawPixel(i, j, matrix.Color444(r, g, b));
}

Python:

import serial
import time

import urllib.request
from PIL import Image

ser = serial.Serial('/dev/tty.usbmodem143301', baudrate=115200)
time.sleep(2)
ser.write(b'S')

url = "https://i.scdn.co/image/ab67616d0000b2734c63ce517dd44d0fbd9416da"
path = "/Users/tyannefong/Desktop/test.jpg"


def pixel(link, file_path):
    urllib.request.urlretrieve(link, file_path)
    with open(path, "rb") as image:
        image = Image.open(image)
        image = image.resize((32, 32))
        image_data = list(image.getdata())

        c = 0
        pxs = []
        for i in range(32):
            for j in range(32):
                pxs.append('{},{} {}'.format(i, j, tuple(round((x / 255) * 15) for x in image_data[c])))
                c += 1

    return pxs


def ack():  # return true if acknowledged
    if ser.in_waiting > 0:
        a = ser.read().decode()
        if a == 'S':
            return True


pxs = pixel(url, path)

while not ack():
    pass

for px in pxs:
    ser.write(px.encode())
    while not ack():
        pass

Avoid the dangerous String type and read immediately into dataIn.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.