◄ PAGE 10 PAGE 12 ►
WEEK #11

NETWORKING & COMMUNICATIONS

Group Assignment: Making microcontrollers talk to each other!

MISSION BRIEFING

For the networking and communications week, our group set out to verify 5 different standard communication protocols. We created a modular test rig where multiple microcontrollers could communicate using different methods. Our objective was to measure the reliability, power usage, and speed of: BLE, ESP-NOW, HTTP, I2C, and MQTT.

Team Members: Javier Vega and Rodrigo Zárate

01. BLUETOOTH LOW ENERGY (BLE)

HERO TEST: SMARTPHONE CONNECTION

We configured an ESP32 as a BLE Server, advertising a custom characteristic. We used a smartphone app to subscribe to updates, successfully reading sensor data every 5 seconds.

Hero Test Video: BLE connection in real-time.

THE CODE LOGIC

// 1. SENDER (BLE SERVER)
#include <Arduino.h>
#include <Wire.h>
#include <WiFi.h>
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>

#define SHT31_ADDR 0x44

// BLE UUIDs
#define SERVICE_UUID        "12345678-1234-1234-1234-1234567890ab"
#define CHARACTERISTIC_UUID "abcdefab-1234-1234-1234-abcdef123456"

BLECharacteristic *pCharacteristic;
BLEServer *pServer;
bool deviceConnected = false;

float temperature = 0.0;
float humidity = 0.0;
unsigned long lastUpdate = 0;

class MyServerCallbacks : public BLEServerCallbacks {
  void onConnect(BLEServer* pServer) {
    deviceConnected = true;
    Serial.println("BLE Client connected");
  }

  void onDisconnect(BLEServer* pServer) {
    deviceConnected = false;
    Serial.println("BLE Client disconnected");
    BLEDevice::startAdvertising();
    Serial.println("Restarting advertising...");
  }
};

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 setup() {
  Serial.begin(115200);
  delay(1000);

  Wire.begin();

  BLEDevice::init("SHT3X_BLE_SERVER");
  pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());

  BLEService *pService = pServer->createService(SERVICE_UUID);

  pCharacteristic = pService->createCharacteristic(
    CHARACTERISTIC_UUID,
    BLECharacteristic::PROPERTY_READ |
    BLECharacteristic::PROPERTY_NOTIFY
  );

  pCharacteristic->addDescriptor(new BLE2902());
  pCharacteristic->setValue("0.0,0.0");

  pService->start();

  BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
  pAdvertising->addServiceUUID(SERVICE_UUID);
  pAdvertising->start();

  Serial.println("BLE Server ready, waiting for client...");
}

void loop() {
  if (millis() - lastUpdate > 2000) {
    lastUpdate = millis();

    readSHT3X();

    String payload = String(temperature, 1) + "," + String(humidity, 1);
    pCharacteristic->setValue(payload.c_str());

    if (deviceConnected) {
      pCharacteristic->notify();
      Serial.print("Notification sent: ");
      Serial.println(payload);
    } else {
      Serial.print("Value updated: ");
      Serial.println(payload);
    }
  }
}
// 2. RECEIVER (BLE CLIENT)
#include <Arduino.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SH110X.h>
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEClient.h>
#include <BLERemoteCharacteristic.h>
#include <BLEScan.h>

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

#define SERVICE_UUID        "12345678-1234-1234-1234-1234567890ab"
#define CHARACTERISTIC_UUID "abcdefab-1234-1234-1234-abcdef123456"

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

BLEAdvertisedDevice* myDevice = nullptr;
BLERemoteCharacteristic* pRemoteCharacteristic = nullptr;
BLEClient* pClient = nullptr;

bool doConnect = false;
bool connected = false;
bool doScan = false;

float temperature = 0.0;
float humidity = 0.0;

void updateDisplay() {
  display.clearDisplay();
  display.drawRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, SH110X_WHITE);

  display.setTextSize(1);
  display.setTextColor(SH110X_WHITE);
  display.setCursor(18, 5);
  display.println("BLE Data");

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

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

  display.display();
}

