
Get full C++ & Python code + lifetime access
TrailChat is a portable wireless communication project that allows two people to exchange text messages and small photos without internet, a SIM card, or mobile network coverage.
The project explores an alternative way to stay connected while trekking, camping, or visiting remote areas. In mountain and forest regions, mobile coverage can be unavailable. TrailChat creates a direct radio link between two devices, provided they remain within usable radio range.
Each person carries an ESP32-S3 connected to an nRF24L01+ radio module. Their phone connects to that device’s local Wi-Fi network and opens a browser-based chat interface. The two devices then exchange messages over NRF radio.
The phones do not need a shared hotspot, a router, or an installed messaging application. Each phone communicates with its own device, and the devices carry the conversation between them.
The system uses two separate wireless links:
| Wireless Link | Purpose | | --- | --- | | Phone to ESP32-S3 over Wi-Fi | Opens the local chat page and submits or displays content | | ESP32-S3 to ESP32-S3 over NRF radio | Carries messages and photos between the two devices |
Sending a message:
The same process works in the opposite direction.
Each phone must remain within Wi-Fi range of its own device, while the two NRF modules must remain within usable radio range of each other.
The complete project uses two matching device assemblies.
| Component | Quantity | Purpose | | --- | --- | --- | | ESP32-S3 development board | 2 | Runs the firmware, Wi-Fi access point, and local web server | | nRF24L01+ radio module | 2 | Exchanges data between devices | | Compatible antennas | 2, if required by the modules | Connects to modules with external antenna connectors | | Suitable regulated 3.3 V NRF supply | One per device | Provides stable power to the radio module | | 10–47 µF electrolytic capacitor | 2 | Supports supply stability close to each NRF module | | 100 nF ceramic capacitor | 2 | Provides additional local supply decoupling | | Jumper wires | As required | Connects the boards and radio modules | | USB cables and power sources | 2 sets | Powers the ESP32-S3 boards | | Smartphone with Wi-Fi and a browser | 2 | Provides the messaging interface |
Antenna-equipped PA+LNA modules are preferable for extended-range experiments.
Check the exact module specification. An external antenna alone does not establish its amplifier type or achievable range.
For PA+LNA modules, use a dedicated regulated supply or compatible NRF adapter with sufficient current capacity. Check the radio’s power requirements against the actual module being used.
Use these connections on both Device A and Device B:
| NRF Module Pin | ESP32-S3 Connection | | --- | --- | | VCC | Regulated 3.3 V | | GND | ESP32-S3 GND and supply GND | | CE | GPIO 4 | | CSN / CS | GPIO 5 | | SCK | GPIO 12 | | MOSI | GPIO 11 | | MISO | GPIO 13 | | IRQ | Leave unconnected |
Use GPIO numbers, not physical header positions. Verify the pin labels on your specific NRF module and ESP32-S3 board.
Connect the capacitors across NRF VCC and GND, close to the module:
Keep SPI wires short and maintain a common ground between the ESP32-S3 and the NRF power supply.
Never connect a bare NRF module’s VCC directly to 5 V. An adapter may accept 5 V at its input only if it is designed to regulate that voltage to the required radio supply.
The firmware is written in Arduino C++ for ESP32-S3 and uses:
The interface is stored in the firmware and served directly by the ESP32-S3. It does not depend on externally hosted scripts, fonts, or internet services.
Both boards use the same firmware, with different node settings:
| Setting | Device A | Device B | | --- | --- | --- | | NODE_ID | 0 | 1 | | Current Wi-Fi name | TrailChat-A-Fix | TrailChat-B-Fix | | Default Wi-Fi password | trail1234 | trail1234 | | Chat page address | http://192.168.4.1/ | http://192.168.4.1/ |
Both devices can use the same page address because each phone joins a separate local network.
Change the default password in config.h before regular use.
The local interface provides:
Each device accepts one connected phone at a time.
Keep the page open during transfers and send one item at a time for the most predictable operation.
The current working firmware keeps the Wi-Fi names visible. Automatic hiding during connection is disabled. An optional setting can hide the network from boot, requiring the phone to join it manually using its exact name and password.
Large smartphone photos are reduced before transmission. The browser resizes the image, converts it to JPEG, and adjusts quality to fit the transfer limit.
This feature is designed for small photo previews, rather than original-resolution images, video, or live streaming.
Transfer time depends on image size, interference, and packet retries. Photos generally take longer to transfer than short text messages.
The NRF configuration uses a 250 kbps raw radio data rate and 32-byte radio payloads.
In this protocol, a 9-byte application header leaves 23 bytes for content in each data packet. The raw radio rate is different from the final messaging throughput.
The firmware combines hardware acknowledgements with application-level confirmation. It:
Delivered means the receiving ESP32-S3 accepted and stored the complete message or photo. It does not mean the other person has read it.
CRC verification detects corruption; it does not encrypt or authenticate the content.
Serial Monitor helps distinguish different parts of the system:
| Status or Message | Meaning | | --- | --- | | NRF detected / NRF=OK | The ESP32-S3 can communicate with its local radio over SPI | | PEER=ONLINE | A valid packet was recently received from the other device | | PHONE ASSOCIATED | A phone established its Wi-Fi association | | PHONE GOT IP | The phone received an address on the local network | | TX=delivered | The peer confirmed the completed transfer | | CRC OK | The received content passed the whole-transfer integrity check | | Transfer failed | The transfer did not obtain the required confirmation |
Local NRF detection alone does not prove that the radio link is working. Confirm peer activity and a successful transfer in both directions.
TrailChat explores communication in places where mobile coverage is unavailable.
Possible uses include:
A 1 km range is a development goal, not a verified specification of this build.
Actual distance depends on:
Mountain terrain can block the radio link. The presence of an external antenna does not guarantee communication through obstacles.
Test the system progressively outdoors and measure successful transfers in both directions before describing its usable range.
Save received photos on the phone before they are replaced by newer ones.
TrailChat combines embedded programming, SPI communication, local web interfaces, radio packet transfer, image compression, and integrity checking in one practical build.
It demonstrates how smartphones can become the interface for a separate radio system, allowing a conversation to operate without an internet connection while making the link’s status and limitations visible to the user.
The firmware package is ESP32S3_NRF24_TrailChat.zip.
It contains:
Build both devices, confirm communication at short distance, and then test the range in your intended environment.