Showing posts with label Gumstix. Show all posts
Showing posts with label Gumstix. Show all posts

Wednesday, October 23, 2013

Resurecting the Arduino/Xbee/Gumstix sensor network

About four years ago, I built a simple sensor network that used a couple of Arduinos, a Gumstix Linux mini computer and Xbee wireless that acted as an indoor-outdoor temperature display. A couple of years back, the outdoor part of the system stopped working. I poked it and prodded it and finally just decided the Arduino clone I was using had died.

Finally, after it had sat on my shelf for a couple of years, I figured I should start to look at salvaging some of the parts for something new. Just as a last chance, I once again unplugged the processor and juggled the wires and suddenly, it works like a charm!! As with most thing, the threat of imminent destruction got it moving!

Anyway, in honour of it's miraculous recovery, I have fixed up my blog posts and reinserted the graphics Google lost for me. The posts can be found at:

  1. Overview of the sensor network
  2. Indoor Outdoor temp display
  3. Xbee -Gumstix hardware
  4. Gumstix-Arduino software

This project is pretty old now and obviously could be done much more easily with newer models of Arduino like the Yun, but it does show some good basics on getting Zigbee and PHP and Arduino all working together. Apparently, too, it is capable of great longevity!

Wednesday, January 28, 2009

Gumstix Arduino Software

I would ask the programmers out there to bear with me! I am a pretty poor coder - probably the result of having two history degrees or being frequently dropped on my head as a child. I tend to not comment my code and I usually work from a single thing that works and just barnacle on elaborations rather than neatly putting things into functions and properly planning my work. I like working in PHP because it has all the ease of C without some of the traps (like handling strings or declaring variables).

So, for my sensor network, the Gumstix Linux box is running PHP 5.0 and the Cherokee web server. This seems to be very robust and I haven't had to reboot it in ages. The main webpage comes up on my internal network like this:


This displays the main info off of the remote sensors and also takes an RSS feed off of www.weatherunderground.com for the current weather in Hamilton, Ontario. This allows me to cross-check the temp readings with the actual weather reported for the area. Note that this still includes a "moisture" reading, but the sensor is now been taken off the system. This was my attempt to detect if it was raining or not based on this circuit from Rob Faludi.

The LED2 On button allows me to control the secondary LED on the remote unit. This is essentially just a way to test remote controlling a digital output over the web and the Zigbee link. When you click the button, it launches a small script that sends out an "h", which turns the light ON. The button will then toggle to the "off" mode and when you press it again it sends an "l" (lower case L) to turn off the LED.

Below is the source code in all it's messy glory. It uses the indispensable "php_serial.class.php" class from Remy Sanchez (found here ) which is absolutely essential to do anything between PHP and your serial port. The script then grabs the Weather Underground RSS feed and generates the HTML to load the web page.

Arduino.php:

<?php
include "php_serial.class.php";

// configure the serial port using php_serial.class.php
 $serial = new phpSerial;
 $serial->deviceSet("/dev/ttyS2");
 $serial->confBaudRate(9600);
 $serial->confParity("none");
 $serial->confCharacterLength(8);
 $serial->confStopBits(1);
 $serial->confFlowControl("none");
 $serial->deviceOpen();

 $serial->sendMessage("g");
 usleep(100000);
 $serial->flush;
 $read = $serial->readPort();
 $ard_array = explode(',',$read,7);

 if (empty($ard_array[6])){
  usleep(100000);
  $serial->sendMessage("g");
  usleep(100000);
  $read = $serial->readPort();
  $ard_array = explode(',',$read,7); 
 }

 if ($ard_array[0] == 1) {
  $plusMinus = "-";
 } elseif ($ard_array[0] == 0){
  $plusMinus = "+";
 }

$weather = 
simplexml_load_file('http://www.weatherunderground.com/auto/rss_full/global/stations/71297.xml?units=both');

echo "<!DOCTYPE html PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN'>";
echo "<html>";
echo "<head>";
echo "<meta content='text/html; charset=ISO-8859-1'
 http-equiv='content-type'>";
echo "<meta http-equiv='refresh' content='6'>";
echo "<img style='float: left; width: 81px; height: 90px;' 
src='images/arduino-nano.jpg'>";
echo " <title>Arduino Control</title>";
echo "</head>";
echo "<body>";
echo "<br>";
echo "<h1><span style='font-family: Arial;'>Arduino Control Panel</h1>";
echo "<br></br>";
echo "<table style='text-align: left; width: 50%;' border='1'
 cellpadding='2' cellspacing='2'>";
