Christmas Tree Water Level Indicator

I built this thing real quick last night so my dad could check the water level without having to crawl underneath the tree. After a handful of requests for parts lists/code on Reddit, I decided the best way to share said information was in the form of an Instructable, so here we are! This instructable was done with the same haste and disregard for quality as the project itself, so I'm sure there will be mistakes.

I will add some more pictures to this Instructable later this week.

Some Future Plans for This Build:

-Possible addition of automatic watering system. Solenoid valve with a gravity fed system is the most likely option.

-Might upgrade to a better and larger depth sensor.

Step 1: Parts List:

(1) Depth Sensor (pictured above)

-This is the sensor I had lying around from a starter kit.

-Over on the original Reddit thread, u/marky-b sent me a link to this awesome sensor. It pricier than the one I used at $30, but it's length is much better suited for the application.

(3) LED lights (second picture above)
-Make sure they are all a different color to indicate different water levels. I used blue, yellow, and red.

(1) Mini Straight Wire Butt Connector (third picture above)

-Or whatever method of connecting the 3 LED ground pins to the resistor. Just as long as the connection is solid and provides adequate separation form the positive terminals.

(1) Arduino Nano

-Any board works fine, but the small size of the Nano is nice for this simple project.

(1) 1kOhm Resistor

(7) Jumper Wires

-Female to Female if you are using a Nano like I did

-Male to female for Arduino Uno or Mega

(1) Power Supply

-I just used the micro USB port in the Nano and plugged it into the wall with a USB adapter.

(1) Electric Tape

-For wrapping up exposed wire ends, or substituting the wire connector.

(1) Whatever Box you can find to waterproof the Arduino

-Because somebody is eventually going to spill water everywhere trying to water the tree.

Step 2: Wiring Schematic

Step 3: Code

I put instructions for calibrating your water sensor in the sketch before I decided to make an Instructable.

<p>//-----------Christmas Tree Water Level Sensor Sloppy Code and Tutorial---------//<br>/* 
 Brief Foreword: I originally copied the code for the serial output of the sensor from 
 an elegoo example sketch, and added the if/else stack to trigger the LEDS. After a couple
 of requests to post the code, I went through and cleaned up/commented throughout the sketch.
 
 tl;dr Half of this sketch is originally from Elegoo's example program. </p><p>     This code/program works with any arduino or clone you have. I used an arduinoNano 
 for mine, but you can use an Uno or Mega if thats what you have. Just make sure you 
 switch the 'LED const int' values to the appropriate pins you're using. </p><p>      I slapped this device together very quickly, and spent very little time testing the 
 water level values. I cannot guarentee that your depth sensor will yeild the same values at
 the same depths as mine. To address this, I wrote a sloppy callibration instructable below. </p><p> --------**********CALLIBRATION/SET UP INSTRUCTIONS********----------------------------
[1]- WITHOUT EDITING any of this sketch, upload sketch to your arduino and open serial monitor.
[2]- Insert depth sensor into water to a depth that you would consider the minimum amount needed
     to trigger the blue LED (full indicator). Write down this value and note it as 'full'.
[3]- Repeat step 2 to determine the value you will assign to the 'low' value. Anything above this 
     value but below the 'full' value will trigger the yellow LED. Any value below this value will 
     trigger the red LED.
[4]- Plug the values determined from steps 2 and 3 into the const int's 'full' and 'low' below. 
[5]- Upload sketch again with updated values, and you're done!
 */</p><p>const int full = 200;