static void notifyCallback(
  BLERemoteCharacteristic* pBLERemoteCharacteristic,
  uint8_t* pData,
  size_t length,
  bool isNotify
) {
  String received = "";
  for (size_t i = 0; i < length; i++) {
    received += (char)pData[i];
  }

  Serial.print("BLE data received: ");
  Serial.println(received);

  int commaIndex = received.indexOf(',');
  if (commaIndex > 0) {
    temperature = received.substring(0, commaIndex).toFloat();
    humidity = received.substring(commaIndex + 1).toFloat();
    updateDisplay();
  }
}

class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks {
  void onResult(BLEAdvertisedDevice advertisedDevice) {
    Serial.print("Device found: ");
    Serial.println(advertisedDevice.toString().c_str());

    if (advertisedDevice.haveServiceUUID() &&
        advertisedDevice.isAdvertisingService(BLEUUID(SERVICE_UUID))) {
      Serial.println("BLE Sensor server found");
      myDevice = new BLEAdvertisedDevice(advertisedDevice);
      doConnect = true;
      BLEDevice::getScan()->stop();
    }
  }
};

bool connectToServer() {
  pClient = BLEDevice::createClient();

  if (!pClient->connect(myDevice)) {
    Serial.println("Could not connect to server");
    return false;
  }

  Serial.println("Connected to BLE server");

  BLERemoteService* pRemoteService = pClient->getService(BLEUUID(SERVICE_UUID));
  if (pRemoteService == nullptr) {
    Serial.println("BLE service not found");
    pClient->disconnect();
    return false;
  }

  pRemoteCharacteristic = pRemoteService->getCharacteristic(BLEUUID(CHARACTERISTIC_UUID));
  if (pRemoteCharacteristic == nullptr) {
    Serial.println("BLE characteristic not found");
    pClient->disconnect();
    return false;
  }

  if (pRemoteCharacteristic->canNotify()) {
    pRemoteCharacteristic->registerForNotify(notifyCallback);
  }

  if (pRemoteCharacteristic->canRead()) {
    String value = pRemoteCharacteristic->readValue().c_str();
    Serial.print("Initial reading: ");
    Serial.println(value);

    int commaIndex = value.indexOf(',');
    if (commaIndex > 0) {
      temperature = value.substring(0, commaIndex).toFloat();
      humidity = value.substring(commaIndex + 1).toFloat();
      updateDisplay();
    }
  }

  connected = true;
  return true;
}

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

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

  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SH110X_WHITE);
  display.setCursor(10, 25);
  display.println("Searching for BLE...");
  display.display();

  BLEDevice::init("");

  BLEScan* pBLEScan = BLEDevice::getScan();
  pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
  pBLEScan->setActiveScan(true);
  pBLEScan->start(5, false);
}

void loop() {
  if (doConnect) {
    if (connectToServer()) {
      Serial.println("BLE ready");
      display.clearDisplay();
      display.setTextSize(1);
      display.setCursor(10, 25);
      display.println("BLE Connected");
      display.display();
      delay(500);
    } else {
      Serial.println("BLE connection failed");
    }
    doConnect = false;
  }

  if (connected && pClient && !pClient->isConnected()) {
    connected = false;
    Serial.println("BLE connection lost");
    display.clearDisplay();
    display.setTextSize(1);
    display.setCursor(10, 25);
    display.println("Reconnecting...");
    display.display();
    doScan = true;
  }

  if (doScan) {
    BLEDevice::getScan()->start(5, false);
    doScan = false;
  }

  delay(200);
}

02. ESP-NOW

POINT-TO-POINT MESH

We tested the fast, connectionless ESP-NOW protocol between two boards. Board A sent button press data, and Board B received it instantly to toggle an LED. We achieved reliable connection up to 80 meters in an open field.

Hero Test Video: Instant response using ESP-NOW.

THE CODE LOGIC

// 1. GET MAC ADDRESS
#include <WiFi.h>

void setup() {
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);
  Serial.println(WiFi.macAddress());
}

void loop() {
}
// 2. TRANSMITTER (SENDER)
#include <Arduino.h>
#include <Wire.h>
#include <WiFi.h>
#include <esp_now.h>

#define SHT31_ADDR 0x44

// Change to the receiver board's MAC address
uint8_t receiverAddress[] = {0x58, 0xE6, 0xC5, 0x10, 0x4D, 0xC0};

