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