MJKITO
Published

Condensation indicator light

Use three M5stack devices. Connect sensors to two of them. Use the third device to automatically calculate the values received from the sens

BeginnerShowcase (no instructions)20 hours53
Condensation indicator light

Things used in this project

Hardware components

ESP32 Basic Core IoT Development Kit
M5Stack ESP32 Basic Core IoT Development Kit
×3
Unit ENV-Ⅳ
×1
ADT7410
×1
Unbuckled Grove Cable 1m/2m/50cm/20cm/10cm
M5Stack Unbuckled Grove Cable 1m/2m/50cm/20cm/10cm
×1
4-Channel Relay Module (STM32)
M5Stack 4-Channel Relay Module (STM32)
×1
Jumper wires (generic)
Jumper wires (generic)
×1
plastic nut and spacer
×1
single-sided glass universal board
×1
2.1mm standard DC jack DIP kit for breadboards
×1
patlight(LR4-302WJNW-RYG)
×1

Software apps and online services

Arduino IDE
Arduino IDE

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)

Story

Read more

Schematics

Wiring diagram for power supply,relay,and patlite

OMG! After completing it,I realized that I needed a circuit diagram.

Code

M5stack + ADT7410

C/C++
The surface temperature is measured once every 10 seconds.Communicate with the receiving side using ESP-NOW.
#include <M5Stack.h>
#include <Wire.h>
#include <WiFi.h>
#include <esp_now.h>
#include <esp_wifi.h>
#include "skADT7410.h"

#define WIFI_CHANNEL 1
#define ADT_ADDRESS 0x48

skADT7410 adt(ADT_ADDRESS);
typedef struct __attribute__((packed)) {
  uint8_t id;
  float sftemp;
} PacketADT;

uint8_t receiverMAC[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };


void onSendStatus(const uint8_t *mac, esp_now_send_status_t status) {
  Serial.printf("Send to %02X:%02X:%02X:%02X:%02X:%02X  %s\n",
                mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
                status == ESP_NOW_SEND_SUCCESS ? "OK" : "FAILED");
}






void setup() {
  M5.begin();
  Serial.begin(115200);
  Wire.begin();



  if (adt.Begin() != 0) {
    Serial.println("ADT7410 init failed");
    while (true)
      ;
  }

  adt.ActionMode(ADT_MODE_CONTINUE);

  WiFi.mode(WIFI_STA);
  esp_wifi_set_channel(WIFI_CHANNEL, WIFI_SECOND_CHAN_NONE);
  if (esp_now_init() != ESP_OK) {
    Serial.println("ESP-NOW init error");
    while (true)
      ;
  }

  esp_now_peer_info_t peer = {};
  memcpy(peer.peer_addr, receiverMAC, 6);
  peer.channel = WIFI_CHANNEL;
  peer.encrypt = false;
  esp_now_add_peer(&peer);

  esp_now_register_send_cb(onSendStatus);
}


void loop() {
  uint16_t data;
  float sftemp = 0;

  Wire.requestFrom(ADT_ADDRESS, 2);  //2byte要求

  data = Wire.read() << 8;  //8bit上へ
  data |= Wire.read();
  data >>= 3;  //3bit右に

  if (data & 0x1000) {                     //13bitの計算式
    sftemp = (float)(data - 8192) / 16.0;  //負の場合
  } else {
    sftemp = (float)data / 16.0;  //正の場合
  }
  Serial.print(sftemp);

  PacketADT pkt;
  pkt.id = 2;
  pkt.sftemp = sftemp;

  esp_now_send(receiverMAC, (uint8_t *)&pkt, sizeof(pkt));
  Serial.printf("Sent[ADT] ID:%d sfTemp:%.2f C\n", pkt.id, pkt.sftemp);

  delay(10000);

  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setCursor(0, 0);
  M5.Lcd.setTextSize(2);
  M5.Lcd.setTextColor(WHITE);
  M5.Lcd.printf("sfTemp keisoku");
  M5.Lcd.setCursor(250, 210);
  M5.Lcd.setTextSize(2);
  M5.Lcd.setTextColor(PINK);
  M5.Lcd.printf("MJ");

  M5.Lcd.drawLine(5, 25, 310, 25, RED);
  M5.Lcd.drawLine(5, 200, 310, 200, RED);

  M5.Lcd.setCursor(0, 80);
  M5.Lcd.setTextSize(3);
  M5.Lcd.setTextColor(CYAN);
  M5.Lcd.print("sfTemp: ");
  M5.Lcd.print(sftemp);
  M5.Lcd.println(" C");
}