typedef struct struct_message {
  float temperature;
  float humidity;
} struct_message;

struct_message sensorData;

esp_now_peer_info_t peerInfo;

void OnDataSent(const wifi_tx_info_t *info, esp_now_send_status_t status) {
  Serial.print("Send status: ");
  Serial.println(status == ESP_NOW_SEND_SUCCESS ? "OK" : "FAILED");
}

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

  Wire.begin();

  WiFi.mode(WIFI_STA);
  WiFi.disconnect();

  Serial.print("Sender MAC: ");
  Serial.println(WiFi.macAddress());

  if (esp_now_init() != ESP_OK) {
    Serial.println("Error initializing ESP-NOW");
    return;
  }

  esp_now_register_send_cb(OnDataSent);

  memcpy(peerInfo.peer_addr, receiverAddress, 6);
  peerInfo.channel = 0;
  peerInfo.encrypt = false;

  if (esp_now_add_peer(&peerInfo) != ESP_OK) {
    Serial.println("Error adding peer");
    return;
  }
}

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 to SHT3X");
    delay(2000);
    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];

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

    Serial.print("Temp: ");
    Serial.print(sensorData.temperature);
    Serial.print(" C | Hum: ");
    Serial.print(sensorData.humidity);
    Serial.println(" %");

    esp_err_t result = esp_now_send(receiverAddress, (uint8_t *) &sensorData, sizeof(sensorData));

    if (result == ESP_OK) {
      Serial.println("Data sent");
    } else {
      Serial.println("Error sending data");
    }
  }

  delay(2000);
}
// 3. RECEIVER
#include <Arduino.h>
#include <Wire.h>
#include <WiFi.h>
#include <esp_now.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SH110X.h>

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

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

typedef struct struct_message {
  float temperature;
  float humidity;
} struct_message;

struct_message receivedData;

void OnDataRecv(const esp_now_recv_info_t *info, const uint8_t *incomingData, int len) {
  memcpy(&receivedData, incomingData, sizeof(receivedData));

  Serial.print("Received Temp: ");
  Serial.print(receivedData.temperature);
  Serial.print(" C | Received Humidity: ");
  Serial.print(receivedData.humidity);
  Serial.println(" %");

  display.clearDisplay();
  display.drawRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, SH110X_WHITE);

  display.setTextSize(1);
  display.setTextColor(SH110X_WHITE);
  display.setCursor(20, 5);
  display.println("SHT3X Data");

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

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

  display.display();
}

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

  Wire.begin();

  if (!display.begin(OLED_ADDR, true)) {
    Serial.println("OLED Error");
    while (1);
  }

  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SH110X_WHITE);
  display.setCursor(10, 25);
  display.println("Waiting for data...");
  display.display();

  WiFi.mode(WIFI_STA);
  WiFi.disconnect();

  Serial.print("Receiver MAC: ");
  Serial.println(WiFi.macAddress());

  if (esp_now_init() != ESP_OK) {
    Serial.println("Error initializing ESP-NOW");
    return;
  }

  esp_now_register_recv_cb(OnDataRecv);
}

void loop() {
}

03. HTTP SERVER/CLIENT

LOCAL WEB SERVER

We set up a microcontroller as a simple HTTP Web Server connected to the Fab Lab WiFi. It served an HTML page that displayed real-time data. A separate PC client requested the data by visiting the board's IP address.

Hero Test Video: Refreshing the HTTP page to get new data.

THE CODE LOGIC

// HTTP WEBSERVER SETUP
#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();
}

04. I2C COMMUNICATION

MASTER & SLAVE COMMUNICATION

We validated the classic I2C wire protocol between two different microcontrollers on the same board. The Master requested data, and the Slave responded with readings. This confirmed our traces and pull-up resistors were correct.

Hero Test Video: Slave transmitting bytes to Master.

THE CODE LOGIC

// MASTER REQUESTING DATA
#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);
}

05. MQTT CLOUD PROTOCOL

PUBLISH & SUBSCRIBE (ADAFRUIT IO)

Our most complex integration used MQTT to push sensor data to the Adafruit IO cloud dashboard. Our board published data to a specific topic, and the cloud dashboard subscribed to visualize the data as a gauge in real-time.

