| Subcribe via RSS

SparkFun USB Weather Board

August 26th, 2009 Posted in AIR, Ajax, Electronics, HTML, JavaScript

Generally, when getting started with something new, it is best to take the path of least resistance. The problem is that if you don’t know much about a subject, sometimes identifying that path can be pretty difficult. When it comes to using sensors to capture weather data, you might be inclined to start with just a temperature sensor. How do you connect it to USB though? Luckily our friends at SparkFun Electronics have a USB-ready weather board that includes not only temperature, but also barometric pressure, ambient light and humidity.

sparkfun-weather

If you recall from my previous post, there are four things you need to get started connecting hardware to the web:

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

Hardware

The first piece we need is USB-enabled hardware. We are good there with the SparkFun USB Weather Board (above). If you read the product documentation, you’ll find details on what it is the board sends to the USB port. We will worry about the exact data format later, but for now we are most interested in the fact that the board sends serial output as a single ASCII string at 9600 bps (baud).

If you have been around long enough, you might know a thing or two about baud. If you don’t, that’s fine too. In short, it is the rate at which the board sends data. That is important because on the other side of the USB port needs to be a serial-to-socket server, and that server needs to know what rate to expect the data. if you tell it a different rate, then you’ll still get something across the wire, but it will be all garbled junk.

Serial to Socket Server

While there are a few options out there, I prefer the Serproxy server to sit on the other side of the USB port. It has been around for a while, works well on Mac, and is freely available. There is no installation process, simply download the Serproxy archive, and then unpack it somewhere readily accessible on your machine. You’ll find an executable as well as a configuration file called “serproxy.cfg”.

Open the “serproxy.cfg” file using a text editor, and take a look at the different parameters. There are only a few. Early on, you’ll find a line labeled “comm_baud” and you will want to make sure that the other side of that assignment reads “9600”. Further down you will find a line labeled “serial_device1”. Essentially, Serproxy needs to know where to find your USB port on the machine.

Connect the SparkFun USB Weather Board to your machine. Then, on a Mac, open Terminal and enter “ls /dev/cu.usb*”. You’ll probably only find one entry listed, and this is the label that your machine gives the USB port to which the weather board is connected. Copy that label and put it on the other side of the “serial_device1” assignment. Make sure that any other “serial_device1” lines are commented out using “#”. For reference, here is my configuration file for this project.

# Do not Transform newlines coming from the serial port into nils
newlines_to_nils=false

# Comm ports used
comm_ports=1

# Communication settings
comm_baud=9600
comm_databits=8
comm_stopbits=1
comm_parity=none

# Idle time out in seconds
timeout=300

# Set TCP port and serial port
# you will have to change serial_device to reflect your configuration
# use "ls /dev/cu.usb*" to look for your serial port.
net_port1=5331

# SparkFun Weather
serial_device1=/dev/cu.usbserial-A6007w6X

Save the “serproxy.cfg” file, head back to Terminal, and navigate to the directory containing the configuration file. In the same directory, you will find the executable to run the Serproxy server. It is very lightweight and fast, so don’t worry about having enough system resources. The server should start up pretty quickly and give you the message that it is “Waiting for clients”. At this point the weather board is sending data to the USB port, and the Serproxy server waiting for clients to connect for that data. Which brings us to the third of the four requirements – the socket library.

Socket Library

In the browser, JavaScript is pretty limited in terms of it’s connectivity. Scripts can only call the server from which they originated, and the browser only gives us HTTP(S). When developing on Adobe AIR however, the security sandbox is significantly lessened. You can connect to whatever endpoint you want, and you can use any TCP/IP format you wish, not just HTTP(S). Further Adobe AIR gives you a Socket class that can connect to any endpoint.

The Adobe AIR documentation covers the Socket class in more detail, but it does pretty much what it sounds like. Along the way it can fire a variety of events that your application may want to listen for and act upon. For our purposes, we are interested in the air.ProgressEvent.SOCKET_DATA event. Once we have instantiated the Socket object and added our event listeners, we can then go ahead and connect to the server. In this case, Serproxy is at “localhost” or “127.0.0.1” and listening on port “5331” which was specified in the configuration file.

// Using jQuery
$( document ).ready( function() {
 
  // Socket instance
  var socket = new air.Socket();
 
  // Handle incoming data
  socket.addEventListener( air.ProgressEvent.SOCKET_DATA, function( evt ) {
    // Do something with the data
    air.trace( socket.readMultiByte( socket.bytesAvailable, 'us-ascii' ) );
  } );
 
  // Conect to the designated server
  socket.connect( '127.0.0.1', 5331 );
 
} );