M5stack + ENVⅣ

C/C++
Temperature and humidity are retrieved from the ENV unit once every 10 seconds.Communicate with the receiving side using ESP-NOW.
#include <M5Stack.h>
#include <Wire.h>
#include <WiFi.h>
#include <esp_now.h>
#include <esp_wifi.h>
#include <SensirionI2cSht4x.h>

#define WIFI_CHANNEL  1
#ifdef NO_ERROR
#undef NO_ERROR
#endif
#define NO_ERROR 0

SensirionI2cSht4x sensor;

static char errorMessage[64];
static int16_t error;

typedef struct __attribute__((packed)){
  uint8_t id;
  float temp;
  float hum;
}PacketENV;

uint8_t receiverMAC[6] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};

void onSendStatus(const uint8_t *mac, esp_now_send_status_t status) {
  Serial.printf("Send to %02X:%02X:%02X:%02X:%02X:%02X  %s\n",
    mac[0],mac[1],mac[2],mac[3],mac[4],mac[5],
    status==ESP_NOW_SEND_SUCCESS?"OK":"FAILED");
}

void setup(){
  M5.begin();
  Serial.begin(115200);
  Wire.begin();
  sensor.begin(Wire, SHT40_I2C_ADDR_44);

    sensor.softReset();
    delay(10);

  WiFi.mode(WIFI_STA);
  esp_wifi_set_channel(WIFI_CHANNEL, WIFI_SECOND_CHAN_NONE);
  if(esp_now_init() != ESP_OK){
    Serial.println("ESP-NOW init error");
    while(true);
  }

  esp_now_peer_info_t peer = {};
  memcpy(peer.peer_addr, receiverMAC, 6);
  peer.channel = WIFI_CHANNEL;
  peer.encrypt = false;
  esp_now_add_peer(&peer);

 esp_now_register_send_cb(onSendStatus);

}

void loop(){
uint16_t data;
float temp;
float hum;

error = sensor.measureLowestPrecision(temp, hum);
    if (error != NO_ERROR) {
        Serial.print("Error trying to execute measureLowestPrecision(): ");
        errorToString(error, errorMessage, sizeof errorMessage);
        Serial.println(errorMessage);
        return;
    }

PacketENV pkt;
pkt.id =1;
pkt.temp = temp;
pkt.hum = hum;

esp_now_send(receiverMAC, (uint8_t*)&pkt, sizeof(pkt));
Serial.printf("Sent[ENV] ID:%d Temp:%.2f C\n Hum:%.2f\n " , pkt.id, pkt.temp, pkt.hum);
delay(10000);

M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setCursor(0,0);
  M5.Lcd.setTextSize(2);
  M5.Lcd.setTextColor(WHITE);
  M5.Lcd.printf("TempHum keisoku");
  M5.Lcd.setCursor(250,210);
  M5.Lcd.setTextSize(2);
  M5.Lcd.setTextColor(PINK);
  M5.Lcd.printf("MJ");

  M5.Lcd.drawLine(5, 25, 310, 25, RED);
  M5.Lcd.drawLine(5, 200, 310, 200, RED);

  M5.Lcd.setCursor(0, 80);
  M5.Lcd.setTextSize(3);
  M5.Lcd.setTextColor(CYAN);
  M5.Lcd.print("Temp: ");
  M5.Lcd.print(temp);
  M5.Lcd.println(" C");

  M5.Lcd.setCursor(0,110);
  M5.Lcd.setTextSize(3);
  M5.Lcd.setTextColor(CYAN);
  M5.Lcd.print("Hum: ");
  M5.Lcd.print(hum);
  M5.Lcd.println(" %");
}

M5stack + relay + Patlite

C/C++
Calculates the received data and displays the condensation risk. Controls the relay based on the condensation risk.
#include <M5Stack.h>
#include <WiFi.h>
#include <esp_wifi.h>
#include <esp_now.h>
#include "Module_4RELAY.h"


esp_now_peer_info_t slave;

typedef struct __attribute__((packed)) {
  uint8_t id;
  float temp;
  float hum;
} PacketBase;

typedef struct __attribute__((packed)) {
  uint8_t id;
  float sftemp;
} PacketADT;

const int WIFI_CHANNEL = 1;

float latestTemp = 0.0;
float latestHum = 0.0;
float latestSftemp = 0.0;
bool envReceived = false;
bool adtReceived = false;

