Skip to content

6. Control Programming.

Final Codes

Master code(MCU-1) soap dispenser

#include <WiFi.h>
#include <esp_now.h>  // - esp now library

#include <Wire.h>
#include <VL53L1X.h>  // - Person_Approaching sensor library

#include <DFRobotDFPlayerMini.h>
#include <HardwareSerial.h>

VL53L1X sensor;

uint8_t receiverMac[] = {0x84, 0xFC, 0xE6, 0x00, 0xCF, 0x78}; // - recievers Address

#define SDA_PIN 4
#define SCL_PIN 6
#define DF_RX_PIN 9
#define DF_TX_PIN 10
#define THRESHOLD 800
#define DEBOUNCE_COUNT 3

HardwareSerial dfSerial(1);
DFRobotDFPlayerMini dfplayer;

bool personPresent = false;
uint8_t debounceCounter = 0;

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

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

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

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

  Wire.begin();
  Wire.setClock(400000); // use 400 kHz I2C

  sensor.setTimeout(500);
  if (!sensor.init())
  {
    Serial.println("Failed to detect and initialize sensor!");
    while (1);
  }

  // information on range and timing limits.
  sensor.setDistanceMode(VL53L1X::Long);
  sensor.setMeasurementTimingBudget(50000);
  sensor.startContinuous(50);

  //dfplayer
  dfSerial.begin(9600, SERIAL_8N1, DF_RX_PIN, DF_TX_PIN);
  if (!dfplayer.begin(dfSerial)) while (1);
  dfplayer.volume(25);

}

void loop() {

  sensor.read();
  int Person_Approaching = sensor.ranging_data.range_mm;

  Serial.print("Range: ");
  Serial.print(Person_Approaching);

  if (Person_Approaching < THRESHOLD && !personPresent) {
    personPresent = true;
    dfplayer.play(1);  // Entry bird sound
    //delay(5000);

  }else if(Person_Approaching > THRESHOLD && personPresent) {
    const char *message = "Person_Exited";  // - SMS like message
    esp_err_t result = esp_now_send(receiverMac, (uint8_t *)message, strlen(message)); // - send SMS

    if (result == ESP_OK) {
      Serial.println("Message sent");
    } else {
      Serial.println("Failed to send");
    }
    dfplayer.stop();
    personPresent = false;
  }

  Serial.println();

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

Final slave codes

//-----final soap dispensor code------------
#include <WiFi.h>
#include <esp_now.h>
#include <Wire.h>
#include <VL53L1X.h>
#include <DFRobotDFPlayerMini.h>
#include <HardwareSerial.h>

// ---------- Configuration ----------
#define PUMP_PIN D2
#define SDA_PIN D4
#define SCL_PIN D5
#define DF_RX_PIN D9
#define DF_TX_PIN D10
#define THRESHOLD 80  // mm

// ---------- Globals ----------
VL53L1X sensor;
HardwareSerial dfSerial(1);
DFRobotDFPlayerMini dfplayer;

bool monitoring = false;
bool soapDispensed = false;
bool handDetected = false;
unsigned long triggerTime = 0;
int reminderStage = 0; // 0 = none, 1 = first msg, 2 = second msg, 3 = final msg

void resetFlags() {
  monitoring = false;
  soapDispensed = false;
  handDetected = false;
  triggerTime = 0;
  reminderStage = 0;
}

// ---------- ESP-NOW Callback ----------
void onDataReceive(const uint8_t *mac, const uint8_t *incomingData, int len) {
  String received = "";
  for (int i = 0; i < len; i++) {
    received += (char)incomingData[i];
  }

  Serial.print("Received: ");
  Serial.println(received);

  if (received == "Person_Exited") {
    resetFlags();
    monitoring = true;
    triggerTime = millis();
    Serial.println("Monitoring started after person exit");
  }
}

// ---------- Setup ----------
void setup() {
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);

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

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

  // VL53L1X
  Wire.begin(SDA_PIN, SCL_PIN);
  Wire.setClock(400000);
  sensor.setTimeout(500);
  if (!sensor.init()) {
    Serial.println("VL53L1X not found");
    while (1);
  }
  sensor.setDistanceMode(VL53L1X::Long);
  sensor.setMeasurementTimingBudget(50000);
  sensor.startContinuous(50);

  // DFPlayer
  dfSerial.begin(9600, SERIAL_8N1, DF_RX_PIN, DF_TX_PIN);
  if (!dfplayer.begin(dfSerial)) {
    Serial.println("DFPlayer init failed");
    while (1);
  }
  dfplayer.volume(30);  // Adjust as needed
}

// ---------- Loop ----------
void loop() {
  sensor.read();
  int distance = sensor.ranging_data.range_mm;

  if (!monitoring) return;

  unsigned long elapsed = millis() - triggerTime;

  // Hand detected
  if (distance < THRESHOLD && !soapDispensed) {
    Serial.println("Hand detected - dispensing soap");
    digitalWrite(PUMP_PIN, HIGH);
    delay(2000);
    digitalWrite(PUMP_PIN, LOW);
    dfplayer.play(4); // Thank you
    soapDispensed = true;
    monitoring = false;
    return;
  }

  // Reminders based on time
  if (elapsed > 5000 && reminderStage == 0) {
    Serial.println("Playing reminder 1: Don't forget to wash your hands");
    dfplayer.play(1); // Don't forget
    reminderStage = 1;
  } else if (elapsed > 10000 && reminderStage == 1) {
    Serial.println("Playing reminder 2: Please wash your hands");
    dfplayer.play(2); // Please wash
    reminderStage = 2;
  } else if (elapsed > 15000 && reminderStage == 2) {
    Serial.println("Playing reminder 3: Unhygienic...");
    dfplayer.play(3); // Unhygienic
    reminderStage = 3;
  }

  delay(100);
}