The company I work for (ABR, Inc.) pays it’s employees to use alternative transportation—bicycle, walk, run, ski, etc.—to get to work. It’s not a lot of money, but human behavior being what it is, even a small incentive really works. I’ve been riding my bicycle to work three or four times a week, carrying a hand-held GPS (Garmin eTrex Vista Cx) along with me and logging the data into spatially aware databases (PostGIS and spatialite). You can see a map of last week’s data on my GIS page.
One problem with my GPS is that I get really inaccurate elevation data, and as anyone who has ridden a bicycle knows, elevation changes are really important to how fast you can ride. I’ve noticed that I ride much faster going home than on my way to work, and had concluded (until examining the data…) that it must be an uphill ride to work.
But how to fix the elevation data? One approach would be to download the new global digital elevation model (DEM) that’s based on data from Japan’s ASTER satellite and use this to find the corrected elevation for GPS trackpoint. I’ll probably try this at some point just to see how well the DEM matches my data. But the approach I wound up using is to generate an “average” track based on all my trips to and from work.
There’s probably a way to do this with a single SQL statement, but I couldn’t figure out how, so I did the point iteration in Python. The first SQL query takes an existing trip and segments the trip into a series of points. I chose a maximum interval of 50 meters because that was approximately how often the GPS reports data at the speeds I’m normally travelling. Here’s the PostGIS SQL:
SELECT ST_AsText(ST_PointN( segpoints.points, generate_series(1, ST_NPoints(segpoints.points))) ) FROM ( SELECT ST_GeometryN( ST_Segmentize(track_utm, 50), generate_series(1, ST_NumGeometries(ST_Segmentize(track_utm, 50))) ) AS points FROM tracks WHERE tid=67 ) AS segpoints;
This yields a series of points (in WKT format) along the track.
My Python script takes each of these points and finds the average X, Y, and Z (elevation) coordinates of all points within 50 meters of the point. Here’s the query:
SELECT count(*), avg(lat), avg(lon), avg(ele)*3.2808399 AS avg_ft FROM points WHERE ST_Within( ST_SetSRID(ST_GeomFromText(POINT_WKT), 32606), ST_Buffer(point_utm, 50) );
And the results:
Elevation and speed, Jul 1 ride to ABR
The red squares show the elevations along my route, and the green markers show the speed I was traveling at that point. In this case, I’m riding to work, so home is on the left and ABR is on the right. The big hill on the left is Miller Hill Road. In general, you can see that a ride to work involves going over Miller Hill, then a gradual climb along Sheep Creek Road to the intersection with Ester Dome Road (the little hitch in this section is the hairpin curve before Anne’s Greenhouses where so many people go off the road in winter…), followed by a steeper descent to ABR. My speed tracks the elevation changes fairly closely. I’ll be interested in seeing how these plots change over time as my legs and cardiovascular system strengthens. Will the green points rise uniformly, or will I be able to see improvements in individual aspects of my performance such as hill climbing?
One final point: the elevation at home and ABR are essentially the same. My conclusion after all this is that elevation can’t account for why my rides home are so much faster (1.28 mph, on average). Wind? Cold mornings? Excitement to get home?
For reference, here's my ride home on the same day:
Elevation and speed, Jul 1 ride from ABR
The Arduino weather station is coming along. Today I integrated a barometric pressure sensor and a calibrated light sensor into the hardware and software. The pressure sensor is a SPC1000-D01, which is sensitive to pressure changes as small as the difference within a 9 cm column of air. It can be used in several different configurations depending on how often you want to get a reading, and how much precision it reports. At the best frequency and precision, the sensor was drawing enough current that I was having trouble adding other sensors to the Arduino, so I’m running it in it’s lowest power configuration (where the chip is in a low power standby mode until you ask it for a reading). The light sensor is a TSL230R, which is also very accurate. It has three different sensitivity levels that can be changed at any time, which means that when the light intensity gets too high or low, the Arduino changes the sensitivity of the sensor to keep the results within range. The only down side to these chips are they require a lot of digital pins (four for the pressure sensor, five for the light sensor).
Here’s a circuit diagram of the current setup. If you click the image, you can view a PDF version. There’s also an Arduino xcircuit diagram. This is the first circuit I’ve ever tried to draw, so it probably isn’t as well laid-out at it should be.
The code is also available. It’s not pretty, but it works. If you do download it, the code include a simple analog light sensor (light0), which isn’t shown on the wiring diagram. I was using it before I got the new sensor set up, and haven’t removed it from the hardware yet.
Arduino setup
My Arduino-based weather station has improved in the last week to the point where it’s delivering useful data. I’ve got five DS18B20 temperature sensors hooked up and reporting their temperatures to my Goldstream Creek Weather Pages. In the image on the top of the post, the Arduino is on the left, the indoor sensors are in the middle, and the outdoor cluster of temperature sensors is on the right (under a yogurt container). At the moment, I’m just averaging the data from the two sensors that are inside and the three outside, but eventually I’d like to place each sensor in a different location. I’m not sure where the outdoor sensors will go, but one of the indoor sensors will move up to the second floor of the house. Twisted-pair telephone cables carry the data and power to the sensor clusters.
I’ve also connected a cheap photoresistor to the sensor cluster in the house. I’m converting the resistance it reports to a value from 0 (dark) to 100 (light). It’s in a place that rarely gets direct sunlight, so the values should give some idea of when the sun is up, and whether it’s sunny or cloudy. I have a more sophisticated light sensor (TSL203R) and a barometric pressure sensor (SCP1000), but haven’t tried them yet. I’ve run out of breadboards, and now that my Arduino is actively delivering data, I’m a bit less inclined to experiment.
I think it’ll be interesting to compare the outdoor temperatures from behind the house with the temperature coming from the Rainwise weather station atop the dog yard gate. Also, there ought to be an obvious relationship between outdoor temperature, light, and indoor temperature, since it seems like the house heats up much more quickly when the sun is beating on the south facing side. If I was really ambitious, the windows and window-shades could be connected to the system: it’d open the windows when it detected cooler temperatures outside than inside, and close the shades in whichever window is getting direct sunlight.
Once the design and software has stabilized, I’ll be sure to post the schematics and code.
Arduino and prototyping shield
Yesterday, my Arduino board showed up in the mail. It’s pictured in the photo alongside a Canadian dollar from when I drove up to Alaska. I ordered it with a prototyping shield and Getting Started with Arduino, a book written by one of the developers of the Arduino platform. The book is a great introduction to the hardware and the software you use to control the gadget. To fully appreciate the book, you’ll want to get a few extra extra components so you can try the experiments in the book. These include a breadboard, solid core wire for the breadboard, a button, light sensor, LEDs, and a variety pack of resistors.
What is it? It’s a very simple computer connected to fourteen digital input / output pins, six analog input / output pins, and a USB communication system so you can read data and put programs on the system. In other words, you can read data from the environment, control things based on that data, and send data back to a computer all on the same small board. I’m interested in using the platform to build my own weather station to complement the professional station we have. But more generically what’s cool about it is that it provides an inexpensive (my board was $35) platform for “programming” the world. Instead of buying a gadget off the shelf that someone else has built to perform a task they think you’ll want, you can build something to do exactly what you want.
In the real world.
All I’ve done with it so far is to control the flashing of the pair of LEDs that came with the prototyping shield. I know that doesn’t sound very exciting, but if you can control LEDs and make them go on and off, or vary their intensity, that means you can control anything that takes an on / off, or variable input. For example, a set of fans in your house whose speed and direction is controlled by the relationship between the temperature in the house, in the attic, and outside. Or controlling a sprinkler system that senses how wet the ground is, reads the weather forecast from the Weather Service and only turns on the sprinklers if no rain is expected. Or a system that operates a dog door, sensing which dog has approached by reading an RFID tag on their collar and then opening or locking the door depending on whether they are allowed in or out.
You get the idea. Combining any of the wide variety of input sensors available with the ability to do things based on logic that you control is a really powerful tool. And the low cost of the board makes it reasonable to experiment and try things out until you get a system working the way you want.
My initial project will include a series of temperature sensors that I’ll put in different places in the house and outside (maybe even in a dog house?), a light sensor and a barometric pressure sensor. Of course, you can buy small weather stations that have all of these things in them, but most can’t read temperatures below -40°F, and most only have one sensor. Best of all, I’ll plug mine into a “real” computer via USB and record the data as it comes in.
Protein after the boil
Spent some of yesterday brewing a batch of Bavarian hefeweizen. It’s a light, easy drinking summer beer that preserves the unique flavors of the Bavarian wheat beer yeasts. Most American varieties of hefeweizen use a cleaner, less flavorful American yeast. My original version of this beer was named after the shed I build to house our water tank in the old house. Now that we’ve moved and have a new shed, the beer has been re-christened “New Shed Hefeweizen.”
The beer has six pounds of base malt—two pounds of 6-row and four pounds of 2-row organic pale malt in this case—and six pounds of malted wheat. Wheat malt contains a lot of protein, as does the 6-row malt. As I mentioned in my post about Piper’s Red Ale, protein causes haze in the final beer and can affect it’s long-term stability. In the case of a hefeweizen, the haze is a feature of the style, and because it’s a summer “session-style” beer, it’ll get consumed more quickly than a typical ale. So all the protein shouldn’t be a problem and will contribute to a nice thick head on the finished beer. You can see all the protein floating around in the wort (it’s the white stuff in the photo that looks like the eggs in egg-drop soup). Most of the big chunks get filtered out in the pot as the wort is chilled, but even with the gross removal, there’s still a lot left over in the fermenter.
My last batch of beer, Devil Dog turned into a comedy of errors. The mash and boil went perfectly, but when chilling I accidentally left the stopcock on my fermenting bucket open. Lost a couple gallons of wort into the snow. After fermentation was finished and it was in the keg, one of my new serving lines had a loose bolt on the keg connector. Not only did this cause all the remaining beer to leak out inside my kegerator (three gallons of it), but I completely drained my CO2 tank. So this time around, I paid very careful attention to everything I was doing.
The mash, boil, and chilling went well. Mashing a grain bill that’s 50% wheat is always a little nerve-wracking because wheat has no husks to help in filtration, and as anyone who had made bread by hand knows, wheat plus water equals a very sticky substance. My mill does a good job of preserving the barley husks, and I didn’t have any extraction issues when sparging. I wound up with an excess of wort, however, so I had to boil it quite a bit longer to get down to five gallons. The final beer might be a bit maltier as a result, because of the additional carmalization of the sugars in the pot. I bumped up the hops slightly in an attempt to offset this.
Chilling was a bit of an experiment. I pulled thirty gallons of water from Goldstream Creek and used that in a closed loop through my plate chiller to chill the wort. It’s in the blue barrel on the right side of the image. The temperature at the start was around 50°F, and that wasn’t quite cool enough to drain the kettle with the valve all the way open. But I got it down to a pitching temperature of 70°F, which is about right for a hefeweizen.
A true hefeweizen yeast is an interesting strain because you can control the flavors from the yeast by changing the fermentation temperature. Like Belgian beers, a Bavarian hefeweizen comes with lots of flavors that would be considered serious defects in a British (or worse, American) ale. At cooler temperatures (cooler than 65°F), you’ll get more banana flavors, and warmer fermentation encourages clove tones. I tend to prefer the banana flavor, but at lower temperatures you’re always risking a sluggish or incomplete fermentation. This time around, I’m hoping to keep fermentation closer to 68°F, which should yield a nice dry beer with a good balance of banana and clove flavors.
Assuming I don’t pump all the beer into my kegerator again, I should know how it turned out in four to six weeks.