Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SoftwareSerial (FAIL) #12

Closed
Hsubtnarg opened this issue Aug 2, 2023 · 11 comments · Fixed by arduino/ArduinoCore-renesas#374
Closed

SoftwareSerial (FAIL) #12

Hsubtnarg opened this issue Aug 2, 2023 · 11 comments · Fixed by arduino/ArduinoCore-renesas#374

Comments

@Hsubtnarg
Copy link

I have been trying to use the SoftwareSerial library but get errors on the receiver. So I had a look at what it is sending and this is what I found. It looks like the Uno R4 is not sending the stop bit correctly. For 9600baud it should be about 120us, but it is only 62us.
image

This is causing the frame to drift and causing errors on the receiver. This is the same code running on a Lenardo.
image

Originally posted by @Hsubtnarg in #3 (comment)

@Hsubtnarg Hsubtnarg changed the title SoftwareSerial errors sending SoftwareSerial errors sending on Uno R4 Aug 5, 2023
@Hsubtnarg Hsubtnarg changed the title SoftwareSerial errors sending on Uno R4 SoftwareSerial (FAIL) Aug 16, 2023
@Binary-System
Copy link

Is there any update on this problem with SoftwareSerial?

@Hsubtnarg
Copy link
Author

I have been testing it with the latest updates and it is still the same

@Hannes7eicher
Copy link
Contributor

Apologies for the late reply! I ran some tests using two UNO R4 WiFi with the following sketches without encountering any issues.

Sender Sketch

#include <SoftwareSerial.h>

// Define the pins for SoftwareSerial
const int TX_PIN = 10;
const int RX_PIN = 11;

// Initialize SoftwareSerial
SoftwareSerial mySerial(RX_PIN, TX_PIN); // RX, TX

void setup() {
  // Start the hardware serial communication at 9600 baud rate
  Serial.begin(9600);
  // Start the software serial communication at 9600 baud rate
  mySerial.begin(9600);
}

void loop() {
  // The message to send
  String message = "Hello, Arduino!";
  
  // Print the message to the SoftwareSerial
  Serial.println("Sending message: " + message);
  mySerial.println(message);
  
  // Wait for a second before sending the next message
  delay(1000);
}

Receiver Sketch

#include <SoftwareSerial.h>

// Define the pins for SoftwareSerial
const int TX_PIN = 11;
const int RX_PIN = 12;

// Initialize SoftwareSerial
SoftwareSerial mySerial(RX_PIN, TX_PIN); // RX, TX

void setup() {
  // Start the hardware serial communication at 9600 baud rate
  Serial.begin(9600);
  // Start the software serial communication at 9600 baud rate
  mySerial.begin(9600);

  Serial.println("Receiver ready");
}

void loop() {
  // Check if data is available to read from SoftwareSerial
  if (mySerial.available() > 0) {
    // Read the incoming data
    String incomingMessage = mySerial.readStringUntil('\n');
    
    // Print the received message to the Serial Monitor
    Serial.println("Received message: " + incomingMessage);
  }

  // Insert a tiny delay to avoid overloading the processor
  delay(100);
}

Let me know if you still encounter issues and I can set aside some time to investigate.

@Hsubtnarg
Copy link
Author

If you use only Arduino boards then you will not see the issue as they are tolerant of the shorter stop bit, but if you are communicating with something that is not so tolerant, then you will get errors. See the traces above that illustrate that the stop bit is shorter on the Uno R4, but is the correct length with the same code on the Lenardo

@iabdalkader
Copy link

If you use only Arduino boards then you will not see the issue

I also tested this library with multiple USB to serial chips and they all work fine. The receiver you're using must have a very low error tolerance. That said, I'll take a look and see if I can improve it.

@iabdalkader
Copy link

iabdalkader commented Sep 10, 2024

The reason for the short stop bit is that DMA transfers are triggered by a timer, cycles are bit-time apart. After the last bit, the transfer is complete as soon as the bit is written out, which is not a full timer cycle. A following byte will just pull the GPIO low too soon.

So one possible solution is to delay for half-bit time after the stop bit. Is this accurate/good enough ?

SDS00004

This depends on the micro-seconds resolution, but it seems good enough. I don't think +-16us will cause an issue with your UART receiver. Another solution would be to poll the timer's counter after the transfer is complete, but this may require more changes to the core as those timer fields are currently private.

@Hsubtnarg
Copy link
Author

Hsubtnarg commented Sep 11, 2024 via email

@iabdalkader
Copy link

iabdalkader commented Sep 11, 2024

Is it possible to get the DMA to send a dummy bit at the end so it would do one more cycle and make the stop bit the correct length

That's another solution I've considered, but it adds even more time than the half-bit solution above. You can actually test this without any changes to the code, just use 2 stop bits and on the receiving end, use 1 stop bit (EDIT: this will only work for sending, it will break receiving).

@iabdalkader
Copy link

I found a better fix, see the details here: arduino/ArduinoCore-renesas#374

@Hsubtnarg
Copy link
Author

I did try 2 stop bits but it was some time ago and all I can remember is that it did not work.

That fix does look promising, I am out of town at the moment, but I will test it when I get back in about 3 weeks

Thanks

@Hsubtnarg
Copy link
Author

I can confirm that your update has fixed this issue. Thanks for your help.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants