« PDP-11 | Main | Propeller Projects »

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.

Friday, March 30, 2012

Phidgets SBC2 - initial impressions

Over the last year or so I've started using Phidgets sensors more and more because they are so convenient. True, they are higher priced than creating ones own hardware, but right now convenience is more important than cost to me. One of the applications that I have planned is monitoring temperature of my shop which is some ways away from the house although I did run a data cable to it when I upgraded the shop power. The parameters that I'm interested in monitoring are the shop temperature, light intensity, status of the door (open or closed) and external temperature as a reading there is sufficiently far from the house that it represents a true outdoor temperature. What quickly became apparent was that I needed more wires in the cable than were available and a solution was found when I got a Phidgets SBC2 to play with.

One of the nice things about Phidgets sensors is that they can be made visible to all computers on the network through the Phidgets web service. Thus, all I'd need to do is to connect the SBC2 to my house network (have a power line modem connection to my shop as well as flaky wifi given the distance) and no longer have any limitation on sensor number and can also monitor the status of motion sensitive lights in the back of the yard through the use of a Phidgets light sensor. SBC2 allows the connection of 8 analog sensors and has 6 USB ports available as well.

Setting up the SBC2 as a remote 8/8/8 board was extremely simple as the SBC2 is accessed via a web interface and it's just a matter of setting the IP address (if one wants static IP instead of DHCP allocated IP address) as well as a few other parameters. Whole process, the first time that I did this, took 15 minutes. The SBC2 showed up immediately on the Phidget control panel and changing one line of code in one of my USB based 8/8/8 sample programs allowed me to remotely access the SBC2. I should note that the SBC2 firmware also comes preflashed with the code for a webcam which was a nice bonus.

So, if one has low speed sampling applications (my shop environmental sampling is about 1 sample/second/channel), then the Phidgets web service can be used unaltered. Of course, I couldn't stop there as I had to play around with the SBC2 to find out its capabilities and I was impressed. The SBC2 is a 400 MHz ARM processor with 60 Mb of SDRAM and 512 Mb of flash on the board (where the other 4 Mb of SDRAM go to I have no idea). It runs Emdebian and has a few very annoying features like only allowing telnet access via SSH (putty program works fine) but also has secure ftp and it took me over an hour to find WinSCP which is an open source secure ftp client. Considering that this is an embedded system, it seems that encrypting data to and from the board is a tad paranoid.

Once I began playing around with Linux realized that this is a far more powerful machine than I had first thought. I should note that my last big embedded system project was in 2005 using Freescale's Zigbee boards which had an 8 bit 6800 relative on board along with a staggering 32 Kb of RAM and a similar amount of flash. More than enough space for me to program my ambulatory accelerometry and breath monitoring project (the latter part isn't very ambulatory).

The SBC2 is the first embedded system that I've used that is so far divorced from the hardware. Whenever I play with a microcomputer system, the first thing I do is to start reading about the instruction set, how to setup timers, interrupt structure, etc. It's nice in a way to not have to worry about these things but I have this overpowering urge to dig deeper in any system. Fortunately, as it is a Linux system, all of the source code is available and I've already found some novel ways to construct web interfaces to the machine (still in the planning stages).

Looking at why the Phidgets web link was slow was the first project and I was shocked by what I found. The SBC2 can serve up 640x480 video at 9.5 fps. This process takes up 10-20% of CPU time. Thus, the SBC2 CPU is damn fast. The first step in looking at the Phidgets web link was to run a packet sniffer while the weblink was actively sending data to my remote machine. The results were, to put it mildly, somewhat surprising:

report 200-periodic report follows: 
report 200-lid4 is pending, key /PSK/PhidgetInterfaceKit//250532/Sensor/4 latest value "380" (changed)
report 200-lid4 is pending, key /PSK/PhidgetInterfaceKit//250532/RawSensor/4 latest value "1555" (changed)
report 200-that's all for now

report 200-periodic report follows:
report 200-lid4 is pending, key /PSK/PhidgetInterfaceKit//250532/RawSensor/6 latest value "344" (changed)
report 200-lid4 is pending, key /PSK/PhidgetInterfaceKit//250532/Sensor/6 latest value "84" (changed)
report 200-lid4 is pending, key /PSK/PhidgetInterfaceKit//250532/Sensor/5 latest value "220" (changed)
report 200-lid4 is pending, key /PSK/PhidgetInterfaceKit//250532/RawSensor/5 latest value "899" (changed)
report 200-that's all for now

report 200-periodic report follows:
report 200-lid4 is pending, key /PSK/PhidgetInterfaceKit//250532/Sensor/7 latest value "371" (changed)
report 200-lid4 is pending, key /PSK/PhidgetInterfaceKit//250532/RawSensor/7 latest value "1518" (changed)
report 200-that's all for now

So, for 4 samples 3 packets are required! The total amount of data, if one coded the network interface efficiently, would be <header>, <data> with the <data> portion taking up no more than 16 bytes, or more likely 12 as the channel number can be a single byte. It's clear that whoever coded the Phidgets webservice portion didn't have much of a concern with bandwidth. OTOH, the system works very well as soon as one plugs the pieces together and one can argue that that should be the primary metric one uses rather than the use of 3 packets to send 4 A/D values (the reason that there are 2 values sent for each A/D channel is that there is a "raw mode" which seems to represent the average of a number of values and hence is a 12 bit quantity unlike the actual A/D values which are sampled at 10 bits).

If this was a M$ product I'd be outraged, but all Phidgets code is open source so, if one doesn't like the way things are done, the code is there to modify. Right now I don't really feel like rewriting Phidgets21 which runs on the remote machine so I'll leave the web interface the way it is but there is the potential to get full A/D sampling rate from the 8/8/8 board portion of the SBC2 remotely by efficiently coding the network transmission code. This is only 1 KHz on 4 channels maximum but it is more than adequate for most of the physiologic signals I'm interested in.

Ambulatory physiologic monitoring was the primary reason I bought another 5 SBC2's to play with. I'm assuming that I'm going to probably fry a system or two during the development phase and it's simpler to have a WiFi connection to a remote set of sensors rather than running long wires (for me anyway). Also, by having wireless links, one can use the SBC2's digital outputs to switch relays controlling 120 VAC devices without the risk of frying my laptop or desktop because WiFi isolation is about as good as one can get. I can't replace any of my laptops or desktops for $225.

The ambulatory physiologic monitor (APM) will be described in more detail in a future blog entry and will involve sampling EKG at 1 KHz as well as earlobe pulse waveform at 1 KHz. Whether or not the SBC2 is fast enough to also work as a pulse oximeter remains to be seen. Other inputs to the device would be accelerometry and gyro data from the spatial 3/3/3, GPS output which will also serve as a precise timebase when the person is where a GPS signal can be picked up and perhaps another 3 axis accelerometer attached to a leg. Also will measure ambient light intensity and sample sound at 20 Hz to get an idea of the ambient sound environment as well as when the person is talking. Respiration would be measured by sampling a strain sensor around the chest (still don't have that bit working). Ambient temperature would also be measured but none of the Phidgets sensors are accurate to measure the small body temperature changes that occur during the course of a day. Also, finding an area of the body to use for this temperature sensor is a bit challenging as most subjects would likely balk at the idea of having a rectal temperature probe inserted for 24 hours, but this is the most stable source for core body temperature. All data would be written to a flash memory stick.

Unlike the Stellaris-based APM that I over-ambitiously tried to build in 2010, the SBC2 based project is almost akin to writing the code on a "mainframe" rather than an embedded system. The SBC2 comes with gcc and the Phidgets library and it is quite trivial to create C programs which run on the SBC2. I'm still having a problem wrapping my head around the concept that the vast majority of APM project will consist of software rather than hardware and having such a vast amount of system memory is a novel experience for an embedded system. We'll have to see whether the remainder of the project will go as easily as my preliminary investigations of the SBC2.