Monthly Archives: March 2010

Three of them

There were, to the best of my recollection, three of them.

I generally try to pay close attention when I’m riding, but this time I got a bit distracted.

There I was, minding my own business, about 18 miles into a beauuuutiful evening ride with the group. I had put on a new chain and sprocket, the bike felt fast, and I was feeling pretty good, too.

We came to a narrow spot, and I saw him. Usually I try to avoid him, sometimes I even get off my bike so that I don’t disturb him, but this time I was, as I said, a bit distracted. And then he jumped out in front of me. Usually that’s not an issue, but then this b*tch threw me off balance so that I found myself face-first with this dude, and I’ll tell you, he may be nice to kids but he was pretty mean to me – he up and whacked me in the face.

It happened fast enough that I didn’t have time to get my hands off the bars. I’m not sure if I clipped before I hit the ground, but it wasn’t more than 30 seconds before I was on my back, my nose bleeding, and my friend Greg telling me that he was calling in an ambulance (really, an aid car). He’s an EMT, so I was lucky to have him there, and he was very subtle in the way he kept his hand sitting on my chest so that I didn’t try to get up. My nose hurt, my lip hurt, and Greg told me that I had a lac (aka “laceration” aka “cut”) on my forehead that was bleeding a lot and a contusion (aka “boo-boo”) on my lip. My nose stopped bleeding and I got as comfortable as one can get lying on cold concrete in biking clothes at 49 degrees (or so). The rest of the group (minus Greg) finished the ride (our usual approach when one of our members is attacked), and the EMTs showed up, proceeded to backboard me, collar me, and load me in the back of their unit for a short trip to Overlake. The whole EMT concept was created in Seattle, and the ones in Bellevue are very good.

Special kudos to Greg at this point for staying at the scene with my bike in the cold and waiting for one of the other ride members to come pick him (and our bikes) up.

I was talking with the EMT in the back about cycling, and he asked me if I was a serious cyclist. I know many people who are more serious than I am (both in the amount of riding I do and the seriousness that I bring to the riding), and many people who are less serious. I settle for telling him I ride about 2400 miles each year, I give him some bike-buying advice (which boils down to “fit is king”), and then we show up at Overlake. If you are having problems staying awake, I recommend getting yourself a backboard, just as comfortable as the aforementioned concrete sidewalk but considerably more portable.

The advantage of taking the aid car is that you get right into the ER, so they take me to a room, and finally I get warmth (from the LPN and the blankets she brought – not much warmth from the nurse). Greg has agreed to pick me up, but the EMT calls my wife who show up about 15 minutes later. I see the ER doc pretty quick, repeat my story, he does a full exam, unhooks me from the backboard and takes off the collar, and says that I don’t need xrays, but he will stitch up the forehead lac and the one I have inside my lip (which is, according to my wife, sticking out approximately as far as my nose (the lip, not the lac)). Nurse compassion comes back in, numbs up my forehead (not really very bad), and the inside of my lip (painful enough to bring tears to my eyes), and the doc comes back and sutures up my forehead (9 stitches or so), and my lip (no idea how many stitches). Greg shows up with his girlfriend, disappointed that he missed the forehead suturing but happy to talk to the doc and watch the lip suturing. Oh, and he tells me that I might have a slight fracture of the nose, and refers me to an otolaryngologist to follow up.

And then it’s sign-out and off to home. There I discover a sore spot (aka “osteo contusion” aka “owwie on me bum”), and then its time for a quick picture and facebook photo (in case people are worrying about me), and off top bed.

Which is, frankly, what many of you already know or suspect. What you don’t know is what happened after…

I was a bit keyed up so I was reading in bed, and my nose started to bleed a bit, but after the application of highly absorbent Kleenex brand facial tissue, it stopped, and I went to sleep. At about 3AM I woke up, and my nose was bleeding pretty hard and didn’t want to stop, so I woke up Kim. With my tiredness (and frankly, lack of calories, since I didn’t eat anything when I got home), I had forgotten the right way to stop a nosebleed. I can tell you that sitting up while your nose is bleeding is decidedly not the right thing to do, since it leads to Vasovagal Syncope.

