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

Change baud on the fly #441

Closed
GermanSheepDog opened this issue Jun 13, 2017 · 22 comments
Closed

Change baud on the fly #441

GermanSheepDog opened this issue Jun 13, 2017 · 22 comments

Comments

@GermanSheepDog
Copy link

Hello,

I like to change baudrate for an ESP32 on the fly to communicate with a VC0706.

My idea is:

  1. HardwareSerial Serial2(2);
  2. Serial2.begin(38400);
  3. ...do something with VC0706 -> This worked
  4. Serial2.end(); -> Here stopped the program!
  5. delay(1000);
  6. Serial2.begin(115400);
  7. delay(1000);
  8. ..do something with VC0706

-> It didn't not work. The ESP32 stopped at line 4.)

My idea of an very easy test was:

  1. HardwareSerial Serial2(2);
  2. Serial2.begin(38400);
  3. ...do something with VC0706
  4. Serial2.end();
  5. delay(1000);
  6. Serial2.begin(38400); -> same baud as in line 1.!!!
  7. delay(1000);
  8. ..do something with VC0706

Is this an issue?

@jestebanes
Copy link

Hi @Papengut , try
Serial2.flush();
delay(2);
before the fourth point

@GermanSheepDog
Copy link
Author

Hi @jestebanes,
thank you for your approach. I tried:

  1. HardwareSerial Serial2(2);
  2. Serial2.begin(38400);
  3. ...do something with VC0706
  4. Serial2.flush();
  5. delay(1000); -> More delay isn't wrong
  6. Serial2.end(); -> Here stopped the program!
  7. delay(1000);
  8. Serial2.begin(38400); -> same baud as in line 1.!!!
    9 delay(1000);
  9. ..do something with VC0706

Same result at Serial2.end()! Program stopped execution.

@me-no-dev
Copy link
Member

I'll have a look at the end command, but you do not need to call it. Just Serial2.begin(new baud) should do

@GermanSheepDog
Copy link
Author

Hi @jestebanes,
thank you for your new approach. I tried:

  1. HardwareSerial Serial2(2);
  2. Serial2.begin(38400);
  3. ...do something with VC0706
  4. Serial2.begin(38400); -> same baud as in line 2.!!!
  5. delay(1000);
  6. ..do something with VC0706 -> nothing send and/or received from VC0706

Result of my test: The program didn't stop execution, but Serial2 didn't work in line 7.
In the next test I removed line 4 and now the VC0706 worked fine in line 6. But so I can't change the baud value!

@eroom1966
Copy link

I have a very similar issue regarding changing the baud rate
do you have a solution to this ?
#476

E

@copercini
Copy link
Contributor

What about this?

void setup() {
  Serial.begin(115200);
  Serial.println("loool1");
  Serial.flush();
  delay(1000);
  Serial.begin(9600);
  Serial.println("loool2");
  Serial.flush();
  delay(1000);
  Serial.begin(115200);
  Serial.println("loool3");
}
void loop() {
}

@eroom1966
Copy link

@copercini
Tried your example which did not help too much,b ut it did push me to look at some alternatives.
As far as I can see - this is totally broken

I first setup the serial @9600baud, perform some read/writes then
I setup @57600baud
I have a packet length of 24 bytes that I send once every 2 seconds (@57600baud)
When I start sending this I see 5 packets of garbage come out the serial,
then I see my packets appear
But this is with a 10 second latency !!!

So I am guessing there is a FIFO involved here and it is only emptying the FIFO
when Full, and only at the same rate that data goes into the FIFO.
so it is not emptying asynchronously at the 57600 baud rate

Not sure what is magical about 5 x 24 - default buffer size perhaps ?

This only seems to occur when the baud rate has been configured at 9600, then changed
to 57600

Something is very wrong, but I think it must be down in the driver detail somewhere

E.

@copercini
Copy link
Contributor

@eroom1966 please post some code, how are you testing it? via computer serial?

@jestebanes
Copy link

Hello @eroom1966, When you write to serial, the low-level functions are asynchronous, look into esp32-hal-uart.c functions uartWrite and uartWriteBuf, they only put your bytes in a FIFO buffer and then exit.
For this reason, I previously suggested making a flush operation before changing the baud rate.

But now I see in line 194 of esp32-hal-uart.c -> uartFlush(uart); inside the begin operation, then apparently there isn't a necessity of making a flush previous to the new Begin operation.
Then the only possible failure according to the temporal behavior you are seeing is an error in the implementation of uartFlush function in line 294 of esp32-hal-uart.c

JEE

@eroom1966
Copy link

@jestebanes
Good pointer!

OK, I am no expert on this Architecture, but this looks very suspicious at line 300

UART_MUTEX_LOCK();
while(uart->dev->status.txfifo_cnt);
...
UART_MUTEX_UNLOCK();

This looks like deadlock code
I wait until I have locked the mutex, then I loop indefinitely while the txfifo_cnt is non-zero

I presume another thread is emptying (and decrementing) this counter, using the same mutex, unfortunately, you now have a deadlock, because this mutex is not released until the count is zero,
but nothing to decrement the count

Hmmm, seems like a better approach is a condvar (assuming this library has such a feature)

E.

@eroom1966
Copy link

Hi All

I have the perfect testcase to show this issue - if anybody can make this work, that would be wonderful

#476

@me-no-dev
Copy link
Member

Should be OK now! Please test and confirm :)

@lonerzzz
Copy link
Contributor

@Papengut Are you able to test this issue?

@GermanSheepDog
Copy link
Author

GermanSheepDog commented Aug 29, 2017