Your Code

This brings us to the last part of this exploration – your code. The first problem you will likely encounter is that there may be latent data on the serial port. Or, you may be joining in the middle of a broadcast, and only get partial data. For this reason I prefer to ignore the first time the data is received. Don’t worry, this isn’t HTTP – you’re still connected to the server – and you’ll get another batch of data every one second from the weather board.

Going back to the weather board documentation, you may recall that the data takes the form of a single line of ASCII text. That line of text is terminated by a newline, which is marked as “\n” in most programming languages, JavaScript included. As the bytes trickle in from the socket, put them on a global string variable as a buffer, and then watch for the newline marker. Once you have picked that up, use String.substring() to take out the weather data.

#42.38,073.60,022.9,073.30,082600,997,0,000024$

In my sample application, I’m going to write over the buffer value as soon as I’ve parsed the data, so I ignore the starting “#” character and ending “$” character, as well as the invisible newline, which gives me the data separated by commas. Well, now that’s just perfect because there’s a String.split() method that will split those data points apart based on a delimiter, like a comma, and give us an array of values back. Then I can just pick out the array values and do with them as I please.

Cell 1: Humidity
Cell 2: SHT15 Fahrenheit
Cell 3: SCP1000 Celsius
Cell 4: SCP1000 Fahrenheit
Cell 5: SCP1000 Pascal
Cell 6: TEMT6000 Light (1 == Light, 1023 == Dark)
Cell 7: Battery Level (0 == No Battery)
Cell 8: Record Number

Barometric pressure comes across as in Pascals, which isn’t the units you might be expecting if you’ve ever watched the local news. To convert to millimeters of mercury (mmHg) multiply the Pascal value by 0.000295299830714. Also note that you can get the temperature in both Fahrenheit and Celsius, and also from multiple sensors. Those two sensors may be off from one another slightly, so you may want to calibrate them accordingly.

Conclusion

That may seem like a lot to take in on the first try, and indeed, it may take a little trial and error to get it right on your system. The good news is that once you’ve got these basics in place, it only gets easier to take advantage of increasingly complex hardware. Eventually you’ll be able to drop down to the individual sensors, cross-reference them with a GPS and log the data on a memory card in a fully autonomous system. Or you might choose to use the BlueSMiRF feature of the weather board and, after a little soldering, broadcast the data wirelessly back to your system. The possibilities are endless.

weather-board-javascript

In the meantime, you can download the source code to a sample application I wrote to display this data. The user interface is modeled after an older Oregon Scientific weather station I have in my kitchen, with a remote sensor outside on the front patio. I’ll be the first to admit that the HTML and CSS is pretty hideous. My goal wasn’t to show how to code great HTML and CSS, but to show you the JavaScript necessary to connect to the weather board. After all the result of this is a desktop application, so I’m not really worried about the semantic web or SEO. Just get ‘er done!

6 Responses to “SparkFun USB Weather Board”

  1. adamoerikom Says:

    Stunning blog and good article. High 5 for u man !


  2. Soldering Says:

    Very well done! For complex soldering I would recommend the use of soldering products from reliable companies. One day I decided to buy one of S-bond’s product lines. They were designed to join over a range of temperatures and for a range of base materials. The alloy model 115 worked very well on sensitive materials, due to its lower temperature. At their website http://www.s-bond.com you are able to check some different and up-to-date soldering product models. Thank you for the useful and informative post.


  3. Poornima Says:

    The blog has been quite noteworthy, as it discusses about the main aspectts as well as components related to weather board. I got sufficent details from this blog.


  4. orengo Says:

    Dear Kevin,

    I download the source code, but don´t see the mxml CODE for compile with adobe air (ADOBE FLEX 3)…


  5. Kevin Hoyt Says:

    Orengo,

    Thanks for your comment. This application is done with HTML/JavaScript. There’s no Flash or Flex in there. The JavaScript code is very similar to what you’d do in Flash.

    Thanks again,
    Kevin


  6. orengo Says:

    Dear Kevin,

    I wonder if you’re interested in doing a paid job to develop usbwheather with this same solution to this article using the arduino ethershield to the display of time information via the arduino webserver.

    Best Regards,

    Jorge orengo


Leave a Reply