echo "<tbody>";
echo "<tr>";
echo "<th>Deg C</th>";
echo "<th>Light Level</th>";
echo "<th>LED 1 ON/OFF</th>";
echo "<th>Moisture</th>";
echo "<th>LED 2 ON/OFF</th></tr>";
echo "<tr>";
echo "<td>$plusMinus$ard_array[1]</td>";
echo "<td>$ard_array[2]</td>";
echo "<td>$ard_array[3]</td>";
echo "<td>$ard_array[4]</td>";
echo "<td>$ard_array[5]</td>";
echo "</tr>";
echo "</tbody>";
echo "</table>";
echo "<br>";
echo "<h2><span style='font-family: Arial;'>Current Weather in Hamilton</h2>";
foreach ($weather->channel->item as $item) {
                $w = $item->description . "";
                $newchar = str_replace("|", "", $w);
                $newestchar = str_replace("Temperature","Current temp", $newchar);
                $newest2char = str_replace("°F","F",$newestchar);
                $newest3char = str_replace("°C","C",$newest2char);
                $newest4char = str_replace("percent","%",$newest3char);
                $newest5char = str_replace(" / "," ",$newest4char);
                $newest6char = str_replace("  "," ",$newest5char);
                $newest7char = str_replace("Direction:","Dir:",$newest6char);
                $newerchar = trim($newest7char);
                $wchar = substr($newerchar,0,80);

$wchar = substr($newerchar,0,300);

echo "<table style='text-align: left; width: 50%;' border='1'
 cellpadding='2' cellspacing='2'>";
echo "<tbody>";
echo "<tr>";
echo "<td>$wchar</td>";
echo "</tr>";
echo "</tbody>";
echo "</table>";
                }

echo "<br>";
echo "<a href='arduino_data2.php'>View Log</a><br>";
echo "<br>";
echo "<table>";
echo "<tbody>";
echo "<tr>";
echo "<td>";
if ($ard_array[5] == 1) {

echo "<form action='led_off.php' method='get'>"; 
echo "<input type='hidden' name='variablename' value='variablevalue'>"; 
echo "<input type='submit' value='TURN LED2 OFF'/>";
echo "</form>";
}
if ($ard_array[5] == 0){
echo "</td>";
echo "<td>";
echo "<form action='led_on.php' method='get'>";
echo "<input type='hidden' name='variablename' value='variablevalue'>";
echo "<input type='submit' value='TURN LED2 ON'/>";
echo "</form>";
}
echo "</td>";
echo "</tbody>";
echo "</table>";
echo "<br>";
echo "<hr style='width: 100%; height: 2px;'>";
echo "<br>";
echo "<img style='float: left; width: 81px; height: 90px;' 
src='images/gumlogo.gif'>";
echo "<h1><span style='font-family: Arial;'>Gumstix Controls</h1>";
echo "<br>";
echo "<table>";
echo "<tbody>";
echo "<td>";
echo "<form action='turn_off.php' method='get'>";
echo "<input type='hidden' name='variablename' value='variablevalue'>";
echo "<input type='submit' value='TURN OFF GUMSTIX'/>";
echo "</td><td>";
echo "</form>";
echo "<form action='reboot_gum.php' method='get'>";
echo "<input type='hidden' name='variablename' value='variablevalue'>";
echo "<input type='submit' value='REBOOT GUMSTIX'/>";
echo "</form>";
echo "</td>";
echo "</tbody>";
echo "</table>";
echo "<hr style='width: 100%; height: 2px;'>";
echo "<img src='images/powered_by_cherokee.png'>";
echo "</body>";
echo "</html>";

$serial->deviceClose();

?>


The other function of the Gumstix is also to act as a data logger. Clicking the link for the log takes you to this page:


This is a very small SQLite database that keeps track of the readings of the remote units sensors. The code below uses a PDO statement to open the database and generate the HTML to display its contents. Eventually, I will need to put some further refinements on it so you can select results from different days and maybe graph the temerature.

Arduino_data2.php:

<?php

$db = new PDO('sqlite:/media/card/back_up/home/root/arduino.db');
$st = $db->query('SELECT * FROM tbl');
$results = $st->fetchAll();
echo "<!DOCTYPE html PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN'>";
echo "<html>";
echo "<head>";
echo "<meta content='text/html; charset=ISO-8859-1'
 http-equiv='content-type'>";
echo "<meta http-equiv='refresh' content='10' >";
echo " <title>Data Log</title>";
echo "</head>";
echo "<body>";
echo "<h1>Arduino Data Log</h1>";
echo "<br></br>";
echo "<form action='clear_log.php')'>";
echo "<input type='submit' value='Clear Log'/>";
echo "</form>";
echo "<table style='text-align: left; width: 50%;' border='1'
 cellpadding='2' cellspacing='2'>";
