Going slow

It’s really easy to get out there and give it everything you have.  It’s even rewarded in our culture.  When’s the last time you heard someone say, “Go out there and give it 20%!”?

Fact is, just like you can’t get your car un-stuck from a snowbank by flooring the pedal, you can’t expect success by giving your full effort.  That’s a certain recipe for burnout.  Mind you, if I’m being chased by a ravenous bear, I might go all out until I pass out from exhaustion or until the bear gets me.  But that’s not what I’m on about.  I’m talking about long-term success.

I’ve signed up for a half-marathon in May.  And for the next few months, I’m subscribing to the 80/20 principle when it comes to my training.  This week begins a 15-week structured training plan: 80% of my workouts will be done at low-intensity, and 20% at moderate-to-high intensity.  I’ll be using heart rate as my primary metric to help manage my effort.

Going slow is hard!

Advertisements

I like blogging, but…

…I never seem to take the time to sit down and put my fingers on the keyboard.  It doesn’t help that nobody (except you, and maybe one other person) reads it.  Then again, some have said that blogging isn’t for them; it’s for me.  And particularly when it comes to projects that I’m working on, it’s probably a nice idea to have some kind of record of what I did, so maybe one day when I need to remember how I did that thing, I’ll have some written (and easily searchable!) memory of it.

And there are the things we all talk about this time of year.  Goal setting, resolutions, whatnot.  I’m not a fan of “New Year’s Resolutions”, because I don’t think we should limit ourselves to just one time of the year when we can look back at the past year and make plans for the new one.  At the same time, I usually take some time off work at this time of year, and I do often find myself with thoughts to spare.

2018 was a big year for me.  Some big life changes.  I travelled overseas (i.e., outside North America) for the first time, to Iceland (too bad; the tourists are ruining Iceland).   But there were some things this year I didn’t focus on.  Good thing: I have time, still.  And better yet: In the end, none of this will matter.  But for now, I make plans for 2019 and the years beyond.

Looking into 2019

I’m not going to get into my personal or career stuff here now, but there are three hobby areas that I’d like to rekindle, broadly categorized under Health, Technical, and Creative.  The three sometimes blend into each other, which is nice.

Triathlon, Running and stuff

Triathlon doesn’t show up much in my calendar this year.  When people ask, I usually just say, “I’ve decided I don’t like long course, and I’ll probably do a sprint or two this year.”  For now, the only thing I’ve actually written in ink on the calendar is the BMO Vancouver Half Marathon.  You should do it too.  It’s fun.  I’ve done it a few times, but not recently.

But I’ll be on Zwift.  Look me up and we’ll do loops around the volcano.

Triathlon: I’ll probably do a sprint or two, this year.  We’ll see.

Robots

I build robots in my spare time.  I say robots, but what I really mean is random crap that uses electricity.  But in my usual learn what I can about something, then move on approach, I’m finding myself wanting to pare my list of projects down to some reasonable shortlist.  Right now, I’m putting the finishing touches on a digital photo frame that uses the parts from an old laptop computer.

Photography

I traded in all my camera gear last year, for a much smaller yet equally capable mirrorless number.  It was mostly so I’d have something for my overseas trip in November (and it served me well for that), but since it’s much smaller yet equally capable, I’ll be more apt to lug carry it around.  I’ll be cheering on my friends at Ironman Canada this summer, so watch my Flickr photostream for that.

That reminds me… Flickr is dead.  Or at least it was dead.  Now it’s in critical condition, and I’m hoping that it recovers.  The PR from SmugMug makes me hopeful, but we’ll see.

Is it goal-setting time again?

Taking a two-week vacation is like hitting that “reset” button on my brain.  And it’s really nice to sit back, and take stock of things.  It also opens up that cavern in the back of my mind, and there are some monsters back there.  I won’t get into those, because they’re like Gremlins: I shouldn’t feed them, lest they become stronger and creepier.

