0

Metro Mini 328 max. baud? PC control of DotStars too slow
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

Metro Mini 328 max. baud? PC control of DotStars too slow

by digitalcircuit on Thu Jan 10, 2019 7:12 pm

What's the maximum supported baud rate for the Adafruit Metro Mini 328 over the Serial interface for communication with a computer?

The SiLabs CP2104 datasheet claims…
Baud rates: 300 bps to 2 Mbits

…and reading posts on the maximum Arduino baud rate suggests people have gotten close to this speed with the Arduino Uno, as per a StackExchange post, a post on the Arduino Uno forums, etc.

However, in testing, baud rates of 115200 seems consistent, 230400 seems hit-or-miss, losing bytes occasionally, and anything higher fails.

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.

I have an existing C# desktop project that currently controls 50 GE ColorEffects LEDs, and I'm reworking it to support any number of LEDs.

With 300 DotStar LEDs, the protocol roughly looks like the following, where each <thing> is a byte…
Code: Select all | TOGGLE FULL SIZE
<command><LED 1 red><LED 1 green><LED 1 blue><LED 2 red><LED 2 green><LED 2 blue>[…]

…resulting in 901 bytes total.

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.

From research, the Teensy appears to be capable of much faster USB serial communication and there's a shield for DotStars on Adafruit, but I don't know if that impacts the speed at which the computer can send to the Teensy, and/or if this would work.

Current hardware:

Software:

Portion of serial reading code:
Code: Select all | TOGGLE FULL SIZE
  if(Serial.available()>0) {
    // Hue, intensity, or both?
    char command = Serial.read();
    if (command=='I') {
      // [these commands aren't used here]
    } else if(command=='H') {
      // read the hue data and assign it
      for(int i=0;i<(LIGHT_COUNT);i++) {
        while(Serial.available() < 3) {
        }
        strip.setPixelColor(i, strip.gamma8(Serial.read()), strip.gamma8(Serial.read()), strip.gamma8(Serial.read()));
      }
      changed = true;
      commandSent = true;
      lastCommandTime = millis();
    }
    // [other commands]
  }
  if(changed) {
    strip.show();
    Serial.println('#');
    // Don't acknowledge the write until the LEDs have been updated
    changed = false;
  }


Serial baud rate test code from the StackExchange post:
Code: Select all | TOGGLE FULL SIZE
void setup(){};

void loop()
{

  delay(1000);
  Serial.begin(57600);
  Serial.println("\r\rBaud-rate = 57600");
  delay(1000);
  Serial.begin(76800);
  Serial.println("\r\rBaud-rate = 76800");
  delay(1000);
  Serial.begin(115200);
  Serial.println("\r\rBaud-rate = 115200");
  delay(1000);
  Serial.begin(230400);
  Serial.println("\r\rBaud-rate = 230400");
  delay(1000);
  Serial.begin(250000);
  Serial.println("\r\rBaud-rate = 250000");
  delay(1000);
  Serial.begin(500000);
  Serial.println("\r\rBaud-rate = 500000");
  delay(1000);
  Serial.begin(1000000);
  Serial.println("\r\rBaud-rate = 1000000");
  delay(1000);
  Serial.begin(2000000);
  Serial.println("\r\rBaud-rate = 2000000");
};

digitalcircuit
 
Posts: 3
Joined: Wed Jan 09, 2019 11:31 pm

Re: Metro Mini 328 max. baud? PC control of DotStars too sl

by westfw on Thu Jan 10, 2019 8:59 pm

There are three things needed to run a particular bit rate on the serial (UART) interface of an Arduino.
  1. 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.
  2. 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.
  3. 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.

All that said...
115200 baud rate, it's taking around 80 ms to send [901 bytes of ] data

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

in testing, baud rates of 115200 seems consistent, 230400 seems hit-or-miss, losing bytes occasionally, and anything higher fails.

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.)
westfw
 
Posts: 1522
Joined: Fri Apr 27, 2007 1:01 pm
Location: SF Bay area

Re: Metro Mini 328 max. baud? PC control of DotStars too sl

by digitalcircuit on Fri Jan 11, 2019 1:41 am

Thank you very much for the detailed explanation!

  1. 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.
  2. 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%.
  3. 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.

Noted!

Referencing your rough estimate (given 8 bits, 1 stop bit, no parity but add a bit anyways), 1 Mbps results in about 1 sec ÷ (1000000 bps × (1 byte ÷ 10 bit) × (1 cmd ÷ 1000 byte)) = 0.01 sec per cmd. With the above determined 4 ms for processing and .show(), 10 ms for raw receiving, that still offers 2 ms of overhead to fall within a 16 ms target for 60 FPS.

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.

I'll put more effort into this, including experimenting with other test programs and different serial console methods (so far: "screen", Putty, C#'s SerialPort), etc. It's likely I overlooked something, whether in the serial terminal, Ubuntu 16.04's configuration, the Arduino sketch, etc.

Plan B: 32-bit hardware:
Yes, anything with "native" USB communications will be "much faster" […]

Thanks again for explaining!

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…

32-bit hardware list:

Does this seem reasonable?

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.

digitalcircuit
 
Posts: 3
Joined: Wed Jan 09, 2019 11:31 pm

Re: Metro Mini 328 max. baud? PC control of DotStars too sl

by westfw on Fri Jan 11, 2019 8:17 pm

Referencing your rough estimate (given 8 bits, 1 stop bit, no parity but add a bit anyways)

One start bit, 8 data bits, one stop bit.


different serial console methods (so far: "screen", Putty, C#'s SerialPort), etc. It's likely I overlooked something, whether in the serial terminal, Ubuntu 16.04's configuration, the Arduino sketch, etc.

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.)
westfw
 
Posts: 1522
Joined: Fri Apr 27, 2007 1:01 pm
Location: SF Bay area

Re: Metro Mini 328 max. baud? PC control of DotStars too sl

by adafruit_support_bill on Fri Jan 11, 2019 8:52 pm

(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.)

And if your Arduino or compatible processor has native USB support, then the 'baud-rate' is essentially meaningless, since everything will move at USB speeds regardless of the rate selected.

adafruit_support_bill
 
Posts: 72774
Joined: Sat Feb 07, 2009 10:11 am

Re: Metro Mini 328 max. baud? PC control of DotStars too sl

by digitalcircuit on Thu Jan 17, 2019 2:19 am

Thank you for the constructive feedback and detailed explanations!

IIRC, unix-like OSes (including linux and MacOS) have a standard "set speed" method for serial ports […]
(As an experiment, try finding a windows box for testing as well. […]


Good advice! Unfortunately, I don't have a native Windows system around, and despite following a guide for VirtualBox Arduino passthrough, it wasn't properly detected and configured despite installing the drivers as per the Adafruit guide. The various methods mentioned for Linux/Unix didn't seem to unlock higher speeds, either, or at best, only twice, not near the 1 mbps to approach a smooth frame rate.

So.. ultimately, I opted for plan B as both of you noted, and got an ItsyBitsy M4 Express + a 74AHCT125 - Quad Level-Shifter.

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.

digitalcircuit
 
Posts: 3
Joined: Wed Jan 09, 2019 11:31 pm

Please be positive and constructive with your questions and comments.