Laurent Ellerbach

Internet of Things, IoT, Arduino, Netduino, Galileo, Spark.IO, NETMF, .NET Microframework and other embedded gadgets :-)

June, 2012

  • Laurent Ellerbach

    A low cost humidity sensor for my sprinkler system

    • 1 Comments

    I’ve developed my own sprinkler system which embed a web server and allow me to control it remotely where ever I am. I can program when and how long I will sprinkler on which circuit. I have 3 circuits but my system can work with a large number of circuits.

    What I want to do is to be able to add intelligence into my netduino board. This .NET Microframework (NETMF) board runs without any OS. So now Windows, no Linux, no Mac, nothing! Directly .NET on the chip. Not a full .NET of course but all what is necessary to be able to pilot IO, have a web server, etc. All this in an embedded board smallest of the size of a credit card.

    Part of my project is to be able to measure the soil humidity. So I’ve decided to develop my own sensor. The basic idea is to measure the conductivity (or resistor) of the soil. Any object/material has it’s own resistance. The more conductive it is, the smallest the resistor is and the less conductive, the higher the resistor is. And it does apply to anything. Metals are usually excellent resistors with a very low resistance of less than 1 Ω. And something like a plastic will have more than 1 MΩ resistor. So if you apply a huge voltage, you’ll get a very small current.

    The rule you have to know to do some electronic is U = R x I where U is the voltage (tension in volt V), R is the resistor (in ohm Ω) and I is the intensity of the current (in ampere, A). So I will measure the resistor 'of the soil and I will determine if it is dry or humid.

    Let start wit a bit of theory there regarding soil conductivity. It is possible to measure the soil conductivity with a Tellurometer. Soil conductivity is measured by this specific sensor and the resistance of the soil is determined. In my case what will interest me is to be able to measure the difference of conductivity between a humid and a dry soil at the same place. It just need to have 2 stick of copper or any other metal put into the soil and have a current going thru one stick and measuring the difference of voltage from the other.

    When a soil is humid the resistor decrease and when it is dry, it does increase. So imagine I will build something like a voltmeter put into the soil and I will measure the resistance. As my netduino has an analogic input I will use it for this purpose. What I measure here, is a voltage so indirectly this variance or resistance. As per the light sensor, I’ll use the same principle:

    image

    So I will measure the voltage of R3. R3 is a high value of 10K to do a pull down. It is a high resistor which will create a small current between the ground and A0. If I don’t put any resistor,I won’t be able to measure any intensity. And if I place A0 on the ogher side of my sensor and remove R3, I will use more current than in this design. It is possible to do the same as for the light sensor but in my case it will be a bit less efficient I guess.

    R1 is here to reduce a bit the current and I will have to adjust this value regarding of my current soil.

    The code is extremely simple:

    SecretLabs.NETMF.Hardware.AnalogInput SoilSensor =
    new SecretLabs.NETMF.Hardware.AnalogInput(Pins.GPIO_PIN_A0); //lightSensor.SetRange(0, 100); int lSoilSensorReading = 0; while (true) { SoilSensorReading = SoilSensor.Read(); Debug.Print(SoilSensorReading.ToString()); Thread.Sleep(500); }

    I create an analogic input on port A0. And then I read the value every 500 milliseconds. And that’s it!

    I’ve done the test with real soil, one is very humid, one a bit humid and one is very dry.

    I get the following results:

    • very humid = 650
    • a bit humid = 630
    • very dry = 550

    And here is the picture of the prototype:

    WP_000792 

    As the analogic port has 1024 values going from 0 to 1023 on 3.3V, I have an amplitude of 100 values which represent a variance of approximately 0.32V.

    So with this prototype I have a difference of 0.32V between dry and very humid with this specific soil.

    I’m sure I can change a bit the sensitivity to use a broader range of the analogic input. I can do like for the light sensor an remove the R3 resistor and measure directly the tension between the sensor and the ground. I can also change R1 to a value close to the middle of the resistance of the soil. I can also change the alimentation value to 5V or so.

    That was just a first experiment! Just to prove it is working Sourire Now, I need to improve a bit the system and see how far I can go. Any feedback from an electronic guy welcome.

  • Laurent Ellerbach

    Using XMLHttpRequest to pilot a Lego train dynamically in HTML 5

    • 4 Comments

    It’s a long time I did not write a blog post. I was very busy and had no time to write and code anything in the last weeks. I still have a lot of work but I need an intellectual break for the evening. So I do not write this post from a plane but from an hotel room. In my past blog posts I’ve explained how to pilot any Lego Power System with a Netduino using .NET Microframework.

    In the HTTP Web server I’ve implemented, I command the train thru a URL with arguments. Those arguments are transformed into parameters which are given to a class. This class output a wave form into an infrared led amplified by a transistor. This is a simple and efficient way to command anything. I do the same for my sprinkler system.

    Now if you want to pilot in a web interface multiple trains, and click on buttons or pictures to get an action without opening a new web page or refreshing the page, you need to do some Scripting in your HTML page. I’m not a web developer, I don’t like Scripting languages as they are not strict enough to write correct code and imply too many errors. They drastically increase your development time! I truly prefer a good language like C#, VB or even Java and I can go up to C/C++ Sourire Now, if I want to avoid any problem, I can jump into Eiffel Sourire OK, I won’t go up to there, I’ll stay with java script in an HTML5 page.

    What I want is to call my command page in the background of the page and stay in the HTML page when I click on a button. There is a nice object in HTML which allow you to do that which is XMLHttpRequest. It is implemented in all decent browsers.

    Here is the code that I generate dynamically (I’ll show you the code later) and I’ll explain you how it works:

    <html xmlns="http://www.w3.org/1999/xhtml"><head>
    <title></title></head><body>
    <SCRIPT language="JavaScript">
    var xhr = new XMLHttpRequest();
    function btnclicked(boxMSG, cmdSend) {
        boxMSG.innerHTML = "Waiting";
        xhr.open('GET', 'singlepwm.aspx?' + cmdSend + '&sec=');
        xhr.send(null);
        xhr.onreadystatechange = function () {
            if (xhr.readyState == 4)
            { boxMSG.innerHTML = xhr.responseText; } 
    };
    }
    </SCRIPT>
    <TABLE BORDER="0"><TR><TD>
    <FORM>Super train</TD><TD>
    <INPUT type="button" 
    onClick="btnclicked(document.getElementById('train0'),
    'pw=11&op=0&ch=254')" 
    value="<"></TD><TD>
    <INPUT type="button" 
    onClick="btnclicked(document.getElementById('train0'),
    'pw=8&op=0&ch=254')" value="Stop"></TD><TD>
    <INPUT type="button" 
    onClick="btnclicked(document.getElementById('train0'),
    'pw=5&op=0&ch=254')" value=">"></TD><TD>
    <span id='train0'></span></FORM></TD></TR>
    
    

    In the script part of the page, I have created a simple script. Those lines of code is what is necessary to do a synchronous call of an HTTP page and display the result in the page.

    I create an XMLHttpRequest object which I call xhr. The function call btnclicked takes 2 arguments. the first one is the element of the page I will put the results of the request. And the second one is the command (the parameters) to pass to the URL which will pilot the infrared led as explain previously.

    The function is very simple. First, I put “Waiting” in the element. Then I open the XMLHttpRequest object. I open it with GET and pass the overall URL.

    The request is done when the send function is called. It is a synchronous call, so it get to the onreadystatechange when it is finished.

    Here, when you read the documentation, the readyState 4 mean that everything went well and you have your data back. My function return “OK” when everything is OK and “Problem” if there is a problem.

    Now let have a look at the rest of the HTML page. I decided to create a form with button input. Each button input has a onClick event. This event can be linked to a script. So I will call the fucntion describe before and give a span element (here train0) and the URL. The URL is different depending if you want to train to go forward, backward or stop. And I put all this in a nice table top be able to have multiple trains.

    The page with 4 trains looks like this:

    image

    I’ve clicked on the forward button, “Wainting” is displayed in span. And as soon as the command will finish, it will either display OK or Problem. In my case, Problem will be displayed as in the Emulator, there is no SPI port!

    // Start HTML document
    strResp = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"
    \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">"
    ; strResp += "<html xmlns=\"http://www.w3.org/1999/xhtml\">
    <head><title></title></head><body>"
    ; //creat the script part strResp += "<SCRIPT language=\"JavaScript\">"; strResp += "var xhr = new XMLHttpRequest(); function btnclicked(boxMSG, cmdSend)
    { boxMSG.innerHTML=\"Waiting\";"
    ; strResp += "xhr.open('GET', 'singlepwm.aspx?' + cmdSend + '&" + securityKey + "');"; strResp += "xhr.send(null); xhr.onreadystatechange = function()
    {if (xhr.readyState == 4) {boxMSG.innerHTML=xhr.responseText;}};}"
    ; strResp += "</SCRIPT>"; strResp = WebServer.OutPutStream(response, strResp); // Create one section for each train strResp += "<TABLE BORDER=\"0\">"; for (byte i = 0; i < myParamRail.NumberOfTrains; i++) { strResp += "<TR><TD><FORM>" + myParamRail.Trains[i].TrainName + "</TD>
    <TD><INPUT type=\"button\"
    onClick=\"btnclicked(document.getElementById('train"
    + i + "')
    ,'pw="
    + (16 - myParamRail.Trains[i].Speed); strResp += "&op="+ myParamRail.Trains[i].RedBlue + "&ch=" +
    (myParamRail.Trains[i].Channel - 1) + "')\" value=\"<\"></TD>"; strResp += "<TD><INPUT type=\"button\"
    onClick=\"btnclicked(document.getElementById('train"
    + i + "'),'pw=8"; strResp += "&op=" + myParamRail.Trains[i].RedBlue + "&ch=" +
    (myParamRail.Trains[i].Channel - 1) + "')\" value=\"Stop\"></TD>"; strResp += "<TD><INPUT type=\"button\"
    onClick=\"btnclicked(document.getElementById('train"
    + i + "'),
    'pw="
    + myParamRail.Trains[i].Speed; strResp += "&op=" + myParamRail.Trains[i].RedBlue + "&ch=" +
    (myParamRail.Trains[i].Channel - 1) + "')\" value=\">\"></TD>"; strResp += "<TD><span id='train" + i + "'></span></FORM></TD></TR>"; strResp = WebServer.OutPutStream(response, strResp); } strResp += "</TABLE><br><a href='all.aspx?" + securityKey +
    "'>Display all page</a>"; strResp += "</body></html>"; strResp = WebServer.OutPutStream(response, strResp);

    The code to generate the HMTL page is here. As you see it is manually generated. The table which contains the name of the train, the backward, stop and forward button is created totally dynamically. Each train may have a different speed and use different channels so the URL is generated dynamically.

    All this takes time to generate and to output in the Stream. So it’s much better to do it only 1 time and then call a simple and small function which will return just a bit of text.

    Last part, on the server header, you have to make sure you add “Cache-Control: no-cache” in the response header. If you don’t do it, only the first request will be send to the netduino board back. XMLHttpRequest will consider that the page will never expire. So I’ve modified the header code of my HTTP Server like this:

    string header = "HTTP/1.1 200 OK\r\nContent-Type: text/html; 
    charset=utf-8\r\nCache-Control: no-cache\r\nConnection:
    close\r\n\r\n"
    ; connection.Send(Encoding.UTF8.GetBytes(header), header.Length,
    SocketFlags.None);

    What is interesting there is that I can now pilot up to 8 Lego trains using this very simple interface and without having to refresh the page.

    And the excellent news is that it is working from my Windows Phone so it’s even cool to pilot your Lego train from your Windows Phone. I haven’t tested from an Android or iPhone but I’m quite sure it will work the same way. Remember that all the code is sitting in a very small hardware with no OS, just .NET Microframework! As always, do not hesitate to send me your comments Sourire

Page 1 of 1 (2 items)