PAGE 10 PAGE 12
WEEK #11

NETWORKING & COMMUNICATIONS

Making devices talk: Wired I2C sensors and Wireless HTTP Servers.

ALL ACCESS MISSION FILES (GITLAB REPO)

MISSION BRIEFING

This week's objective is to establish communication between two processors or devices. I decided to tackle both wired and wireless protocols using the powerful ESP32-C6 microcontroller. The mission involves configuring an I2C bus to extract data from a sensor and setting up an HTTP web server to stream that data directly to my laptop over Wi-Fi.

01. THE I2C NETWORK (WIRED)

The I2C (Inter-Integrated Circuit) protocol is perfect for connecting multiple devices using just a few pins on the microcontroller. It works like a shared bus where the ESP32 acts as the "Master" and calls out to different "Slave" devices using unique hexadecimal addresses.

For my setup, I routed a total of 4 wires in parallel (2 SDA and 2 SCL) directly to the same I2C bus on the ESP32-C6. This allowed me to hook up two completely different devices simultaneously: an SH1106G OLED display (Address: 0x3C) and an SHT31 Temperature/Humidity Sensor (Address: 0x44). The ESP32 first asks the SHT31 for the environmental data, translates the raw bytes into Celsius and percentage, and then immediately routes that data to the OLED display for real-time visualization.

I2C IN ACTION: ESP32 fetching data from the SHT31 and routing it to the SH1106 OLED.

02. HTTP WIRELESS PROTOCOL

Moving from wires to invisible waves, I used the ESP32-C6's built-in Wi-Fi capabilities to create a local HTTP server on port 80. This allows me to communicate with the microcontroller directly from my laptop's web browser.

The Process: First, the ESP32 connects to my local Wi-Fi router. Once authenticated, the router assigns it a unique local IP address. The code prints this IP to the Serial Monitor. I simply copied that IP address and pasted it into my laptop's browser URL bar.

To make the interface look professional, I used a C++ rawliteral string to inject custom HTML and CSS directly from the microcontroller. I styled it with dark mode colors, rounded cards, and added a crucial <meta http-equiv="refresh" content="2"> tag so the webpage auto-refreshes every 2 seconds to show live updates!

WIRELESS ACCESS: Entering the local IP to load the live-refreshing Web Server.
PART C

Upper Wings Geometry.

03. THE CODE VAULT

Below is the complete mission code separated into two crucial protocols: the Dual-Device I2C system and the Wi-Fi HTTP Server.

PART 1: THE I2C MULTI-DEVICE LOGIC

This code demonstrates the power of the I2C bus. It initializes both the SH1106 OLED and the SHT31 sensor. In the loop, it requests 6 bytes of data from address 0x44 (Sensor), does the math, and then sends formatting commands to address 0x3C (OLED) to draw the text on the screen.

#include <Arduino.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SH110X.h>
#include <SPI.h>

#define i2c_Address 0x3C
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1

#define SHT31_ADDR 0x44   // Change to 0x45 if your sensor uses that address

Adafruit_SH1106G display(
  SCREEN_WIDTH,
  SCREEN_HEIGHT,
  &Wire,
  OLED_RESET
);

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

  // Initialize I2C
  Wire.begin();

  // Initialize OLED
  if (!display.begin(i2c_Address, true)) {
    Serial.println("Fail to initialize OLED SH110X");
    while (1);
  }

  display.clearDisplay();
  display.setTextColor(SH110X_WHITE);
  display.setTextSize(1);
  display.setCursor(10, 20);
  display.println("Starting...");
  display.display();

  delay(1000);
}

