| Subcribe via RSS

Phidgets Light Sensor and JavaScript

October 26th, 2009 Posted in AIR, Ajax, Electronics, HTML, JavaScript, Phidgets, jQuery

One more Phidgets example, which should be old school by now, and I’ll move onto other hardware. Hardware that’s a little more demanding in knowledge, but exponentially more powerful for it. In fact, this little experiment with a Phidget Light Sensor provides the perfect jumping off point. In this example we’ll monitor the ambient light in the environment, and chart the incoming data, including high and low values using a jQuery charting plug-in call Flot.

Phidget Light Sensor

Before we get too far along the road however, let’s review the four basic components necessary to connect our web applications to external hardware. They are:

1. Hardware
2. Serial to Socket Server
3. Socket Library
4. Your Code and Innovation

Hardware

The hardware we will be using this time is the aforementioned Phidget Light Sensor. While it may sound intimidating to figure out how to measure light, it is actually easier than any of the previous projects. It’s does however take a turn for the more low-level understanding of electronics. If you’re not interested in a little electronics basics, feel free to jump forward to the next section.

Fundamentally, light is composed of particles called photons that behave like waves of energy. Photons are produced when electrons that have been excited to higher than normal levels, fall back to their normal state. To that end, energy entering a semiconductor crystal excites the electrons in that material to higher levels, leaving holes. These electrons and holes can recombine to emit photons, or they can move away from one another to form a current.

There are many different semiconducting materials, but the most well known is silicon, which is made mostly of sand. In the case of detecting light, specifically light in the spectrum visible to the human eye, we’ll use a semiconductor made from cadmium sulfide.

By itself, the cadmium sulfide semiconductor resists the flow of electricity – referred to as resistance. When light energy is introduced however, the resistance lessens as the electrons attempt to move away from one another forming a current. The more light, the more current. The more current the less resistance, and the more electricity will flow through the circuit. If we measure the current coming through the circuit, we then know how much light is striking the semiconductor.

Putting it all together, you have a resistor that is light sensitive. The Latin for light is “photo”. In the end, when we say Phidgets Light Sensor, what we’re really referring to is a photo resistor. While it sounds fancy and expensive, a photo resistor (also called a photocell) can be picked up at your local electronics store (i.e. Radio Shack) for about $1.50 USD. The Phidgets Light Sensor is a photocell that’s been wrapped in a few extra components to make it more plug-and-play.

8/8/8

Figuring that you might want to plug and play more than one sensor, and that those sensors might trigger logic that drives motors (like the servo motor from the previous post), Phidgets offers what is called an 8/8/8 board. That is a pre-configured board with eight digital connections, eight analog inputs, and eight analog outputs. The photocell component will plug into the expansion board, and the expansion board into your computer via USB.

Serial to Socket Server

There is no difference in the Phidgets driver software that you will need to use.

Socket Library

There is no difference in the Phidgets library that you used from the previous examples. The one library handles everything that Phidgets offers.

Your Code

As with the earlier examples, since Phidgets has wrapped all the connectivity into a library for you, all you need to do is instantiate the correct classes. You won’t find a light sensor or photocell class, but you will find a class for the Phidget Interface Kit. You can instantiate it, add event listeners to get at your data, and connect using the following code snippet.

// Setup connection to hardware
var phidget = new runtime.com.phidgets.PhidgetInterfaceKit();
 
// When the hardware has been attached we can collect data 
phidget.addEventListener( runtime.com.phidgets.events.PhidgetEvent.ATTACH, function( evt ) {
  setInterval( function() {
    // Poll sensor data
  } );
} );
 
phidget.open( "localhost", 5001 );

Notice that in the above snippet that I am using the PhidgetEvent.ATTACH event, and incrementally polling for the value from the photocell. You can also listen for data to arrive, but I found that the data may not come over in equally spaced intervals. The result would be a chart that would plot some values, pause for a random amount of time, and then suddenly jump forward to plot some more data.

The alternative here allows us to use setInterval() to occasionally ask the sensor for it’s value. How long you wait is up to you, but to make the chart seem interesting, and to create the sense of motion for incoming data, I’ve chosen to wait fifty (50) milliseconds between polling. Keep in mind that this isn’t a web server dealing with HTTP, but a dedicated socket for one device. The result is that you don’t have to worry about scalability for that poll rate.

// Get the sensor value
// Map range to height of display
var value = phidget.getSensorValue( 0 );

Since the Phidget Interface Kit may have up to eight (8) digital sensors connected to it, you will notice that in the above snippet, we tell the interface board to get the value for the sensor plugged into “0”. In this case, zero represents the first port on the board, which is where I have the light sensor connected. If you have yours connected to a different port, then you will need to change that value. If you find that you’re not getting data from the sensor, you may have counted from zero starting on the wrong side. For reference, here are the port numbers.

8/8/8 Labeled

And Innovation

