Skip to content

Enable UART Flow Control #6185

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

Closed
1 task done
GioTB opened this issue Jan 24, 2022 · 9 comments · Fixed by #6272
Closed
1 task done

Enable UART Flow Control #6185

GioTB opened this issue Jan 24, 2022 · 9 comments · Fixed by #6272
Assignees
Labels
Area: Peripherals API Relates to peripheral's APIs. Status: In Progress ⚠️ Issue is in progress Type: Feature request Feature request for Arduino ESP32

Comments

@GioTB
Copy link

GioTB commented Jan 24, 2022

Related area

UART

Hardware specification

ESP32

Is your feature request related to a problem?

No, i just need to use uart flow control.

Describe the solution you'd like

Enable support for flow control (RTS and CTS, perhaps it would be also usefull to enable DTR and DSR)

Describe alternatives you've considered

Add a parameter on the "begin" function that allows to select if the serial should use CTS/RTS and a pin assigment (might be just adding de pins, and if they are different than -1 the flow control would be enabled).
Also a "setRts" and "setCts" function could be implemented to enable one or both flow control pins

Additional context

No response

I have checked existing list of Feature requests and the Contribution Guide

  • I confirm I have checked existing list of Feature requests and Contribution Guide.
@GioTB GioTB added the Type: Feature request Feature request for Arduino ESP32 label Jan 24, 2022
@VojtechBartoska VojtechBartoska added the Area: Peripherals API Relates to peripheral's APIs. label Jan 24, 2022
@VojtechBartoska
Copy link
Contributor

@SuGlider Can you please take a look?

@SuGlider
Copy link
Collaborator

@GioTB

Thanks for the suggestion.

In the meanwhile, Arduino UART is based on IDF, thus all the IDF calls can be used in conjunction with Arduino HardwareSerial
You can activate it by using specific IDF calls within your Arduino Sketch.

You can use this IDF call with UART_PIN_NO_CHANGE for the pins that you don't want to change.
uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int rts_io_num, int cts_io_num)

You can also set Hardware Flow Control mode to use CTS, RTS together or each one isolated.
uart_set_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t flow_ctrl, uint8_t rx_thresh)

For instance:

#include "driver/uart.h"
void setup() {
  Serial.begin(115200);   // uses default RX/TX pins for UART 0

  // it sets pin 2 for RTS and pin 4 for CTS in UART 0 (Arduino Serial)
  uart_set_pin(UART_NUM_0, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, 2, 4);
  
  // UART_HW_FLOWCTRL_CTS_RTS or only UART_HW_FLOWCTRL_CTS | UART_HW_FLOWCTRL_RTS
  // UART_HW_FLOWCTRL_DISABLE to disable Hardware Control on UART
  // 64 is the Threshold for RX Flow control when RTS is used. It goes from 0 to 127 (bytes).
  uart_set_hw_flow_ctrl(UART_NUM_0, UART_HW_FLOWCTRL_CTS_RTS, 64);
}

Please let me know if this would solve your current need.

@GioTB
Copy link
Author

GioTB commented Jan 24, 2022

Hello, thanks for your response. I didn´t know the esp-idf functions where available on the Arduino framework, i tested it, and it works!, but, it still has the problem of the queue of the HardwareSerial filling up if i don´t empty it, of course this wouldn´t be a "hardware flow control" implementation, and i could just set the buffer to a bigger size, but i need totally confident that the flow control will prevent the other device from sending data. Since the hardware serial doesn´t give direct access to that queue i can´t check it on my code to empty it or to disable CTS line if the queue it´s full. Never the less since i see i have access to the esp-idf functions i´ll implement the project using those. As an idea, for the implementation of this flow control on the arduino framework: on the uart_isr it could check if the queue it´s "almost full" (like the Rx thresshold), for de-asserting the CTS line, so any byte will be lost.

Thanks for your help!, if there is anything that i could help let me know.

@SuGlider
Copy link
Collaborator

SuGlider commented Jan 24, 2022

Arduino HardwareSerial, in Arduino Core V2.0.0+, is implemented on top of IDF.
Thus any IDF call will affect directly HardwareSerial as well.

I didn't test it, but uart_set_hw_flow_ctrl(UART_NUM_0, UART_HW_FLOWCTRL_CTS_RTS, 64); shall rise RTS line when ESP32 has more than 64 bytes, in this example, in FIFO that have not been sent to IDF UART Driver Queue - which is the same used by Serial.read(), for instance. In case IDF Queue if full, incoming data shouldn't be moved from FIFO to the RX Queue and RTS should go high.

Anyway, we have now a UART ISR Callback that may help your application in dealing with incoming UART data.
Serial.onReceive(userCallBackFunc); - PR #6134

Not sure about which Arduino Core version you are using. We are currently in version 2.0.2.
Please test it and let me know by droping a message in this issue.
Thanks!

@GioTB
Copy link
Author

GioTB commented Jan 25, 2022

I´m using platformio, and it seems that it´s using the 1.0.6 version, so i´m trying to upgrade it to the lastest version. As far as i can see from the code, i think it should work exactly the way you say it, once i try it i will let you know, Thanks!!!!

@SuGlider
Copy link
Collaborator

SuGlider commented Jan 25, 2022

1.0.6 will use IDF 3.3. Its HardwareSerial isn't based on IDF calls and the issue you commented with Queue and FIFO will actually happen.

The Arduino Core 2.0.2 uses IDF 4.4 and as said its HardwareSerial implementation is built on top of IDF, which will allow you to just use Serial.begin() followed by IDF RTS setup call making it work seamless all together.

@SuGlider
Copy link
Collaborator

See PR #6272

@GioTB
Copy link
Author

GioTB commented Feb 13, 2022

Anaother comment about the hardware flow control, when i implemented it at first it didin´t work well, and a colleague found out that it was becuase on the uart_begin function it has de uart_set_mode to "UART_MODE_RS485_HALF_DUPLEX" and after changing it to UART_MODE_UART, it works great.
so the final code we have to implement to make it work was:

Serial.begin(115200);
uart_set_pin(UART_NUM_0, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE,RTS_PIN , CTS_PIN);
uart_set_hw_flow_ctrl(UART_NUM_0, UART_HW_FLOWCTRL_CTS_RTS, 64);
uart_set_mode(UART_NUM_0, UART_MODE_UART);

@SuGlider
Copy link
Collaborator

SuGlider commented Feb 14, 2022

Yes, it was also fixed and removed in a prior PR #6133

Thanks for reporting it!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: Peripherals API Relates to peripheral's APIs. Status: In Progress ⚠️ Issue is in progress Type: Feature request Feature request for Arduino ESP32
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants