So I’ve blogged about using the Precon Temperature/Humidity sensor before, but it is time, apparently,to re-visit the topic. We’re working on a project with Vodafone, and I needed to write a brief “How To” for them, so I thought I’d just make it here so everyone (both of you) could benefit.
First, this sensor is possibly the easiest to hook up and interact with of any I have worked with. It has a simple analog temperature sensor and an analog humidity sensor that are just read as a percentage of the reference voltage supplied to the unit. So if the voltage supplied is 3.3v, and the humidity value read is 3.3, then you’re at 100% humidity. And it’s a simple linear scale, so there is no complex conversion, etc. The same is true of the temperature value, though the scale is -30° C to +100° C, so you have to do a little bit of adjusting of the raw value.
The wiring is extremely simple:
That’s Pin 1 — Temperature — of the Precon to Pin A1 on the Sun SPOT for Temperature readings. Pin 2 of the Precon to +3v on the Sun SPOT — to power the sensor. Pin 3 — Relative Humidity — of the Precon to pin A2 of the Sun SPOT for RH readings. And Pin 4 — Ground — of the Precon to Ground on the Sun SPOT. The only other connection you need is +3.3v on the Sun SPOT to Pin A0 on the Sun SPOT for reference Voltage (vref). Since the sensor readings are a percentage of supplied voltage, you have to keep track of the supplied voltage, and this is how.
That’s it for wiring. Really.
Now, the code is just as simple. Once gain, really.
I used NetBeans, of course, to create the project using the Sun SPOT Application Template Module (for information of installing these templates, see here). Here’s the code for the main class:
/*
* RHGPS.java
*
* Created on Aug 21, 2008 4:54:22 PM;
*/
package org.sunspotworld;
import com.sun.spot.peripheral.Spot;
import com.sun.spot.sensorboard.EDemoBoard;
import com.sun.spot.sensorboard.peripheral.ISwitch;
import com.sun.spot.sensorboard.peripheral.ITriColorLED;
import com.sun.spot.sensorboard.io.IScalarInput;
import com.sun.spot.util.*;
import java.io.*;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;
/**
* The startApp method of this class is called by the VM to start the
* application.
*
* The manifest specifies this class as MIDlet-1, which means it will
* be selected for execution.
*/
public class RHGPS extends MIDlet {
private ITriColorLED flash = EDemoBoard.getInstance().getLEDs()[0];
private static int SLEEP_INT = 250;
protected void startApp() throws MIDletStateChangeException {
System.out.println("Hello, world");
new BootloaderListener().start(); // monitor the USB (if connected) and recognize commands from host
IScalarInput vref = EDemoBoard.getInstance().getScalarInputs()[EDemoBoard.A0];
RHSensor rh = new RHSensor(EDemoBoard.A1, vref);
TempSensor ts = new TempSensor(EDemoBoard.A2, vref);
long ourAddr = Spot.getInstance().getRadioPolicyManager().getIEEEAddress();
System.out.println("Our radio address = " + IEEEAddress.toDottedHex(ourAddr));
ISwitch sw1 = EDemoBoard.getInstance().getSwitches()[EDemoBoard.SW1];
flash.setRGB(100,0,0); // set color to moderate red
while (sw1.isOpen()) { // done when switch is pressed
try {
// done when switch is pressed
flash.setOn(!flash.isOn());// Blink LED
System.out.println("Temp: " + ts.getTemp() + " Degrees C.");
System.out.println("Humidity: " + rh.getRH() + "%");
Utils.sleep(SLEEP_INT); // wait 1 second
} catch (IOException ex) {
ex.printStackTrace();
}
}
notifyDestroyed(); // cause the MIDlet to exit
}
protected void pauseApp() {
// This is not currently called by the Squawk VM
}
/**
* Called if the MIDlet is terminated by the system.
* I.e. if startApp throws any exception other than MIDletStateChangeException,
* if the isolate running the MIDlet is killed with Isolate.exit(), or
* if VM.stopVM() is called.
*
* It is not called if MIDlet.notifyDestroyed() was called.
*
* @param unconditional If true when this method is called, the MIDlet must
* cleanup and release all resources. If false the MIDlet may throw
* MIDletStateChangeException to indicate it does not want to be destroyed
* at this time.
*/
protected void destroyApp(boolean unconditional) throws MIDletStateChangeException {
for (int i = 0; i < 8; i++) {
flash.setOff();
}
}
}
So that's the Main portion. You will notice that there is reference to 2 other classes, RHSensor and TempSensor. Those are amazingly simple classes, listed here:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.sunspotworld;
import com.sun.spot.sensorboard.EDemoBoard;
import com.sun.spot.sensorboard.io.IScalarInput;
import java.io.IOException;
/**
*
* @author davidgs
*/
public class TempSensor {
private IScalarInput temp;
private IScalarInput vref;
/**
*
* @param pin Pin number for analog reading of Temperature
* @param vref IScalarInput pin for voltage reference
*/
public TempSensor(int pin, IScalarInput vref) {
this.temp = EDemoBoard.getInstance().getScalarInputs()[pin];
this.vref = vref;
}
/**
*
* @return Double value of degrees C
* @throws java.io.IOException
*/
public double getTemp() throws IOException {
return (((double) temp.getValue() - 115) / (double) vref.getValue()) * 100;
}
}
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.sunspotworld;
import com.sun.spot.sensorboard.EDemoBoard;
import com.sun.spot.sensorboard.io.IScalarInput;
import java.io.IOException;
/**
*
* @author davidgs
*/
public class RHSensor {
private IScalarInput rh;
private IScalarInput vref;
/**
*
* @param pin pin number for the relative Humidity sensor
* @param vref IScalarInput pin for voltage reference
*/
public RHSensor(int pin, IScalarInput vref){
this.rh = EDemoBoard.getInstance().getScalarInputs()[pin];
this.vref = vref;
}
/**
*
* @return double-precision relative humidity as calculated by:
* rh pin value / vref pin value * 100
* @throws java.io.IOException
*/
public double getRH() throws IOException{
return ((double)this.rh.getValue() / (double)vref.getValue()) *100;
}
}
And that's all there is to it. A simple ant deploy run will put the application in your Sun SPOT, and start it spitting out Humidity and temperature readings every 1/4 second.