echo "<tbody>";
echo "<tr>";
echo "<th>Index</th>";
echo "<th>Date-Time</th>";
echo "<th>Light Level</th>";
echo "<th>LED1</th>";
echo "<th>Moisture</th>";
echo "<th>LED2</th>";
echo "<th>+/-</th>";
echo "<th>Temp</th>";
echo "</tr>";

$rows = count($results);
 
 for ($i=0; $i <= $rows; $i++){
  echo "<tr>";
  for ($x=0; $x <= 7; $x++){
   echo "<td>{$results[$i][$x]}</td>";
  }
  echo "</tr>";
 }
echo "</tbody>";
echo "</table>";
echo "<br>";
echo "<a href='arduino.php'>Return to Control Panel</a><br>";
echo "</body>";
echo "<html>";
$db = null;

?>


How does the data actually get into the database? This is pretty straightforward. Read the serial port with the aforementioned PHP serial class and put the results into an array, then use the SQL INSERT command to put it into the database:

data_logging.php:

<?php
include "php_serial.class.php";

// configure the serial port using php_serial.class.php
   $serial = new phpSerial;
   $serial->deviceSet("/dev/ttyS2");
   $serial->confBaudRate(9600);
   $serial->confParity("none");
   $serial->confCharacterLength(8);
   $serial->confStopBits(1);
   $serial->confFlowControl("none");
   $serial->deviceOpen();

   $serial->sendMessage("g");
   usleep(100000);
   $serial->flush;
   $read = $serial->readPort();
   $ard_array = explode(',',$read,7);
   $serial->deviceClose();
   if ($ard_array[0] == 0){
       $ard_array[0] = "'+'";
       }
   elseif ($ard_array[0] == 1){
       $ard_array[0] = "'-'";
       }
//print_r($ard_array);

putenv("TZ=UTC+5");


$db = new PDO('sqlite:/media/card/back_up/home/root/arduino.db');
$db->exec("INSERT INTO tbl (lightLev,LED1,SW1,LED2,plus_minus,temp)
VALUES
($ard_array[2],$ard_array[3],$ard_array[4],$ard_array[5],$ard_array[0],$ard_array[1])");

Print("Insert successful\n");

?>


This is driven by a crontab item on the Gumstix that runs every 15 minutes. For those out there who might be struggling to figure out crontab on Linux, the way I did this was via the command "crontab -e" and I included the line:

*/15 * * * * /usr/bin/php /var/www/data_logging.php > /dev/null

Well, that should be enough for now on my sensor network project. Soon, I will have to start actually building some of the elements of the solar pool heater concept that started all this. I now have some solenoid valves and a small pump, so I need to do a proptype of an Arduino managing flud control. Maybe I might do something again with RFID first!

Gumstix-Xbee Modem Hardware

Hola Amigos!

Now to continue with documenting the Remote Sensor rig, this section will describe the physical hardware that is used to interface the Gumstix server via Xbee to the Remote Sensor box and the Indoor-Outdoor Temperature display described earlier. I will discuss the PHP scripts running on the Gumstix in a later post.

The astute observer will note that this circuit is actually rather silly. Why is there an RS232-TTL converter and a USB-TTL converter? The answer is that the Gumstix does not at this point support the FTDI USB-Serial chip, but I needed something to power the circuit so I could avoid having an extra wall-wart in the picture. So, a very good DLP USB converter (Digi-key part 813-1018-ND) is essentially being totally wasted. I did try just pulling the power directly off a USB connector, but it didn't seem to be sufficient to run the Xbee, so the DLP Converter is obviously doing some sort of power conditioning along the way.


This shows the layout of the board. Very neat! This actually uses the Sparkfun Xbee breakout board (Sparkfun part number BOB-08276) which just provides a simple breakout for the Xbee pins rather than the complete power package on the Lady Ada carrier board I used on the Indoor-Outdoor Temperature Display. There is no design reason for this. I just happened to build this unit before I had discovered the Lady Ada breakout board. This is why I needed to put in a separate 3.3 VDC voltage regulator and the two power conditioning capacitors.

There is a 10 uF capacitor on the 5 VDC input of the regulator and a 1 uF on the 3.3 VDC output. I ain't no expert on this stuff, but what I understand is if they ain't there it ain't workin'.



Again, this circuit is built using wire wrap, which provides a quick way to make a reasonably permanent circuit. I should be good and color code the power, ground and data wires and arrange them all more neatly, but I'm sure that will come with practise.

And here is the completed unit in the inevitable plastic food container. The Gumstix case is my own design (described here). The RS232 comes off of the Gumstix LCD-Serial board and through a gender changer to the RS232-TTL converter. The USB connects to the USB on the converter. The Arduino units communicated with the Xbee on this and the Gumstix then communicates over Wi-Fi to my home network.



Next post, I will describe the software that runs everything!