Skip to content

Week 11 Networking and Communications

Group assignment

Week 11 Chaihuo group assignment.

Individual assignment

For my final project, the Xiao ESP32 needs to connect to Wi-Fi, then send out all the voice information for ASR and wake-up words. I use Cursor to help me with the software.

Connect device to Wi-Fi

After connecting with the laptop, tell Cursor you want to connect the device to Wi-Fi.

Provide the Wi-Fi account and password to generate the firmware, and burn the firmware.

Testing

Testing: when the display shows green, it means the device is connected to Wi-Fi.

  • Green: connected
  • Red: disconnected
  • Yellow: connecting

Key source code — WiFi connect + WiFi test (GC9A01 round LCD)

Early Wi-Fi hardware test on Seeed Xiao ESP32-C3 + GC9A01: round screen shows connection state by colour, Serial prints RSSI, auto-reconnect on disconnect.
The same wifi_connect module is reused in the full Lucky Bot firmware (main.cpp).

Project files: include/secrets.h, src/wifi_connect.cpp, src/gc9a01_hsd.cpp, src/main.cpp

Screen colour Meaning
Yellow Connecting to Wi-Fi
Green Connected (got IP)
Red Disconnected / connect failed

1. Wi-Fi credentials (include/secrets.h.example → copy to secrets.h):

#pragma once

#define WIFI_SSID "your_wifi_name"
#define WIFI_PASS "your_wifi_password"

// Mac LAN IP (terminal: ipconfig getifaddr en0)
#define ASR_SERVER_HOST "192.168.0.100"
#define ASR_SERVER_PORT 8765

2. Wi-Fi driver API (src/wifi_connect.h):

struct WiFiConnectResult {
  bool ok;
  int8_t rssi;
  IPAddress ip;
  const char* message;
};

void wifiInitSta();
bool wifiIsLinked();   // WL_CONNECTED + valid IP

WiFiConnectResult connectWiFi(const char* ssid, const char* password,
                              uint32_t timeoutMs = 45000);
void printWiFiStatus();  // SSID, IP, RSSI dBm

3. Wi-Fi connect function (src/wifi_connect.cpp):

#include "wifi_connect.h"
#include <WiFi.h>
#include <esp_wifi.h>

void wifiInitSta() {
  WiFi.onEvent(onWiFiEvent);
  WiFi.mode(WIFI_STA);
  WiFi.setAutoReconnect(false);
  WiFi.setSleep(false);
  esp_wifi_set_ps(WIFI_PS_NONE);
}

bool wifiIsLinked() {
  return WiFi.status() == WL_CONNECTED &&
         WiFi.localIP() != IPAddress(0, 0, 0, 0);
}

WiFiConnectResult connectWiFi(const char* ssid, const char* password,
                              uint32_t timeoutMs) {
  WiFiConnectResult result = {false, 0, IPAddress(), "timeout"};
  if (!ssid || !ssid[0]) {
    result.message = "SSID empty — edit include/secrets.h";
    return result;
  }

  wifiInitSta();
  Serial.printf("[WiFi] Connecting to \"%s\" ...\n", ssid);

  // Scan hotspot first (helps iPhone hotspot — find channel + RSSI)
  int targetChannel = 0;
  const int found = WiFi.scanNetworks(false, true);
  for (int i = 0; i < found; i++) {
    if (WiFi.SSID(i) == ssid) {
      targetChannel = WiFi.channel(i);
      Serial.printf("[WiFi] Found \"%s\" ch=%d rssi=%d\n",
                      ssid, targetChannel, WiFi.RSSI(i));
      break;
    }
  }
  WiFi.scanDelete();

  WiFi.disconnect(false);
  delay(400);
  if (targetChannel > 0)
    WiFi.begin(ssid, password, targetChannel);
  else
    WiFi.begin(ssid, password);

  const uint32_t start = millis();
  while (!wifiIsLinked()) {
    if (WiFi.status() == WL_CONNECT_FAILED ||
        WiFi.status() == WL_NO_SSID_AVAIL) {
      result.message = "auth failed or SSID not found";
      return result;
    }
    if (millis() - start > timeoutMs) {
      result.message = "connection timeout";
      return result;
    }
    delay(400);
    Serial.print('.');
  }
  Serial.println();

  result.ok = true;
  result.rssi = WiFi.RSSI();
  result.ip = WiFi.localIP();
  result.message = "connected";
  Serial.printf("[WiFi] OK IP=%s rssi=%d\n",
                result.ip.toString().c_str(), (int)result.rssi);
  return result;
}