Vasovagal (named after one of Attila’s sons) means a vascular issue having to do with the vagus nerve, which, among other things, controls your heart rate. And I’m sure you all know what Syncope is, so I won’t bother to define that.

What happens is that, under certain stimuli (and nose bleeding is a common one), you trigger an autonomic reaction in your body, and it lowers your heart rate. And you pass out.  Kim says I passed out twice, but I’m sticking with once because I have no recollection of the time between them. While I was passed out, I exhibited what I think are known as “Clonic limb jerks” (a *killer* name for a band) where I apparently shook my arms and torso back and forth, in a poor recreation of one of the more memorable scenes from 1973’s “The Exorcist”.

I pick up the story to find my wife on the phone with the 911 dispatcher, and soon get to play the home version of the “Bellevue Aid Car” game. At this point I have the other symptoms of vasovagal syncope, cold sweats and nausea, and my nose is still bleeding, though it’s slowing down. The usual questions to determine my mental state, an IV, and they tarp me out of the bed (literally, they slide a tarp under you slide you onto it, and use it to lift you up) – thankfully I can skip the back board – and after a few problems in applied furniture moving, I’m out of the house, into the aid car, and back to Overlake, for visit #2.

They wheel me into one room which really isn’t much larger than the average bathroom, and after they view the bed (“There’s *no* way he’s going to fit in that bed”), I leave and head out to room 21. If you visit Overlake, I definitely recommend asking for it as it is convenient to both the entrance and the CAT scan room.

This time I get an EKG (fine), and a lot of discussion about my heart rate (56 BPM), since under 60 beats is an indication for Brachycardia, which could be more serious. I spend a lot of time telling them what my resting heart rate is these days… And I have both the leftovers of the syncope and the adrenalin afteraffects, which means I get some nice nausea medicine, but even with that I have a choice between shivering and nausea. I also have some pain on my chest right where the Nike logo is on my blue fleece sweatshirt.

Then, it’s off to the CAT scan, where I get to move from the gurney to the scanner, and I figure out what is causing the pain in my chest. A quick 2 minute scan, 2 minutes sitting on the gurney (note to scan tech – you do not take a patient who has syncope, raise the head of their bed, and then go in the other room to process the scan). Back to the room, a switch to a saline IV, and half a bag later the doc comes in and turns me loose. This time I go home and actually get to sleep, and the rest of the night passes uneventfully.

Here’s what I look like right now. The forehead cut – which was caused by a ridge on my clear riding glasses – is luckily up a bit so I don’t have too much of the unibrow effect, and anyway, chicks dig scars.

 

Oh, and the chest feels soooo much like a cracked rib – and I’ve had enough that I have a CrackedRib category on my other blog (well, one of my other blogs). It’s what I call the “type 2” cracked rib – it hurts a fair bit when you breathe but doesn’t really constrain your movement as much as a type 1 cracked rib.

It *might* just be the cartilage between the bones, in which case it will hurt for a couple of weeks, while if it’s a cracked rib it will hurt for 6 weeks. 


Not quite a midlife crisis…

Last spring, I had the pleasure of spending $1200 to replace a set of brake rotors (because you can’t resurface BMW rotors) and the window mechanism on the driver’s side (a design defect in 3-series cars). That, combined with the spousal desire to have a second AWD car led me to sell the BMW in September and start looking for a replacement. I didn’t need to get a replacement right away since we had the car that I got for my daughter – a 1998 Honda Accord – but when she gets her license in May, I’d be stuck driving the Ranger.

After a bit of research, I settled on a not-so-obvious choice – a Subaru Legacy sedan.

Subaru spends a lot of effort marketing the Outback, the Forester, and the WRX. They’ve spent – at least until this year – very little money marketing the Legacy.

