Christmas Tree Watering

The Problem

I Have a 2 year old son, Henry. Like most two year olds, he loves everythig to do with Christmas.

So, to make the most of the festive season, we got a real Christmas tree at the weekend. And he *loves* it :

Here is it in all it's glory. the problem is that it is still over two weeks from Christmas, and we'd like there to be some meat left on it.

The best way to preserve them is keep them cool, and give them *lots* of water. I mean lots... they drink water at a heckuva rate.

The holder thingy that it is mounted in hold about 2 litres of water, but that empties at an alarming rate...

Note the bits of wood jammed in there to keep it sturdy, upright and safe. The circular casting it is all sitting is about 8" across and about 4" deep.

To ensure it always has water we have a system: I top it up in the morning, and my wife tops it up in the evening. However, I dont have such a good memory. Here is what happened last time I forgot to water the tree* :

 *I have been asked to point out that this has never actually happened.

The Solution

In the name of marital harmony, I broke out my mbed, an original BoB, a clothes peg and a glue gun.

Theory

Casting my mind back to D&T at school, I seem to remember the project of choice was an alarm that hooks over the bath, so that when the bath water level reached the predetermined height, a current passed between two probes, triggering a circuit that switched on a lame buzzer to alert the happless incompetant that the bath is full. In this case we want to detect when the water is *below* a certain level, and the happless incompetant is someone who cant even remember to water the 7' tree that has just appeared in his lounge, even though it is covered in flashing lights.

Setting Up

So my plan is to get some 0.1" header strip and glue it to clothes peg with some flying wires. I can then clip the clothes peg over the side of the casting my tree is mounted in so that the 0.1" header will stop touching the water when it drops below a predetermined level. If I can sense the current, or lack of then the water stops shorting out the contacts, I can raise some kind of alarm.

So far so good. The 0.1" strip is just poiing out the front of the peg, the flying leads are securely attached by a long bead of hot glue.

Experiment 1

The first thing to do is see if I can measure a current through water with *just* the mbed. In the days of D&T there was always a transistor involved.

#include "mbed.h"

DigitalIn sensor(p20);
DigitalOut led (LED1);

int main() {

    sensor.mode(PullDown);

    while(1) {
        led = sensor;
    }
}

I connect the flying leads between Vout (3.3v) and p20. Nothing. I lick the header, there is a slight tingle, but clearly not enough to detect.

I move the live flying wire to the Vu (5v), give it a lick... yup.. that has more bite...(LED still doesnt light though). Still this is a water level detector, not a tongue detector, so lets try properly.

Bingo! It works a treat. [video to follow]

So I can now go about working out the alert.

Experiment 2

To detect that the tree needs more water, we are looking for a falling edge on my DigitalIn. Since the tree drinking process is slow, and the refills are not often i probably dont have to worry to much about debouncing and stuff. However, I do want to send multiple reminders, so I might just activate a ticker when I detect the water is low, and deactivate it when is filled.

#include "mbed.h"

DigitalIn sensor(p20);
DigitalOut led (LED1);

Ticker activated;

void alert (void) {
   led = !led;
}
 

int main() {

    sensor.mode(PullDown);

    while (1) {
    
        // while the water is deep enough, wait
        while(sensor) {
        }
    
        // we are here because the water is low
        activated.attach(&alert,0.1);

        // crude debounce
        wait (30);
    
        // while water remains low, wait
        while (!sensor) {
        }
    
        // We hare here as the water level is back up
        activated.detach();

        // crude debounce
        wait (30);
    }
}

 

Wow, that worked like a charm first time! Here is the test rig :

 

Experiment 3 Some alert system

Okay, I say "some".. I have a good idea :-)

At the moment I am highly inspired by Rolfs work on the HTTP Client. I Have a Netgear HomePlug adaptor (XE103) and there is one hooked up to my broadband router, so I *could* get onto the internet pretty easily.. there is a socket right behind the Christmas tree, and I am using a BoB with an RJ45 connector. Coincidence? I think not :-)

The first port of call is Rolfs page:

https://os.mbed.com/projects/cookbook/wiki/HTTPClient

It all looks too simple to be true.  

I import the prebuilt library from :

https://os.mbed.com/projects/cookbook/svn/EMAC/lwip/precomp

I fuse Rolfs example code with my own. I decide that whatever I'll do I will do it in the ticker, and that I should make the ticker run on a 300 second interval. I can chande this easily enough... it will depend on the final alert mechanism.

I register a hosting account at http://www.000webhost.com for this experiment.

Here is the code :

#include "mbed.h"
#include "HTTPClient.h"

DigitalIn sensor(p20);
DigitalOut led (LED1);

HTTPClient http;

Ticker activated;

// new alert function calls a PHP script
// I registered an account on www.000webhost.com
void alert (void) {    
    char result[64];
    led = !led;
    http.get("http://mbed.comxa.com/tree.php", result);    
}
 

int main() {

    sensor.mode(PullDown);

    while (1) {
    
        // while the water is deep enough, wait
        while(sensor) {
        }
    
        // we are here because the water is low
        activated.attach(&alert,10);

        // crude debounce
        wait (30);
    
        // while water remains low, wait
        while (!sensor) {
        }
    
        // We hare here as the water level is back up
        activated.detach();

        // crude debounce
        wait (30);
    }
}

 

PHP Scipt

The ticker is just going to call a PHP script at the address in the listing. So I need to write that script.

I'm no PHP wizzard, but I know PHP has a nice function called mail()

<?php

$to      = 'chris_styles@yahoo.com';
$subject = 'The tree needs water';
$message = 'Quick, before it dries out';

$headers = 'From: "The Christmas Tree" <chris_styles@yahoo.com>' . "\r\n" .
    'Reply-To: chris_styles@yahoo.com' . "\r\n" .
    'X-Mailer: PHP/' . phpversion();

mail($to, $subject, $message, $headers);

?>

The first test is to call it by typing in the the URL of the script directly into IE, and see what happens...

IE seems to load the page and complete silently (I should have put some debug in there). Behold, 60 seconds later :

 

Right, that seems to work a treat. Can I trigger one from my mbed now. Moment of truth, I have to compile and download the code. Oh, and run a teraterm so I can see the mbed fetch it's IP address.

Phut, nothing, not even an IP address. I download Rolfs example program, run it, and teraterm happily reports 192.168.0.36.

So I try a program that is simpler :

#include "mbed.h"
#include "HTTPClient.h"

DigitalOut led(LED1);
HTTPClient http;

int main(void) {

    char result[64];
    http.get("http://mbed.comxa.com/tree.php", result);
    printf("Done!\n");
    while(1) {
        led = !led;
        wait(0.5);
    }

}

This works like a charm :

After 30 seconds I get an email. Yay!

So why didn't it work with the ticker i wonder?

I'll remove the ticker and strip my code back a bit. Start simple.

#include "mbed.h"
#include "HTTPClient.h"

DigitalIn sensor(p20);
DigitalOut led (LED1);

HTTPClient http;

int main() {

    sensor.mode(PullDown);

    while (1) {
    
        // while the water is deep enough, wait
        while(sensor) {
        }
    
        led = !led;
        char result[64];
        http.get("http://mbed.comxa.com/tree.php", result);    

        // crude debounce
        wait (30);
    
        // while water remains low, wait
        while (!sensor) {
        }
    
        // crude debounce
        wait (30);
    }
}

That works great!

But what if i'm not picking up email? Surely there is some other method :)

Experiment 4

For this experiment I paid a visit to http://www.txtlocal.co.uk and registered and account. They have very nice APIs which allows you to send and receive SMS messages in all sorts of ways, the one that is of interest is via PHP script.

For more details have a look here:

http://www.txtlocal.co.uk/api/#code

For now, I intend to tweek thier script slightly, upload it to my 000webhost account, so that calls to http://mbed.comxa.com/tree.php will cause an SMS to be sent to me.

Using the txtlocal code as and example, I add my authentication details, customise my message and add my cell number : 

<?php
// Authorisation details
$uname = "";
$pword = "";

// Configuration variables
$info = "1";
$test = "0";

// Data for text message
$from = "Xmas Tree";
$selectednums = "447957363xxx"; // my cell number
$message = "I'm your tree - I need water please!";
$message = urlencode($message);

// Prepare data for POST request
$data = "uname=".$uname."&pword=".$pword."&message=".$message."&from=". $from."&selectednums=".$selectednums."&info=".$info."&test=".$test; // Send the POST request with cURL
$ch = curl_init('http://www.txtlocal.com/sendsmspost.php');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch); //This is the result from Txtlocal
curl_close($ch);
?>

As always, the first and best test is to call the script directly from IE. I do this and get :

  

 Cant argue with that!

Last job before it all gets deployed under the tree is to fuse email and SMS code so I get both. I'll test it from IE first - and yes, I'll rename stuff so no one can send me loads of emails and SMS :-)

Done.

It is all happily installed under the tree, powered, with network connection thanks to the Netgear XE103 homeplug.

All that remains to be seen now is when the first trigger happens. It is 00:55 GMT, so i'll see what my inbox and cellphone has for me tomorrow morning ;-)

'Night.

 To do..

  • Add some cool video clips
  • Figure why I got nothing when the HTTP call ran in a ticker


8 comments

08 Dec 2009

Nice one! My upgrade would be to add a windscreen washer pump and jerrycan. I guess that would need a second waterlevel sensor to alert you to fill up the reserve tank...

08 Dec 2009
Why not use InterruptIn instead of polling?
08 Dec 2009

What about a hose?

08 Dec 2009

Hi Igor,

Yeah, I could have used an interrupt in I guess, I just started simple.

There is so little for the MCU to do i guess the reality is just it spinning in a polling loop rather than spinning in a while (1).. maybe there is less power taken doing while(1) than continually reading GPIO.

InterruptIn would definitely be the way forward if I could go into a sleep mode and then wake on interrupt.

I need to go check now actually, as I've not recieved an email or an SMS, and I'd expect it to have dropped below

09 Dec 2009

Adding __WFI(); to the loop's body should work.

21 Dec 2009

Hi Chris,

Thanks for your festive mbed application. This is not an mbed question or comment but I hope you can help. I liked the email example and have attempted to mimic what you did. I got an account on http://www.000webhost.com/ and created a PHP script like yours with my email details but running the script does not seem to produce any email. I put an "echo" statement in the script so I know it has run. Any ideas on what I need to check?

Thanks,

Peter

21 Dec 2009

Hi Chris,

In response to a query about the problem with my PHP script, http://www.000webhost.com/ support said that "Mail sending and receiving works fine for all servers, however sometimes emails are blocked since it is sent to/from free hosting server with high email volumes. There is nothing we can do about it. You can upgrade account and then you will be setup on the server with small email sending volumes so this will help get rid of this problem."

I tried the same PHP script using the web space provided by my ISP and it did work so that would seem to confirm this. Just thought this may help someone.

Thanks,

Peter

24 Dec 2009

If 000webhost does not work well for you guys, I have a simple reseller server that has tons of space in it if anyone needs.

You need to log in to post a comment