void printWiFiStatus() {
  if (!wifiIsLinked()) {
    Serial.printf("[WiFi] Status=%d (not ready)\n", WiFi.status());
    return;
  }
  Serial.println("[WiFi] Connected (stable)");
  Serial.printf("  SSID: %s\n", WiFi.SSID().c_str());
  Serial.printf("  IP:   %s\n", WiFi.localIP().toString().c_str());
  Serial.printf("  RSSI: %d dBm\n", WiFi.RSSI());
}

4. Wi-Fi test — colour screen + periodic status (early test main.cpp, reconstructed from hardware-check logic):

#include "gc9a01_hsd.h"
#include "wifi_connect.h"
#include "secrets.h"

GC9A01_HSD lcd;

constexpr uint32_t kStatusPrintMs = 10000;   // print RSSI every 10 s
constexpr uint32_t kReconnectMs   = 10000;   // retry if link lost

void showWifiColour(uint16_t color) {
  lcd.fillScreen(color);
}

void setup() {
  Serial.begin(115200);
  delay(500);
  Serial.println("=== WiFi test — GC9A01 colour status ===");

  lcd.begin();

  showWifiColour(COLOR_YELLOW);              // Yellow = connecting
  WiFiConnectResult r = connectWiFi(WIFI_SSID, WIFI_PASS);

  if (r.ok) {
    showWifiColour(COLOR_GREEN);            // Green = connected
    printWiFiStatus();
  } else {
    showWifiColour(COLOR_RED);              // Red = failed
    Serial.printf("[WiFi] FAIL: %s\n", r.message);
  }
}

void loop() {
  static uint32_t lastPrint = 0;
  static uint32_t lastReconnect = 0;
  const uint32_t now = millis();

  if (wifiIsLinked()) {
    showWifiColour(COLOR_GREEN);
    if (now - lastPrint >= kStatusPrintMs) {
      lastPrint = now;
      printWiFiStatus();                    // e.g. RSSI: -45 dBm
    }
  } else {
    showWifiColour(COLOR_RED);              // Red = disconnected
    if (now - lastReconnect >= kReconnectMs) {
      lastReconnect = now;
      Serial.println("[WiFi] Link lost — reconnecting...");
      showWifiColour(COLOR_YELLOW);
      connectWiFi(WIFI_SSID, WIFI_PASS);
      if (wifiIsLinked()) {
        showWifiColour(COLOR_GREEN);
        printWiFiStatus();
      }
    }
  }
  delay(300);
}

LCD colour constants (src/gc9a01_hsd.h):

constexpr uint16_t COLOR_RED    = 0xF800;
constexpr uint16_t COLOR_GREEN  = 0x07E0;
constexpr uint16_t COLOR_YELLOW = 0xFFE0;

5. Merged into full Lucky Bot (src/main.cpp — same connectWiFi, UI upgraded to photos):

void setup() {
  lcd.begin();
  ui.show(LuckyScreen::kOffline);
  wifiInitSta();
  connectWiFi(WIFI_SSID, WIFI_PASS);
}

void loop() {
  if (!wifiIsLinked()) {
    ui.show(LuckyScreen::kOffline);
    if (now - lastReconnect >= 8000)
      connectWiFi(WIFI_SSID, WIFI_PASS);
    return;
  }
  if (!printedStable) {
    printWiFiStatus();
    ui.show(LuckyScreen::kWakeListen);
  }
  deviceStatusTick(ASR_SERVER_HOST, ASR_SERVER_PORT, WIFI_SSID);
}

Expected behaviour: power on → yellowgreen + RSSI: -45 dBm → every 10 s status print → link lost → red → auto-reconnect.

How to change the Wi-Fi configuration

Step 1

Revise the Wi-Fi information in include/secrets.h.

Step 2

Burn the firmware again.

Edit Wi-Fi credentials (include/secrets.h — copy from secrets.h.example if needed):

#pragma once

#define WIFI_SSID "your_wifi_name"
#define WIFI_PASS "your_wifi_password"

// Mac LAN IP (terminal: ipconfig getifaddr en0)
#define ASR_SERVER_HOST "192.168.0.100"
#define ASR_SERVER_PORT 8765

Build, upload, and monitor (connect Xiao ESP32-C3 via USB first):

cd "/Users/jerryrong/Fablab/Final project/Final- coding"
python3 -m platformio run -t upload
python3 -m platformio device monitor

After re-flashing, check the round display: yellow = connecting, green = connected, red = failed.
Serial monitor prints the new IP and RSSI, for example:

[WiFi] Connected (stable)
  SSID: your_wifi_name
  IP:   192.168.x.x
  RSSI: -45 dBm