Search This Blog

Friday, April 5, 2013

Midnight, on the Schweitzer Road

I travel for a living. In elephants, to trade my dreams for their gold. Fortunately, there seems to be a never ending supply of both, but I’ll never tell that to them.
This month I’m in Idaho, in a tiny lake town trying hard to make itself into a closet for rich peoples’ money. It’s nice, and there’s a restaurant named Trinity where they know me, with the pleasant result than I never have to even see okra. I’ve been here for a few months, and I’ll be here for a few more.
Usually I keep a tiny apartment in towns like this, but it’s on the lake, and there’s a music festival, and there isn’t any place to stay in town. My borrowed secretary has managed to find me lodgings in a nice hotel, twelve miles from town, at the ski resort. It’s named Schweitzer and is nearly empty this summer, after a dry winter.
To get here there’s a narrow, winding road that’s paved in theory, but barely in practice. Nine miles long and a half mile climb from bottom to top, the Schweitzer road takes an hour from every day. Half a dozen switchbacks and if you crack 40mph on any straightaway you’re an idiot.
Until two days ago, it was just commuting, when during my evening commute home I was stopped by a flagman standing behind a dozen cars parked on a steep curve. He comes up to say,
“There’s a accident up ahead. Guy turned over his dump truck. It’s gonna be a while. Like a hour. You could turn around.”
No, thanks, I think. I have a book, and the new CD of Stephen Foster songs, and my phone is in range, if barely. I open the doors and turn up the stereo loud enough to hear but soft enough to listen to the wind. It’s an hour ‘til sundown, the light dies in peace as I read quietly, until I hear the growl of a big semi drifting down from the switchbacks above. A tractor rig with a big flatbed trailer is hauling something around the near bend, something about 8 feet tall, as wide, and maybe 25 feet long.
It takes a moment recognize what I’m looking at. It’s a dump truck, or rather, the main mass of what might once have been one. No wheels. No cab to speak of, and the engine looks as though it got dropped into a blender. There are no police cars, or ambulances. The stalled line of cars comes to life and strings out as we all head towards the ski basin. Around the fourth bend I see the real horror.
On one side of the road lie half the dump truck’s wheels, with the other peeking up from the downhill slope. A pile of metal that might have been a cab has been carefully stacked into a neat pile. The volunteer fireman are hosing diesel off the road, and in a tight knot behind a silent and darkened ambulance stand the paramedics and police. He didn’t tip over his truck, the driver rolled it over the side of the road and straight down a switchback. Stephen Foster’s cheerful minstrelsy isn’t right, and I turn off the music as I finish the drive home.
In the morning the stink of diesel is all over the accident, and then the same in the evening as I returned. This morning the stain is diminished but that just lets me see the hundred foot long skid marks that lead off into nowhere. And it still stinks.
Tonight I stayed in town to do some laundry at a friend’s house. He’s playing poker-Monopoly with his boys, a game apparently of their own invention. The TV does TV things while I sit crammed into a big couch near the window, writing a love letter to someone I’ve never met, an apology to someone I have, and an explanation to yet another person I’ve managed to misunderstand on a regular basis.
It takes a while, the laundry, and it’s 11:30 pm when I leave. The moon is off playing somewhere and it’s dark. I throw everything into the cab and head for home. There’s no one on the road tonight, except me and Stephen Foster’s ghosts. I can’t get the wreck out of my head, and with the windows open I’m going to have to smell it as well.
The switchbacks seem steeper in the dark, and tiny mice run out to dance with the truck, requiring me to dance on the pedals. None of them die, but it’s a close thing. Finally it’s high enough and cold enough that there are no mice, and I speed up so I can get off the damned road. The lullaby Slumber my darling starts, softly,
Slumber, my darling, the birds are at rest,
The wandering dews by the flowers are caressed;
Slumber, my darling, I'll wrap thee up warm,
And pray that the angels will shield thee from harm.
I don’t hear voices. I’ve never heard voices, but as that final line plays, I shift into neutral and slow down, stepping on the brakes hard for some reason, and around the next corner a doe and a fawn stand motionless in the road, now safe from me, thanks to Stephen. We all owe him one. They drift slowly off the road, peering into the headlights and through me.
The final steep curve lies just beyond, and I need to stop to and let the adrenaline go away. I’m at the highest overlook and as I drift to a stop with the motor and lights off I can see the tiny lake towns dotting the shore. I look up as I close the door and in the perfectly clear cold night air I see the Milky Way, stretching from to horizon to horizon, so perfect and full of light that I can’t make out any familiar constellations. My breath catches, and as the noise of the slamming door echoes to silence I look out over the lake and in that split second flashes a falling star so bright that it leaves a white streak punctuated by a final brilliant detonation, etched on my vision. Slowly, the Milky Way returns as the darkness resumes.
There is no sound but the wind and no one there but me, but I am not alone. It’s midnight, on the Schweitzer Road.
For M, and D, and H. Thank you all.

