Week 11

Networking & Communication

Overview

Individual. I made a small Wi‑Fi sensor node with an ESP32 and an HC‑SR04 ultrasonic sensor. The ESP32 joins my iPhone hotspot in WIFI_STA mode, then every 500 ms it measures distance (TRIG D4, ECHO D5) using the HC‑SR04 timing method (cm ≈ pulse(μs)/58). It prints node ID + distance to the Serial monitor and flips the on‑board LED on when the reading is closer than 50 cm. This behavior matches the “ESP32 Wi‑Fi Node” code below.

Group. To communicate with a teammate, my node also sends messages over UDP. Each reading is formatted as DIST:<value> and sent to 172.20.10.2:1234. Shengtao’s receiver (another ESP32) listens on that port, parses the message, and shows a simple status on a 128×64 SSD1306 OLED over I²C (SDA D8, SCL D7): NO DATA, TOO CLOSE, NEAR, FAR, or OUT. See the “OLED Display Receiver” code block for details.

Download project files (.zip)  ·  Browse files directory ↗

Gallery

Videos

LED lights on when within range of distance.

Final result for group assignment.

Code — Individual (ESP32 Wi‑Fi)

ESP32 Wi‑Fi Node
#include <WiFi.h>

// ===== 1. WiFi Settings (change to your phone hotspot) =====
const char* ssid     = " Justin's iPhone";      // Your hotspot name
const char* password = "12345678";              // Your hotspot password

// ===== 2. Pin definitions (modify according to your wiring) =====
// Assume TRIG is connected to D4 and ECHO to D5; if incorrect, try D5/D6
const int TRIG_PIN = D4;
const int ECHO_PIN = D5;

const int LED_PIN  = LED_BUILTIN;   // Built-in LED used as a local indicator
const int NODE_ID  = 2;             // Assign a node ID to this board

// Measurement interval
const unsigned long MEASURE_INTERVAL = 500;  // milliseconds
unsigned long lastMeasureTime = 0;

// Distance measurement function, returns cm, or -1 if failed
float measureDistanceCm() {
  // Ensure TRIG starts LOW
  digitalWrite(TRIG_PIN, LOW);
  delayMicroseconds(2);

  // Trigger a 10us pulse
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);

  // Read the ECHO high pulse width (wait up to 30ms)
  long duration = pulseIn(ECHO_PIN, HIGH, 30000);

  if (duration == 0) {
    // Timeout: no echo received, return -1
    return -1.0;
  }

  // HC-SR04 formula: cm ≈ pulse width (μs) / 58
  float distance = duration / 58.0;
  return distance;
}

void setup() {
  pinMode(TRIG_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);
  pinMode(LED_PIN, OUTPUT);

  Serial.begin(115200);
  delay(1000);

  Serial.println();
  Serial.println("Ultrasonic WiFi node booting...");

  // ---- Connect to WiFi ----
  WiFi.mode(WIFI_STA);
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println();
  Serial.println("WiFi connected!");
  Serial.print("My IP address: ");
  Serial.println(WiFi.localIP());  // This IP is the node's network address

  Serial.println("Ready. Measuring distance...");
}

void loop() {
  unsigned long now = millis();
  if (now - lastMeasureTime >= MEASURE_INTERVAL) {
    lastMeasureTime = now;

    float d = measureDistanceCm();

    // Local output: turn LED on if distance < 50cm, otherwise turn off
    if (d > 0 && d < 50.0) {
      digitalWrite(LED_PIN, HIGH);
    } else {
      digitalWrite(LED_PIN, LOW);
    }

    // Print to serial with node ID
    Serial.print("node ");
    Serial.print(NODE_ID);
    Serial.print(" distance: ");
    Serial.print(d);
    Serial.println(" cm");
  }
}

Code — Group (Message Passing)

Justin’s Ultrasonic Sender Node
#include <WiFi.h>
#include <WiFiUdp.h>

const char* ssid = "Justin's iPhone";
const char* password = "12345678";

const int TRIG_PIN = D4;
const int ECHO_PIN = D5;

WiFiUDP udp;
const unsigned int sendPort = 1234;

IPAddress fishIP(172, 20, 10, 2);

const unsigned long MEASURE_INTERVAL = 500;
unsigned long lastMeasureTime = 0;

float measureDistanceCm() {
  digitalWrite(TRIG_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);

  long duration = pulseIn(ECHO_PIN, HIGH, 30000);
  if (duration == 0) return -1.0;

  float distance = duration / 58.0;
  return distance;
}

void setup() {
  pinMode(TRIG_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);

  Serial.begin(115200);
  delay(1000);

  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) delay(500);

  Serial.println("Sense ready");
}

void loop() {
  unsigned long now = millis();
  if (now - lastMeasureTime >= MEASURE_INTERVAL) {
    lastMeasureTime = now;

    float d = measureDistanceCm();

    char msg[32];
    if (d < 0)
      snprintf(msg, sizeof(msg), "DIST:-1");
    else
      snprintf(msg, sizeof(msg), "DIST:%.1f", d);

    udp.beginPacket(fishIP, sendPort);
    udp.write((const uint8_t*)msg, strlen(msg));
    udp.endPacket();

    Serial.print("Sent: ");
    Serial.println(msg);
  }
}
Shengtao’s OLED Display Receiver
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <WiFi.h>
#include <WiFiUdp.h>

#define W 128
#define H 64

const int SDA_PIN = D8;
const int SCL_PIN = D7;
TwoWire I2C(1);
Adafruit_SSD1306 display(W, H, &I2C, -1);

const int BTN[4] = { D0, D1, D2, D3 };
const char* LABEL[4] = { "RIVER", "LAKE", "OCEAN", "???" };

const char* ssid = " Justin's iPhone";
const char* password = "12345678";

WiFiUDP udp;
const unsigned int localPort = 1234;

void showText(const char* s) {
  display.clearDisplay();
  display.setTextSize(2);
  display.setTextColor(SSD1306_WHITE);

  int16_t x1, y1;
  uint16_t w, h;
  display.getTextBounds(s, 0, 0, &x1, &y1, &w, &h);
  int x = (W - (int)w) / 2;
  int y = (H - (int)h) / 2;
  display.setCursor(x, y);
  display.println(s);
  display.display();
}

void updateDisplayFromDistance(float d) {
  if (d < 0)
    showText("NO DATA");
  else if (d < 10)
    showText("TOO CLOSE");
  else if (d < 30)
    showText("NEAR");
  else if (d < 100)
    showText("FAR");
  else
    showText("OUT");
}

void setup() {
  Serial.begin(115200);
  delay(200);

  I2C.begin(SDA_PIN, SCL_PIN, 100000);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);

  for (int i = 0; i < 4; i++) pinMode(BTN[i], INPUT_PULLUP);

  showText("BOOTING");

  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) delay(300);

  showText("READY");

  udp.begin(localPort);
}

void loop() {
  static uint8_t last[4] = {HIGH, HIGH, HIGH, HIGH};
  static unsigned long lastDebounce[4] = {0,0,0,0};
  const unsigned long DEBOUNCE_MS = 30;

  int packetSize = udp.parsePacket();
  if (packetSize > 0) {
    char buf[64];
    int len = udp.read(buf, sizeof(buf) - 1);
    if (len > 0) buf[len] = 0;

    if (strncmp(buf, "DIST:", 5) == 0) {
      float d = atof(buf + 5);
      updateDisplayFromDistance(d);
    }
  }
}