This perplexes me. The base legacy is a pretty nice 4 door AWD sedan at a good price. And they also put a slightly detuned version of their WRX turbo engine, making it a bit of a stealth racer. 0-60 under 6 seconds.

So, of course that was the one we wanted. But there was a problem.

We wanted a manual transmission. We wanted the Limited version (leather, heated seats). And, if at all possible, we wanted it in red. After a couple of months looking through auto trader and craigslist, I found one in San Jose at a dealer, but that one fell through. Then I finally found one in Portland, and picked it up about a week ago.

It’s quite the sleeper. Looks like a normal 4-door sedan, flies on the road.250 hp, 250 ft-lbs of torque, intercooled turbocharger. Needs a new stereo to round it out.

Very nice, but according to the rules, it doesn’t count as a midlife crisis because it’s not a 2-door, so I guess I’ll have to look elsewhere…


XBee Landscape lighting project – Software

The software is all written in C using Codevision AVR, a pretty nice C compiler. It has a very nice wizard that lets you say that you are running your chip at 8MHz and then allows you to set (for example) the timer1 refresh rate to by 52000Hz from a pulldown menu rather than knowing that you need to set a specific register to a specific value. It also writes the shell of your interrupt servicing for you. Oh, and it knows what AVR microcontrollers support which features, so it won’t let you configure the chip to do something it can’t.

The only place where it falls down is setting the fuse bits (burned in settings for things like clock speed, whether you use the internal/external clock, and some pin assignments), which it just labels by name. For those I use AVR studio, Atmel’s free development tool. If you want to go this route there is a version of GCC that you can use.

For the base station, all of the important operations are handled in interrupt code – the main loop just loops endlessly.

Timer1 code

The timer code runs at 10Hz. We get there by the following:

The timer rate is set to 31,250Hz. Since I’m looking for 10Hz, I need a base frequency that is evenly divisible by 10. The timer is set so that an interrupt is generated whenever the timer overflows (ie goes from 0xFFFF to 0x0000). We need this to happen every 3125 counts, so we set the initial value to 0xFFFF – 0x0C35 = 0xF3CA. That gives us the heartbeat.

Here’s the code:

interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
        // Reinitialize Timer1 value
    TCNT1H=TCNT1H_VALUE;
    TCNT1L=TCNT1L_VALUE;

        // read the buttons from the remote, and turn on the output channels as necessary.
HandleButtons(); if (timeRemainingTicks > 0) {
// In the last 5 minutes, blink the lights off for 1/10th of a second every minute. if ((timeRemainingTicks % 600 == 0) && (timeRemainingTicks <= 3000)) { PORTB = 0; } else { PORTB = outputState; } timeRemainingTicks--; } else { outputState = 0; PORTB = 0; }

        // every second or if the state is changed, we send out the heartbeat over the serial link.

ticks++; if (outputState != outputStateLast || ticks == 10) { SendOutputState(); outputStateLast = outputState; }
        // every second we blink the led for 1/10th of a second
    if (ticks == 10)
    {
        ticks = 0;
        if (outputState != 0 && timeRemainingTicks > 0)
        {
            STATUS = 1;
        }
    }
    else
    {
        STATUS = 0;
    }  
}

Serial port code

The interrupt handler is simple:

interrupt [USART_RXC] void usart_rx_isr(void)
{
    char status,data;
    status=UCSRA;
    data=UDR;
    if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)
    {
        HandleChar(data);
    };
}

char state = 0;

void HandleChar(char c)
{
    switch (state)
    {
        case 0: // ready;
            if (c == 'S') state = 5;
            break;
            
        case 5: // 'S'
            if (c == '1')
            {
                AllOn();
            }
            else if (c == '0') 
            {
                AllOff();
            }
            state = 0;
            break;
    }
}

HandleChar is an implementation of a finite state machine – it looks for “S0” or “S1” and performs the appropriate action.

