I have been doing a lot of googling in and out side of Arduino.cc in regards to the software serial. Unfortunately, I'm not getting solid warm-fuzzy information.
First question, what software serial libraries are out there?
Does the current Arduino built-in library for SoftwareSerial contain blocking code or is that from a past version?
The latter I was warned on, but some of my results show this may be from an older version or may still apply.
It appears there was a SoftwareSerial from Arduino then a NewSoftSerial was developed to overcome some limitations and issues of Arduino's version. Then NewSoftSerial was adopted and renamed as SoftwareSerial and is now what you get when you load Software Serial from the library manager. I think this is true but the question still applies, does the current Arduino built-in library for SoftwareSerial contain blocking code or is it 100% interrupt driven and the blocking is gone.
If the last of that is true, then back to question 1, what other libraries are out there? Are they any better? Do they have blocking issues?
I think this is true but the question still applies, does the current Arduino built-in library for SoftwareSerial contain blocking code or is it 100% interrupt driven and the blocking is gone.
From my experience dealing with the programming/operations of SoftUART, the serialEvent() routine is not attached with SoftUART. serialEvent() is a routine (subroutine or ISR?) which is automatically called upon when the Receiver Section of the HardUART has received a character.
GolamMostafa: serialEvent() is a routine (subroutine or ISR?) which is automatically called upon when the Receiver Section of the HardUART has received a character.
At least in Arduino AVR Boards, it's actually pretty stupid:
I'd much rather put those few lines of code in my sketch when I need them and not have the overhead of a function call on every single loop when I don't. When practical, I prefer to be able to follow the program code rather than having some special function called out of nowhere. IIRC at some point in the distant past serialEvent() either was called or was planned to be called from an interrupt. I forget the details.
Very nice derivation; I would not know it before. (Thanks+.)
In Arduino HardUART, the receiver section is interrupt driven. So, I follow the first principle -- I always write codes for the serialEvent() function and keep waiting in the loop() for the interrupt signal. As I know that the serialEvent() function will be called upon when the receiver is ready with a character, I do not execute the Serial.available(); function in the serialEvent() routine. I read the character from the FIFO, save it in the user array, and then check the received character if it is an end-of-string marker; if so, I go for processing.
GolamMostafa:
and keep waiting in the loop() for the interrupt signal. As I know that the serialEvent() function will be called upon when the receiver is ready with a character
It's not an interrupt. It will only be called after loop() returns:
int main(void)
{
init();
initVariant();
#if defined(USBCON)
USBDevice.attach();
#endif
setup();
for (;;) {
loop();
if (serialEventRun) serialEventRun();
}
return 0;
}
If you have blocking code in your loop then serialEvent() will be blocked.
GolamMostafa:
I do not execute the Serial.available(); function in the serialEvent() routine.
Makes sense as that function will only be called when there are characters available.
It's not an interrupt. It will only be called after loop() returns:
This is where my confusion is as to calling the serialEvent() function -- a simple subroutine or an ISR?
The MCU has been waiting in the loop() function without executing any instructions. Then, how does it enter into the serialEvent() routine unless it is interrupted! From this understanding, I have been always considering serialEvent() -- an ISR.
@GolamMostafa, I was under the same impression once upon a time. Then finally someone showed me the programming in main().
int main(void)
{
init();
initVariant();
#if defined(USBCON)
USBDevice.attach();
#endif
setup();
for (;;) {
loop();
if (serialEventRun) serialEventRun();
}
return 0;
}
That also explains how setup() is used. As you can see loop() is just another subroutine and after loop() has executed it checks to see if serialEvent exists and should be executed; otherwise it returns to the top of loop().
While this is a good discussion on the hardware serial port, it does not address the question at hand. Robin2 mentions two libraries back in post #6, anyone know of any other libraries?
Ignore serialEvent(). You get identical functionality with
For practical reasons, we do ignore many things; but, it is difficult to ignore serialEvent() function when the principle says that the arrival of a character in the receiver interrupts the MCU; in response, the MCU calls upon the serilaEvent() routine (subroutine or ISR?). Program codes written following this principle work well!
serialEvent() is not interrupt driven, it is a subroutine called at a fixed point in the sequence unchangeable without customizing the main.cpp file provided with the Arduino IDE.
If the program was:
loop()
{
...all your loop stuff
if (serial.Available())
{ serial stuff }
}
The you are correct there is no difference between that and
serialEvent()
{ serial stuff }
loop()
{
...all your loop stuff
}
in terms of the sequence of execution. Both are loop() then serial.
BUT if the program is
loop()
{
...some of your loop stuff
if (serial.Available())
{ serial stuff }
...rest of your loop stuff
}
Then there is a big difference in the sequence of execution. The latest is some loop() then serial then more loop(). If it is critical for the serial to be checked between the two halves then serialEvent() cannot be used.
Personally, I prefer to have my ISR say ISR. Such as
ISR (PCINT0_vect) // Pins D8 to D13
{
unsigned long current_time;
current_time = millis();
}
Notice that serialEvent() does not include the keyword ISR. Instead I have to remember when, where, how it is called because the function call does not appear anywhere in my .INO file and is not marked as an ISR.
That is not my point. My point is that only the hardware serial has serialEvent(). All other option only have serial.Available().
Notice that serialEvent() does not include the keyword ISR. Instead I have to remember when, where, how it is called because the function call does not appear anywhere in my .INO file and is not marked as an ISR.
Just for the shake or argument, I can ask the question: From where does data come into the variable when we execute the instruction byte x = Serial.read();? The data comes from the FIFO buffer which is not seen by the user; but, it is seen by the Serial.Read(); function.
ISR is a keyword that we must use while declaring user-defined ISR; for a system-initiated ISR? like serialEvent() use of ISR is prohibited.
void setup()
{
Serial.begin(9600);
}
void loop()
{
//waiting for interrupt?
}
void serialEvent() //receives character (s) from Serial Monitor.
{
byte x = Serial.read();
Serial.write(x);
}
GolamMostafa, your sketch does not work for this reason you think. You are so sure serialEvent() is an ISR try this:
In your example sketch
Add set pin 13 to output and low
In loop() add for(); (now loop will never end)
In serialEvent() add digitalWrite(13, HIGH); then type in the serial monitor and let me know is the LED comes on.