Go Down

Topic: Java or C library for USB communication with Due (Read 464 times) previous topic - next topic

Winzell

Hey guys! I'm working on a project where I will control a bunch (900) ws2812b LEDs with an Arduino Due and have an interface with the pc-program that's supposed to determine the colors. The program on the pc end is going to be used for doing real-time animations and probably some kind of ambilight.

I've gotten this to work on an UNO using a USB-cable directly through the programming port. On the pc I used a Java-program, and everything worked fine. This was however with 200 LEDs. Using more that those 200 LEDs will not give me a refresh rate of 60hz as I want to achieve because of the limitations in transfer speed. I heard that the Arduino Dues native USB supposedly works as a USB device/host and can transfer data as fast as USB goes and that I would be able to get a couple of Mbauds.

On the Due I see that I have to use the SerialUSB library and that's supposed to work as the normal Serial one. Now to the problem. I have no idea how to setup the connection on the pc side. Is there a special library for USB connections or does the any serial library? For the Uno I used jSerialComm. Like for the SerialUSB on the Arduino you still set a baudrate but that's supposed to be ignored. Will the baudrate on the pc also be ignored if I use the same serial library or do I need another one?

So, to clear up. What do I need on the computer side to be able to use the Dues native USB and get higher transfer speeds?

I prefer Java since that's the only language I know well but if C has better options, I guess I could try learn that. Or just wrap it for java.

sterretje

#1
Dec 11, 2018, 11:59 am Last Edit: Dec 11, 2018, 12:04 pm by sterretje
My experience is with Leonardos (also using native USB). Part of the below might apply to the Due as well.

Moving code from an Uno to a Leonardo only requires to add the while(!Serial); in setup() if it's not already there. The PC side does not change, it will still show as a serial port.

Problem with that is if it has to run stand alone as it will not get passed there. A timeout is the usual way.

There is a pitfall as well in case you send data to the PC. At the moment that you disconnect or close the PC application, the Leonardo will come to a grinding halt as it can't get rid of the data that you're placing in the low level 'USB' buffer via the Serial prints / writes. The solution is to only print/write when there is enough place in the buffer using Serial.availableForWrite().

If you know that you have to send 10 bytes, make sure that there is space for 10 bytes or more.
Code: [Select]

if(Serial.availableForWrite() >= 10)
{
  // send
}


===
Be aware that the Due is a 3.3V device. If transmission speed is the only issue, you can also use a Arduino Leonardo or Micro, or a Sparkfun / Pololu equivalent; the latter are often smaller in size. I only have experience with the Leonardo and know that the bootloader takes more space. So if you are tight on code space, they might not be the solution. You can easily test by compiling your code for e.g. the Leonardo.
If you understand an example, use it.
If you don't understand an example, don't use it.

Electronics engineer by trade, software engineer by profession. Trying to get back into electronics after 15 years absence.

Winzell

But will that give me higher transfer speeds? isn't copying the code from the Uno and still use the normal Serial library going to have the same restrictions? I thougth that i needed to use the SerialUSB one in order to get the higher speeds that you usually get with USB.

And i'm really just sending data from the pc to the arduino and not the other way. Like tha handshaking and protocols i believe i can figure out by my self as long as i know how to set up the connection with a fast enough transfer speed from the beginning.

I don't really get the diffrence in code using "real" USB vs the virtual com.

If i use the SerialUSB on the arduino will the computer ignore its set baudrate aswell beacause the drivers are handeling the communication or do i need to change anything in my java program like switching to another library to be able to use the "real" USB?

ard_newbie


Once SerialUSB has been initialized, the DUE is in Device Mode, High Speed (480 MHz), however SerialUSB do not leverage all the High Speed potential. Be sure to write while(!SerialUSB); just after SerialUSB.begin(250000); // Baud rate not relevant

Maybe a partial answer with this blog relative to Processing (written in java ?) and SerialUSB:

https://mpuprojectblog.wordpress.com/2013/07/19/arduino-dues-serialusb-and-processing/


sterretje

But will that give me higher transfer speeds? isn't copying the code from the Uno and still use the normal Serial library going to have the same restrictions? I thougth that i needed to use the SerialUSB one in order to get the higher speeds that you usually get with USB.
Yes, it will.

In the 32U4 based systems, Serial is mapped to the native USB port; and Serial1 is the hardware UART.


If i use the SerialUSB on the arduino will the computer ignore its set baudrate aswell beacause the drivers are handeling the communication or do i need to change anything in my java program like switching to another library to be able to use the "real" USB?
Referring to the Leonardo, it ignores the baudrate settings. You can set Serial in the Leonardo to any speed and the PC side does not care.
If you understand an example, use it.
If you don't understand an example, don't use it.

Electronics engineer by trade, software engineer by profession. Trying to get back into electronics after 15 years absence.

Winzell