Remote Code

The remote uses the same timer approach as the base station.

// Timer1 overflow interrupt service routine
interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
        // Reinitialize Timer1 value
    TCNT1H=0xF3CA >> 8;
    TCNT1L=0xF3CA & 0xff;
// The timeout is set to 20 ticks. If two seconds go by without
// getting a heartbeat from the base station, we turn off the link LED
if (linkDetectedTimeout > 0) { linkDetectedTimeout--; LED_LINK = LED_ON; } else { LED_LINK = LED_OFF; LED_LIGHTS = LED_OFF; currentLightState = 0; }

// Set the light LED based on the current light state if (currentLightState == 1) { LED_LIGHTS = LED_ON; } else { LED_LIGHTS = LED_OFF; }
// If the button is pressed (and it's newly pressed),
// send the appropriate on or off command. if (BUTTON == 0) { if (!buttonPressed) { buttonPressed = 1; if (currentLightState == 1) { SendString("S0"); } else { SendString("S1"); } } } else { buttonPressed = 0; }
// Flash the power LED on for one cycle out of 10 tenths++; if (tenths == 10) { tenths = 0; LED_POWER = LED_ON; } else { LED_POWER = LED_OFF; } }

Serial port

void HandleChar(char c)
{
    putchar(c);
    switch (state)
    {
        case 0: // ready;
            if (c == 'E') state = 3;
            break;
            
        case 3: // "E"   
            if (c == 'G') state = 4;
            else state = 0;
            break;
           
        case 4: // 'EG'
            if (c == '1')
            {
                SetLightState(1);
                LinkDetected();
            }
            else if (c == '0') 
            {
                SetLightState(0);
                LinkDetected();
            }
            state = 0;
            break;
    }
}

Another finite state machine. Whenever it gets “EG0” or “EG1”, it sets the link timeout and the appropriate light state.


XBee Landscape lighting project – Hardware

I’ve finished my landscape lighting project, and thought I’d share how it came out.

I had a few requirements:

  1. I wanted to be able to turn on and off the lights from out where the lights were (some 150′ from the house) so we could have light when we showed up at night.
  2. I wanted the lights to turn off automatically after 2 hours if they were accidentally left turned on.

My first design was pretty simple – I would put pushbuttons out with the lights and do a simple program for an AVR microcontroller to detect the pushbuttons and handle turning on and off the lights. That hit a couple of snags.

The first was a physical one – putting physical pushbuttons out meant that I’d have to run about 700’ of signal wire, build waterproof boxes to hold the pushbuttons, mount them on the trees, etc. That was a fair bit of extra work, and not the fun kind.

The second was a bigger problem. Sensing physical pushbuttons was insufficiently challenging and interesting.

So, a V2 design was born. I had been looking for an excuse to do something with some of xbee radio modems, and I decided to use the xbee pro modems for the project, since they are higher power and longer range. These are really cool devices which, in their default mode, act like a virtual serial cable. You send characters into the modem at one end, and the same characters come out the other end. It will do this at up to 250kbps and a maximum distance of a mile (your mileage may vary. Actual mileage will probably be less). You can do a lot more sophisticated stuff with it (meshes, repeaters, etc.) in the advanced modes as well. The modems also have some built-in analog->digital conversion and digital I/O circuitry built in, but since you need a microcontroller to drive it I don’t see a ton of use for that in most applications (though it might be useful in some pc connected applications).

If you are building something that is xbee-based, I highly recommend getting one of the usb adapter boards like the one from sparkfun. It is really useful to send command from the PC, and you can use putstring to write debugging information back to the PC.

After a fair bit of experimentation, I ended up with the following scheme:

The base station sends out a status heartbeat every 1/10th of a second. It also handles the status led, any button presses on the wired remote, and timekeeping. Separately, it also handles any on/off command that come in over the xbee.

