
Week 11 - Networking and communications
In this week's group assignment, we experimented with wireless ESP-NOW communication between two ESP32-C3 boards. It was eye-opening to see how easy it is to get started with simple communication-based applications, such as smart home or IoT projects.
What will use networking and communication in the final project
- I'll split the tasks between two microcontrollers that talk to each other. That way, I can work on them separately and get more I/O pins to work with. A dedicated microcontroller at the target loop will detect a ping pong ball passing through an optical gate and control Neopixel lighting for each hit. An ATtiny412 should be sufficient for this task. To prototype quickly, I'll use an RP2040, which is similar to the ESP32-C3 but has a better analog-to-digital converter—potentially useful for the optical gate detector. The ESP32-C3 will serve as the main microcontroller.
- Game scores will be saved on an SD card.
- The final scores will be sent to this web page to display real-time game statistics.
Distributed Microcontroller System
SD card connection
According to Adafruit's SD card tutorial, SD cards are fairly sensitive to signal integrity, so the interface wires should be kept as short as possible. To account for this, I’ll design another version of the main PCB with the SD card slot placed close to the ESP32-C3.
The Fab Lab inventory includes a MicroSD card reader slot, which I’ll use for this project.
For the PCB layout, I’ll follow Neil’s example.



Wi-Fi web server & sending scores
It would be nice to send the scores stored on the microSD card via Wi-Fi and display them as a histogram on this web page.
To begin exploring how to do this, I followed this tutorial, which explains how to build a web server using the WebSocket communication protocol.
As part of the tutorial, I first installed the following Arduino libraries:
ESPAsyncWebServer
by ESP32AsyncAsyncTCP
by ESP32Async
Then, I uploaded the example code from the tutorial, updating the following lines with my own Wi-Fi network SSID and password:
const char* ssid = "REPLACE_WITH_YOUR_SSID"; const char* password = "REPLACE_WITH_YOUR_PASSWORD";
At first, it didn't work. The Serial Monitor just kept printing "Connecting to WiFi..."
To troubleshoot, I asked ChatGPT "Doing the random nerd tutorial on ESP32 WebSocket Server I just get Connecting to WiFi.. in the Serial Monitor"
The main issues were:
- The Wi-Fi network must be 2.4 GHz — the ESP32-C3 doesn't support 5 GHz networks
- The computer accessing the ESP32-C3's IP address must be connected to the same Wi-Fi network
After fixing those issues, the ESP32-C3 connected successfully and I was able to control a pin on the ESP32-C3 from a web browser.

This was a good starting point, but not yet what I was aiming for.
I asked ChatGPT: "Can the web page be accessible by all or does it need to be on the same Wi-Fi network?" The answer was:
- No — only devices on the same Wi-Fi network (same LAN) can access it.
- Router port forwarding can make the ESP32 publicly accessible, but this exposes the device to security risks.
Another issue is that the Fab Academy GitHub page is a static site, meaning it can't receive live data directly from the ESP32 - there's no backend or server-side code.
As a workaround, ChatGPT suggested using a free cloud service like ThingSpeak, where the ESP32 can send data. The web page can then fetch and display that data.
I created a free user account and a new channel on ThingSpeak. I copied my ThingSpeak API key and channel ID from the API Keys tab on the ThingSpeak channels page:

ChatGPT also provided sample code for the ESP32-C3 to send random test data to ThingSpeak every 60 seconds. I modified the code by inserting my wifi SSID and password, as well as the ThingSpeak API key.
Demo code to send data from ESP32-C3 to ThingSpeak every 60 seconds
#include
#include
const char* ssid = ""; //put my own wifi ssid here
const char* password = ""; //wifi password here
// ThingSpeak info
const char* server = "https://api.thingspeak.com/update?api_key=xxxxxxxxxxxxxxxx&field1=0"; //get API key from thingspeak.mathworks.com and replace xxxxxxxxxxxxxxxx with it
const char* apiKey = "xxxxxxxxxxxxxxxx"; //get API key from thingspeak.mathworks.com and replace xxxxxxxxxxxxxxxx with it
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, password);
Serial.print("Connecting to WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(500); Serial.print(".");
}
Serial.println("\nConnected!");
}
void loop() {
int Scores = random(0, 100); // replace with your real scores
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http;
String url = String(server) + "?api_key=" + apiKey +
"&field1=" + String(Scores);
http.begin(url);
int httpCode = http.GET();
if (httpCode > 0) {
Serial.println("Data sent!");
} else {
Serial.println("Error sending data");
}
http.end();
}
delay(60000); // wait 60 seconds
}
Now the ESP32-C3 successfully uploads data to the cloud, and the web page can display a visualization using the following HTML code, where the src
value needs to be replaced with the public URL obtained from the ThingSpeak website.
<iframe width="450" height="258" style="border: 0px solid #000000;" src="https://thingspeak.mathworks.com/apps/matlab_visualizations/614866"></iframe>
Here are a few different real-time visualizations of the data received from the microcontroller. The microcontroller isn't running continuously, which is why data only appears in a few time slots.
The time is in UTC (Coordinated Universal Time). If for some reason ThingSpeak is not working, here is an example of how one of the visualizations above should look.