I’ve said before that I don’t believe in resolutions; I believe in goals.  But, frankly, no matter what you call them, both fail equally miserably.  I still think there’s value in the process.  Stop, review, think, plan, act; repeat.

So here’s something I’m throwing out there: The most important part of goal-setting is retrospective.  Setting attainable goals is easy, because we keep our ideas tethered on what we know is possible.  A whole realm of possibility is untapped, simply because we’re not looking for it.  Not because we can’t, but because we don’t.  Chances are, it’s the things that didn’t go well that are hiding the opportunities for breakthrough.

The most exciting phrase to hear in science, the one that heralds new discoveries, is not ‘Eureka!’ but ‘That’s funny…’

Isaac Asimov

Sometimes, you just have to suck at something

Tonight, while sweating up a storm, a spark: Sometimes you have to really just suck at something before you can start to get with it.

In the last five years, my life has changed at least as many times.  I set goals and succeeded at a lot of things.  But I fell flat on my face a few times too.  I’ve been injured and sick at times, and I used that as an excuse to stay on the couch.  I let each of my failures dictate how I’d spend the next few months.

For me, that meant wallowing in a sort of self pity.  I felt sorry for myself all the time.  I couldn’t even walk down the street without being reminded of just how much I screwed up on the one thing I believed so much in.

A spark: Maybe it doesn’t have to be that way.  After all:

Success consists of going from failure to failure without loss of enthusiasm.

-Winston Churchill

and

Life is full of setbacks, success is determined by how you handle setbacks.

-A Shopping Bag

Do I need to fail more?  I’ve learned more from my failures over the last few years than I’d ever learned by succeeding at anything.  (Remind me, and maybe one day I’ll get more into that, and how a major setback at work led to a major epiphany…)

So I remember, thinking to myself when I moved to Kits, that there would be “no more excuses”.  Screw that.  Excuses are something that you make for something you don’t want to do.  The real joy is in surrounding yourself with the people that you want to be around, and kicking ass at the things that make your life — and their lives better.

So, this is now.  And that’s really it.  Is it the excitement of something new?  Or is it the spark of nostalgia?  Or does it matter?  It’s a spark.  And it’s my job to share sparks with you.

Moving forward…

My First Raspberry Pi HAT

I’m a bit late in reporting on this, because much of the work happened over the Labour Day weekend, waiting in ferry lineups and such.  I spent too much time poring over datasheets, double- and triple-checking my design, and while I’m still not sure that it’ll work, I’m going ahead with the first revision of my first Raspberry Pi HAT.

My first HAT is intended to be a part of the Office Robot.  But I can see some other potential uses for it, so I tried to make the design a little more flexible.

Designed Features:

  • Mono microphone input
  • 3.7W stereo speaker output
  • SPI peripheral connector, with an interrupt and reset line
  • I2C peripheral connector, with shared interrupt and reset lines
  • 5V power input
  • Power control button

I am confident that the level-shifted peripheral connectors will work properly, as I’ve prototyped both on a breadboard.  It’s the audio stuff I’ve never played with before, that I’m nervous about.  But even if those bits don’t work properly, the HAT will still be a lot cleaner than the breadboard covered in jumper wires.

I’ve got my fingers crossed, but if I have to build Version 2, I’m okay with that, too.

 

Apartment living, and hobbies

It turns out, living in an apartment and trying to manufacture things, can be a bit of a challenge.  I’ve spent the last two days tiptoeing around a plastic painter’s dropsheet, upon which are pieces of trackbed for the Office Train.

I’ve been holding off on doing any further work on the train, since I’m told that a desk shuffle is imminent.  But then I remembered that I made all the pieces so that they’d match the length of the modular cubicle walls.  And as long as I install the flex track, cut to match, the trackbed pieces can be easily moved and adjusted!

But more importantly, I’ll finally get this pile of wood out of my cramped living quarters!

Measuring wheel speed

