This commit is contained in:
2026-05-22 21:52:50 +03:00
commit be7c60e4dd
1854 changed files with 583428 additions and 0 deletions
@@ -0,0 +1,265 @@
/*
Hardware Flow Control Demo for ESP32
This sketch demonstrates UART hardware flow control using RTS (Request To Send)
and CTS (Clear To Send) signals with UART1 (HardwareSerial Serial1).
CONFIGURATION:
==============
Set USE_INTERNAL_MATRIX_PIN_LOOPBACK to 1 for internal GPIO matrix connections
(no external wires needed). Set to 0 to use external wire connections.
PIN CONNECTIONS (when USE_INTERNAL_MATRIX_PIN_LOOPBACK = 0):
============================================================
For basic loopback with hardware flow control:
- Connect GPIO2 (RTS1) to GPIO4 (CTS1) - Flow control loopback
- Connect TX1 pin to RX1 pin - Data loopback
For GPIO-controlled flow control demonstration:
- Connect TX1 pin to RX1 pin - Data loopback
- Connect GPIO2 (RTS1) to GPIO5 (GPIO_RTS_MONITOR) - Monitor RTS state
- Connect GPIO4 (CTS1) to GPIO13 (GPIO_CTS_CTRL) - Control CTS signal
- Use GPIO13 to manually control CTS signal (LOW = allow, HIGH = block)
HARDWARE FLOW CONTROL EXPLANATION:
===================================
RTS (Request To Send):
- Output signal from UART (GPIO2 in this example)
- Asserted LOW when UART is ready to receive data (RX buffer has space)
- De-asserted HIGH when RX buffer is getting full (threshold reached)
CTS (Clear To Send):
- Input signal to UART (GPIO4 in this example)
- UART will only transmit when CTS is LOW (asserted)
- UART will pause transmission when CTS is HIGH (de-asserted)
OPERATION:
==========
The sketch demonstrates:
- Periodic transmission of messages every second
- Automatic flow control when USE_GPIO_CONTROL = false
- Manual CTS control when USE_GPIO_CONTROL = true
- Loopback reception of transmitted data
- Status monitoring of RTS/CTS pin states
NOTE: When USE_INTERNAL_MATRIX_PIN_LOOPBACK = 1, no external connections
are needed as the ESP32 GPIO matrix handles the loopback internally.
*/
// setting it to 1 will allow internal matrix pin connection for RX1<->TX1 and RTS1<->CTS1
// otherwise it needs a wire for cross connecting the pins
#define USE_INTERNAL_MATRIX_PIN_LOOPBACK 1
// Pin definitions for UART1
#define UART1_RX_PIN RX1 // Default GPIO - UART1 RX pin
#define UART1_TX_PIN TX1 // Default GPIO - UART1 TX pin
#define UART1_RTS_PIN 2 // GPIO2 - UART1 RTS pin (output from UART)
#define UART1_CTS_PIN 4 // GPIO4 - UART1 CTS pin (input to UART)
// Optional: GPIO pins for manual flow control demonstration
// If using GPIO-controlled flow control, connect:
// - RTS1 to GPIO_RTS_MONITOR (to monitor RTS state)
// - CTS1 to GPIO_CTS_CTRL (to control CTS signal)
#define GPIO_RTS_MONITOR 5 // GPIO5 - Monitor RTS signal (connect RTS1 to this)
#define GPIO_CTS_CTRL 13 // GPIO13 - Control CTS signal (connect CTS1 to this)
// Set to true to use GPIO-controlled flow control, false for simple loopback
// Note: this control will be overridden by USE_INTERNAL_MATRIX_PIN_LOOPBACK when it is 1
#define USE_GPIO_CONTROL false
// Variables for demonstration
unsigned long lastSendTime = 0;
unsigned long lastStatusTime = 0;
const unsigned long sendInterval = 1000; // Send data every 1 second
const unsigned long statusInterval = 2000; // Print status every 2 seconds
int sendCounter = 0;
void printPinStatus() {
Serial.println("\n=== UART1 Pin Status ===");
Serial.printf("RX Pin (GPIO%d): Receiving data\n", UART1_RX_PIN);
Serial.printf("TX Pin (GPIO%d): Transmitting data\n", UART1_TX_PIN);
if (USE_GPIO_CONTROL) {
// Read RTS state from monitor GPIO (connected to RTS1)
bool rtsState = digitalRead(GPIO_RTS_MONITOR);
Serial.printf("RTS Pin (GPIO%d): %s (LOW = ready to receive)\n", UART1_RTS_PIN, rtsState == LOW ? "LOW (Ready)" : "HIGH (Busy)");
// Read CTS state from control GPIO (connected to CTS1)
bool ctsState = digitalRead(GPIO_CTS_CTRL);
Serial.printf("CTS Pin (GPIO%d): %s (LOW = can transmit)\n", UART1_CTS_PIN, ctsState == LOW ? "LOW (Clear)" : "HIGH (Blocked)");
} else {
Serial.printf("RTS Pin (GPIO%d): Hardware controlled (LOW = ready to receive)\n", UART1_RTS_PIN);
Serial.printf("CTS Pin (GPIO%d): Hardware controlled (LOW = can transmit)\n", UART1_CTS_PIN);
Serial.println("Note: RTS/CTS pins are hardware-controlled. Connect RTS1 to CTS1 for loopback.");
}
Serial.printf("Available for write: %d bytes\n", Serial1.availableForWrite());
Serial.printf("Available to read: %d bytes\n", Serial1.available());
Serial.println("========================\n");
}
void setup() {
// Initialize Serial (USB) for debugging
Serial.begin(115200);
delay(1000);
Serial.println("\n\n========================================");
Serial.println("ESP32 Hardware Flow Control Demo");
Serial.println("========================================\n");
// Configure GPIOs for flow control (only if using GPIO-controlled mode)
if (USE_GPIO_CONTROL) {
// Configure CTS control GPIO - this will control the CTS signal
pinMode(GPIO_CTS_CTRL, OUTPUT);
digitalWrite(GPIO_CTS_CTRL, LOW); // Start with CTS LOW (clear to send)
// Configure RTS monitor GPIO - this will monitor the RTS signal
pinMode(GPIO_RTS_MONITOR, INPUT);
Serial.println("Using GPIO-controlled flow control mode");
} else {
Serial.println("Using hardware-controlled flow control (simple loopback)");
}
// Initialize UART1 with hardware flow control
Serial.println("Initializing UART1...");
// Begin UART1 with 115200 baud, 8N1 configuration
Serial1.begin(115200);
// Set all pins for UART1
if (!Serial1.setPins(UART1_RX_PIN, UART1_TX_PIN, UART1_CTS_PIN, UART1_RTS_PIN)) {
Serial.println("ERROR: Failed to set CTS and RTS UART1 pins!");
while (1) {
delay(1000);
}
}
Serial.println("Enabling hardware flow control...");
if (!Serial1.setHwFlowCtrlMode(UART_HW_FLOWCTRL_CTS_RTS, 64)) {
Serial.println("ERROR: Failed to enable hardware flow control!");
while (1) {
delay(1000);
}
}
#if USE_INTERNAL_MATRIX_PIN_LOOPBACK
uart_internal_loopback(1, UART1_RX_PIN);
uart_internal_hw_flow_ctrl_loopback(1, UART1_CTS_PIN);
#endif
// Diagnostic: Check initial state after enabling flow control
Serial.println("\nPost-initialization diagnostics:");
Serial.printf(" Serial1.available(): %d bytes\n", Serial1.available());
Serial.printf(" Serial1.availableForWrite(): %d bytes\n", Serial1.availableForWrite());
if (USE_GPIO_CONTROL) {
Serial.printf(" GPIO%d (CTS control): %s\n", GPIO_CTS_CTRL, digitalRead(GPIO_CTS_CTRL) == LOW ? "LOW" : "HIGH");
Serial.printf(" GPIO%d (RTS monitor): %s\n", GPIO_RTS_MONITOR, digitalRead(GPIO_RTS_MONITOR) == LOW ? "LOW" : "HIGH");
}
Serial.println();
Serial.println("UART1 initialized successfully!");
Serial.println("Hardware flow control: ENABLED (RTS + CTS)");
Serial.printf("RX Pin: GPIO%d\n", UART1_RX_PIN);
Serial.printf("TX Pin: GPIO%d\n", UART1_TX_PIN);
Serial.printf("RTS Pin: GPIO%d (output from UART)\n", UART1_RTS_PIN);
Serial.printf("CTS Pin: GPIO%d (input to UART)\n", UART1_CTS_PIN);
#if USE_INTERNAL_MATRIX_PIN_LOOPBACK
Serial.println("\nNO EXTERNAL PIN CONNECTIONS ARE REQUIRED:");
Serial.println("-------------------------");
Serial.println("Internal GPIO Matrix connection with flow control mode:");
Serial.printf(" 1. Automatic Internal Connection of GPIO%d (TX1) to GPIO%d (RX1) - Loopback\n", UART1_TX_PIN, UART1_RX_PIN);
Serial.printf(" 2. Automatic Internal Connection of GPIO%d (RTS1) to GPIO%d (CTS1) - Flow control loopback\n", UART1_RTS_PIN, UART1_CTS_PIN);
Serial.println("\n Note: In this mode, RTS/CTS are automatically controlled by hardware.");
Serial.println(" RTS goes LOW when ready to receive, HIGH when buffer is full.");
Serial.println(" CTS must be LOW for transmission to proceed.");
#else
Serial.println("\nPIN CONNECTIONS REQUIRED:");
Serial.println("-------------------------");
if (USE_GPIO_CONTROL) {
Serial.println("GPIO-controlled flow control mode:");
Serial.printf(" 1. Connect GPIO%d (TX1) to GPIO%d (RX1) - Loopback\n", UART1_TX_PIN, UART1_RX_PIN);
Serial.printf(" 2. Connect GPIO%d (RTS1) to GPIO%d - Monitor RTS state\n", UART1_RTS_PIN, GPIO_RTS_MONITOR);
Serial.printf(" 3. Connect GPIO%d (CTS1) to GPIO%d - Control CTS signal\n", UART1_CTS_PIN, GPIO_CTS_CTRL);
} else {
Serial.println("Hardware-controlled flow control (simple loopback):");
Serial.printf(" 1. Connect GPIO%d (TX1) to GPIO%d (RX1) - Loopback\n", UART1_TX_PIN, UART1_RX_PIN);
Serial.printf(" 2. Connect GPIO%d (RTS1) to GPIO%d (CTS1) - Flow control loopback\n", UART1_RTS_PIN, UART1_CTS_PIN);
Serial.println("\n Note: In this mode, RTS/CTS are automatically controlled by hardware.");
Serial.println(" RTS goes LOW when ready to receive, HIGH when buffer is full.");
Serial.println(" CTS must be LOW for transmission to proceed.");
}
#endif
Serial.println("\nStarting demonstration in 2 seconds...\n");
delay(2000);
}
void loop() {
unsigned long currentTime = millis();
// Print status periodically
if (currentTime - lastStatusTime >= statusInterval) {
lastStatusTime = currentTime;
printPinStatus();
// Demonstrate flow control by toggling CTS (only in GPIO-controlled mode)
if (USE_GPIO_CONTROL) {
static bool ctsState = false;
ctsState = !ctsState;
if (ctsState) {
Serial.println(">>> Blocking transmission (CTS HIGH)...");
digitalWrite(GPIO_CTS_CTRL, HIGH); // Block transmission
} else {
Serial.println(">>> Allowing transmission (CTS LOW)...");
digitalWrite(GPIO_CTS_CTRL, LOW); // Allow transmission
}
}
}
// Send data periodically
if (currentTime - lastSendTime >= sendInterval) {
lastSendTime = currentTime;
sendCounter++;
// Check if we can transmit (CTS must be LOW)
// In GPIO-controlled mode, check the control GPIO; otherwise hardware handles it
bool canTransmit = true;
if (USE_GPIO_CONTROL) {
canTransmit = (digitalRead(GPIO_CTS_CTRL) == LOW);
}
if (canTransmit) {
char message[64];
snprintf(message, sizeof(message), "Message #%d: Hello from UART1! Time: %lu ms\r\n", sendCounter, currentTime);
Serial.print("Sending: ");
Serial.print(message);
size_t bytesWritten = Serial1.write((const uint8_t *)message, strlen(message));
Serial.printf(" -> Written: %d bytes\n", bytesWritten);
// Flush to ensure data is sent
Serial1.flush();
} else {
Serial.println("!!! Transmission blocked - CTS is HIGH !!!");
}
}
// Read and echo received data
if (Serial1.available()) {
Serial.print("Received: ");
while (Serial1.available()) {
char c = Serial1.read();
Serial.write(c);
}
Serial.println();
}
// Small delay to prevent tight loop
delay(10);
}
@@ -0,0 +1,366 @@
# Hardware Flow Control Demo
This example demonstrates UART hardware flow control using RTS (Request To Send) and CTS (Clear To Send) signals with ESP32's HardwareSerial (UART1).
## Overview
Hardware flow control is a mechanism that prevents data loss by controlling when data can be transmitted and received. It uses two additional signals:
- **RTS (Request To Send)**: Output signal from the UART indicating it's ready to receive data
- **CTS (Clear To Send)**: Input signal to the UART that controls when transmission is allowed
## Configuration Options
The sketch supports two configuration options:
### USE_INTERNAL_MATRIX_PIN_LOOPBACK
**Location in code:** Line 55 in `HardwareFlowControl_Demo.ino`
```cpp
#define USE_INTERNAL_MATRIX_PIN_LOOPBACK 1 // Set to 1 for internal loopback, 0 for external wires
```
- **`USE_INTERNAL_MATRIX_PIN_LOOPBACK = 1`** (Default): Uses ESP32's internal GPIO matrix to create loopback connections. **No external wires needed!**
- **`USE_INTERNAL_MATRIX_PIN_LOOPBACK = 0`**: Requires external wire connections (see Pin Connections section below)
### USE_GPIO_CONTROL
**Location in code:** Line 72 in `HardwareFlowControl_Demo.ino`
```cpp
#define USE_GPIO_CONTROL false // Set to true or false
```
**Note:** When `USE_INTERNAL_MATRIX_PIN_LOOPBACK = 1`, the `USE_GPIO_CONTROL` setting is overridden and hardware-controlled mode is used.
## Pin Connections
**Important:** Pin connections are only needed when `USE_INTERNAL_MATRIX_PIN_LOOPBACK = 0`.
### Default Pin Assignments
- **RX1**: Uses board default (`RX1` constant - typically GPIO26 for ESP32, varies by board)
- **TX1**: Uses board default (`TX1` constant - typically GPIO27 for ESP32, varies by board)
- **RTS1**: GPIO2 (configurable via `UART1_RTS_PIN`)
- **CTS1**: GPIO4 (configurable via `UART1_CTS_PIN`)
- **GPIO_RTS_MONITOR**: GPIO5 (for GPIO-controlled mode, configurable via `GPIO_RTS_MONITOR`)
- **GPIO_CTS_CTRL**: GPIO13 (for GPIO-controlled mode, configurable via `GPIO_CTS_CTRL`)
**Note:** RX1 and TX1 pin numbers are board-specific. Check your board's pin definitions or use the serial output to see the actual GPIO numbers being used.
### Option 1: Simple Loopback (`USE_GPIO_CONTROL = false`)
For a basic loopback test with automatic flow control:
```
ESP32 Pin Connections:
- TX1 ────┐
├──> RX1 (Data loopback)
- GPIO2 (RTS1) ────┐
├──> GPIO4 (CTS1) (Flow control loopback)
```
**Physical Connections (when USE_INTERNAL_MATRIX_PIN_LOOPBACK = 0):**
1. Connect TX1 pin to RX1 pin with a jumper wire - read the console serial output to know which pins are the default ones
2. Connect GPIO2 (RTS1) to GPIO4 (CTS1) with a jumper wire
### Option 2: GPIO-Controlled Flow Control (`USE_GPIO_CONTROL = true`)
For manual control of flow control signals:
```
ESP32 Pin Connections:
- TX1 ────> RX1 (Data loopback)
- GPIO2 (RTS1) ────> GPIO5 (RTS Monitor) (Monitor RTS state)
- GPIO4 (CTS1) <─── GPIO13 (CTS Control) (Control CTS signal)
```
**Physical Connections (when USE_INTERNAL_MATRIX_PIN_LOOPBACK = 0):**
1. Connect TX1 pin to RX1 pin with a jumper wire
2. Connect GPIO2 (RTS1) to GPIO5 with a jumper wire
3. Connect GPIO4 (CTS1) to GPIO13 with a jumper wire
## How Hardware Flow Control Works
### RTS (Request To Send)
- **Output signal** from the UART
- **LOW (0 V)**: UART is ready to receive data (RX buffer has space)
- **HIGH (3.3 V)**: UART RX buffer is getting full, cannot receive more data
### CTS (Clear To Send)
- **Input signal** to the UART
- **LOW (0 V)**: UART is allowed to transmit data
- **HIGH (3.3 V)**: UART must pause transmission (transmission is blocked)
### Flow Control Behavior
1. **Receiving Data (RTS)**:
- When UART1's RX buffer has space, RTS1 is driven LOW
- When RX buffer fills up (threshold reached), RTS1 is driven HIGH
- This signals the sender to stop transmitting
2. **Transmitting Data (CTS)**:
- UART1 checks CTS1 before transmitting
- If CTS1 is LOW, transmission proceeds normally
- If CTS1 is HIGH, UART1 pauses transmission until CTS1 goes LOW again
### Understanding the Two Modes
**`USE_GPIO_CONTROL = false` (Default - Simple Loopback)**
- Use this mode when you connect RTS1 directly to CTS1 (hardware loopback)
- Flow control operates automatically - no software intervention needed
- RTS/CTS signals are controlled entirely by the UART hardware
- Best for: Basic testing and understanding automatic flow control behavior
- **Wiring (when USE_INTERNAL_MATRIX_PIN_LOOPBACK = 0):** Connect GPIO2 (RTS1) → GPIO4 (CTS1)
**`USE_GPIO_CONTROL = true` (GPIO-Controlled Mode)**
- Use this mode when you want to manually control or monitor flow control signals
- Software can read RTS state and control CTS signal via GPIO pins
- Demonstrates explicit flow control blocking behavior
- Best for: Testing flow control behavior, interfacing with external logic, or learning how external devices control UART transmission
- **Wiring (when USE_INTERNAL_MATRIX_PIN_LOOPBACK = 0):**
- Connect GPIO2 (RTS1) → GPIO5 (to monitor RTS)
- Connect GPIO4 (CTS1) → GPIO13 (to control CTS)
- **Note:** This mode is overridden when `USE_INTERNAL_MATRIX_PIN_LOOPBACK = 1`
### How to Configure
1. Open `HardwareFlowControl_Demo.ino` in Arduino IDE
2. **For internal loopback (no wires):** Set `USE_INTERNAL_MATRIX_PIN_LOOPBACK` to `1` (default)
3. **For external wires:** Set `USE_INTERNAL_MATRIX_PIN_LOOPBACK` to `0` and configure `USE_GPIO_CONTROL`:
- `false` for hardware-controlled mode
- `true` for GPIO-controlled mode
4. Make sure your physical wiring matches the selected mode (only if `USE_INTERNAL_MATRIX_PIN_LOOPBACK = 0`)
5. Upload the sketch
**Important:**
- When `USE_INTERNAL_MATRIX_PIN_LOOPBACK = 1`, no external connections are needed
- When `USE_INTERNAL_MATRIX_PIN_LOOPBACK = 0`, the wiring configuration must match the `USE_GPIO_CONTROL` setting
## Code Explanation
### Key Functions Used
1. **`begin(baudrate)`**
- Initializes the UART with the specified baud rate
- Must be called before setting pins and enabling hardware flow control
2. **`setPins(rxPin, txPin, ctsPin, rtsPin)`**
- Configures the UART pins
- Note: The order `begin()` then `setPins()` is important for proper initialization
3. **`uart_internal_loopback(uartNum, rxPin)`** (when `USE_INTERNAL_MATRIX_PIN_LOOPBACK = 1`)
- Creates internal GPIO matrix connection for TX→RX loopback
- No external wires needed
4. **`uart_internal_hw_flow_ctrl_loopback(uartNum, ctsPin)`** (when `USE_INTERNAL_MATRIX_PIN_LOOPBACK = 1`)
- Creates internal GPIO matrix connection for RTS→CTS flow control loopback
- No external wires needed
5. **`setHwFlowCtrlMode(mode, threshold)`**
- Enables hardware flow control
- Modes:
- `UART_HW_FLOWCTRL_DISABLE`: Disable flow control
- `UART_HW_FLOWCTRL_RTS`: Enable RX flow control only
- `UART_HW_FLOWCTRL_CTS`: Enable TX flow control only
- `UART_HW_FLOWCTRL_CTS_RTS`: Enable full flow control (default)
- Threshold: Number of bytes in RX FIFO before RTS is asserted (default: 64)
### Example Behavior
The sketch demonstrates:
- Periodic transmission of messages
- Flow control blocking when CTS is HIGH
- Monitoring of RTS/CTS pin states
- Loopback reception of transmitted data
## Expected Output and Behavior
The sketch behavior differs depending on the `USE_GPIO_CONTROL` setting (see Configuration section above for details).
### Mode 1: Hardware-Controlled Flow Control (`USE_GPIO_CONTROL = false`)
**Behavior:**
- RTS and CTS signals are automatically controlled by the UART hardware
- RTS1 is directly connected to CTS1 (hardware loopback)
- Flow control operates automatically without software intervention
- RTS goes LOW when ready to receive, HIGH when buffer is full
- CTS must be LOW for transmission to proceed (automatically controlled by RTS)
**Expected Output:**
```
========================================
ESP32 Hardware Flow Control Demo
========================================
Initializing UART1...
Using hardware-controlled flow control (simple loopback)
UART1 initialized successfully!
Hardware flow control: ENABLED (RTS + CTS)
RX Pin: GPIO26 (for the ESP32 RX1 or board-specific RX1 default)
TX Pin: GPIO27 (for the ESP32 TX1 or board-specific TX1 default)
RTS Pin: GPIO2 (output from UART)
CTS Pin: GPIO4 (input to UART)
NO EXTERNAL PIN CONNECTIONS ARE REQUIRED:
-------------------------
Internal GPIO Matrix connection with flow control mode:
1. Automatic Internal Connection of TX1 to RX1 - Loopback (via GPIO matrix)
2. Automatic Internal Connection of GPIO2 (RTS1) to GPIO4 (CTS1) - Flow control loopback
Note: In this mode, RTS/CTS are automatically controlled by hardware.
RTS goes LOW when ready to receive, HIGH when buffer is full.
CTS must be LOW for transmission to proceed.
Starting demonstration in 2 seconds...
=== UART1 Pin Status ===
RX Pin (GPIO26): ESP32 Receiving data (or board-specific RX1)
TX Pin (GPIO27): ESP32 Transmitting data (or board-specific TX1)
RTS Pin (GPIO2): Hardware controlled (LOW = ready to receive)
CTS Pin (GPIO4): Hardware controlled (LOW = can transmit)
Note: RTS/CTS pins are hardware-controlled. Connect RTS1 to CTS1 for loopback.
Available for write: 128 bytes
Available to read: 0 bytes
========================
Sending: Message #1: Hello from UART1! Time: 1000 ms
-> Written: 45 bytes
Received: Message #1: Hello from UART1! Time: 1000 ms
=== UART1 Pin Status ===
RX Pin (GPIO26): ESP32 Receiving data (or board-specific RX1)
TX Pin (GPIO27): ESP32 Transmitting data (or board-specific TX1)
RTS Pin (GPIO2): Hardware controlled (LOW = ready to receive)
CTS Pin (GPIO4): Hardware controlled (LOW = can transmit)
Note: RTS/CTS pins are hardware-controlled. Connect RTS1 to CTS1 for loopback.
Available for write: 128 bytes
Available to read: 45 bytes
========================
Sending: Message #2: Hello from UART1! Time: 2000 ms
-> Written: 45 bytes
Received: Message #2: Hello from UART1! Time: 2000 ms
```
**Key Characteristics:**
- No manual CTS toggling messages
- Flow control happens automatically based on RX buffer state
- RTS/CTS states are not directly readable (hardware-controlled)
- Transmission is always allowed (CTS follows RTS automatically)
### Mode 2: GPIO-Controlled Flow Control (`USE_GPIO_CONTROL = true`)
**Behavior:**
- RTS signal is monitored via GPIO5 (connected to RTS1)
- CTS signal is controlled via GPIO13 (connected to CTS1)
- Software can manually block/allow transmission by controlling GPIO13
- Demonstrates explicit flow control blocking behavior
- Shows how external devices can control UART transmission
- **Note:** This mode only works when `USE_INTERNAL_MATRIX_PIN_LOOPBACK = 0`
**Expected Output:**
```
========================================
ESP32 Hardware Flow Control Demo
========================================
Initializing UART1...
Using GPIO-controlled flow control mode
UART1 initialized successfully!
Hardware flow control: ENABLED (RTS + CTS)
RX Pin: GPIO26 (or board-specific RX1 default)
TX Pin: GPIO27 (or board-specific TX1 default)
RTS Pin: GPIO2 (output from UART)
CTS Pin: GPIO4 (input to UART)
PIN CONNECTIONS REQUIRED:
-------------------------
GPIO-controlled flow control mode:
1. Connect TX1 to RX1 - Loopback (board-specific pins)
2. Connect GPIO2 (RTS1) to GPIO5 - Monitor RTS state
3. Connect GPIO4 (CTS1) to GPIO13 - Control CTS signal
Starting demonstration in 2 seconds...
=== UART1 Pin Status ===
RX Pin (GPIO26): Receiving data (or board-specific RX1)
TX Pin (GPIO27): Transmitting data (or board-specific TX1)
RTS Pin (GPIO2): LOW (Ready) (LOW = ready to receive)
CTS Pin (GPIO4): LOW (Clear) (LOW = can transmit)
Available for write: 128 bytes
Available to read: 0 bytes
========================
Sending: Message #1: Hello from UART1! Time: 1000 ms
-> Written: 45 bytes
Received: Message #1: Hello from UART1! Time: 1000 ms
=== UART1 Pin Status ===
RX Pin (GPIO26): Receiving data (or board-specific RX1)
TX Pin (GPIO27): Transmitting data (or board-specific TX1)
RTS Pin (GPIO2): LOW (Ready) (LOW = ready to receive)
CTS Pin (GPIO4): LOW (Clear) (LOW = can transmit)
Available for write: 128 bytes
Available to read: 45 bytes
========================
>>> Allowing transmission (CTS LOW)...
Sending: Message #2: Hello from UART1! Time: 2000 ms
-> Written: 45 bytes
Received: Message #2: Hello from UART1! Time: 2000 ms
=== UART1 Pin Status ===
RX Pin (GPIO26): Receiving data (or board-specific RX1)
TX Pin (GPIO27): Transmitting data (or board-specific TX1)
RTS Pin (GPIO2): LOW (Ready) (LOW = ready to receive)
CTS Pin (GPIO4): HIGH (Blocked) (LOW = can transmit)
Available for write: 128 bytes
Available to read: 45 bytes
========================
>>> Blocking transmission (CTS HIGH)...
!!! Transmission blocked - CTS is HIGH !!!
=== UART1 Pin Status ===
RX Pin (GPIO26): Receiving data (or board-specific RX1)
TX Pin (GPIO27): Transmitting data (or board-specific TX1)
RTS Pin (GPIO2): LOW (Ready) (LOW = ready to receive)
CTS Pin (GPIO4): HIGH (Blocked) (LOW = can transmit)
Available for write: 128 bytes
Available to read: 45 bytes
========================
>>> Allowing transmission (CTS LOW)...
Sending: Message #3: Hello from UART1! Time: 3000 ms
-> Written: 45 bytes
Received: Message #3: Hello from UART1! Time: 3000 ms
```
**Key Characteristics:**
- Explicit messages showing CTS state changes ("Allowing transmission" / "Blocking transmission")
- Transmission blocking messages when CTS is HIGH
- RTS/CTS pin states are readable via GPIO5 and GPIO13
- Demonstrates manual flow control
- Useful for testing flow control behavior or interfacing with external flow control logic
- Only works when `USE_INTERNAL_MATRIX_PIN_LOOPBACK = 0`
## Troubleshooting
1. **No data received**:
- If `USE_INTERNAL_MATRIX_PIN_LOOPBACK = 1`: Check that the internal loopback functions are being called
- If `USE_INTERNAL_MATRIX_PIN_LOOPBACK = 0`: Check that TX1 is connected to RX1
2. **Transmission always blocked**: Verify CTS pin connection and state (only applies when `USE_INTERNAL_MATRIX_PIN_LOOPBACK = 0`)
3. **RTS always HIGH**: RX buffer may be full, try reading data
4. **Compilation errors**: Ensure you're using ESP32 Arduino Core 2.0.0 or later
5. **GPIO-controlled mode not working**: Make sure `USE_INTERNAL_MATRIX_PIN_LOOPBACK = 0` (internal loopback overrides GPIO control)
## Notes
- **Internal Loopback Mode** (`USE_INTERNAL_MATRIX_PIN_LOOPBACK = 1`): No external connections needed! The ESP32 GPIO matrix handles all connections internally. This is the easiest way to test hardware flow control.
- **External Wire Mode** (`USE_INTERNAL_MATRIX_PIN_LOOPBACK = 0`): Requires physical connections between RTS and CTS pins (and TX/RX for data loopback)
- The threshold parameter controls when RTS is asserted (default: 64 bytes = half of 128-byte FIFO)
- Flow control is most useful when communicating with devices that support it (modems, some sensors, etc.)
- For simple point-to-point communication without flow control support, you can disable it