About Serial.print() function for DUE

Hi there,

I've noticed that using Serial.print() function DUE takes more time than Mega 2560.

The thing is that I need to read data from a sensor and send it to serial port through a string which contains 44 characters. I've attached the screenshot for detailed information. I'm just wondering why this is happening, is it to do with the precision of the timer?

The sketch I was using is:

int t1,t2;
void setup() {

Serial.begin(115200);

}

void loop() {
t1=micros();
Serial.print("ABCDABCDABCDABCDABCDABCDABCDABCDABCDABCDABCD ");
t2=micros();
Serial.print("time taken: ");
Serial.println(t2-t1);

}

I also test the printf() function on both boards, using the code from the following page:
http://playground.arduino.cc/Main/Printf

The version of the IDE is 1.5.7.

Thank you very much!

I think both has similar speed.

As seen in your result,
Mega print has 44 bytes ( ABCD 11times) sending operation with 3800usec
Due print has 52 bytes ( ABCD 11times and ,xxx,xxx )sending operation with 4500usec
speed caculation below,
3800usec/44bytes = 86usec/byte
4500usec/52bytes = 86usec/byte

I can't find any difference.

Furthermore, Serial.print speed does not rely on microcontroller speed, but rely on Serial communication speed you defined.
You wrote down "Serial.begin(115200);" <- this determines the Serial communication speed

115200bps = 14400 bytes per sec = 1,000,000 usec / 14400bytes = 69.4 usec/ byte, which is a bit smaller than above

You should use the native port, not the programming port, if you care about speed.

SoccerHenry is right.
I have faced similar issues, which is when I did these tests. My code is as follows

int t1, t2;
void setup() {
  Serial.begin(115200);
}
void loop() {
String str = "abcdefghi|abcdefghi|abcdefghi|abcdefghi|abcdefghi|abcdefghi|abcdefghi|abcdefghi|abcdefghi|abcdefghi|";
  t1 = micros();
  Serial.println(str);
  t2= micros();
  Serial.print(" time: ");Serial.println(t2-t1);
  delay(500); 
}

I downloaded this on a DUE and an UNO using the newest 1.5.7 version of the IDE.

The DUE shows a time taken of 8586-8591 uS while the UNO shows around 3172 uS.

Now this is something interesting that I did. Since the string I'm printing is 100 characters long plus 2 for \r \n that is added by the println() function I went to the file

C:\Users\MYUSERNAME\Documents\arduino-1.5.7\hardware\arduino\avr\cores\arduino\HardwareSerial.h
and in lines 40 and 41 I modified my buffers from 64 to 256 just to have extra space in the RAM

#define SERIAL_TX_BUFFER_SIZE 256
#define SERIAL_RX_BUFFER_SIZE 256

and voila! the time taken by the UNO is shown to be 996 uS. My friend tested the same with his MEGA and he had similar results.
Unfortunately the C:\Users\MYUSERNAME\Documents\arduino-1.5.7\hardware\arduino\sam\cores\arduino\HardwareSerial.h which configures the serial for the SAM does not have this BUFFER_SIZE define line and I cannot change it, which is why the DUE is acting so slow in serial writes.

I would appreciate it a lot if someone can point out how to increase the buffer size for the DUE's SAM core.

Thanks

I think I found the buffer, its SERIAL_BUFFER_SIZE in the RingBuffer.h file under C:\Users\MYUSERNAME\Documents\arduino-1.5.7\hardware\arduino\sam\cores\arduino\

However increasing this buffer size did not help the way it helped on the MEGA and UNO. It almost seems to me that the hardwareserial for the DUE has IO blocking going on :s

Someone please help me with this issue.

OK upon further research I have come accross lines 54-57 in the UARTClass.cpp file in the sam\cores\arduino folder

// Configure interrupts
_pUart->UART_IDR = 0xFFFFFFFF;
_pUart->UART_IER = UART_IER_RXRDY | UART_IER_OVRE | UART_IER_FRAME;

Basically interrupts are enabled only for receiver not transmitter. And, I believe this is the problem.

Unfortunately I am not great with C++ programming so can someone with more experience shed some light in this matter?

These measurements are misleading. At 115200, the speed of transmission is exactly the same for Mega and Due.

The difference in Due is that the write blocks, so you waste time waiting. So if you have other stuff to do, it could be made more efficient, but you won't be able to transmit faster. The Mega appears faster because it has not actually sent the data, it has just put the data into a buffer.

In the worst case on Mega, if the transmit buffer is full, then you still end up waiting.

However, I can't see any good reason why the Due should not support a transmit buffer, I think it would be quite easy to add. With the new availableForWrite function, the user can maximise the amount of processing done while waiting for comms, and perhaps minimise latency between transmissions.

I will have a go at creating a patch.

Bob,
I totally agree with you, the speed of transmitting a character is exactly the same for MEGA, UNO or DUE. However, since the MEGA and UNO implements a tx_buffer, the main loop can simply write to the buffer (as long as it doesn't fill up) and the data can be sent out through the use of interrupts. On the DUE, I am baffled as to why the tx_buffer with interrupt service is not implemented.
Also, the Serial data rates I have tested on the MEGA go up to 1000,000bps with the use of other terminal programs to read on the windows side. Do you think this can still be done with the DUE?
Looking forward to your patch.