Different TX buffer for serial, serial1, serial2, ...?

Is it possible to have different SERIAL_TX_BUFFER_SIZEs for the different serial ports of an Arduino Mega or Due?

I will transmit long messages only over one port, while the others will receive only. So increasing the buffer size for all 4 channels seems like a big waste of RAM to me.

The size of RX and TX buffer for serial communications can be adjusted in the file HardwareSerial.h found in "hardware/arduino/avr/cores/arduino/"

by changing

#define SERIAL_RX_BUFFER_SIZE 64
#define SERIAL_TX_BUFFER_SIZE 64

But this affects all ports identically, doesn't it?

That's where it's located for a Mega.

The due is SAM architecture, and is not in the same place (not sure how similar the hardware serial code is)

But yeah, that effects all serial ports. Looking at the code, I don't see a clean path towards making it port-specific.

Here is a first draft of an additional transmit buffer, when only one of multiple serial ports needs a significant bigger TX buffer. It compiles, but I haven't tested it yet.

/*
-baudrate cannot be changed during runtime
-works for 8N1 or shorter characters / >=12 bit not
-between two consecutive Serial.print's is always the time that it would take to transmit a full buffer (eg 64 chars)

-does not work with const char arrays
*/

char string0[] ="000000000011111111112222222222";
char string1[] ="aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeeeffffffffffgggggggggghhhhhhhhhh";

const int baudrate = 9600;    //cannot be changed during runtime

const byte size_of_TX_BUFFER = 64;
const int size_of_extra_serial_buffer = 200;
char extra_serial_buffer[size_of_extra_serial_buffer];



bool append_to_serial_buffer(char * source_char){
    int length_of_source = sizeof(source_char);
    //find first_empty_position in extra_serial_buffer
    int first_empty_position;
    for (first_empty_position = 0; first_empty_position < size_of_TX_BUFFER; first_empty_position++){
        if(extra_serial_buffer[first_empty_position] == '\0')
            break;
    }
    if (first_empty_position + length_of_source >= size_of_extra_serial_buffer)
        //string too long / buffer overflow, string will not be added to queue / transmitted 
        return 0;
    else {
        strncpy(extra_serial_buffer + first_empty_position, source_char, length_of_source);
        return 1;
    }
}

void print_serial(){
    const unsigned long transmit_duration_of_buffer = (12*1000000 * size_of_TX_BUFFER) *(11/10) / baudrate;   //12bits/char, in microseconds,  + 10%
    static unsigned long last_transmission = 0;

    if (extra_serial_buffer[0] == '\0')
        //empty extra_serial_buffer
        return;
    else {
        unsigned long current_micros = micros();
        if (current_micros - transmit_duration_of_buffer > last_transmission){
            last_transmission = micros();

            for (int i = 0; i< size_of_TX_BUFFER; i++){
                //move first chars to serial
                if (extra_serial_buffer[i] == '\0') {
                    //buffer completely transferred
                    memset(extra_serial_buffer, '\0', size_of_TX_BUFFER);
                    return;
                }
                else Serial.print(extra_serial_buffer[i]);
            }
            int upper_limit = size_of_extra_serial_buffer - size_of_TX_BUFFER;
            for (int i = 0; i< upper_limit; i++){
                //move up buffer content
                char char_to_move = extra_serial_buffer[size_of_TX_BUFFER + i];
                extra_serial_buffer[i] = char_to_move;
                //for speed increase
                if (char_to_move == '\0') break;
                
            }//2534 / 396
        }
    }
}
 

void setup(){
    Serial.begin(baudrate);
    delay(5000);
    Serial.println(F("standard w flush"));
    Serial.println(string0);
    Serial.flush();
    Serial.println(string0);
    Serial.flush();
    Serial.println(string1);
    Serial.flush();
    Serial.println("\nnew method");
    Serial.flush();
    append_to_serial_buffer(string0);
    append_to_serial_buffer(string1);
    append_to_serial_buffer(string1);
    append_to_serial_buffer(string0);

}

void loop(){
    print_serial();
}

Perhaps it can be solved in the sketch.
Transmitting too much data is possible if it is allowed to wait until everything has finished. Increasing the baud rate will help a lot.
Or you can check the transmit buffer. There is code for that, but I don't know if that is already in the library. With a software timer using millis() it is possible to fill the Serial transmit buffer with small chunks of data.

How long is the data ? and for what ?

I plan to intercept serial data on ports 1-3, process it and forward it on serial port 0. Each sentence may contain up to 80 character. Therefore I wanted a bigger TX buffer.
In that context I do not want to use millis() and my sketch works without it.

I wonder if there is a better / faster / more efficient way to
-find the first \0 entry in the buffer
-send multiple char's at once from the intermediate buffer to the actual TX buffer.

Somehow I missed your Reply #2 with the sketch while I wrote my Reply #3.
I'm sorry, but that is not a pretty solution.
Increasing the TX buffer size is simpler, if you don't mind the ram usage. 80 bytes instead of 64 ? is that a big deal ?

This is the function to check the transmit buffer : Serial.availableForWrite() - Arduino Reference

The 9600 baud is slow, transmitting 80 bytes takes 83ms. That means you can only transmit 12 of those sentences per second. Is that enough ? If you transmit more during a peak, the whole sketch slows down.

There is code for circular buffers for the Arduino. Or you could use a "stack" and push the 80 bytes into an array of 60 bytes elements and transmit that one by one, using the 'Serial.availableForWrite()'. But that might not be pretty as well.

halfdome:
Is it possible to have different SERIAL_TX_BUFFER_SIZEs for the different serial ports of an Arduino Mega or Due?

I will transmit long messages only over one port, while the others will receive only. So increasing the buffer size for all 4 channels seems like a big waste of RAM to me.

I can't imagine why you would need to increase the buffer size (either for transmission or reception).

Have you actually experienced a problem?
If so post the code that illustrates the problem.
If not, try your program with the standard buffer size and see if there is a problem before you start trying to fix it.

...R

#I am using an Arduino Mega = multiple serial ports#

At this point, I am in the planning phase and do not have set up the electronic circuitry. So I have not experienced an actual problem.
But I have indeed experienced problems when sending more characters than fit into the TX buffer, though in different projects.

For the current project I know that the length of a data sentences can be up to 80 char's long.

For receiving this is no problem, because the microcontroller reads each RXn buffer basically while each char arrives and stores it in a temporary char array (one for each RX channel). When an entire sentence is received the microcontroller checks for validity (among other) and then forwards the sentence to the Serial 0 port.

Assuming a worst case, 3 sentences could arrive at once, yielding 380=240 bytes to be transmitted over Serial 0.
Now instead of increasing the TX_Serial_Buffer to 240 bytes which would result in 4
240= 960 bytes of RAM, I thought of the earlier script which only needs a single 240 byte big buffer (not counting overhead).

(The numbers in the test script above differ, but the principle still stands.)

And for clarification: The given script only shows the buffering part and transmitting of long char sentences, not the receiving of the data etc.

halfdome:
Assuming a worst case, 3 sentences could arrive at once, yielding 3*80=240 bytes to be transmitted over Serial0.

I think the real issue here is how fast the data arrives compared to how fast it can be sent on. For example if you continuously receive data on 3 inputs at 9600 baud there is no way that you can send all that data out on Serial0 at 9600 baud no matter what size buffer you have.

More information on what you actually want to achieve will get you more useful advice.

...R