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

Changing UART Baud rate messes up UART #476

Closed
eroom1966 opened this issue Jun 30, 2017 · 12 comments
Closed

Changing UART Baud rate messes up UART #476

eroom1966 opened this issue Jun 30, 2017 · 12 comments

Comments

@eroom1966
Copy link

Hello,

I think I have a similar issue to #441

If I configure UART2 to run at 57600 baud, I can send data messages and all works well.
However, I need to be able to perform configuration of the end device at 9600 baud,
then flip both sides of the interface into 57600 - I cannot get this to work reliably.

I have a fixed message length of 24 bytes (at 57600 baud), but when I send messages, there is some strange buffering occuring, such that on the serial line, 21 bytes of the message(0) are sent, then there is a pause until the next message(1) is sent, then I have the missing 3 bytes from message(0), followed by the next 21 bytes if message(1) - and so on.

This only occurs IF the baud rate is changed from 9600 to 57600, if I start with a baud rate of 57600, the messages are transmitted as expected. so effectively what I have is the following

void setup() {
Serial2.begin(9600, SERIAL_8N1, gpioX, gpioY);
}

in the functional code, at some point the interface is reconfigured
Serial2.begin(57600, SERIAL_8N1, gpioX, gpioY);

I have tried with various combinations of
Serial2.end(); // causes the program to stop

and adding delays to no avail.

so can anybody provide a snippett of code to show how to reconfigure the BAUD rate of the interface, without introducing the buffering issue described above.

E.

@eroom1966
Copy link
Author

eroom1966 commented Jul 8, 2017

@me-no-dev
Apologies for contacting you directly me-no-dev, nut I am really stuck on this issue, I would really appreciate a little help or direction 👍

I now have a simple loopback testcase on Serial2 that shows this issue, as you will see if you run this, the data sent over the serial is totally corrupted after a change of baud rate
the test simply sends a message with a timestamp

write(12    ): 0123456789 BAUD=9600
 read(36    ): 0123456789 BAUD=9600

after changing the baud rate, its totally garbled

write(20101 ): 0123456789 BAUD=57600
 read(20105 ): ⸮8⸮�-E⸮�4⸮%l0�&⸮⸮⸮⸮?⸮⸮
#include <HardwareSerial.h>
//
// Note: you need to link IO16 to IO17
//
HardwareSerial Ser2(2);

#define RF_ESP_RX  16
#define RF_ESP_TX  17
#define RF_BAUD_HI 57600
#define RF_BAUD_LO 9600

void setup() {
    Ser2.begin(RF_BAUD_LO, SERIAL_8N1, RF_ESP_RX, RF_ESP_TX);
    Serial.begin(RF_BAUD_LO);
    Serial.println("\r\n** Start **\r\n");
}

static int baud = RF_BAUD_LO;
static char buf1[256], buf2[256];

static void toggleBaud() {
  baud = (baud==RF_BAUD_LO) ? RF_BAUD_HI : RF_BAUD_LO;
  
  sprintf(buf1, "\r\n*** Change BAUD=%d ***\r\n", baud);
  Serial.write(buf1);
    
  Ser2.begin(RF_BAUD_HI, SERIAL_8N1, RF_ESP_RX, RF_ESP_TX);
  Ser2.flush();
  delay(100);
}

void loop() {
  static int t1=0, t2=0, tdiff;
  int tnow = millis();
  
  tdiff = tnow - t1;
  if ((tdiff>4000) || (t1==0)) {
    t1 = tnow;
    
    sprintf(buf2, "0123456789 BAUD=%d\r\n", baud);
    Ser2.write(buf2);

    sprintf(buf1, "write(%-6d): %s", tnow, buf2);
    Serial.write(buf1);
  }

  if (Ser2.available()) {
    char c;
    sprintf(buf1,  " read(%-6d): ", tnow);
    Serial.write(buf1);
    while(Ser2.available() > 0) {
      c = Ser2.read();
      Serial.write(c);
    }
    if (c != '\n') {
      Serial.println("");
    }
  }

  //
  // 20 second interval toggle baud rate
  //
  tdiff = tnow - t2;
  if (tdiff>20000) {
    t2 = tnow;
    toggleBaud();
  }
}

@eroom1966
Copy link
Author

Update:
This is actually unrelated to the baud rate change.
If you change the baud to the same rate, ie using Ser2.begin to the same rate 9600 -> 9600
it gets messed up

@eroom1966
Copy link
Author

eroom1966 commented Jul 8, 2017

I have a solution / workaround.
I added a new function in the class

void HardwareSerial::changeBaud(unsigned long baud)
{
    uartChangeBaudRate(_uart_nr, baud);
}

and in the library added the function uartChangeBaudRate()

void uartChangeBaudRate(uint8_t uart_nr, uint32_t baudrate)
{
    if(uart_nr > 2) {
        return NULL;
    }
    uart_t* uart = &_uart_bus_array[uart_nr];
    uartSetBaudRate(uart, baudrate);
}

I can now change my baud rate on the fly.
Would it be possible to add this to the standard library ?
E
I now call this from my application, rather than calling begin()
Uart.changeBaud(baud);

@transonic22
Copy link

@eroom1966 I would like to thank you for this, I can confirm it works great.

@me-no-dev
Copy link
Member

has been fixed in master ;)

@eroom1966
Copy link
Author

eroom1966 commented Sep 25, 2017

@me-no-dev
Hi,
Only just got back to testing this, and it does not fix my issue.
Can I ask what is the fix to this problem, should the above testcase work ?
The testcase was a reduced version of the real problem in a much more complex example.

E

@me-no-dev
Copy link
Member

I hope all issue will be fixed once I change the driver with the IDF one.

@nkostis
Copy link

nkostis commented Oct 29, 2017

hi @me-no-dev, any timeline for this driver change? as mentioned in the issue referenced above, this seems related to another issue and using IDF's driver will likely solve the issue (or help reject frame errors more easily)

@Vorms
Copy link

Vorms commented Jan 5, 2018

I am very concerned by this bug. Please keep me informed for a workarround.
vormsty@gmail.com
Best regards
Thierry

@thezenox
Copy link

thezenox commented Feb 2, 2018

eroom1966's fix worked for me as well, why isn't it (re)implemented in master, yet ?

@terryjmyers
Copy link
Contributor

/bump
Would love to see this added to Master as well

@terryjmyers
Copy link
Contributor

I'm going to create a pull request for something similar to eroom's, as this is still an issue. I can't change from 9600 to 921600 or 2M by simply Serial.End(), then Serial.Begin(XXXXX)

terryjmyers added a commit to terryjmyers/arduino-esp32 that referenced this issue Jan 5, 2019
terryjmyers added a commit to terryjmyers/arduino-esp32 that referenced this issue Jan 5, 2019
This should resolve issue espressif#476
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

No branches or pull requests

7 participants