Hero Test Video: Visualizing data changes on the cloud dashboard.

THE CODE LOGIC

// PUBLISH TO BROKER
#include <Arduino.h>
#include <Wire.h>
#include <WiFi.h>
#include <PubSubClient.h>

// =========================
// WIFI
// =========================
const char* WIFI_SSID = "RoyZ";
const char* WIFI_PASSWORD = "Zarate28";

// =========================
// MQTT
// =========================
const char* MQTT_BROKER = "test.mosquitto.org";
const int MQTT_PORT = 1883;

// Unique Client ID
String clientId = "xiao_" + String((uint32_t)ESP.getEfuseMac(), HEX);

const char* MQTT_PUBLISH_TOPIC = "fabacademy/xiao/sht3x";
const char* MQTT_SUBSCRIBE_TOPIC = "fabacademy/xiao/command";

// =========================
// SHT3X
// =========================
#define SHT31_ADDR 0x44

// =========================
// LED
// =========================
const int LED_PIN = LED_BUILTIN;

// =========================
// VARIABLES
// =========================
WiFiClient wifiClient;
PubSubClient mqttClient(wifiClient);

unsigned long lastPublishTime = 0;

float temperature = 0.0;
float humidity = 0.0;

// =========================
// WIFI
// =========================
void connectToWiFi() {
  Serial.print("Connecting to Wi-Fi");
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);

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

  Serial.println();
  Serial.println("Wi-Fi connected");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
}

// =========================
// MQTT CALLBACK
// =========================
void mqttCallback(char* topic, byte* payload, unsigned int length) {
  String message = "";

  for (unsigned int i = 0; i < length; i++) {
    message += (char)payload[i];
  }

  Serial.print("MQTT message received on topic: ");
  Serial.println(topic);
  Serial.print("Payload: ");
  Serial.println(message);

  if (message == "on") {
    digitalWrite(LED_PIN, HIGH);
    Serial.println("LED turned ON");
  } else if (message == "off") {
    digitalWrite(LED_PIN, LOW);
    Serial.println("LED turned OFF");
  }
}

// =========================
// MQTT CONNECT
// =========================
void connectToMQTT() {
  while (!mqttClient.connected()) {
    Serial.print("Connecting to MQTT broker...");

    if (mqttClient.connect(clientId.c_str())) {
      Serial.println("connected");

      mqttClient.subscribe(MQTT_SUBSCRIBE_TOPIC);

      Serial.print("Subscribed to: ");
      Serial.println(MQTT_SUBSCRIBE_TOPIC);
    } else {
      Serial.print("failed, rc=");
      Serial.print(mqttClient.state());
      Serial.println(". Trying again in 2 seconds.");
      delay(2000);
    }
  }
}

// =========================
// READ SHT3X SENSOR
// =========================
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 setup() {
  Serial.begin(115200);
  delay(1000);

  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, LOW);

  Wire.begin();

  connectToWiFi();

  mqttClient.setServer(MQTT_BROKER, MQTT_PORT);
  mqttClient.setCallback(mqttCallback);
}

void loop() {

  if (!mqttClient.connected()) {
    connectToMQTT();
  }

  mqttClient.loop();

  if (millis() - lastPublishTime > 5000) {
    lastPublishTime = millis();

    readSHT3X();

    String payload = "{";
    payload += "\"temperature\":" + String(temperature, 1) + ",";
    payload += "\"humidity\":" + String(humidity, 1) + ",";
    payload += "\"wifi_rssi\":" + String(WiFi.RSSI());
    payload += "}";

    bool ok = mqttClient.publish(MQTT_PUBLISH_TOPIC, payload.c_str());

    if (ok) {
      Serial.println("MQTT publish OK");
    } else {
      Serial.println("MQTT publish FAILED");
    }

    Serial.print("Published to ");
    Serial.print(MQTT_PUBLISH_TOPIC);
    Serial.print(": ");
    Serial.println(payload);
  }
}

MISSION ACCOMPLISHED

Week 11 Group Mission is complete. We successfully tested and documented the 5 networking protocols, verifying they all work perfectly for our upcoming individual projects.

← BACK TO HQ (INDEX)