Serial latency (again)...on Mega 2560

I know there are several topic about the 20ms delay latency in serial comunication beetwen Arduino board and PC, but they don't seem to match my situation...

I'm fighting with some serial latency issues on my Mega 2560: as far as i can see with oscilloscope, i have always about 20ms delay during serial comunication between my PC (Win7 64bit) and the Arduino.

I read that it can be fixed setting the latency time in the advance setting of the COM port under Devices in windows, but it's not my case: this option doesn't exist in the advance settings of my serial port, i guess because 2560 does not use the FTDI USB-to-serial driver chip, but ATmega8U2...so probaly different drivers.

I also see many pages about a delay in RXTX library, that shoul be fixed in IDE 1.5.6 (Update rxtx library, fix some common issues (high latency..) [imported] · Issue #532 · arduino/Arduino · GitHub) so i tried it, but still the same problem (even if the bug has been closed 3 months ago).

Currently as workaround, i used a usb to serial board based on PL-2303hx chip, connected to RX3-TX3 and it works fine with low latency time.

So...is there some other solution to this problem, or i must use my workaround forever?
I need at least 20 pins for digital I/O and 5V (not 3.3V)...is there another board (possibly Arduino) i can use?

It's hard to comprehend your latency issue without seeing how you send data. Is it ASCII data or binary data? ASCII data is easier for humans to read, but it takes time to convert binary data to an ASCII representation, and the representation is typically larger than the binary data, meaning that it takes longer to send.

How are you measuring the latency? What marks the beginning of the latency period? What marks the end? I can't see how you can measure latency using an oscilloscope.

Can you post a short sketch that demonstrates your problem?

And the PC code as well if that is necessary.

...R

i’m sending binary data.

With oscilloscope i saw the low latency of the usb dongle displaying TX3 and RX3: the protocol i implemented between PC<->Arduino has been made so that when the PC send a 8bit number to the Arduino, it responde soon with a proper answer, checked by the PC; in VB code i repeated this step in a loop, and so i see the very fast answers between the two devices (with usb dongle).

When i try to do the same without the usb-dongle, the process is very slow (i see it because when Arduino receives the number, it change some pins status). Tomorrow i’ll try to post some screenshots of the scope (i’ll try also for the TX1/RX1, without the dongle).

I post here the sketch i’m using:

/*
 My serial protocol
 Language: Wiring/Arduino
 
 Implement a serial proptocol to read/write the digital pins of ArduinoMega 

 the format for the byte to send to set the n pin as output with specified value is: XXXXXX0V
 where XXXXXX is the ID of the pin (6 bit -> max 64 pins), and V is the value to be set for the pin (0-LOW / 1-HIGH)
         
 the format for the byte to send to read the n pin is: XXXXXX10
 where XXXXXX is the ID of the pin (6 bit -> max 64 pins)
        
 the byte to send back for the response is in the form XXXXXXYV
                
 */
 
int inByte = 0;         // incoming serial byte
int pinNum;
int op;
int pinValue;
int outByte;

void setup()
{
  // start serial port at 9600 bps:
  Serial.begin(115200);
  // initialize the digital pin as an output.
  // Pin 13 has an LED connected on most Arduino boards:
  pinMode(13, OUTPUT); 
  digitalWrite(13, LOW);
}

void loop()
{
  // if we get a valid byte, read analog ins:
  if (Serial.available() > 0) {
    // get incoming byte:    
    inByte = Serial.read();
    outByte = inByte;
    pinNum = inByte >> 2;
    op = inByte & 2; // the operation I/O is stored in bit 1
    if (op==0) { // OUTPUT operation
       pinMode(pinNum, OUTPUT);
       pinValue = inByte & 1; // the value to set for the pin is specified at bit 0
       digitalWrite(pinNum, pinValue);
    } else {    // INPUT operation
        pinMode(pinNum, INPUT);
        pinValue = digitalRead(pinNum);
        outByte = outByte | pinValue; // set the value read as LSB 
    }
    Serial.write(outByte);               
    
  }
}

And here is the main VB function i’m using:

Function writeArd(ByVal pinID As Byte, ByVal valueToWrite As Byte) As Byte
        'the format for the byte to send to set the n pin as output with specified value is: XXXXXX0V ...
        ' ... where XXXXXX is the ID of the pin (6 bit -> max 64 pins), and V is the value to be set for the pin (0-LOW / 1-HIGH)
        Dim byteTosend As Byte = (pinID << 2) + valueToWrite
        Dim byteRead As Byte
        Try
            s.Write(New Byte() {byteTosend}, 0, 1)
            While s.BytesToRead() <= 0
            End While
            byteRead = s.ReadByte()
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try
        If byteTosend = byteRead Then
            Return 1
        Else : Throw (New System.Exception("Error reading Arduino pin; byteToSend = " + IntToBin(byteTosend) + ", byteRead = " + IntToBin(byteRead)))
        End If
    End Function

I’ll try to write some code to replicate the issue in some easier way…meanwhile every suggestion is appreciated :slight_smile:

You haven't said how you are measuring the latency - as @PaulS requested.

Without knowing that I can't test anything.

...R

Ok…
i made some test, and i have to admit that i was wrong talking about “latency”: the waveforms taken through scope show that Arduino is answering fast in both cases (as with usb-dongle, as with is “native” usb ), but with native usb the PC is waiting more time (about 3-4ms) before sending the next byte, while with usb-dongle is able to do it after about 200us.
Thanks to PaulS to put my attention on the measures i did (wrong :slight_smile: ).
Here two screenshots.
The first with usb dongle:

ans this one is the native-usb:

You can see clearly the PC (blu one on the top) sending the data, and the Arduino responding in 50us (yellow waveform on the bottom); but in the second case, the PC is “waiting” 4ms.

So, the problem is different from what i supposed, but still here: why with the same code the PC is waiting so long before to send another byte?
Of course the drivers used for the two devices are different, but they have the same settings both in Windows (as far as i can see in Windows Devices, in port details) and in my VB code.

Any ideas?

My understanding of the USB system is that there is a delay of at least 1 msec between new transmissions. Which makes USB very poor for sending small packets of data. Of course once it starts it is fast.

But I can't figure out how this matters for your project?

In my experience the Arduino-PC comms can operate as fast as you would expect for a given baud rate.

...R

As you can see from the waveform related to the usb-dongle, actually IS possible to send many repeated trasmission separated by only 200us (not 1ms) over usb, and i saw the same with other device (similar to Arduino, with serial over usb) doing the same, which i used in my project before trying Arduino.

I think that running 20 times slower, is an issue for every kind of project :slight_smile:

rafscipio:
As you can see from the waveform related to the usb-dongle, actually IS possible to send many repeated trasmission separated by only 200us (not 1ms) over usb, and i saw the same with other device (similar to Arduino, with serial over usb) doing the same, which i used in my project before trying Arduino.

I think that running 20 times slower, is an issue for every kind of project :slight_smile:

I have no idea what your nice graphs are displaying - you have not said how they were produced. The graphs seem to show single pulses at intervals. But a piece of data is not a single pulse - so I have no idea what the pulses are.

Saying something is 20 times slower is meangingless without a context. When I was experimenting I wrote some PC and Arduino code that sent data in both directions and I timed how long it took to do 1000 loops. As I said already, the throughput was consistent with the chosen baud rate.

If you have some code that demonstrates the problem you perceive I will be happy to try it.

...R

Probably i wasn’t clear enough…i try again.
As the code show (pls check it), the PC is simply sending 8bit of data (doesn’t matter what its meaning is, but if you’r curious, it’s describred in the code i posted too) and soon after, it waits for a response and then it keeps the message received:

            s.Write(New Byte() {byteTosend}, 0, 1)
            While s.BytesToRead() <= 0
            End While
            byteRead = s.ReadByte()

This transmission is the blu waveform (the “pulse” is the trasmission of 8 bit all set to “0” @115200bps), taken with the probe of the scope on the Arduino pin RX (RX0 for the native usb, RX3 for the usb-dongle).
When Arduino receive this data, it analyze it (again: doesn’t matter in which way, but everything is in the sketch i posted) and it answer with 8 bit of data. This waveform is the yellow one at the bottom and as you can see, it takes less then 50us after the end of the blu one to be transmitted.

This process (PC send 8bit data+Arduino answer) is repeated in a loop many times; with usb-dongle the PC is able to send another 8bit after about 200us (first graph: from the end of the first yellow “pulse” to the beginning of second blu one there are about two units, so @100us/div is 200us); but with native usb there are 4 units @1ms/div=4ms.

The effect is: when i repeat (let’s say 2000 times) this loop, with usb-dongle takes 1sec, while with the native-usb it takes 20sec.

I’ll try to post some easier code asap; if you’r not familiar with VB, pls let me know which language u prefer.

Other suggestions are welcome (if something is not clear, i’ll happy to (try to) clarify it).

The signal you detect at the Arduino pins is BEFORE the outgoing data gets into the USB system or AFTER the incoming data has left the USB system. Your 'scope is not viewing the USB system and your pictures do not invaildate what I said about the USB2 1 millisec delay.

Perhaps what you are really concerned with is how quickly, after it receives a incoming byte on the Rx pin can the Arduino present a byte on the outgoing Tx pin?

…R

I rencently ran into the same issue while developing a remote procedure call library. The 4 ms delay is due to the firmware on atmega8u2. It is based on a by now outdated example from the LUFA usb library. Basically it will only send serial data to PC every 4 ms or after receiving 96 bytes. You can upload new firmware to the chip by installing dfu-programmer or atmels flip. I did it on Uno, search google for mega. You need to make the 8u2 go into dfu-mode.

As for new firmware I haven't found any on the internet, so I tried out modifying the existing. By changing the original arduino-usbserial firmware to pass on serial data to the pc in each loop in the main function, I went from 244 remote function calls per second to 400 - 500. These are function calls with return data. Calling functions without return data the number of function calls correspond to the baud rate divided by data transmitted (in both original and modified firmware). But looking at just the amount of data, I was supposed to to 2000+ calls per second if there was no latency. So the situation had improved, but it still wasn't impressive.
The original arduino-usbserial is built against a LUFA library release from 2010, but the have been numerous releases since. Unfortunately the code doesn't build against the newer version right away. But the LUFA library contains its own example of a usb-serial converter which has evolved a bit since the one the arduino version was based on back in 2010.
I modified the LUFA example to work with the UNO board. This improved function calls to 700-900 per second. Increasing the baud rate makes function calls with less/more return have more similar performance, but they never get much above 900 per second. So there is latency somewhere I still can't get around.
The new firmwares have been acting a bit strange right after the com port is opened. When the connection is up it seems to go on without problems, but when calling remote functions immediately after opening the comm port I've been getting unexpected data or not getting expected data. Not sure what the problem is.

EDIT:
The weird behavour turned out to be due to noise on the line when resetting the main AVR (it is reset when opening the connection). I don't know why this didn't happen with the old firmware, as the code in this part is fairly similar. Probably the timing changed somewhere in LUFA. Anyways, checking the framing error flag of the USART before passing on data to USB solved the problem. I think this is good practice in any case.
The new firmware works great. When boosting the baud rate, remote function calls get very close to 1000/sec, typically 950.