Each wheel on the robot is paired with a slotted disc, which passes through an optical sensor.  There are 20 slots on each disc, which translates to 20 “on” pulses per rotation.  However, it’s easier for me to count both the “on” and “off” pulse edges, so I’m dealing with 40 pulse edges per each wheel rotation.  I’m going to call these ticks as that’s a lot easier to say.
DSC_9248
But ultimately, I don’t care about ticks.  I do care about speed, though.  So I’m going to start there, and figure out what I need in order to calculate that.

Simply stated:

speed=frac{distance}{time}

or:

speed=frac{1 tick}{timeSinceLastTick}

or, if I throw some averaging in there:

speed=frac{numTicks}{elapsedTime}

I can already see that there’s going to be a problem when the speed approaches zero, as there are no ticks to measure the timings.  So I’m going to start by measuring both the number of ticks that have occurred, and the amount of time that’s passed.  If too much time has passed, I’ll consider the speed to be zero.

// Store up to 10 "tick" (or "no-tick") events
const uint8_t NUM_SAMPLES = 10;

// Keep track of how many of the "tick" or "no-tick" events have happened.
uint8_t _tickCount[NUM_SAMPLES];
volatile uint8_t _totalTicks = 0;

// Keep track of the event timestamps
uint32_t _timings[NUM_SAMPLES];

// Some pointers to the arrays above.
volatile uint8_t _oldestIndex = 0;
volatile uint8_t _newestIndex = NUM_SAMPLES - 1;

When a tick occurs, the system calls an interrupt:

ISR(PCINT1_vect) {
    uint8_t newState = PINC & (_BV(PINC2) | _BV(PINC3));
    uint64_t nowStamp = micros(); // timestamp in µs
    uint8_t changes = newState ^ _encoderState;
    _encoderState = newState;

    if (changes & (_BV(PINC2))) {
        _totalTicks = _totalTicks - _tickCount[_oldestIndex] + 1;
        _tickCount[_oldestIndex] = 1;
        _timings[_oldestIndex] = nowStamp;

        // Move the pointers along, overflowing back to zero if needed.
        _newestIndex = _oldestIndex;
        _oldestIndex++;
        if (_oldestIndex >= NUM_SAMPLES) {
            _oldestIndex = 0;
        }
    }
}

If a tick didn’t happen, we inject a zero into the mix:

// Called when... nothing happened!
void nothingHappened() {
    cli();
    // Overwrite the "oldest" item in the averaging loop, and adjust pointers.
    _totalTicks = _totalTicks - _tickCount[_oldestIndex] + 0;
    _tickCount[_oldestIndex] = 0; // nothing happened!
    _timings[_oldestIndex] = micros();

    _newestIndex = _oldestIndex;
    _oldestIndex++;
    if (_oldestIndexB >= NUM_SAMPLES) {
        _oldestIndexB = 0;
    }
    sei();
}

And finally, in order to calculate the current speed:

double getSpeed() {
    cli(); // Make sure the interrupt doesn't fire while we're in here.
    uint8_t totalTicks = _totalTicks;
    uint64_t oldestTime = _timings[_oldestIndex];
    uint64_t newestTime = _timings[_newestIndex];
    sei(); // Set the interrupts free!

    // To get the time difference, we can't simply subtract,
    // because micros() overflows every 70 minutes or so.
    // Implementation of getTimeDiff is left as an exercise
    // to the reader.
    uint64_t timeDiff = getTimeDiff(oldestTime, newestTime);

    if (totalTicks == 0 || timeDiff == 0 || timeDiff > 10000000) {
        return 0.0;
    } else {
        return (float)((totalTicks - 1) * 1000000) / (float)(timeDiff);
    }
}

There’s a little more to it, but you’ve got the idea.  It’s just a bunch of code that watches how far we’ve gone, another bunch that watches the clock, and at the end of the day, it’s just simple physics:

speed=frac{distance}{time}

Triathlete, Tinkerer