Grid Beam Workbench

February 26th, 2009 § 4 comments § permalink

Grid Beam is a building technique developed in the 70’s. It is a simple technique which uses perforated square beams, connected by normal furniture bolts. I first learned about the technique from the book How to build with Grid Beam by new society publishers:

how-to-build-with-grid-beam

While the book is more of an history of grid beam, it does have some techniques and discussion on design. I think the technique has huge potential as a reusable building method

In need of a Dirty workbench, I decided to build a ‘stick’ making jig and attempt to build a bench. I was surprised by a few things:

  1. Beam stability is a function of the species, not the holes
  2. Hole accuracy is important, but not a deal breaker – the bolts pull the beams together nicely
  3. It takes about 20 minutes to drill a 6 foot beam – not including finishing touches like chamfer

Here’s my bench:
Bench

Tri-joint

Leg

Why is my home so Drafty?

February 22nd, 2009 § 3 comments § permalink

Couldn’t be the new Windows could it?

Front Door has a 1″ gap:
img_7050

Here’s the thermal:
ir20090213_1727

New Windows:
img_7049

No more gap:
img_7051

Smart home improvement

February 21st, 2009 § 6 comments § permalink

Our home is expensive to heat. Not only is that, but it feels drafty. We were convinced that our main heating problems were the Windows in our family room (where the thermostat is) – all were replaced without any effect.

Annoyed, we needed to find a way to pinpoint our homes problems. We turned to Thermal Imaging by Northwest Infrared to help us understand the problems. I am very impressed and highly recommend their service. I believe this is the single best thing that can be done to your home. It is inexpensive and pinpoints phantom energy loss. Northwest Infrared only does energy evaluation – you’ll get brutally honest information without the sales pitch.

Thermal analysis is a two step process:

  1. Depressurize the home taking accurate barometric measurements to determine how much leakage there is.
  2. Use a thermal imager to see where cold air is leaking into the home.

Common Problems

Attic access not sealed well:
ir20090213_1757

Pipe cutouts are huge openings to the crawl space:
ir20090213_1756

Downdraft vent in the cooktop isn’t sealed or baffled:
ir20090213_1735

Return air vent uses the floor joists instead of being ducted – drawing lots of air from the ‘area between floors’
ir20090213_1734

– And in our case those floor joists are open to the outside!
ir20090213_1729

Check out this ghostly image:
ir20090213_1731

Our Unique Problems

Our new windows weren’t sealed correctly (you can bet we’ll be bringing that up with Anderson Renewable):

ir20090213_1719

Our vents aren’t sealed correctly:
ir20090213_1757

Our worst offender is our heating room which is open to the crawl space. This room is essentially outside, but not insulated like it is an inside closet:
ir20090213_1741

Just a dog

ir20090213_1737

Video

I took some video during the process:

avr-libc realloc ‘fix’

February 11th, 2009 § Comments Off on avr-libc realloc ‘fix’ § permalink

I’ve been working on patterns for Arduino, which relies on a dynamic array for managing event loops, observables, and device abstraction. However, I was blocked by a critical failure in realloc. While I could have worked around it using malloc/free, but wanted to understand what was going on in libc.

One thing that struck me about realloc was the naming conventions; What was the difference between fp1, fp2, cp1, cp2? Some referred to a free block, some referred to a free pointer. I gave up and renamed the variables to something more readable.

The fatal flaw has to do with mixing sizeof(__freelist) and sizeof(size_t). In many cases, the difference results in indexing into the middle of a free list entry, thus corrupting memory.

(compare to avr-libc/libc/stdlib/realloc.c)