const int low = 50;</p><p>int depthSensor = 0; //set depthsensor L pin to Analog 0. You can set to any analog pin you want. 
int lastValue = 0;
char printBuffer[128];</p><p>// The following is setting the LED pins to the corresponding digital pins. You can set these to any digital pin you want.
const int blueLED= 2;
const int yellowLED= 3;
const int redLED= 4;</p><p>//-------After setting your water level and pin assignments above, ideally you should't have to change any of the code below.
void setup()
{
  //Begin communication with serial port. This is used to set test your depth sensor and determine which values you want to assign to your full/low/empty values.
  Serial.begin(9600);</p><p>  //Set LED pins to OUTPUT
  pinMode(blueLED, OUTPUT);
  pinMode(yellowLED, OUTPUT);
  pinMode(redLED, OUTPUT);
  
}</p><p>void loop()
{
    // get sensor value:
    int value = analogRead(depthSensor); </p><p>    //If the change from last value to current value is greater than 10, display the current value.
    if(((lastValue>=value) && ((lastValue - value) > 10)) || ((lastValue 10))) 
    {
      //Displays depth sensor value to serial port.
      sprintf(printBuffer,"ADC%d level is %d\n",depthSensor, value);
      Serial.print(printBuffer);
      Serial.println();
      Serial.println(value);
      Serial.println();
      lastValue = value; // sets last value to current value for next loop.
    }
    if(value>=200)
     {
      digitalWrite(blueLED, HIGH);
      digitalWrite(yellowLED, LOW);
      digitalWrite(redLED, LOW);
     }
     else if((value <200)&& (value>=50))
     {
      digitalWrite(blueLED, LOW);
      digitalWrite(yellowLED, HIGH);
      digitalWrite(redLED, LOW);
     }
     else
     {
      digitalWrite(blueLED, LOW);
      digitalWrite(yellowLED, LOW);
      digitalWrite(redLED, HIGH);
     }
     delay(250);
}

Step 4: Calibrate

I cannot guarantee that your depth sensor will read the same values at the same depths as mine. To address this, I put some set up instructions in the sketch that I will also post here.

At this point you should have:

  • Your depth sensor connected to the appropriate ports on your Arduino board of choice
  • Your Arduino board connected to your computer
  • A glass of water nearby for testing.

[1]- WITHOUT EDITING any of the sketch, upload the original unedited sketch to your Arduino and open serial monitor.
[2]- Insert depth sensor into water to a depth that you would consider the minimum amount needed to trigger the blue LED (full indicator). Make note of what value this registers as in the serial monitor. For now we'll refer to this value as 'full'.

[3]- Repeat step 2 to determine the value you will assign to the 'low' value. Anything above this value, but below the 'full' value will trigger the yellow LED. Any value below this value will trigger the red LED. For now this will be referred to as 'low'.

[4]- The first 2 variable declarations you see in the sketch are:

const int full = 200;
const int low = 50;

You want to replace '200' with your 'full' value, and replace '50' with your 'low' value.

Resulting code should look like this:

const int full = 'full';
const int low = 'low';

Obviously with 'full' and 'low' being replaced by the actual integer values you got.

Other than that, you do not need to change any other values in the sketch. Unless you are using the pins in the original sketch for any additional sensors or displays, in which case I doubt you need me to walk you through the configuration.

Step 5: DONE!

Now go set that thing up so your dad/grandfather can ignore it anyway and crawl under the tree to physically check the water level because he hasn't trusted technology since Terminator 2 came out.

