SoftwareSerial: How to know when data has been sent

Hi,
I am using this piece of code to be able to wait until all the bytes have been sent through the serial port in a project with serial hardware communication.

while (!(UCSR0A & _BV(TXC0))); //wat till data sent.

It is working fine.

However, I have to add an additional serial communication and I have to use the software serial to use different pins than 0/1 (I am using arduino mini pro and so only 1 serial available).

Is there any equivalent code to be used with the softwareserial????

I have no clue what UCSR0A & _BV(TXC0) are about.

So you need to post your entire sketch so we can figure out what library you are using.

Would suggest you consider a mega instead of an uno, mini or micro.

Mega has 3 hardware serial ports - Serial, Serial1 and Serial2.

Perfect for your situation.

SoftwareSerial sends the data immediately, forcing the Arduino to wait for the print to complete. All characters are sent before it returns from the print statement.

SoftwareSerial also disables interrupts for long periods of time. This can interfere with other parts of your sketch or with other libraries.

AltSoftSerial is much more efficient. It will complete the transmissions in the background so the sketch can do other things while the print completes. It is available from the IDE Library Manager.

Unfortunately, it does not have the availableForWrite function, so it can't tell you when the last character has been sent.

Instead, use millis () to check that the required transmission time has elapsed.

boylesg:
I have no clue what UCSR0A & _BV(TXC0) are about.

So you need to post your entire sketch so we can figure out what library you are using.

Would suggest you consider a mega instead of an uno, mini or micro.

Mega has 3 hardware serial ports - Serial, Serial1 and Serial2.

Perfect for your situation.

Hi,

while (!(UCSR0A & _BV(TXC0))); //wait till data sent.

This sentece waits till all the bytes has been sent. I am using it and it works fine.

I know about arduino mega but I have no room to use it.

-dev:
SoftwareSerial sends the data immediately, forcing the Arduino to wait for the print to complete. All characters are sent before it returns from the print statement.

SoftwareSerial also disables interrupts for long periods of time. This can interfere with other parts of your sketch or with other libraries.

AltSoftSerial is much more efficient. It will complete the transmissions in the background so the sketch can do other things while the print completes. It is available from the IDE Library Manager.

Unfortunately, it does not have the availableForWrite function, so it can't tell you when the last character has been sent.

Instead, use millis () to check that the required transmission time has elapsed.

Thanks
I had a look at AltSoftSerial but if I understand correctly, on ATMEGA328 use of pins 8 and 9 are mandatory.
Unfortunatelly I have not htem free......

link

I'm in no way affiliated with the company, only used their stuff and i think the quality is good enough to recommend.

Maybe you could use this one.

piel:
Mega 2560 PRO (Embed) CH340G/ATmega2560 16AU, NO pinheaders. Compatible for Arduino Mega 2560.|arduino 2560| - AliExpress

I'm in no way affiliated with the company, only used their stuff and i think the quality is good enough to recommend.

Maybe you could use this one.

I have already something developed with already some boards manufactured but anyway this is a product I might take into account!!!!

I will keep trying with what I have but thanks for sharing!!!!

As -dev said, with SoftwareSerial library, any write to the SoftwareSerial port will take the chip's full attention until the transmission is complete.

Thus, there is no need to check for it. By the time the next line of code is executing, you know the data has been sent.

Unlike the situation on hardware serial, where you need to do Serial.flush() followed by checking for the TXC bit (alternately, flush() followed by a 1ms delay or something to make sure that last character has printed)

DrAzzy:
As -dev said, with SoftwareSerial library, any write to the SoftwareSerial port will take the chip's full attention until the transmission is complete.

Thus, there is no need to check for it. By the time the next line of code is executing, you know the data has been sent.

Unlike the situation on hardware serial, where you need to do Serial.flush() followed by checking for the TXC bit (alternately, flush() followed by a 1ms delay or something to make sure that last character has printed)

Thanks DrAzzy!!

I will definitelly have to take this into account......

With newer IDEs, just use flush() that is what it is for.
When flush() returns, any/all the queued TX characters will have been transmitted.
This works for HardwareSerial, SoftwareSerial, and AltSoftSerial.

There was an long hard debate about this years ago because different serial classes were doing it differently and most operating systems and drivers have two functions not just one

  • a function to push any/all TX queued data out of a port
  • a function to throw away any RX queued data.

And there are real-world valid reasons to need to do both.

In earlier versions of the IDE, HardwareSerial and SoftwareSerial did different things in flush()
and I believe that flush() on HardwareSerial threw away the RX buffered characters and had no way to know when all the TX buffered characters had been transmitted.

The debate wandered all over and also included discussion of how to tell how many characters were available for queuing into an output buffer before blocking occurred and the possibility of being able to configure write() for blocking or returning a status but not blocking.
I proposed several solutions to address all of these, but in the end, Arduino ended up with flush() being used to wait until all the queued up TX characters drained out the port, no way to flush out and throw away all the queued up RX characters and a new function that returns a number of additional characters that can be queued up for transmission before the write blocks.
But when using print() you can always still get blocked depending on how much you print and there is no way to configure it otherwise.

--- bill

-dev:
Unfortunately, it does not have the availableForWrite function, so it can't tell you when the last character has been sent.

availableForWrite() is not about telling you when the last character has been sent.
It is about telling you how much room is available for future TX queuing using write() before a block might occur.
It reports how many bytes are available for TX buffering.
So while you could query it when you know nothing has been queued or is currently being transmitting to get the maximum size of the queue and then monitor it to see when the available bytes is equal to the maximum size, it still can't tell you when the last byte has actually been transmitted since the TX buffer will show empty (max bytes available) then the last byte has been handed to the h/w and is still being transmitted.
And in some cases that can be up to two bytes since some h/w has a extra byte internally in addition to the one currently being transmitted.

--- bill