void* realloc(void *ptr, size_t newLength)
{
    struct __freelist *currentBlock, *nextBlock, 
        *currentFreeBlock, *previousFreeBlock;
    char *currentPointer, *nextPointer;
    void *memp;
    size_t largestBlockSize, sizeIncrease;
    
    /* Trivial case, required by C standard. */
    if (ptr == 0)
        return Malloc(newLength);
    
    currentPointer = (char *)ptr;
    currentBlock = (struct __freelist *)
         (currentPointer - sizeof(size_t));
    
    nextPointer = (char *)ptr + newLength; /* new next pointer */
    if (nextPointer < currentPointer)
    {
        /* Pointer wrapped across top of RAM, fail. */
        return 0;
    }
    
    nextBlock = (struct __freelist *)(nextPointer - sizeof(size_t));
    
    /*
     * See whether we are growing or shrinking.  When shrinking,
     * we split off a chunk for the released portion, and call
     * free() on it.  Therefore, we can only shrink if the new
     * size is at least sizeof(struct __freelist) smaller than the
     * previous size.
     */
    if (newLength <= currentBlock->sz) 
    {
        /* The first test catches a possible unsigned int
         * rollover condition. */
        if (currentBlock->sz <= sizeof(struct __freelist) ||
            newLength > currentBlock->sz - sizeof(struct __freelist))
        {
            return ptr;
        }
        
        nextBlock->sz = currentBlock->sz - newLength - sizeof(size_t);
        currentBlock->sz = newLength;
        Free(&(nextBlock->nx));
        return ptr;
    }
    
    /*
     * If we get here, we are growing.  First, see whether there
     * is space in the free list on top of our current chunk.
     */
    sizeIncrease = newLength - currentBlock->sz;
    currentPointer = (char *)ptr + currentBlock->sz;
    for (largestBlockSize = 0, previousFreeBlock = 0, 
         currentFreeBlock = __flp; currentFreeBlock; 
         previousFreeBlock = currentFreeBlock, 
             currentFreeBlock = currentFreeBlock->nx) 
    {
        if (currentFreeBlock == nextBlock && 
            currentFreeBlock->sz >= sizeIncrease) 
        {
            /* found something that fits */
            if (sizeIncrease <= currentFreeBlock->sz + sizeof(size_t))
            {
                /* it just fits, so use it entirely */
                currentBlock->sz += 
                    currentFreeBlock->sz + sizeof(size_t);
                if (previousFreeBlock)
                    previousFreeBlock->nx = currentFreeBlock->nx;
                else
                    __flp = currentFreeBlock->nx;
                return ptr;
            }
            
            /* split off a new freelist entry */
            currentPointer = (char *)ptr + newLength;
            nextBlock = (struct __freelist *)
                (currentPointer - sizeof(size_t));
            nextBlock->nx = currentFreeBlock->nx;
            nextBlock->sz = currentFreeBlock->sz -
                 sizeIncrease - sizeof(size_t);
            
            if (previousFreeBlock)
                previousFreeBlock->nx = nextBlock;
            else
                __flp = nextBlock;
            currentBlock->sz = newLength;
            return ptr;
        }
        
        /*
         * Find the largest chunk on the freelist while
         * walking it.
         */
        if (currentFreeBlock->sz > largestBlockSize)
        {
            largestBlockSize = currentFreeBlock->sz;
        }
    }
    /*
     * If we are the topmost chunk in memory, and there was no
     * large enough chunk on the freelist that could be re-used
     * (by a call to malloc() below), quickly extend the
     * allocation area if possible, without need to copy the old
     * data.
     */
    if (__brkval == (char *)ptr + currentBlock->sz && newLength > largestBlockSize) 
    {
        nextPointer = __malloc_heap_end;
        currentPointer = (char *)ptr + newLength;
        if (nextPointer == 0)
        {
            nextPointer = STACK_POINTER() - __malloc_margin;
        }
        
        if (currentPointer < nextPointer) 
        {
            __brkval = currentPointer;
            currentBlock->sz = newLength;
            return ptr;
        }
        
        /* If that failed, we are out of luck. */
        return 0;
    }
    
    /*
     * Call malloc() for a new chunk, then copy over the data, and
     * release the old region.
     */
    if ((memp = Malloc(newLength)) == 0)
        return 0;
    memcpy(memp, ptr, currentBlock->sz);
    Free(ptr);
    return memp;
}

Where am I?

You are currently viewing the archives for February, 2009 at OoeyGUI.