Cirkit Designer LogoCirkit DesignerYour all-in-one circuit design IDE Launch Cirkit Designer App

Arduino UNO-Based Water Detection and Motor Control System with SD Logging

View and Edit Project In Cirkit DesignerImage of Arduino UNO-Based Water Detection and Motor Control System with SD Logging

Circuit Documentation

Summary

This circuit is designed to monitor water levels using multiple water sensors and to take action based on the sensor readings. It includes an Arduino UNO microcontroller for processing sensor data and controlling other components. The circuit features a power management system using a TP4056 charger module, a DC-DC boost converter, and an 18650 Li-Ion battery. It also includes a motor driver (L298N) to control two DC motors, piezo speakers for audible alerts, and an SD module for data logging. The system is designed to be responsive to water detection and to manage power effectively.

Component List

Microcontroller

Power Sources

Sensors

Actuators

Motor Driver

Storage

Protection and Filtering

Wiring Details

Arduino UNO

18650 Li-Ion Battery

TP4056

DC-DC Boost Converter

Water Sensors

DC Motors

Piezo Speakers

L298N DC Motor Driver

SD Module

Diodes

Ceramic Capacitor

Documented Code

#include <SD.h>

const int waterSensorPins[3] = {A0, A1, A2};
const int piezoPins[3] = {8, 4, 13};
const int motor1Pin1 = 9;
const int motor1Pin2 = 10;
const int motor2Pin1 = 11;
const int motor2Pin2 = 12;
const int waterSensorPowerPins[3] = {7, 6, 5};
const int voltageCapPin = A3;
const int sdChipSelect = 5;
const int waterThreshold = 500;
const int debounceDelay = 200;
const int hysteresis = 20;

unsigned long lastDebounceTime[3] = {0, 0, 0};
int lastSensorState[3] = {LOW, LOW, LOW};
unsigned long lastActivityTime = 0;
const unsigned long idleTimeLimit = 8000; // 8 seconds to simulate watchdog timer

void setup() {
  for (int i = 0; i < 3; i++) {
    pinMode(waterSensorPins[i], INPUT);
    pinMode(waterSensorPowerPins[i], OUTPUT);
    digitalWrite(waterSensorPowerPins[i], HIGH);
    pinMode(piezoPins[i], OUTPUT);
  }
  pinMode(motor1Pin1, OUTPUT);
  pinMode(motor1Pin2, OUTPUT);
  pinMode(motor2Pin1, OUTPUT);
  pinMode(motor2Pin2, OUTPUT);
  pinMode(voltageCapPin, INPUT);
  Serial.begin(9600);

  digitalWrite(sdChipSelect, LOW);
  if (!SD.begin(sdChipSelect)) {
    Serial.println("Error initializing SD card!");
    logError("SD card initialization failed");
  }
  digitalWrite(sdChipSelect, HIGH);
}

void loop() {
  unsigned long currentMillis = millis();
  
  if (currentMillis - lastActivityTime >= idleTimeLimit) {
    resetSystem(); // Simulate watchdog reset if idle for too long
    lastActivityTime = currentMillis;
  }

  lastActivityTime = currentMillis;
  int waterDetectedCount = 0;

  for (int i = 0; i < 3; i++) {
    int reading = digitalRead(waterSensorPins[i]);
    
    if (reading != lastSensorState[i]) {
      lastDebounceTime[i] = currentMillis;
    }
    
    if ((currentMillis - lastDebounceTime[i]) > debounceDelay) {
      if (reading == HIGH) {
        int waterValue = analogRead(waterSensorPins[i]);
        if (waterValue > waterThreshold) {
          waterDetectedCount++;
        }
      }
    }
    lastSensorState[i] = reading;
  }

  int toneFrequency = 0;
  switch (waterDetectedCount) {
    case 1:
      toneFrequency = 1000;
      break;
    case 2:
      toneFrequency = 1500;
      break;
    case 3:
      toneFrequency = 2000;
      break;
    default:
      toneFrequency = 0;
      break;
  }

  for (int i = 0; i < 3; i++) {
    if (toneFrequency > 0) {
      tone(piezoPins[i], toneFrequency);
    } else {
      noTone(piezoPins[i]);
    }
  }

  int voltageCapValue = analogRead(voltageCapPin);
  if (voltageCapValue > 512 + hysteresis) {
    digitalWrite(motor1Pin1, HIGH);
    digitalWrite(motor1Pin2, LOW);
    digitalWrite(motor2Pin1, HIGH);
    digitalWrite(motor2Pin2, LOW);
  } else if (voltageCapValue < 512 - hysteresis) {
    digitalWrite(motor1Pin1, LOW);
    digitalWrite(motor1Pin2, LOW);
    digitalWrite(motor2Pin1, LOW);
    digitalWrite(motor2Pin2, LOW);
  }

  delay(1000); // To simulate low-power mode by slowing down the loop
}

void logError(const char* errorMsg) {
  Serial.print("Persistent Error: ");
  Serial.println(errorMsg);

  digitalWrite(sdChipSelect, LOW);
  File logFile = SD.open("error_log.txt", FILE_WRITE);
  if (logFile) {
    logFile.print("Error: ");
    logFile.println(errorMsg);
    logFile.close();
    Serial.println("Error logged to SD card.");
  } else {
    Serial.println("Failed to write to SD card.");
  }
  digitalWrite(sdChipSelect, HIGH);
}

void takeCorrectiveAction(const char* errorType) {
  Serial.print("Taking corrective action for ");
  Serial.println(errorType);
  if (strcmp(errorType, "voltage") == 0) {
    digitalWrite(motor1Pin1, LOW);
    digitalWrite(motor1Pin2, LOW);
    digitalWrite(motor2Pin1, LOW);
    digitalWrite(motor2Pin2, LOW);
  } else if (strcmp(errorType, "sensor") == 0) {
    for (int i = 0; i < 3;