Once SerialUSB has been initialized, the DUE is in Device Mode, High Speed (480 MHz), however SerialUSB do not leverage all the High Speed potential. Be sure to write while(!SerialUSB); just after SerialUSB.begin(250000); // Baud rate not relevant

Maybe a partial answer with this blog relative to Processing (written in java ?) and SerialUSB:

Thank you for the link I will be checking it out! With high speed i just meant higher than what you can squeeze out of an Uno and atleast like 2Mbaud. I read that the baudrate would not affect the actual speed, however at 1200 it will reset the SAM3X

Yes, it will.

In the 32U4 based systems, Serial is mapped to the native USB port; and Serial1 is the hardware UART.

So, whats the difference between Serial and SerialUSB then if they both uses the native USB? I tried a simple loopback sketch on the arduino, first with Serial and then SerialUSB. The Serial library still considered the set baudrate and did not work at megabauds.

Referring to the Leonardo, it ignores the baudrate settings. You can set Serial in the Leonardo to any speed and the PC side does not care.
Maybe it's different on the Due because my Serial object seems to use the baudrate setting. However using SerialUSB the baudrate was ignored on both arduino and pc

sterretje

#6
Dec 11, 2018, 06:22 pm Last Edit: Dec 11, 2018, 06:26 pm by sterretje
So, whats the difference between Serial and SerialUSB then if they both uses the native USB? I tried a simple loopback sketch on the arduino, first with Serial and then SerialUSB. The Serial library still considered the set baudrate and did not work at megabauds.
Did you use a 32U4 based board (like the Leonardo)?

From pins_arduino.h for the Leonardo

Code: [Select]
// These serial port names are intended to allow libraries and architecture-neutral
// sketches to automatically default to the correct port name for a particular type
// of use.  For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN,
// the first hardware serial port whose RX/TX pins are not dedicated to another use.
//
// SERIAL_PORT_MONITOR        Port which normally prints to the Arduino Serial Monitor
//
// SERIAL_PORT_USBVIRTUAL     Port which is USB virtual serial
//
// SERIAL_PORT_LINUXBRIDGE    Port which connects to a Linux system via Bridge library
//
// SERIAL_PORT_HARDWARE       Hardware serial port, physical RX & TX pins.
//
// SERIAL_PORT_HARDWARE_OPEN  Hardware serial ports which are open for use.  Their RX & TX
//                            pins are NOT connected to anything by default.
#define SERIAL_PORT_MONITOR        Serial
#define SERIAL_PORT_USBVIRTUAL     Serial
#define SERIAL_PORT_HARDWARE       Serial1
#define SERIAL_PORT_HARDWARE_OPEN  Serial1

// Alias SerialUSB to Serial
#define SerialUSB SERIAL_PORT_USBVIRTUAL

which boils down to SerialUSB being the same as Serial. However, Serial on the 32U4 based board is defined differently from Serial on e.g an 328P based board

All AVR processors (HardwareSerial.h)
Code: [Select]
#if defined(UBRRH) || defined(UBRR0H)
  extern HardwareSerial Serial;
  #define HAVE_HWSERIAL0
#endif
#if defined(UBRR1H)
  extern HardwareSerial Serial1;
  #define HAVE_HWSERIAL1
#endif
#if defined(UBRR2H)
  extern HardwareSerial Serial2;
  #define HAVE_HWSERIAL2
#endif
#if defined(UBRR3H)
  extern HardwareSerial Serial3;
  #define HAVE_HWSERIAL3
#endif

This basically tells you the hardware serial port type and how you can refer to them in the code. You can find the implementations in the HardwareSerial.cpp and HardwareSerialX.cpp files.

You have to dig a little further and consult the datasheets. The 328P has the UBRR0 register and hence the UART is 'called' Serial. The 32U4 does not have the UBRR0 (or UBRR) register so the condition #if defined(UBRRH) || defined(UBRR0H) evaluates to false and there is no Serial from that block of code. The 32U4 has the UBBR1 register and hence the UART is called Serial1.

So we have a 32U4 without Serial at this stage. Looking further you can find this
324U (USBAPI.h)
Code: [Select]
extern Serial_ Serial;

which says that Serial is of type Serial_. The implementation can be found in CDC.cpp.
If you understand an example, use it.
If you don't understand an example, don't use it.

Electronics engineer by trade, software engineer by profession. Trying to get back into electronics after 15 years absence.

ard_newbie

#7
Dec 11, 2018, 06:24 pm Last Edit: Dec 11, 2018, 06:49 pm by ard_newbie
This is quiet simple: Serial uses UART peripheral, Serial1,2,3,4 use USART0,1,3,2 and SerialUSB uses the UOTGHS peripheral.

Edit: Speed of SerialUSB.print() is ~ 849 KBytes/sec. I don't know SerialUSB.read() speed.

This speed may seem relatively high, however SerialUSB do not leverage UOTGHS DMA, so, as per datasheet, the maximum achievable speed should be much higher. Even if it may sound strange for a 64-bit uc PC, but the PC itself is a limiting speed factor.