That’s really all that there is to it. Just putting a number on the screen however isn’t particularly exciting. It needs some flair! Using a feature from CSS3 to make a little custom chrome, and the a jQuery charting plug-in called Flot, we’re able to spice things up considerably. It might also be nice to see the high/low range for the chart (or for all records), so we’ll include a snazzy looking graphic for that as well.

For more information on how to use CSS3 border slicing, check out my post on the topic.

Flot, like most UI components written in JavaScript, takes a variety of configuration options. One of the configuration options is “yaxis” which allows you to set a minimum and maximum value for the axis. In the case of a Phidgets Light Sensor, the minimum value is zero (0) and the maximum value is 1,000. After setting the color for the line, I put some initial seed data into the chart.

// Track high/low values over a range
var high = -1;
var low = -1;		
 
// Chart variables		
var data = [];
var options = {
  lines: {
    show: true
  },
  points: {
    show: false
  },
  yaxis: {
    min: 0,
    max: 1000
  },
  grid: {
    borderWidth: 1
  }
};
 
var series = {
  color: 'rgb( 36, 64, 107 )',
  data: data
};	
 
// Seed the chart data
for( var d = 0; d < 100; d++ )
{
  data.push( [d, 0] );		
}
 
// Draw the chart
$.plot( $( '#chart' ), [series], options );

The reason for putting the initial values into the chart is to seed it with data. At this point all the data is zero, but the chart itself thinks it is displaying 100 values, and draws itself accordingly. Then to create a sense of motion we can pop the first value off the data, and place the new incoming data onto the end. A little refresh on the chart drawing itself and it seems like the data is scrolling across the screen as it comes in – a very nice effect.

By comparison, if you just left the chart blank, without data, it would jitter around as it tried to redraw the new incoming sensor values, and would be really unpleasant to watch.

Data points in Flot are expressed as multi-dimensional arrays. The first array represents the place of the data in the chart. I use a simple numeric 0 – 99 range, though you might chose to use time of day, etc. The second array represents the actual point value. Once we have chopped the first value off the array, we iterate through shift the values down one place, and update their position number. Note that Array.shift() doesn’t work here since we’re dealing with a multidimensional array. Then at the end, we update the last position and value with the latest sensor data.

var step = 1000 / 339;
 
// Move the data over (shift)
// Shift not used
// The values themselves need to change along the way
for( var d = 0; d < 99; d++ )
{
  data[d] = [d, data[d+1][1]];
}
 
// Put the latest value on the end
// Set as data for the series
data[99] = [99, value];
series.data = data;
 
// Clear range high/low values
high = -1;
low = -1;
 
// Find high/low values for the series
for( d = 0; d < 100; d++ )
{
  if( high == -1 || data[d][1] > high )
  {
    high = data[d][1];
  }
 
  if( low == -1 || data[d][1] < low )
  {
    low = data[d][1];
  }
}

I have chosen to represent the high and low values on a single bar, and representing the range in the chart. There’s certainly no reason that you couldn’t alternatively keep all-time high and low values. In terms of positioning the markers over the high/low bar, I simply need to know the height of the bar, and the total range of the sensor values. In this case, there’s 1,000 point to be covered in 339 pixels. That means that each value step must be multiplied by 0.339 to be made to fit. A little CSS positioning and we have our range markers.

// Display high/low for series
$( '#imghigh' ).css( 'top', 339 - ( high / step ) + 89 - 6 + 'px' );
$( '#imglow' ).css( 'top', 339 - ( low / step ) + 89 - 6 + 'px' );

In terms of this charting stuff, using CSS3 border slicing, and relying on absolute positioning, you might be wondering about browser compatibility. Remember that with Adobe AIR, the browser is always WebKit, regardless of the user or operating system. This gives us a high degree of reliability, and a chance to play with new things. There are other gems in WebKit that might make your life easier, so be sure to check out the Surfin’ Safari blog for the latest and greatest.

photocell

Conclusion

Phidgets are really easy and fun to play with if you are just starting out with electronics. There was a popular blog post not too long ago about a gentleman that had charted two light sensors – one taped to a window, and the other on his desk. It was interesting to see the two lines trade off, and then go away when the developer went to sleep. In his case, he went one step further and put the data, as it was coming in, onto a service called Pachube (patch-bay) so others could see the charts in real-time.

Many of the Phidgets boards are labeled, and with a little study, you can start to understand the circuits that are in play. I’ve tried to start getting slightly deeper in this post, so that those circuits won’t intimidate you as much. I’ll be continuing that trend. As you expand your knowledge of basic electronics, you may outgrow Phidgets. That’s where we’ll be headed next – the Arduino. Until then, the code for this project is available for download. Enjoy!

2 Responses to “Phidgets Light Sensor and JavaScript”

  1. vitaLee Says:

    i have to admit i enjoy the phidget series so much.
    thanks for the detailed exploration and well written posts.


  2. Jermaine Zeilinger Says:

    Great stuff as usual…I personally have embraced the new technologies and the CMS platforms, I think the new tools only make the web designs better. I am glad that new technologies are coming out in web design that make things easier, improved, and better looking for design.


Leave a Reply