const float THRESHOLD1 = 85.0; //閾値1
const float THRESHOLD2 = 95.0; //閾値2

MODULE_4RELAY RELAY;

bool setRelayState(uint8_t relayMask) {
  Wire.beginTransmission(0x26);
  Wire.write(relayMask & 0x10);
  uint8_t err = Wire.endTransmission();
  if (err != 0) {
    Serial.printf("Relay I2C error: %d\n", err);
    return false;
  }
  return true;
}



float satVaporPressure(float T) { //飽和水蒸気の計算
  return 6.112 * exp(17.62 * T / (243.12 + T));
}

void onDataRecv(const uint8_t *mac, const uint8_t *buf, int len) { 
  
  if (len == sizeof(PacketBase)) { //ENVのパケット
    PacketBase envPkt;
    memcpy(&envPkt, buf, sizeof(PacketBase));
    latestTemp = envPkt.temp;
    latestHum = envPkt.hum;
    envReceived = true;
    Serial.printf("[ENV] id=%d, T=%.2f, H=%.2f\n",
                  envPkt.id, envPkt.temp, envPkt.hum);
  }
  
  else if (len == sizeof(PacketADT)) { //ADTのパケット
    PacketADT adtPkt;
    memcpy(&adtPkt, buf, sizeof(PacketADT));
    latestSftemp = adtPkt.sftemp;
    adtReceived = true;
    Serial.printf("[ADT] id=%d, sftemp=%.2f C\n",
                  adtPkt.id, adtPkt.sftemp);
  }

  
  if (envReceived && adtReceived) {
    
    float e_air = satVaporPressure(latestTemp) * latestHum / 100.0; //水蒸気圧
    
    float e_surf = satVaporPressure(latestSftemp); //表面温度の飽和水蒸気圧
    
    float condRisk = e_air / e_surf * 100.0; //結露リスク

    Serial.printf("e_air(hPa)=%.2f, e_surf(hPa)=%.2f, Risk=%.2f%%\n",
                  e_air, e_surf, condRisk);


    M5.Lcd.fillScreen(BLACK); //画面更新わかりやすいようにあえてGFXは使わない
    M5.Lcd.setTextSize(3);
    M5.Lcd.setTextColor(WHITE);
    M5.Lcd.setCursor(100, 60);
    M5.Lcd.printf("CD RISK");
    M5.Lcd.setCursor(250, 210);
    M5.Lcd.setTextSize(2);
    M5.Lcd.setTextColor(PINK);
    M5.Lcd.printf("MJ");
    M5.Lcd.drawLine(5, 25, 310, 25, RED);
    M5.Lcd.drawLine(5, 200, 310, 200, RED);

    M5.Lcd.setTextSize(5);

    RELAY.setAllRelay(false);
    if (condRisk < THRESHOLD1) {
      M5.Lcd.setTextColor(GREEN);
      RELAY.setRelay(0, true);
    } else if (condRisk < THRESHOLD2) {
      M5.Lcd.setTextColor(YELLOW);
      RELAY.setRelay(1, true);
    } else {
      M5.Lcd.setTextColor(RED);
      RELAY.setRelay(2, true);
    }
    M5.Lcd.setCursor(100, 140);
    M5.Lcd.printf("%.1f%%", condRisk);

 
    envReceived = adtReceived = false;
  }
}

void setup() {
  M5.begin(true, false, true, true);

  while(!RELAY.begin(&Wire, MODULE_4RELAY_ADDR, 21, 22, 200000L)){
    Serial.println("4RELAY INIT ERROR");
    delay(1000);
  }

  Serial.begin(115200);
  Wire.begin(21, 22);
  Serial.println("I2C Scanner Start");
  for (uint8_t addr = 1; addr < 127; ++addr) {
    Wire.beginTransmission(addr);
    if (Wire.endTransmission() == 0) {
      Serial.printf("Found I2C device at 0x%02X\n", addr);
    }
  }

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

  if (esp_now_init() != ESP_OK) {
    Serial.println("ESPNow Init Failed");
    ESP.restart();
  }
  Serial.println("ESPNow Init Success");

  memset(&slave, 0, sizeof(slave));
  memset(slave.peer_addr, 0xFF, 6);
  if (esp_now_add_peer(&slave) == ESP_OK) {
    Serial.println("Peer added");
  }
  esp_now_register_recv_cb(onDataRecv);
}

void loop() {
  delay(1000);
}

Credits

MJKITO
1 project • 0 followers

Comments