The end goal of my project is to use python to send serial information to a Arduino uno that runs a strip of neopixels spanning my room. The plan is to make some music visualizers/redshifts night light/wake up alarm lights/that cool lights behind your monitor that show the average screen color.
to meet this flexibility was hoping I could do all of the pixel color processing on my computer and have the arduino act as a dumb input to display. but if I can't speed things up I'll switch to just sending animation info and writing all producing all of the animations on the arduino.
So, my current issues is I'm not getting as high a refresh as id like so I wanted to know if there were any things I could do to speed things up
my arduino code
#include <Adafruit_NeoPixel.h>
const byte PIN = 7;
const int PIX_NUM = 150;
uint32_t color;
int idx = 0;
int red;
int green;
int blue;
Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIX_NUM, PIN, NEO_GRB + NEO_KHZ800);
void setup() {
strip.begin();
strip.show();
Serial.begin(500000);
Serial.print("#");
}
void loop() {
nextPixel();
}
void nextPixel() {
if(Serial.available() >= 63) {//wait for buffer to have 21 pixels or 63 bytes
for(int i=0; i < 21 ; i++) {
red = Serial.read();
green = Serial.read();
blue = Serial.read();
color = strip.Color(red,green,blue); //converts rgb to a single uint32_t
showNewData();
}
Serial.print("#"); //tells program buffer is empty again
} }
void showNewData() {
strip.setPixelColor(idx,color);
idx++; //keeps track of pixel index
if(idx == 150){
strip.show(); //only updates strip when full new img is there because this function is slow
idx = 0;
} }
my python code that displays a simple animation for testing:
import serial,random,time,struct
ser = serial.Serial('COM3', 500000)
#wait until a '#' is sent
def ArdWait():
while True:
x = ser.read()
if x == b'#':
break
#wait for ard to be ready
ArdWait()
#setting some variables up
idx = 0
t = time.time()
flip = False
count = 1
bpsCounter = 0
bpsUpdateSec = 2 # how many sec to wait to display bps, python is slow af at printing
brightness = 0
pixelIndex = 0
#main loop
while True:
#sends brightness three times then sends 0 three times to turn on every other pixel
#having every other pixel off helps me to tell if there is any desyncing caused by high BUAD
if flip == False:
value = struct.pack('>B', brightness)
if flip == True:
value = struct.pack('>B', 0)
if count == 3:
flip = not flip
count = 0
pixelIndex = pixelIndex + 1
ser.write(value)
count = count + 1
if pixelIndex == 149:
pixelIndex = 0
if brightness < 255:
brightness = brightness + 1
else:
brightness = 0
#wait for buffer to empty before repopulating, this also fixes any desync caused by high BAUD rates
#63 is used instead of 64(size of arduino buffer) because it is divisable by 3, 3 bytes per pixel
if idx == 63:
ArdWait()
idx= 0
idx = idx+1
#for displaying 'bps'
bpsCounter+=1
if (time.time() - t) > bpsUpdateSec :
print("bytes sent per sec: ", bpsCounter / (time.time() - t))
bpsCounter = 0
t = time.time()
python output:
bytes sent per sec: 7169.44018428738
bytes sent per sec: 7465.607360341261
bytes sent per sec: 7147.383546265492
bytes sent per sec: 7415.0659037044825
bytes sent per sec: 7618.0125068798325
bytes sent per sec: 7385.654689745196
bytes sent per sec: 8677.095821100802
bytes sent per sec: 7380.6209164907705
bytes sent per sec: 8299.705158217294
bytes sent per sec: 7174.294169611728
bytes sent per sec: 7438.116854144725
bytes sent per sec: 9978.895260607414
bytes sent per sec: 9183.865011077163
So 150 pixels * 3 bytes per pixel = 450 bytes per refresh.
advantage bytes per sec is about 7700, so 7700 / 450 = about 17 refreshes per sec. Id like this to be 30+.
Is there anything I can do or is this just too much info for serial?