The remote receives the status heartbeat, and uses that to turn on the link led (lighted whenever the status heartbeat is received), and set the light status either on or off based on the current status of the lights.

Time for some pictures. Click on the picture for a bigger version that has the parts identified.

The big black box on the left is the base station. To the right of it is the wired remote, and on the far right is the wireless remote.

I should note that everything here is hand-wired. It’s not what you would call neat, but it is simple to do and functional. The thin wire that you see is 30 gauge wire wrap wire, which is more than enough to carry digital signals. When I’m hooking it to discrete components (caps, resistors, leds, etc.) I use my cheap wire-wrap tool and wrap the wire around 3 or 4 turns, and then solder it. This makes it easy to hook the wire up so it doesn’t come off while I solder it.

We’ll start with base station.

In the upper left is the xbee pro radio modem sitting on top of a sparkfun adapter. The sparkfun adapter gives you easy access to all the pins, but the only reason I used it here was because it does the conversion between the 5v that the attiny is using and the 3v that the xbee wants. I could have done it all at 3v, but I didn’t think about that option until I had already put in my last order for parts in.

Below that is the relay board. It has 4 channels (I added individual channels addressable from the base station). Each channel features a 5V relay that switch the 12VAC that the lights use. I’m not a big fan of relays – for AC either using solid-state relays or triacs is generally simpler, but 12VAC is an odd beast and nobody builds a lot of designs for that, so I went with the relays. The downside of the relays is that they require a fair bit of current – about 200mA each. That will cause a bit of an issue later. Each relay is driven by a dedicated transistor, since there’s no way the ATTiny can push 800mA through it. The transistors are NPN power transistors in TO220 packages, which are a bit more rugged than the small ones in case I needed to dissipate a bit more heat. The relay board is the the least optimal part of the design, since it requires a 5V power supply that can put out a lot of current. A better approach would have been to use relays with 12VAC coils, and then drive the coils with some small triacs – that would have reduced the power supply requirements way down. If I had built that power supply up front and tested it driving 4 relays, I would have found that out, but I drove it from my bench supply instead. At the bottom of the relay board is where the 7805-based power supply lived originally, which worked but put out way too much heat.

To the left of the relay board is the terminal strip to connect the lights, and the 12VAC input at the bottom. This sticks through a slot cut in the side of the box.

To the right of the relay board is the switching power supply. I could have built one myself using the popular lm7525, but to make things simpler I ordered a prebuilt one. There’s a hefty 2200uF capacitor on the input from the board to smooth out the rectified 12V from the full-wave bridge on the relay board, and then a 470uF capacitor to smooth the output of the 7525. That gives me the power I need to drive the relays without too much heat.

Finally, on the right side is a DB9 (aka “old-school serial port”) connector. In my current installation, the base station will live close to the wired switches, but will eventually move to an outbuilding. At that point I can just pull some cat5 wire and add connectors to hook the base to the wired remote. To the right is the wired remote, which couldn’t be simpler – there are 5 pushbuttons and a status led, some wire, and a DB9 connector.

On the far right is the wireless remote.

In the upper left is the power switch. I went with a hardwired switch because the remote will likely rattle around in a glove compartment, and I was worried that any button-press approach would be prone to accidental activation. Below the switch is two AAA batteries, which gives me the 3V that the remote runs on. To the right of that is the xbee pro module, with 4 wires hooked to it – +3V, ground, transmit, and receive. Above that is the on/off pushbutton. Finally, lurking at the top-right is the bottom of the board that holds the attiny2313 – it’s upside down because the status LEDs are underneath the board on one end, and if it was the other way it would be likely to short out.

Here are the assembled remotes:

On the left one, we have the three separate channels on the left, all on/all off on the right, and status at the top. The wireless remote has the pushbutton, on/off switch, and 3 status leds. The top led is power – it is on for 1/10th of a second, off for 9/10ths of a second. The middle led is link status (on =  linked), and the bottom is the light status (on or off, in case you can’t actually see the lights).