Share

    Recommendations

    • Big and Small Contest

      Big and Small Contest
    • Make it Glow Contest 2018

      Make it Glow Contest 2018
    • First Time Author

      First Time Author

    4 Discussions

    0
    None
    JohnnyBxo

    4 days ago

    Cool idea. I built it and I found out that the water sensor barely goes a few days before completely corroding over. Back to the drawer board!

    2 replies
    0
    None
    BoskovitchJohnnyBxo

    Reply 13 hours ago

    Actually on mine, the connections corroded! Another redditor suggested using a supersonic sensor, and I'll give that a shot. I'm finishing up finals right now but I'll post it by the end of the week.

    0
    None
    JohnnyBxoBoskovitch

    Reply 11 hours ago

    Good luck on finals. I actually did exactly as you said. I used a ultrasonic sensor, this one (https://www.sparkfun.com/products/13959) with a slightly modified version of your code. Works great! Here is my code below. I have 6 LEDs on mine. 3 green, 2 yellow and 1 red. Like a battery indicator. When the water is REALLY low, the red light is flashing. My LED values are set to 50 so not to be too bright on the tree base.

    #define trigPin 4
    #define echoPin 7
    #define Green1 3
    #define Green2 5
    #define Green3 6
    #define Yellow1 9
    #define Yellow2 10
    #define Red1 11
    int brightness = 0; // how bright the LED is
    int fadeAmount = 5; // how many points to fade the LED by

    void setup()
    {
    Serial.begin(9600);
    pinMode(trigPin, OUTPUT);
    pinMode(echoPin, INPUT);
    pinMode(Green1, OUTPUT);
    pinMode(Green2, OUTPUT);
    pinMode(Green3, OUTPUT);
    pinMode(Yellow1, OUTPUT);
    pinMode(Yellow2, OUTPUT);
    pinMode(Red1, OUTPUT);

    }

    void cosine_pulse(int pin, float time_step, int pause) {
    for(float t = 0; t < 2*PI; t += time_step) {
    float value = (cos(t - PI)*0.5+0.5)*255;
    analogWrite(pin, value);
    delay(pause);
    }
    }

    void loop()
    {
    long duration, distance;
    digitalWrite(trigPin, LOW);
    delayMicroseconds(2);
    digitalWrite(trigPin, HIGH);
    delayMicroseconds(10);
    digitalWrite(trigPin, LOW);
    duration = pulseIn(echoPin, HIGH);
    distance = (duration/2) / 29.1;

    if (distance <= 2) //Green 1
    {
    Serial.print(distance);
    Serial.println(" cm");
    analogWrite(Green1, 50);
    analogWrite(Green2, 50);
    analogWrite(Green3, 50);
    analogWrite(Yellow1, 50);
    analogWrite(Yellow2, 50);
    analogWrite(Red1, 50);
    }
    else if ((distance > 2) && (distance <= 3)) //Green 2
    {
    Serial.print(distance);
    Serial.println(" cm");
    analogWrite(Green1, 0);
    analogWrite(Green2, 50);
    analogWrite(Green3, 50);
    analogWrite(Yellow1, 50);
    analogWrite(Yellow2, 50);
    analogWrite(Red1, 50);
    }
    else if ((distance > 3) && (distance <= 4)) //Green 3
    {
    Serial.print(distance);
    Serial.println(" cm");
    analogWrite(Green1, 0);
    analogWrite(Green2, 0);
    analogWrite(Green3, 50);
    analogWrite(Yellow1, 50);
    analogWrite(Yellow2, 50);
    analogWrite(Red1, 50);
    }
    else if ((distance > 4) && (distance <= 5)) //Yellow 1
    {
    Serial.print(distance);
    Serial.println(" cm");
    analogWrite(Green1, 0);
    analogWrite(Green2, 0);
    analogWrite(Green3, 0);
    analogWrite(Yellow1, 50);
    analogWrite(Yellow2, 50);
    analogWrite(Red1, 50);
    }
    else if ((distance > 5) && (distance <= 6)) //Yellow 2
    {
    Serial.print(distance);
    Serial.println(" cm");
    analogWrite(Green1, 0);
    analogWrite(Green2, 0);
    analogWrite(Green3, 0);
    analogWrite(Yellow1, 0);
    analogWrite(Yellow2, 50);
    analogWrite(Red1, 50);
    }
    else if ((distance > 6) && (distance <= 8)) //Red 1
    {
    Serial.print(distance);
    Serial.println(" cm");
    analogWrite(Green1, 0);
    analogWrite(Green2, 0);
    analogWrite(Green3, 0);
    analogWrite(Yellow1, 0);
    analogWrite(Yellow2, 0);
    analogWrite(Red1, 255);
    }
    else if ((distance > 8) && (distance <= 20)) //Red//Red Flashing
    {
    Serial.print(distance);
    Serial.println(" cm");
    analogWrite(Green1, 0);
    analogWrite(Green2, 0);
    analogWrite(Green3, 0);
    analogWrite(Yellow1, 0);
    analogWrite(Yellow2, 0);
    analogWrite(Red1, 0);
    analogWrite(Red1, 50);
    cosine_pulse(Red1, 0.0025, 1);
    }
    delay(250);
    }