I have an ESP32-S2 and an external unit, which is wired up to Serial2 (pin 16/17 and CTS on pin 8). The external unit can be accessed using a built-in USB->UART controller and I can open a terminal and submit HEX-commands, manually. Now, I disconnect the USB and run all communication through the ESP32. Transmitting commands requires CTS. The unit also reports back every 30th second, giving a reading. So far, so good.
The problem is, that the unit isn't responding to commands from the ESP-32. As you can see below, it waits 10 seconds and then fires a command (0x09 0x00) in two different ways, which should trigger an almost immediate response.
I have RealTerm open at COM4 (the ESP32) in order to monitor the communication. After 10 seconds, I see the command being sent - but no answer is ever returned. Since the unit returns readings, I believe it relates to the unit not knowing when to receive commands (CTS-problem).
Any suggestions?
#include "driver/uart.h"
#include <HardwareSerial.h>
#define RXD2 16
#define TXD2 17
#define CTS 8
#define BUF_SIZE (1024)
void setup() {
Serial.begin(115200);
init_uart();
Serial2.begin(115200, SERIAL_8N1, RXD2, TXD2); // To peripheral
delay(10000);
// Send hex code 09 00 to Serial2. The loop-function should then show an answer and display something like 59 24 FF FF 1A FF FF BD FF FF 1D FF FF BF FF FF BE 00 12 25 FF FF B3 FF FF A3 FF FF 82 FF FF D4 FF FF 78 FF FF F0
byte message[] = {0x09,0x00};
Serial2.write(message, sizeof(message));
// Another test
uart_write_bytes(uart_num, (const char*)message, sizeof(message));
}
void loop() {
if (Serial2.available()) {
// Communication works - peridically receiving something like 52 12 00 12 00 09 00 20 00 08 00 00 68 F8 00 00 00 00 00 00
Serial.print(Serial2.readString());
}
}
void init_uart() {
const uart_port_t uart_num = UART_NUM_2;
uart_config_t uart_config = {
.baud_rate = 115200,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_CTS
};
//ESP_ERROR_CHECK(uart_param_config(uart_num, &uart_config));
uart_param_config(UART_NUM_2, &uart_config);
uart_set_pin(UART_NUM_2,UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE,UART_PIN_NO_CHANGE,UART_PIN_NO_CHANGE);
uart_driver_install(UART_NUM_2, BUF_SIZE * 2, 0, 0, NULL, 0);
}
Now it works.
I initially failed to understand the two different methods of communicating to the UART.
Below, you can see that Serial2.begin, Serial.write etc. is gone and that I use the uart_ commands instead - uart_write_bytes, uart_read_bytes etc.
The flow control also works perfectly, but I had to remap it to another GPIO (I chose GPIO19) since I read somewhere that I should leave GPIO6-11 alone. According to the datasheet, the default CTS for UART2 is GPIO8, but this pin caused the ESP32 to reboot constantly.
CTR-pin is ignored and wired up CTS-to-CTS as shown here
#include "driver/uart.h"
#include <HardwareSerial.h>
#define ECHO_TEST_TXD (GPIO_NUM_17)
#define ECHO_TEST_RXD (GPIO_NUM_16)
#define ECHO_TEST_RTS (UART_PIN_NO_CHANGE)
//#define ECHO_TEST_CTS (UART_PIN_NO_CHANGE)
#define ECHO_TEST_CTS (GPIO_NUM_19)
#define BUF_SIZE (1024)
unsigned long previousMillis = 0;
unsigned int interval = 45000;
byte message[] = {0x09, 0x00};
const uart_port_t uart_num = UART_NUM_2;
void setup() {
Serial.begin(115200);
uart_config_t uart_config = {
.baud_rate = 115200,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_CTS // Enable flow-control
};
uart_param_config(UART_NUM_2, &uart_config);
//uart_set_line_inverse(UART_NUM_2, UART_INVERSE_CTS); // The CTS-pin on the DCE is active high, so we invert the signal
uart_set_pin(UART_NUM_2, ECHO_TEST_TXD, ECHO_TEST_RXD, ECHO_TEST_RTS, ECHO_TEST_CTS);
uart_driver_install(UART_NUM_2, BUF_SIZE * 2, 0, 0, NULL, 0);
delay(3000);
}
void loop() {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
// Send hex code 09 00 to UART every 45th second.
// The loop-function should return an answer, display something like 59 24 FF FF 1A FF FF BD FF FF 1D FF FF BF FF FF BE 00 12 25 FF FF B3 FF FF A3 FF FF 82 FF FF D4 FF FF 78 FF FF F0
uart_write_bytes(uart_num, (const char*)message, sizeof(message));
}
// Read data from UART.
uint8_t data[128];
int length = 0;
ESP_ERROR_CHECK(uart_get_buffered_data_len(uart_num, (size_t*)&length));
length = uart_read_bytes(uart_num, data, length, 100);
if (length > 0) {
for (int i=0; i<length; i++) {
Serial.write(data[i]);
}
}
}
Here, you can see the communication. Yellow is data, blue is CTS