Tuesday, April 03, 2012
Use of standard deviation as marker for temperature event changes with Phidgets IR temperature sensor
One project that I'm working on is a system to turn on the tap for my cat, Billy, who has unfortunately trained me to turn the tap on for her whenever she jumps onto the counter beside the kitchen sink. For some reason she far prefers water when it is running out of a tap than in her water bowl. This got me thinking of how best to implement a system which would do this automatically.
What is needed is a cat sensor and, when the cat is detected, an electrically controlled valve will be turned on. The water remains on while the cat is by the tap drinking. Because this process causes considerable local spray, the sensor would have to detect her from a distance of at least 3'. My initial thought was to utilize a webcam which would run on an SBC2 and the data would be monitored by one of my desktop machines. A Billy detection algorithm would be quite simple as all that would be needed is a collection of black pixels larger than a preset threshold to turn on the tap. (It's easy to detect black cats). While this approproach would have worked, it seemed a bit excessive in terms of CPU requirements for such a simple task.
Then, a novel solution suggested itself. I was playing with my Phidgets 1045 IR temperature sensor a few days ago and found that it responded to warm or cold objects at a greater distance than I had expected it to work. Right now, my current motion sensing application for this sensor picks up my waving my arm at a distance of 12'! Given how warm cats are, the IR sensor will be the primary cat detector.
Given that temperature in the house changes depending on the time of day and whether the furnace is on or not, some type of high pass filter was needed to filter out the slow temperature changes. The other interesting property of the 1045 unit is that it is very uniform over the short term but is subject to significant fluctuations over the long term. A graph of the 1045 temperature sensor together with the high precision non-IR temperature sensor which is on the same board (and used to correct the IR temperature) is shown below:
There is a lot of noise in the IR sensor at this timescale. Note that the on-board temperature sensor has very good temperature resolution and easily picks up temperature changes from the furnace vent which is located at least 15' from the 1045 board.
A 10 minute section of a portion of the record is shown below:
There are 600 1 second averaged samples in the graph above and, while the IR signal may appear very noisy, in this case appearances are deceptive.
To get an idea of the noise levels and variability in the signal, I averaged 32 samples at a time and computed the SD on each sample. The 1045 outputs a pair of readings every 32 msec and the 1.024 seconds/sample is close enough to 1 second for my purposes. What astounded me was how low the SD's were for the IR temperatures as can be seen in the graph below which is the same section of data but now plotting IR temp and IR_temp_SD below:
The SD was the filter I was looking for! All that was necessary to detect a change in temperature was to look for SD values that were above a threshold. Essentially no false triggering occurs with using an SD threshold of 0.03 or greater. A histogram of about a days worth of IR temp SD values is shown below.
There is a very rapid falloff of the right handed tail of the SD distribution function and one can use a threshold of 0.025 for maximal sensitivity as long as one is prepared to accept that there will be spurious events. For warm or cold objects a few feet from the IR sensor, SD values of 5 or more are obtained for my hand or a cold beer held in the field of view of the sensor. That's the other beauty of using the SD as the detection function as it is always a positive number and it's magnitude is a function of how different IR readings are in the set of 32 sequential samples that are used to compute the mean and SD. Also, the sample period is short enough that there are no false triggers from slow changes in local environmental temperatures. It's clearly a good enough filter to reject the periodic furnace waveform.
Using SD as the basis of my filtering function was a serendipitous discovery; I wrote a quick test program to compute the means and SD's of 32 sample chunks of IR data and looked at the results in DPlot. The utility of the SD in picking up movement events was immediately obvious:
Note the scale for the SD - the tiny blue bumps hugging the x-axis indicate actual movements and use of SD with a fixed threshold is far simpler than keeping track of the IR temperature baseline and using a floating threshold. The other option one has is to set a high IR temperature threshold - say 26.5 C. This would pick up all of the large temperature changes which are the result of my being a couple of feet from the sensor, but would miss all of the small changes.
The only reason I computed SD was that I was testing an algorithm that computes mean and SD in one step:
mean = sum(x(i))/n and SD = (sum(x(i)^2) - sum(x(i))^2/2)/(n-1)
It's just more elegant to have a single loop to compute both mean and SD. At the time that I started this project I figured I'd have to adapt one of my neuronal action potential finding algorithms modified for noisy data to determine when movements occurred. Time to look at use of SD in this application also.
I've written a test program which will demonstrate the use of the 1045 sensor and SBC2. Currently, the 1045 sensor is connected to the SBC2 and is accessed through the Phidgets web service. The nice thing about this program is that it works on Phidget serial numbers. Thus, instead of being connected to the SBC2, the 1045 could be connected to another computer on the network and any 8/8/8 board could be used to flash the LED that is used to indicate that a temperature discontinuity has occurred. Once I clean up the code a bit and write some documentation will post it as it's far less frustrating to use that way.