AvBrand Exploring Technology
Dog Water Dish Source Code
This code is copyright © 2011 Avatar-X. If you use it, please let me know.
// These values help bring the readings from the water in evenely and throw out errant readings.
int meter1[10];
int meter2[10];
byte sampleCount = 0;
byte currSample = 0;
byte readingLow = 0; // The reading on the LOWER sensor
byte readingHigh = 0; // The reading on the HIGHER sensor
byte blinkPattern = 0; // Number of blinks.
byte blinkPoint = 0;
// The pins where items are connected
#define PIN_SENSE_LOW 5 // The LOW sense wire (bottom of dish)
#define PIN_SENSE_HIGH 9 // The HIGH sense wire (top of dish)
#define PIN_WATER 12 // Turn on the water flow
#define PIN_BUZZER 6 // Piezo buzzer for alerts
#define PIN_SENSE_POWER 8 // Turn on the power for the sensors to prevent corrosion
void setup() {
// Pin 13 has an LED connected on most Arduino boards:
pinMode(13, OUTPUT);
pinMode(PIN_SENSE_LOW, INPUT);
pinMode(PIN_SENSE_HIGH, INPUT);
pinMode(PIN_WATER, OUTPUT);
pinMode(PIN_BUZZER, OUTPUT);
pinMode(PIN_SENSE_POWER, OUTPUT);
// Make sure these things are off.
digitalWrite(PIN_WATER, LOW);
digitalWrite(PIN_SENSE_POWER, LOW);
// Startup sound
buzz(230);
buzz(270);
buzz(320);
// Open the serial connection for debugging
Serial.begin(9600);
}
void loop() {
long timerA = 0;
long timerB = 0;
// Main logic loop.
if (sampleCount < 10) // Not enough readings yet. 10 readings are needed as a baseline.
{
updateSensors();
}
else
{
// LOGIC LOOP A
blinkPattern = 60;
Serial.println("A. Waiting for No Low");
waitForNoLow();
// At this point, the LOW sensor is not activated.
// Try for another 30 seconds to see if it will come back.
blinkPattern = 10;
Serial.println("B. No Low Detected. Confirming for 30 seconds.");
timerA = millis();
do {
delay(500);
updateSensors();
if (millis() - timerA > 30000 || millis() < timerA) break;
} while (readingLow == 0 && readingHigh == 0);
// Are we still reading no low?
if (readingLow == 0)
{
// Now we wait 30 minutes to let the water evaporate.
// 10 minutes = 1800 seconds.
blinkPattern = 2;
// Alert that we have entered this state via buzzer.
buzz(230);
delay(200);
buzz(230);
Serial.println("C. No Low confirmed. Evaporating for 10 minutes.");
for (int i = 0; i < 1800; i++)
{
doBlinks();
delay(1000);
}
// Turn on the water.
blinkPattern = 3;
Serial.println("WATER: TURNING ON");
buzz(270);
buzz(230);
digitalWrite(PIN_WATER, HIGH);
// Start timer B.
timerB = millis();
// Monitor the water levels.
Serial.println("D. Monitoring water levels...");
do {
delay(20);
updateSensors();
if (millis() - timerB > 35000 || millis() < timerB)
{
Serial.println("Water should be full by now. Detection failure.");
// Enter the error state.
digitalWrite(PIN_WATER, LOW);
do {
alarm(5);
} while (true); // Infinite loop, requires user reset.
break;
}
} while (readingHigh == 0);
Serial.println("E. Fill level reached.");
Serial.println("WATER: TURNING OFF");
digitalWrite(PIN_WATER, LOW);
buzz(230);
buzz(270);
// At this point the loop begins again.
} else {
Serial.println("False positive. The low water is back.");
}
}
delay(20);
}
// This function waits for the dish to be empty.
void waitForNoLow()
{
do {
delay(10000); // Check once every 10 seconds.
updateSensors();
} while (readingLow == 1 || readingHigh == 1);
}
void doBlinks()
{
if (blinkPoint == 0)
{
digitalWrite(13, HIGH);
delay(10);
digitalWrite(13, LOW);
}
blinkPoint++;
if (blinkPoint > blinkPattern) blinkPoint = 0;
}
void buzz(long nFreq)
{
for (long i = 0; i < 1000; i++ )
{
// 1 / 2048Hz = 488uS, or 244uS high and 244uS low to create 50% duty cycle
digitalWrite(PIN_BUZZER, HIGH);
delayMicroseconds(nFreq);
digitalWrite(PIN_BUZZER, LOW);
delayMicroseconds(nFreq);
}
}
void alarm(byte nCount)
{
for (byte i = 0; i < nCount; i++)
{
buzz(230);
buzz(270);
}
}
void updateSensors()
{
// Take a sample
digitalWrite(PIN_SENSE_POWER, HIGH);
delay(1);
byte m1 = digitalRead(PIN_SENSE_LOW);
byte m2 = digitalRead(PIN_SENSE_HIGH);
// Turn this off to not cause corrosion
digitalWrite(PIN_SENSE_POWER, LOW);
meter1[currSample] = m1;
meter2[currSample] = m2;
currSample++;
if (currSample > 9) currSample = 0;
if (sampleCount < 10)
{
// First 10 samples are not counted
sampleCount++;
} else {
// All samples have to be the same to change the reading.
float t1 = 0;
float t2 = 0;
for (byte i = 0; i < 10; i++)
{
t1 = t1 + meter1[i];
t2 = t2 + meter2[i];
}
t1 = t1 / 10;
t2 = t2 / 10;
if (t1 == 0 || t1 == 1) { // All samples are the same
readingLow = t1;
}
if (t2 == 0 || t2 == 1) { // All samples are the same
readingHigh = t2;
}
}
doBlinks();
}