I realize the Adafruit Metro Mini is merely Arduino-compatible, not an Arduino exactly.

Background

I want to control 300 DotStar LEDs via a USB interface (e.g. via Arduino) to the computer as fast as inexpensively possible, in a cross-platform (Windows/Linux) way. From what I've read, the .NET and Mono runtime can handle higher than normal baud rates, and indeed with 230400 it's able to read the Metro's announcement message, it's just not able to send the data without seemingly missing bytes.

However, at 115200 baud rate, it's taking around 80 ms to send this data. Simply reading and discarding the data as fast as possible on the Metro results in 77 ms. I'd hope to get at least something four times as fast, if not as close to the update rate of the DotStars as possible.

There are three things needed to run a particular bit rate on the serial (UART) interface of an Arduino.

The AVR UART and the USB/Serial device both have to support that bitrate. In theory, the AVR supports speeds "up to" 2Mbps (F_CPU/8) - in reality, the higher bitrates are very quantized - you can get exactly 250k, 500k, 1M, and 2M, but 230400bps would have a pretty high error (actually running at 250k) I don't know if the cp2104 has similar limitations.

The AVR UART and USB/Serial device have to agree within less than 5% on the bitrate. When you set the AVR to 115200bps, it actually generates a rate that's about 2.1% off (because of the "quantization.") That's usually OK, unless the CP2104 is off by 3% in the other direction.

The AVR has to have enough cycles to process the data. At 1Mbps, you have 160 clock cycles for each byte. That's not very much. In your case, you're also blasting out dotstar serial, which is similarly "costly", so I suspect you'll hit a CPU limit.

I am surprised that you can't get 500k to work, at least in a test program. It might be worth additional effort to figure out why it's not working.

the Teensy appears to be capable of much faster USB serial communication ..., but I don't know if that impacts the speed at which the computer can send to the Teensy

Yes, anything with "native" USB communications will be "much faster", both because USB is inherently faster, but also because the USB hardware will receive entire blocks worth of data without CPU intervention. This should include numerous 32u4 boards (feather and itsybitsy 32u4 boards, since this is the Adafruit forum!) as well as most of the SAMDxx boards. I've gotten in excess of 6Mbps throwing away data over a USB port on a SAMD21 board.

You might want to look into some method of compressing the communications protocol, as well. The PC side can probably do LOTS of computation to come up with a data stream that the Arduino side can uncompress quickly, and it might be a "net gain." (OTOH, it might make timing more difficult.)

AVR UART and USB/Serial bitrate:That makes sense! Given the 48 MHz rate of the CP2104, and the formula from the datasheet 6.1. Baud Rate Generation, it appears the USB/Serial device should also be able to perfectly align with 250k, 500k, 1M, and 2M. Specifically, 48 MHz÷(2×1×1 MHz) = 24, and with clock divider of 24, baud rate = 48 MHz÷(2×1×24) = 1 MHz, assuming bps and Hz are interchangeable in this situation.

AVR UART and USB/Serial bitrate error:Also makes sense. According to the CP2104 datasheet, its own error for e.g. 1Mbps should be within 0.25%.

AVR processing cycles:I suspect this will be my limiting factor when I move into ludicrous refresh rates. Going by the 77 ms (discarding) vs. 81 ms (with LEDs) time to acknowledge differences, there's about a 4 ms performance hit to send to the LEDs via SPI. Still pretty fast.

Plan A: faster baud rate for Metro Mini:

That seems about right. 115k is about 10k bytes/s, so 1k bytes takes about 0.1s.

I recall reading on USB blocks elsewhere, too, and that I should make sure to send as much data over serial at once, to let the drivers attempt to group writes (which I do - the entire 901 byte array is sent from the computer in a single write call).

Theoretically, if I cannot get the UART Serial communication method to work satisfactorily, going by your recommendations and other sources, one possible "native USB" route would be…

It's probably excessive, but given the price difference of ~$5 for a one-off purchase, the room for expanding on-board capabilities is nice.

You might want to look into some method of compressing the communications protocol, as well.

Good advice, and I am considering this… though as a later resort. If I can get raw streams to work, I'll stick with that to avoid the unpredictability of compression ratios. I'm still developing LED patterns for e.g. music reaction, and it'd be rather unfortunate to devise some fancy new arrangement that breaks the compression setup.

IIRC, unix-like OSes (including linux and MacOS) have a standard "set speed" method for serial ports that selects one of several standard bit rates, and a different mechanism for selecting "other" speeds. You may have to hunt a bit for for a program that supports the later. Related?: https://stackoverflow.com/questions/490 ... port-linux

(As an experiment, try finding a windows box for testing as well. If 500kbps doesn't work there, it might not be worth continuing to fiddle with linux.)

(It's a bit silly, since the windows side is talking USB and all it really does when you "set speed 19200" is send a USB command "set speed 19200" to the USB/Serial adapter on the Arduino.)

I haven't yet connected the level shifter, but I can at least confirm that without optimization, 300 × 4 = 1200 bytes of data get received via USB and pushed out to the (not yet connected) DotStar strip within 4 ms, a significant improvement. The extra byte is for brightness; I may try to make use of the SK9822's constant current driver.

The only thing left hardware-wise is connecting the level shifter, which hopefully is hard to mess up - and I got two spares, just in case :) I'll probably repurpose the Metro Mini 328 to slim down an older Arduino Uno project.

Thanks again for your guidance! For now, I'll consider this resolved/worked around.