2

I have 4 Arduino boards pushing data over UART to 4 serial ports on the Arduino Due at 115200 baud rate.

Data format - <Short URL>,<Number of the Node>

Eg: px.ht/d/mCxG,1"

Arduino Due has 4 hardware serial ports and one native USB port. I want to interface all the 4 UART nodes to each hardware serial of the Due and then push this data onto the SerialUSB port which is native USB at baud rate of 2000000.

What did I try?

  1. Sequential read of all Serial ports - Obviously poor performance
  2. Used Serial Events - For some reason never able to get the callback triggered.
  3. Used some FreeRTOS library and there are a lot of data misses.

When using RTOS, the data from multiple nodes is getting mixed up and printed incorrectly. I'm looking for some efficient way to read parallel data from all UARTs without data overlap and stream data and given the MCU on Arduino Due is very powerful I don't think that's what is bottlenecking the performance.

6
  • Sequential read of all Serial ports - Obviously poor performance ... why should the performance be poor? ... have you tested this?
    – jsotola
    Nov 10, 2023 at 15:38
  • 1
    Add a line terminator to your data format (e.g. '\n'). This will make your life much easier. Nov 10, 2023 at 15:39
  • @jsotola It seems the arduino's wrappers for serial API's are very slow and reading/managing the data is very slow. Yes i did test it
    – Hako
    Nov 10, 2023 at 15:42
  • @EdgarBonet Yes I do have a delimiter at the end, however what's the idea you have that could make it easier? You want me to implement a logic to look for this \n and not print until it is found?
    – Hako
    Nov 10, 2023 at 15:43
  • this may help ... gammon.com.au/serial
    – jsotola
    Nov 10, 2023 at 16:08

1 Answer 1

1

It seems the arduino's wrappers for serial API's are very slow

They aren't. There are some functions that depend on timeouts: these can indeed be very slow. However, if you read the ports in a non blocking fashion, everything should be fast. Non blocking basically means never waiting, and never trying to read more bytes than what is currently available(). For example:

const int buffer_size = 64;  // tune to taste

char buffer1[buffer_size];
int size1 = 0;
// same for buffer2, size2, etc.

void loop() {
    while (Serial1.available()) {
        char c = Serial1.read();
        if (size1 < buffer_size - 1)
            buffer1[size1++] = c;  // buffer the incoming character
        if (c == '\n') {  // found end-of-message
            buffer1[size1] = '\0';  // terminate the string
            Serial.print(buffer1);  // send through USB
            size1 = 0;  // get ready for next message
        }
    }
    // then the same for Serial2, ...
}

If you know a bit about object oriented programming, you can easily rewrite this in a more elegant way, with no repeated code.

4
  • Thanks @EdgarBonet, I'll definitely try out this logic, however I'm wondering if there's a way I can utilize DMA of the SAM3X to directly push data from UART buffer into the USB buffers. I believe this significantly increases performance. What do you say? Is there a DMA wrapper you're aware of that I can use with Arduino IDE?
    – Hako
    Nov 10, 2023 at 16:09
  • There is no DMA-specific support in the Arduino APIs that I know about. But given that you have a fast CPU, I would expect you don't need it. Nov 10, 2023 at 16:12
  • @Hako don't lose sight of the fact that the data arrives at snail's pace ... if the computer was a person, a byte would arrive once a week
    – jsotola
    Nov 10, 2023 at 16:14
  • @jsotola hahahaha, ofcourse i understand sam3x runs at high frequencies but my concern is these nodes might increase in future and I need my code to be scalable. Anyway, let me first try out the edgar's code and come back with some quick results.
    – Hako
    Nov 10, 2023 at 16:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.