Wednesday, June 13, 2012

Object Model for the Internet of Things

Here’s a first pass at an open source SCADA object model for the Internet of Things
The short story:
  • Devices are of a type, produce one or more Points (e.g. measurement), and are in a location.  These points are collected/pushed into a history on a periodic or demand basis. 
  • Each of these attributes can be virtual/calculated.
  • This model uses my standard lightweight metadata type system to avoid relying on a manufacturer/vendor-based structural standard.
  • It is intended for use with exabyte-quantity data stores
  • Some thought has been given to using IPv6 addresses as Point (and other entity) GUIDs
  • I release this design under the following license:
  • Internet of Things SCADA Schema by Lynne Whitehorn is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
    Creative Commons License

Wednesday, April 25, 2012

Invention of the week: Now, meet then

Augmented reality application for war crimes. Imagine walking through the ruins of Auschwitz, and you find yourself looking mostly at building foundations and fields. Now hold up your phone, or put on your smart specs, and instead of empty streets and fields, you see the camp as it was, in color, filled with people.

Yuck, but it does make the experience more palpable. Since it's an application, you can embody your narrators. Stand in front of a barracks building, and summon a guard to tell you, in your native language, about his job. Now summon a prisoner, and get the actual story.

Of course, this would work for lots of things.  Imagine seeing Bandelier or Mesa Verde through the eyes of an inhabitant.

Experience the stinking, damp, rotting failure of the initial Jamestown colony as you and your fellows die slowly, of starvation and disease.

No need to thank me, I’m just doing my part to make museum-going a vaguely nauseating experience. 

Sunday, April 22, 2012

NetDuino Plus–steerable webcam

Did some practice with the Netduino Plus this weekend, trying to see how hard it would be to make a remotely-steerable webcam.  Answer:  not very hard at all.  Right now I just have it hooked up to a potentiometer on the left.  (The other one was for the other servo, but it turned out I only had a continuous rotation one in the box, so I just have the yaw axis working despite having a a pitch-axis pot on the board.)

The code's pretty simple, too.  See below.  Now I just integrate this as a thread/subroutine with the tiny-webserver code from last week and fabricate a mount for the webcam.  I've found some interesting libraries/modules for the .NET Micro Framework at CodePlex.  Check out:

The webcam itself is a Linksys WVC54GCA, which is a standalone unit with a built-in webserver, so I'll probably wrap a simple steering UI around the URLs available on the camera.


using System;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.NetduinoPlus;
namespace BlinkLED {
    public class Program {
        static OutputPort led = new OutputPort(Pins.GPIO_PIN_D13, false);
        static AnalogInput pot = new AnalogInput(Pins.GPIO_PIN_A0);
        static int SensorValue = 0;
        static int LastSensorValue = SensorValue;
        const int ErrorBand = 50;
        const int PotRange = 1023 - 0;
        //  Parallax Standard Servo range seems to be roughly 2300-400
        const int ServoFullLeft = 2300;
        const int ServoFullRight = 400;
        const int Middle = (ServoFullLeft + ServoFullRight) / 2;
        const int ServoPulseDuration = 20000;
        const int ServoRange = ServoFullLeft - ServoFullRight;
        public static void Main() {
            PWM Servo = new PWM(Pins.GPIO_PIN_D10);
            //            int Position = Middle;
            while (true) {
                //  0 (fastest/full right) - 1024 (slowest/full left)
                SensorValue = pot.Read();
                if (SensorValue > LastSensorValue + ErrorBand || SensorValue < LastSensorValue - ErrorBand) {
                    Debug.Print("Potentiometer-> Last value: " + LastSensorValue.ToString() + "  Current value: " + SensorValue.ToString());
                    float NormalizedValue = ((float) SensorValue / ((float) PotRange / (float) ServoRange)) + ServoFullRight;
                    Debug.Print("Set servo to " + ((int) NormalizedValue).ToString());
                    //                Servo.SetDutyCycle(0);
                    Servo.SetPulse(ServoPulseDuration, (uint) NormalizedValue);
                //  Enable for flashy LED
                //  Don't adjust more than 4x/second
                LastSensorValue = SensorValue;