Winzell

Did you use a 32U4 based board (like the Leonardo)?
No I actually have a Due with the SAM3X. I stated that in my original post but wasn't super clear.

I guess it's different on the due then since my tests seemed to use the baudrate aswell.

This is quiet simple: Serial uses UART peripheral, Serial1,2,3,4 use USART0,1,3,2 and SerialUSB uses the UOTGHS peripheral.

Edit: Speed of SerialUSB.print() is ~ 849 KBytes/sec. I don't know SerialUSB.read() speed.

This speed may seem relatively high, however SerialUSB do not leverage UOTGHS DMA, so, as per datasheet, the maximum achievable speed should be much higher. Even if it may sound strange for a 64-bit uc PC, but the PC itself is a limiting speed factor.
Yes the UART chip was the bottleneck on the Uno I believe. I'm aware that I will not be able to get the max speeds with the Arduino not the pc. Now there is other limitations. I'm pretty sure I'll get the speeds I need anyway. Like 100-200 kByte/a should be enough.

Thanks for all the help guys! I've got the two of them talking to each other now and it seems to be very fast. Not yet tested the transfer speed

sterretje

Sorry, it was me that got side tracked after my first reply and possibly derailed the thread. Your opening post was clear.
If you understand an example, use it.
If you don't understand an example, don't use it.

Electronics engineer by trade, software engineer by profession. Trying to get back into electronics after 15 years absence.

Winzell

It's okay.

I've been doing some testing and it's definetly faster than what i had with the Uno. It now seems like the Arduino Dues processing speed is the limitation?

By just having a Arduino sketch that reads the incoming bytes in the loop method only gives me about 80kByte/s. I thought that i would be getting a bit more. I was hoping for 200kByte/s, and thats when the sketch is done and has some more code in it aswell.

Do you guys know any tricks to speed this up or am i hitting the limitations of the Arduino?

ard_newbie

#11
Dec 12, 2018, 10:43 am Last Edit: Dec 12, 2018, 11:00 am by ard_newbie
Some have found a workaround to improve ( a bit) SerialUSB for buffer reading. However, a much higher speed could be reached for reading and writing using UOTGHS DMA, but unfortunately neither Atmel nor Arduino team didi it . We should do that ourselves.....

See this thread, from reply #14:

https://forum.arduino.cc/index.php?topic=391757.0

Note 1: that SamS70 has the exact same USB 2.0 peripheral (except that it does not have OTG) called USBHS instead of UOTGHS. Since this uc is more recent, maybe someone knows a fast version for Reading with DMA.

Note2: I recently posted a sketch to leverage UART PDC DMA for receiving and transmitting. It should be rather fast to receive with this sketch from a PC, even if this is not as fast as it could be the USB 2.0 interface and a DMA in High Speed Mode.

See reply #4:

https://forum.arduino.cc/index.php?topic=470005.0

Winzell

Some have found a workaround to improve ( a bit) SerialUSB for buffer reading. However, a much higher speed could be reached for reading and writing using UOTGHS DMA, but unfortunately neither Atmel nor Arduino team didi it . We should do that ourselves.....
Thank you. I'll try out the changes they suggest and see if it makes a difference. It seemd like they were getting almost 10x the speed i got. As I said i only got 80kBytes/s.

Note 1: that SamS70 has the exact same USB 2.0 peripheral (except that it does not have OTG) called USBHS instead of UOTGHS. Since this uc is more recent, maybe someone knows a fast version for Reading with DMA.

Note2: I recently posted a sketch to leverage UART PDC DMA for receiving and transmitting. It should be rather fast to receive with this sketch from a PC, even if this is not as fast as it could be the USB 2.0 interface and a DMA in High Speed Mode.
I'll try your sketch aswell and try and look up if someone else has managed something similar. I'm still in high school and don't really know much about how communication really works. All these shortenings doesn't say me much even if i can work out what thay stand for. And have very little experience in C so changing around in the arduino librarys is a bit over my head i believe. Making the actuall program-code for the arduino is enough for me. This is for a schoolproject im doing and i definitly want to learn but this stuff is a bit to advanced for me so im glad i'm getting help!

So i'll try switching around with the sketches posted in the threads you linked and see if that makes any difference. Otherwise i'll cope with what i have now. I'm probably able to get a refreash rate around 20hz with 900 LEDs which still is fine.

I'll post my results tomorrow sometime.

Again, thanks for all the help!

Winzell

Also if it's the transfer speed thats the limitation, do you believe that i could gain fps by making the Arduino create frames between the ones it gets from the pc by making a average of the frame before and the one after.

This would only work if the time it takes to create a new frame based on 2 others is less than the time it takes to read a frame. And it's not really worth if this method only give me a slight increase since I will lose the abillity to control every other frame.

Any idéa of time consumptions for those two options?

Go Up