water_link
https://github.com/IDTenev/water_link
W5500 on a Multi-Protocol Embedded Board — Water-Link v1.0
What Is This Project?
water_link is an ESP-IDF based firmware SDK for situations where RS-485, RS-232, CAN, I2C, and Ethernet need to run together on a single board.
The project provides driver and service layers that can bring up all interfaces immediately on the custom board Water v1.1 (ESP32-S3 + WIZnet W5500), along with ready-to-run example code for each interface.
A brief overview of the board:
| Item | Details |
|---|---|
| MCU | ESP32-S3 |
| Ethernet | WIZnet W5500 (SPI) |
| Serial | RS-485 (UART2), RS-232 (UART1) |
| Fieldbus | CAN 2.0 / TWAI |
| Sensor Bus | I2C |
| Status Display | WS2812 RGB LED, HT16K33 FND |
| Interfaces | USB-C, Pin header (GPIO, PWM, ADC, Touch) |
Role of the W5500
In this project, all network connectivity is handled by the W5500.
Connected via SPI, the W5500 offloads the TCP/IP stack in hardware, so the MCU can handle socket communication without implementing a software TCP/IP stack.
Within the firmware, the W5500 is abstracted into two layers:
water_driver/d_w5500— W5500 register initialization and SPI communicationwater_service/s_ethernet— Socket-level APIs for UDP, DHCP, Ping, etc.
Application code does not need to know anything about W5500's internal registers. For example, a UDP Echo server works in three lines:
s_udp_open(&udp, 0, 5000);
int32_t n = s_udp_recvfrom(&udp, &peer, buf, sizeof(buf));
s_udp_sendto(&udp, &peer, buf, n);
Ping works the same way:
bool ok = s_ping_once(2, target, 1000, &r);
// ok: success/failure, r.rtt_ms: round-trip time
Software Architecture
The firmware is organized into four layers:
app_main()
└── water_service/ Network services — UDP, DHCP, Ping
└── water_driver/ Chip drivers — W5500, WS2812, HT16K33
└── water_port/ Hardware abstraction — RS-485, RS-232, CAN, I2C, SPI, GPIO
└── water_common/ Pin definitions, error codes, board constants
Each layer is an independent component. For instance, replacing the W5500 with another WIZnet chip would only require changes to d_w5500 and s_ethernet — application code stays untouched.
Included Examples
The SDK includes independently runnable examples for each interface:
| Example | Description |
|---|---|
| RS-232 | Send hello every 1 s, verify Loopback reception |
| RS-485 | Echo received data + append first byte |
| CAN | Receive 8 bytes, return each byte +1 on the same ID |
| I2C | Scan for devices in address range 0x08–0x77 |
| HT16K33 | Display 0–9999 counter on 4-digit FND every 200 ms |
| WS2812 | Cycle colors R→G→B→W→Fade In→Off |
| UDP Echo | Receive on port 5000, retransmit to same peer |
| Ping | Ping a target IP every 1 s, log RTT |
Each example runs independently by swapping out the app_main() body. UDP and Ping run as separate FreeRTOS tasks, making them a useful reference for concurrent multi-function designs.
Potential Applications
The clearly separated layer structure makes it possible to apply this in various directions.
It could be used as a gateway that forwards RS-485 or CAN device data to a network via W5500, or as a reference for embedded projects that require multiple communication interfaces. Modifying the pin definitions in water_common may allow porting to other ESP32-S3 based boards.
Project: github.com/IDTenev/water_link
