ESP32 Serial Won't Start After Serial.end() - Page 1
Forum section: electronics / projects

author: petersanch
author_rank: Regular Contributor
timestamp: March 23, 2019, 11:02:00 pm
content: I wrote program to begin serial 1, send a byte then disable serial1 and loop. If Serial1.end() is called then the TX pin will not function properly. The first time loop() runs it send the byte then stays low for about 600 microseconds and stays high after that. The TX channel stops toggling after that.The reason I need to call Serial1.end() is because my TX pin is multiplexed and I need to use it as a general IO later.I tried using Serial1.flush() before and after end(), but it doesn't help.Code:#include "HardwareSerial.h"uint8_t a= 10;void setup() {}void loop() {Serial1.begin(250000);Serial1.write(a);Serial1.end();//MAKE PIN 10 GENERAL IO AND DO SOMETHING WITH digitalWrite(10,LOW) or digitalWrite(10,HIGH) HEREdelay(100);}Using the ESP32 Pico with 1.0.2-rc1 version in Arduino.Cheers

author: petersanch
author_rank: Regular Contributor
timestamp: March 24, 2019, 12:31:28 am
content: I tried changing the code to use HardwareSerial specifically but the results are the same.Code:#include <HardwareSerial.h>uint8_t a= 10;HardwareSerial MySerial(1);void setup() {}void loop() {MySerial.begin(250000, SERIAL_8N1, 9, 10);MySerial.write(a);MySerial.end();//MAKE PIN 10 GENERAL IO AND DO SOMETHING WITH digitalWrite(10,LOW) or digitalWrite(10,HIGH) HEREdelay(100);}

author: cv007
author_rank: Frequent Contributor
timestamp: March 24, 2019, 07:23:47 am
content: I believe the arduino/sdk code is simply checking the fifo's- for the flush it waits until the fifo count is 0, but that still means a byte could still be on its way out (fifo is empty, but transmit shift register is not). Looking at the esp32 datasheet, they have a UART_TX_DONE_INT, which could be put to use I imagine (don't really need the irq, just its flag). There is also UART_ST_UTX_OUT which gives the state machine status of the transmitter.I would try the simple approach first- do the Serial1.flush() then delay for one byte of time + a little fudge. The flush will block until the fifo is empty (so if you later do more than one byte, your method will still work), then you delay while the last byte is going out. You could also move that code closer to where the pins will be used for the general io if you do not like the idea of waiting around (if for example a lot of bytes going out at once), assuming there is something useful to do while waiting.

author: petersanch
author_rank: Regular Contributor
timestamp: March 24, 2019, 09:11:28 am
content: Thanks. Your suggestion helped with part of it.Adding a flush and delay makes this program work as expected now. A byte is written on the TX pin every 100 ms.Code:#include <HardwareSerial.h>uint8_t a= 10;HardwareSerial MySerial(1);void setup() {pinMode(10, OUTPUT);}void loop() {MySerial.begin(250000, SERIAL_8N1, 9, 10);MySerial.write(a);MySerial.flush();delay(1);MySerial.end();delay(100);}The problem now is that I want to have TX pin be a digital output after MySerial.end(). If I try to do that then the output stays HIGH until the loop() starts again and the serial commands are run. There is no difference in the output of the TX pin in the bottom code vs the top code.Code:#include <HardwareSerial.h>uint8_t a= 10;HardwareSerial MySerial(1);void setup() {pinMode(10, OUTPUT);}void loop() {MySerial.begin(250000, SERIAL_8N1, 9, 10);MySerial.write(a);MySerial.flush();delay(1);MySerial.end();//MAKE PIN 10 GENERAL IO AND DO SOMETHING WITH digitalWrite(10,LOW) or digitalWrite(10,HIGH) HEREpinMode(10, OUTPUT);digitalWrite(10, LOW);delay(1);digitalWrite(10, HIGH);delay(1);digitalWrite(10, LOW);delay(1);digitalWrite(10, HIGH);delay(1);delay(100);}end() calls uartDetachRx(uart) and uartDetachTx(uart). Is it possible the detach is not working?

author: Nusa
author_rank: Super Contributor
timestamp: March 24, 2019, 09:46:10 am
content: Check your assumptions. Does the general i/o code work as expected if the serial i/o is disabled?

author: petersanch
author_rank: Regular Contributor
timestamp: March 24, 2019, 09:53:46 pm
content: Do you mean this code?Code:#include <HardwareSerial.h>uint8_t a= 10;HardwareSerial MySerial(1);void setup() {pinMode(10, OUTPUT);}void loop() {//MySerial.begin(250000, SERIAL_8N1, 9, 10);//MySerial.write(a);//MySerial.flush();//delay(1);//MySerial.end();//MAKE PIN 10 GENERAL IO AND DO SOMETHING WITH digitalWrite(10,LOW) or digitalWrite(10,HIGH) HEREpinMode(10, OUTPUT);digitalWrite(10, LOW);delay(1);digitalWrite(10, HIGH);delay(1);digitalWrite(10, LOW);delay(1);digitalWrite(10, HIGH);delay(1);delay(100);}Yes this code toggles pin 10 with 1 ms pulses on the oscilloscope.

author: cv007
author_rank: Frequent Contributor
timestamp: March 24, 2019, 10:50:01 pm
content: Now I'm just wild guessing, but it could be the pin init code for the uart ends up setting the io mux function to the uart, but when detaching only sets the matrix back to gpio but does not set the io mux function to gpio, so after the first use the gpio has no path to the pad/pin.I'm not sure if this would work (I could be misunderstanding the datasheet and the code), but try it for the tx pin after done with the uart-gpio_pad_select_gpio( 10 );It could also be that the pinMode code should be doing this, but I didn't take the time to figure out what its doing.

author: petersanch
author_rank: Regular Contributor
timestamp: March 25, 2019, 01:42:05 am
content: I tried gpio_pad_select_gpio( 10 ); before and after pinMode but same results as before. I tried using PWM instead of general IO in case its to do with pinMode.Sadly is the same as before.Code:#include <HardwareSerial.h>uint8_t a= 10;HardwareSerial MySerial(1);void startPWM(){ledcSetup(0, 5000, 8);ledcAttachPin(10, 0);}void setup() {pinMode(10, OUTPUT);startPWM();}void loop() {MySerial.begin(250000, SERIAL_8N1, 9, 10);MySerial.write(a);MySerial.flush();delay(1);MySerial.end();startPWM();ledcWrite(0, 50);delay(100);}

author: hamster_nz
author_rank: Super Contributor
timestamp: March 25, 2019, 03:59:19 am
content: Quote from: petersanch on March 25, 2019, 01:42:05 amHad a brief look at the GitHub repo for the uart and ledc modules:https://github.com/espressif/arduino-esp32/blob/master/cores/esp32/esp32-hal-uart.chttps://github.com/espressif/arduino-esp32/blob/master/cores/esp32/esp32-hal-ledc.cNothing in them looks like a one-way door through which you can't get back from...Do you call "void ledcDetachPin(uint8_t pin)" to release the GPIO pin before you try to start up the Serial port again?

author: cv007
author_rank: Frequent Contributor
timestamp: March 25, 2019, 04:21:32 am
content: It looks to me like pinMode is setting the pin function to gpio mode (FUNCTION_3) when OUTPUT or INPUT are used, so my previous guess was indeed a wild one.