Skip to content

6. Control Programming.

Testing VLK53L1X distance sensor with Mini water pump

This code was to dispense the soap solution.

codes i developed.

#include <Wire.h>
#include <VL53L1X.h>

VL53L1X sensor;

#define RELAY_PIN D3            // Relay control pin (connect to IN on relay module)
#define TRIGGER_DISTANCE_MM 10    // Hand detection distance (adjustable)
#define DISPENSE_TIME_MS 1000      // Pump ON duration (1 second)

bool handDetected = false;         // Tracks if a hand was already detected

void setup() {
  Serial.begin(115200);
  while (!Serial) {}

  Serial.println("Starting Automatic Soap Dispenser...");

  // Initialize I2C
  Wire.begin();
  Wire.setClock(400000); // Fast I2C

  // Setup relay pin
  pinMode(RELAY_PIN, OUTPUT);
  digitalWrite(RELAY_PIN, LOW); // Ensure relay is OFF initially

  // Initialize VL53L1X sensor
  sensor.setTimeout(500);
  if (!sensor.init()) {
    Serial.println("Sensor not found or failed to initialize!");
    while (1); // Halt
  }

  sensor.setDistanceMode(VL53L1X::Long);           // Use long-range mode
  sensor.setMeasurementTimingBudget(50000);        // 50ms measurement time
  sensor.startContinuous(50);                      // Continuous measurements
}

void loop() {
  sensor.read(); // Read new measurement

  uint16_t distance = sensor.ranging_data.range_mm;
  uint8_t status = sensor.ranging_data.range_status;

  Serial.print("Distance: ");
  Serial.print(distance);
  Serial.print(" mm | Status: ");
  Serial.println(VL53L1X::rangeStatusToString((VL53L1X::RangeStatus)status)); // FIXED casting

  if (status == VL53L1X::RangeValid) {
    if (distance < TRIGGER_DISTANCE_MM) {
      if (!handDetected) {
        Serial.println("Hand detected → Dispensing soap...");
        digitalWrite(RELAY_PIN, HIGH);      // Turn ON pump
        delay(DISPENSE_TIME_MS);            // Run pump
        digitalWrite(RELAY_PIN, LOW);       // Turn OFF pump
        handDetected = true;                // Mark hand detected
      }
    } else {
      handDetected = false;                 // Hand moved away, reset
    }
  }

  delay(10); // Small delay
}

code to test VL53L1X sensor with DF player mini and speaker.

Connections details:

- VCC of VL53L1X distance sensor to 3.3V of XIAO ESP32C3
- GND of VL53L1X to GND of XIAO ESP32C3
- SDA of VL53L1X to SDA(D4) of XIAO ESP32C3
- SCL od VL53L1X to TX(D6) of XIAO ESP32C3
- VCC of DF Player mini to 5V of XIAO ESP32C3
- GND of DF Player mini GND of XIAO ESP32C3
- RX of DF Player Mini via 1kohm resistor to MOSI(D10) of XIAO ESP32C3
- TX of DF Player mini to MISO(D9) of XIAO ESP32C3
#include <Wire.h>
#include <VL53L1X.h>
#include <DFRobotDFPlayerMini.h>
#include <HardwareSerial.h>

// I2C pins for VL53L1X
#define SDA_PIN D4
#define SCL_PIN D5

// Hardware Serial for DFPlayer Mini (UART1)
#define DF_RX_PIN D9   // ESP32 RX (connect to DFPlayer TX)
#define DF_TX_PIN D10  // ESP32 TX (connect to DFPlayer RX)

// Distance threshold (in mm)
#define PERSON_DETECTED_THRESHOLD 800
#define DEBOUNCE_COUNT 3  // Require consecutive readings to trigger

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

bool personPresent = false;
uint8_t debounceCounter = 0;
bool isPlaying = false;

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

  // Initialize I2C
  Wire.begin(SDA_PIN, SCL_PIN);

  // Initialize VL53L1X
  if (!sensor.init()) {
    Serial.println("Failed to initialize VL53L1X!");
    while (1);
  }
  sensor.setTimeout(500);
  sensor.setDistanceMode(VL53L1X::Long);
  sensor.setMeasurementTimingBudget(50000);
  sensor.startContinuous(50);

  // Initialize DFPlayer
  dfSerial.begin(9600, SERIAL_8N1, DF_RX_PIN, DF_TX_PIN);
  delay(300);  // Wait for DFPlayer initialization

  if (!dfplayer.begin(dfSerial)) {
    Serial.println("DFPlayer not responding!");
    while (1);
  }
  dfplayer.volume(30);
  dfplayer.stop();  // Ensure player is stopped initially

  Serial.println("System ready");
}

void loop() {
  static uint32_t lastCheck = 0;
  if (millis() - lastCheck >= 50) {  // Non-blocking delay
    lastCheck = millis();

    int distance = sensor.read();
    Serial.print("Distance: ");
    Serial.print(distance);
    Serial.println(" mm");

    if (sensor.timeoutOccurred()) {
      Serial.println("Sensor timeout!");
      return;
    }

    // Debounce detection
    if (distance < PERSON_DETECTED_THRESHOLD) {
      if (debounceCounter < DEBOUNCE_COUNT) debounceCounter++;
    } else {
      if (debounceCounter > 0) debounceCounter--;
    }

    // State changes
    if (!personPresent && (debounceCounter >= DEBOUNCE_COUNT)) {
      personPresent = true;
      playSound(1);  // Entry sound
    }
    else if (personPresent && (debounceCounter == 0)) {
      personPresent = false;
      playSound(2);  // Exit sound
    }
  }
}

void playSound(uint8_t track) {
  if (!isPlaying) {
    dfplayer.play(track);
    isPlaying = true;
    Serial.print("Playing track ");
    Serial.println(track);

    // Reset playing status after track duration (approximate)
    uint32_t duration = (track == 1) ? 3000 : 3000; // Set actual durations
    delay(duration); // Blocking delay for demo purposes - adjust as needed
    isPlaying = false;
  }
}