teensy 3.0 USB Serial speed at 7,5K Bytes/sec

Status
Not open for further replies.

WaltZie

Member
Dear all,
i cannot replicate the maximum speed available by USB Serial port!
I'm expect 820kbytes/sec but i got 7,5kbytes/sec !!! :confused:

here is my test program (client and server).
Someone can help me to find the reason?

Thanks much

________________
Teensy source
________________

#include <stdlib.h>
#include <string.h>

const uint8_t BUFFERDATA = 128;
uint8_t receivedData[BUFFERDATA];
uint8_t *receivedData_ptr = &receivedData[0];
int receivedData_len;

void setup()
{
Serial.begin(57600); // USB is always 12 Mbit/sec
}

void loop()
{
receivedData_len=0;
while (Serial.available()>0)
{
receivedData[receivedData_len] = Serial.read();
receivedData_len++;
}
if (receivedData_len>0)
{
// Received data
sendCOMData(receivedData_ptr,receivedData_len);
}
}

void sendCOMData(uint8_t *data, int data_len)
{
Serial.write(data, data_len);
Serial.send_now();
}


____________
Client c#.NET
____________

using System;
using System.Collections.Generic;
using System.Text;
using System.IO.Ports;


namespace SerialOATH
{
class Program
{

static SerialPort _serialPort;

static void Main(string[] args)
{


// Create a new SerialPort object with default settings.
_serialPort = new SerialPort();

// Allow the user to set the appropriate properties.
Console.WriteLine("COM7");
_serialPort.PortName = "COM7";
_serialPort.BaudRate = 115200;

byte[] data = new byte[] { 0x01, 0x14, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
byte[] result = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };


TimeSpan start = new TimeSpan(DateTime.UtcNow.Ticks);

for (int pp = 0; pp < 1000; pp++)
{
_serialPort.Open();
_serialPort.Write(data, 0, data.Length);
while (_serialPort.BytesToRead < 1) { };
int tot = _serialPort.BytesToRead;
Array.Resize<byte>(ref result, tot);
for (int i = 0; i < tot; i++)
result = (byte)_serialPort.ReadByte();
_serialPort.Close();
}
TimeSpan stop = new TimeSpan(DateTime.UtcNow.Ticks);
Console.WriteLine("It required {0} millisec to complete", (stop.TotalMilliseconds - start.TotalMilliseconds));

Console.ReadKey();
}
}
}
 
Did you try running this benchmark? The complete code for both Teensy and your PC is on that page, and there's even a pre-compiled Windows executable, so all you have to do is download the code, program it onto your Teensy, and run the test program.

I highly recommend you do this first. That can show whether there's a problem with your PC (drivers, other USB device, flaky USB hubs, etc). The known-good test can give you a good baseline measurement, so you can at least know what's possible on your PC.

As for why your test is running so slowly, a second good question (after discovering the baseline performance) would be how many bytes are actually being transferred at once. It looks like your C# code tries to send 28 bytes. That's a pretty small chunk of data, which won't use the USB very efficiently. Are you sure it's being sent as a 28 byte packet? Then the Teensy program reads it byte-wise and send it back. Are you sure it's sending all 28 bytes at once?

From the published benchmarks, you can see Windows is very slow with small transfer sizes. With only 28 bytes, if anything is causing partial transfers, it will really hurt performance. You're also doing a transmit-and-wait-for-reply approach, which tends to be slow. Even if the USB is fast, this sort of communication also suffers from the operating system's latency in scheduling your userspace program to run. In other words, when the USB packet arrives, your program may or may not actually be executing the loop "while (_serialPort.BytesToRead < 1) { };". Windows runs lots of other processes, so there can be delay before your program actually runs again. There also seems to be some strange delay in how Windows schedules actual I/O events. As you can see on the benchmarks, Windows is terrible slow compared to Mac and Linux when it has to process a very large number of small data transfers. I simply don't know enough about what's really going on inside the Windows drivers and kernel. But I do know this sort of small size and wait-for-reply communication runs slowly on all platforms, but particularly slow on Windows.

A much better test would involve sending 1000 messages, each with an incrementing number or some other identifier, and while still sending, when data is available read and parse it, but continue sending until all 1000 messages are transmitted. The reception will be several messages "behind", but at least you'll only wait at the end when there's nothing more to transmit.
 
Thanks I try to follow your suggestions ... your test code work perfectly!
I need to found a way to get best performance in data transfert from teensy and c# lib (max throughput!)


Thanks
 
Last edited:
I need to get maximum performances by teensy3 under windows ...

You'll NEVER get good performance on any system's USB stack, and especially Windows, with a wait-for-reply protocol.

If you want good speed, you must design your protocol to keep sending data without waiting for confirmations.
 
I am still slightly confused with the usb serial transfer. The teensy serial object communicates at 1.2Mbit/s via USB. When I am communicating (sending data) with a program on my computer, example processing or matlab etc, when I create a serial port object, I need to specify the baud rate of the serial port. On matlab, the maximum stable baud rate is 460800. Does it mean that I am limited by the baud rate of my receiving program on my computer?

When teensy communicates with the Arduino serial console isn't it limited by the baud rate of the serial console?
 
when I create a serial port object, I need to specify the baud rate of the serial port. On matlab, the maximum stable baud rate is 460800. Does it mean that I am limited by the baud rate of my receiving program on my computer?

Teensy ignores the baud rate. Data is always transmitted as fast as possible **, regardless of the baud rate you choose. If you're skeptical, try a slow baud rate like 300. You'll see it's still the same very fast speed..

However, Teensy doesn't completely ignore it. The baud rate which you configured on the PC can be read on the Teensy side, using Serial.baud(). Details here:

http://www.pjrc.com/teensy/td_serial.html

This is useful if you're building a USB to hardware serial converter, so you can automatically configure the hardware serial to whatever baud rate the PC actually wanted.


When teensy communicates with the Arduino serial console isn't it limited by the baud rate of the serial console?

No. The baud rate is also ignored. Again, you can verify this easily by trying the slow baud rates. You'll see they have absolutely no effect.


** However, something to understand about "as fast as possible" is USB has true end-to-end flow control and error checking. The speed is automatically reduced if either Teensy or the PC are too busy to process the data at maximum speed. If you stop using Serial.available() and Serial.read() for 5 seconds, and the PC keeps trying to transmit at maximum speed, you won't miss 5 seconds of incoming data, and the incoming data will not overflow any buffers and get lost, like happens with real hardware serial. The very next byte you read 5 seconds later will be the next one the PC actually transmitted. No data gets lost. USB is a really smart, well designed protocol like that! A tremendous amount of complex USB stuff happens behind the scenes to work this magic.
 
Status
Not open for further replies.
Back
Top