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;
}
}