Yes, but earliest next week.

@GermanSheepDog
Copy link
Author

Hello,

I try to test it, but I am missing some information and so I write here all details:

  1. Insert in "esp32-hal-uart.c" (and "esp32-hal-uart.h")
    Location of the file: ~/Documents/Arduino/hardware/espressif/esp32/cores/esp32
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);
}
  1. Insert in "HardwareSerial.cpp" (and "HardwareSerial.h")
    Location: ~/Documents/Arduino/hardware/espressif/esp32/cores/esp32
void HardwareSerial::changeBaud(unsigned long baud)
{
    uartChangeBaudRate(_uart_nr, baud);
}
  1. Insert in my program:
Serial.print("Set UART-Baud to ");
Serial.println(baud);
hwSerial->changeBaud(baud);
  1. Run my program:
WiFi STA got IP: 192.168.0.109
...............
UART-Baudrate in Adafruit_VC0706::begin:115200
Set UART-Baud to 115200
/Users/ficeto/Desktop/ESP32/ESP32/esp-idf-public/components/freertos/./queue.c:1438 (xQueueGenericReceive)- assert failed!
abort() was called at PC 0x4008441d on core 1
Guru Meditation Error: Core  1 panic'ed (abort)

Backtrace: 0x40008155:0x3ffcd660 0x40007d06:0x3ffcd680 0x400d5337:0x3ffcd6c0 0x400d546e:0x3ffcd6e0 0x400d4827:0x3ffcd700 0x400d12c4:0x3ffcd720 0x400d3be0:0x3ffcd760 0x400d1b15:0x3ffcd780 0x4011d764:0x3ffcd7a0 0x400d27de:0x3ffcd7c0 0x400d282e:0x3ffcd7e0 0x400d2865:0x3ffcd810 0x400d2a6f:0x3ffcd850 0x400d201a:0x3ffcd890 0x40116567:0x3ffcd8b0

CPU halted.

Did I something wrong?

@GermanSheepDog
Copy link
Author

I reopen the issue because it didn't work for me. Please look at last entry here.

@jestebanes
Copy link

Why don't you try

Serial.changeBaud(baud);

@GermanSheepDog
Copy link
Author

I used "hwSerial->changeBaud(baud)" because my serial device (=VC0706) used Serial2. Serial1 was my debugging output.

At Serial1 change Baud worked! If I start the Sketch, Serial1 used baud=115200. Then I call "Serial.changeBaud(9600)" and I got all messages with 9600. Fine.

My trick for Serial2:

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

// In main:
Serial.changeBaud(115200); //Yes Serial1, not Serial2. It ist a trick

This worked for Serial2. This problem is the call of "changeBaud". I will analyze it.

@GermanSheepDog
Copy link
Author

My last problem was "hwSerial->changeBaud(baud)".

Now I used:

// esp32-hal-uart.c
void uartChangeBaudRate(uint8_t uart_nr, uint32_t baudrate)
{
    if(uart_nr > 2) {
        return;       //Not return NULL
    }
    uart_t* uart = &_uart_bus_array[uart_nr];
    uartSetBaudRate(uart, baudrate);
}

// The standard version of changeBaud in HardwareSerial.cpp
void HardwareSerial::changeBaud(unsigned long baud)
{
    uartChangeBaudRate(_uart_nr, baud);
}

// My special version of changeBaud in "HardwareSerial.cpp
void HardwareSerial::changeBaudSpecial(unsigned long my_uart, unsigned long baud)
{
    uartChangeBaudRate(my_uart, baud);
}

This worked fine for me. Please add "uartChangeBaudRat" and "changeBaud" to the libraries.

@jestebanes
Copy link

Hi, it works for me in serial2, thanks @Papengut

I propose another couple of functions to change the baud-rate and Parity

//esp32-hal-uart.c
void uartChangeBaudRateParity(uint8_t uart_nr, uint32_t baudrate, uint32_t config)
{
if(uart_nr > 2) {
return; //Not return NULL
}
uart_t* uart = &_uart_bus_array[uart_nr];
uartSetBaudRate(uart, baudrate);
UART_MUTEX_LOCK();
uart->dev->conf0.val = config;

if ( uart->dev->conf0.stop_bit_num == TWO_STOP_BITS_CONF) {
    uart->dev->conf0.stop_bit_num = ONE_STOP_BITS_CONF;
    uart->dev->rs485_conf.dl1_en = 1;
}
UART_MUTEX_UNLOCK();

}

// HardwareSerial.cpp
void HardwareSerial::changeBaud(unsigned long baud, unsigned long config)
{
uartChangeBaudRateParity(_uart_nr, baud, config);
}

@mterveen
Copy link

this seems to work for me:

#include <driver\uart.h>

esp_err_t status = uart_set_baudrate(UART_NUM_2, baudrate);

@mudgalp
Copy link

mudgalp commented Jan 2, 2022

hello everyone,
thank you for this discussion, i have tested a code that works for me without any problem on esp32-wroom module.
i found a function in HardwareSerial.cpp file and it worked like this.

unsigned long baudrate1 = 9600;
unsigned long baudrate2 = 115200;

void setup()
{
delay(2000);
Serial.begin(baudrate1);
Serial.println("This is baudrate TEST");
delay(3000);
}

void loop()
{
Serial.updateBaudRate(baudrate2);
Serial.println("This is baudrate : 115200");
delay(3000);

Serial.updateBaudRate(baudrate1);
Serial.println("This is baudrate : 9600");
delay(3000);

}

//-----------------
// Thank you
//PM

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

8 participants