void loop() {

  // =========================
  // SEND COMMAND TO SHT3X
  // =========================
  Wire.beginTransmission(SHT31_ADDR);
  Wire.write(0x24);
  Wire.write(0x00);

  if (Wire.endTransmission() != 0) {
    Serial.println("Error sending command");

    display.clearDisplay();
    display.setCursor(10, 25);
    display.setTextSize(1);
    display.println("SHT3X Error");
    display.display();

    delay(1000);
    return;
  }

  delay(20);

  // =========================
  // READ DATA
  // =========================
  Wire.requestFrom(SHT31_ADDR, 6);

  if (Wire.available() == 6) {
    uint8_t data[6];

    for (int i = 0; i < 6; i++) {
      data[i] = Wire.read();
    }

    uint16_t rawTemp = (data[0] << 8) | data[1];
    uint16_t rawHum  = (data[3] << 8) | data[4];

    float temperature = -45.0 + (175.0 * rawTemp / 65535.0);
    float humidity    = 100.0 * rawHum / 65535.0;

    // Show on Serial Monitor
    Serial.print("Temp: ");
    Serial.print(temperature);
    Serial.print(" C | Hum: ");
    Serial.print(humidity);
    Serial.println(" %");

    // Show on OLED
    display.clearDisplay();
    display.drawRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, SH110X_WHITE);

    display.setTextSize(1);
    display.setCursor(10, 10);
    display.println("SHT3X Sensor");

    display.setTextSize(2);
    display.setCursor(10, 25);
    display.print(temperature, 1);
    display.print(" C");

    display.setCursor(10, 45);
    display.print(humidity, 1);
    display.print(" %");

    display.display();

  } else {
    Serial.println("Error reading sensor");

    display.clearDisplay();
    display.setCursor(10, 25);
    display.setTextSize(1);
    display.println("Read error");
    display.display();
  }

  delay(2000);
}

PART 2: THE HTTP WEB SERVER LOGIC

This section connects the ESP32 to the local Wi-Fi, prints the IP, and hosts an auto-refreshing HTML/CSS page injecting the variables obtained from the sensor.

#include <Arduino.h>
#include <Wire.h>
#include <WiFi.h>
#include <WebServer.h>

#define SHT31_ADDR 0x44

const char* ssid = "RoyZ";
const char* password = "Zarate28";

WebServer server(80);

float temperature = 0.0;
float humidity = 0.0;

void readSHT3X() {
  Wire.beginTransmission(SHT31_ADDR);
  Wire.write(0x24);
  Wire.write(0x00);

  if (Wire.endTransmission() != 0) {
    Serial.println("Error sending command to SHT3X");
    return;
  }

  delay(20);

  Wire.requestFrom(SHT31_ADDR, 6);

  if (Wire.available() == 6) {
    uint8_t data[6];

    for (int i = 0; i < 6; i++) {
      data[i] = Wire.read();
    }

    uint16_t rawTemp = (data[0] << 8) | data[1];
    uint16_t rawHum  = (data[3] << 8) | data[4];

    temperature = -45.0 + (175.0 * rawTemp / 65535.0);
    humidity    = 100.0 * rawHum / 65535.0;

    Serial.print("Temp: ");
    Serial.print(temperature);
    Serial.print(" C | Hum: ");
    Serial.print(humidity);
    Serial.println(" %");
  } else {
    Serial.println("Error reading sensor");
  }
}

void handleRoot() {
  readSHT3X();

  String html = R"rawliteral(
  <!DOCTYPE html>
  <html>
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="refresh" content="2">
    <title>SHT3X Monitor</title>
    <style>
      body {
        font-family: Arial;
        text-align: center;
        background-color: #111;
        color: white;
        margin-top: 50px;
      }

      .card {
        background: #222;
        display: inline-block;
        padding: 30px;
        border-radius: 20px;
        box-shadow: 0 0 20px rgba(255,255,255,0.1);
      }

      h1 {
        font-size: 32px;
      }

      p {
        font-size: 28px;
        margin: 20px 0;
      }
    </style>
  </head>
  <body>
    <div class="card">
      <h1>SHT3X Sensor</h1>
      <p>🌡 Temperature: )rawliteral";

  html += String(temperature, 1);
  html += R"rawliteral( °C</p>
      <p>💧 Humidity: )rawliteral";

  html += String(humidity, 1);
  html += R"rawliteral( %</p>
    </div>
  </body>
  </html>
  )rawliteral";

  server.send(200, "text/html", html);
}

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

  Wire.begin();

  WiFi.begin(ssid, password);

  Serial.print("Connecting to WiFi");

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

  Serial.println();
  Serial.println("WiFi connected");
  Serial.print("IP: ");
  Serial.println(WiFi.localIP());

  server.on("/", handleRoot);
  server.begin();

  Serial.println("HTTP Server started");
}

void loop() {
  server.handleClient();
}

COMMUNICATION ESTABLISHED

I2C and HTTP protocols mastered. The network is secure and live data is flowing.