Hendra Kusumah
Published © GPL3+

Digital Lab Sensor Display

Display climate data across rooms — no Wi-Fi needed!

BeginnerFull instructions provided6 hours97
Digital Lab Sensor Display

Things used in this project

Hardware components

Seeed Studio XIAO ESP32S3 Sense
Seeed Studio XIAO ESP32S3 Sense
×1
XIAO ESP32C3
Seeed Studio XIAO ESP32C3
×1
MAXREFDES99# MAX7219 Display Driver Shield
Maxim Integrated MAXREFDES99# MAX7219 Display Driver Shield
×1
Grove - Temperature&Humidity Sensor (SHT40)
Seeed Studio Grove - Temperature&Humidity Sensor (SHT40)
×1
Jumper wires (generic)
Jumper wires (generic)
×1

Software apps and online services

Arduino IDE
Arduino IDE

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)
Solder Wire, Lead Free
Solder Wire, Lead Free

Story

Read more

Custom parts and enclosures

schematic

Schematics

schematic

Code

sender code

Arduino
#include <esp_now.h>
#include <WiFi.h>
#include <Adafruit_SHT4x.h>

// Create SHT40 object
Adafruit_SHT4x sht4 = Adafruit_SHT4x();

// Structure to send
typedef struct struct_message {
  float temperature;
  float humidity;
} struct_message;

struct_message msg;

// Receiver MAC address (update this according to your esp32 mac address!)

uint8_t receiverAddress[] = {0xE4, 0xB3, 0x23, 0xC3, 0x6C, 0x28};
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  Serial.print("Delivery Status: ");
  Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Success" : "Fail");
}

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

  // Initialize sensor
  if (!sht4.begin()) {
    Serial.println("Couldn't find SHT4x sensor!");
    while (1) delay(10);
  }
  sht4.setPrecision(SHT4X_HIGH_PRECISION);
  sht4.setHeater(SHT4X_NO_HEATER);

  // Initialize WiFi + ESP-NOW
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();

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

  esp_now_register_send_cb(OnDataSent);

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

  if (!esp_now_is_peer_exist(receiverAddress)) {
    if (esp_now_add_peer(&peerInfo) != ESP_OK) {
      Serial.println("Failed to add peer");
      return;
    }
  }

  Serial.println("ESP-NOW sender with SHT40 ready");
}

void loop() {
  sensors_event_t humidity, temperature;
  sht4.getEvent(&humidity, &temperature);
  
  msg.temperature = temperature.temperature;
  msg.humidity = humidity.relative_humidity;

  Serial.print("Sending temperature: ");
  Serial.print(msg.temperature);
  Serial.print(" °C, humidity: ");
  Serial.print(msg.humidity);
  Serial.println(" %");

  esp_err_t result = esp_now_send(receiverAddress, (uint8_t*)&msg, sizeof(msg));
  if (result == ESP_OK) {
    Serial.println("Message sent");
  } else {
    Serial.println("Send failed");
  }

  delay(5000); // Send every 5 seconds
}

receiver code

Arduino
#include <MD_Parola.h>
#include <MD_MAX72XX.h>
#include <esp_now.h>
#include <WiFi.h>
#include <SPI.h>

// MAX7219 config
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 4
#define DATA_PIN  10
#define CLK_PIN   8
#define CS_PIN    5

MD_Parola display = MD_Parola(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);

// Static scrolling text
const char* runningText = "DIGITAL LAB MONITOR";

// Display mode switching
unsigned long lastSwitch = 0;
int mode = 0; // 0: temperature, 1: humidity, 2: running text
const int switchInterval = 7000; // 12 seconds

// Latest received values
volatile float temperatureValue = 0.0;
volatile float humidityValue = 0.0;
unsigned long lastReceived = 0; // Time of last valid data
const unsigned long dataTimeout = 10000; // 10 seconds

// Structure for ESP-NOW message
typedef struct struct_message {
  float temperature;
  float humidity;
} struct_message;

// ESP-NOW receive callback
void OnDataRecv(const esp_now_recv_info_t *recvInfo, const uint8_t *data, int len) {
  if (len == sizeof(struct_message)) {
    struct_message receivedData;
    memcpy(&receivedData, data, sizeof(receivedData));

    temperatureValue = receivedData.temperature;
    humidityValue = receivedData.humidity;
    lastReceived = millis(); // Update timestamp

    // Print sender MAC and data
    char macStr[18];
    const uint8_t *mac = recvInfo->src_addr;
    snprintf(macStr, sizeof(macStr),
             "%02X:%02X:%02X:%02X:%02X:%02X",
             mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
    
    Serial.printf("Received from %s: Temp = %.2f °C, Humidity = %.2f %%\n", macStr, temperatureValue, humidityValue);
  }
}

void setup() {
  Serial.begin(115200);
  display.begin();
  display.setIntensity(8);
  display.displayClear();

  WiFi.mode(WIFI_STA);
  if (esp_now_init() != ESP_OK) {
    Serial.println("ESP-NOW init failed");
    return;
  }

  esp_now_register_recv_cb(OnDataRecv);

  display.displayScroll("ESP-NOW Receiver Ready", PA_LEFT, PA_SCROLL_LEFT, 50);
  while (!display.displayAnimate()) {
    // Wait until the startup message scrolls
  }
  display.displayClear();
}

void loop() {
  unsigned long nowMillis = millis();

  // Reset values if no data received recently
  if ((nowMillis - lastReceived) > dataTimeout) {
    temperatureValue = 0.0;
    humidityValue = 0.0;
  }

  // Toggle mode every switchInterval
  if (nowMillis - lastSwitch > switchInterval) {
    mode = (mode + 1) % 3;
    lastSwitch = nowMillis;
    display.displayClear();
  }

  if (mode == 0) {
    // Show temperature
    char buffer[10];
    snprintf(buffer, sizeof(buffer), "%.1fC", temperatureValue);
    display.setTextAlignment(PA_CENTER);
    display.print(buffer);
    delay(1000);
  } else if (mode == 1) {
    // Show humidity
    char buffer[10];
    snprintf(buffer, sizeof(buffer), "%.1f%%", humidityValue);
    display.setTextAlignment(PA_CENTER);
    display.print(buffer);
    delay(1000);
  } else {
    // Show scrolling text
    if (display.displayAnimate()) {
      display.displayScroll(runningText, PA_LEFT, PA_SCROLL_LEFT, 50);
    }
  }
}

Credits

Hendra Kusumah
47 projects • 159 followers
Love hacking and making new things from IoT to robotics

Comments