Community

I am pretty selfish. I would like to think I can be wholly altruistic, but I cannot remember a deed I did for someone else where I was not rewarded by a general feeling of well-being. Perhaps this is normal and we kid ourselves that true altruism exists because, well, it feels good to believe that. Recently, I realised it is because of this feeling that I volunteer as part of the local developer community.

I have been involved in the Ann Arbor area developer community for just under five years. A couple of colleagues had suggested I attend an Ann Arbor .NET Developer (AADND) meeting, but oddly, a woodworking class is what led me there. In that class, I met fellow developer Steve Meagher, we became friends, and he eventually persuaded me to tag along with him to a .NET meeting. Like many within the developer community, I avoided user groups and other community events for fear of not fitting in or some other perceived discomfort. At that first meeting, I met David Giard as he was the speaker that evening. Meeting David turned out to be a gateway into the wider community and volunteering. At the time, he was the president of the Great Lakes Area .NET group (GANG) and he invited me to attend a meeting there the following week. Just as with Steve at woodworking class, another connection was made and so it was that my adventures in the developer community continued. Through the friends I made attending the local groups, I ventured to far off places like CodeMash and Kalamazoo X. Through the friends I made attending those far off places, I ventured to electronic wonderlands like Twitter, StackOverflow, and my own blog. And eventually, through the encouragement I received from this amazingly supportive community, my family, and my friends, I found the courage to look inward, to seek help for the demons that fostered my low self-esteem, and to grow.

I have volunteered on the board of AADND, as a participant and team leader at Give Camp, and as a speaker at CodeMash; having thoroughly enjoyed every second, I can tell you that volunteering is 100% pure fun.

OK, that is utter bollocks; volunteering is hard. There is no pleasure in finding content for newsletters and slide decks, no joy in the conflicts a team faces when you have less than a day to get a database migrated, no comfort in preparing and rehearsing a talk1. Volunteering is often stressful, sometimes boring, and always built upon a foundation of compromise and sacrifice. If those things were the rewards of volunteering, I cannot imagine anyone who would do it. Every year, Michael Eaton tells a tale of how he declares that this Kalamazoo X will be his last. That it is too much work. Too much worry. Too much sacrifice.

Thankfully, the hard work leads to gratitude: the emotional words of a non-profit director overwhelmed by the generosity of local developers; a room of people applauding at the end of a talk; or a simple "thank you". Regardless of its delivery, seeing or hearing that someone is grateful makes all the effort worthwhile. It feels good. For community volunteers like Michael Eaton it is the gratitude shown by attendees, speakers, and co-organizers that ultimately leads to more events (like just one more Kalamazoo X).

So, next time you enjoy something that someone volunteered to do, show your gratitude. And if the opportunity arises, try volunteering; you have no idea who might be grateful and how good that might feel.

  1. or a last minute Pecha Kucha that your friends then make sure will get heard while you are busy searching for that lost sleep []

CodeMash 2.0.1.5

Happy New Year, everyone! I missed my opportunity to post last week since I was on vacation at the beginning of the year and then at CodeMash immediately afterwards. This year, CareEvolution sponsored two days of NodeBot hacking during the CodeMash precompilers. I did not do a comprehensive survey, but it seemed that everyone had a fun time while learning a little something about building robots programmed using Johnny Five and NodeJS.

Besides walking around and helping people out when facing various problems with their bots, I was master of ceremonies (more commonly known as 'emcee') for the battles at the end of each day. On Thursday afternoon I presented our sponsor session on the culture we have in the CareEvolution workplace. Finally, we also had an open house on Thursday night where attendees could see some of the cool bots that had been created, ask questions, and witness a few exhibition matches.

http://instagram.com/p/xj0RWyAJ6-/

http://instagram.com/p/xhiJcTgJxl/

http://instagram.com/p/xhKBVrgJ5A/

All in all it was a busy and very successful CodeMash for everyone who helped put on all the NodeBots events. If you took part, we would love to hear what you liked or disliked about any of the NodeBots-related sessions at CodeMash this year.

Hackery: Line following bots at CodeMash

NodeBots @ CodeMash

CodeMash 2.0.1.5, the latest installment of the popular community-organised conference is fast approaching. This time, I will be attending with several of my colleagues from CareEvolution, which is sponsoring the NodeBot precompiler sessions. One such colleague and good friend, Brian Genisio (also a co-organiser of the Southeast Michigan JavaScript group more commonly known as SEMjs) has been working night and day for months to prepare for each of the two epic software and hardware hacking events that will be the NodeBot precompilers. Though myself and a few other friends (many of which you can meet in person at CodeMash) have assisted Brian over the last few weeks, the success of this event really is down to his vision and commitment. From creating documentation to submitting Johnny Five pull requests1, ordering components to building kits, Brian's efforts have been considerable; if you join us to hack NodeBots (and you really should), be sure to take a moment and show him your gratitude.

My biggest contribution to the NodeBots preparation was to organize and take part in a hack day at work where Brian, a few colleagues (Brandon Charnesky, Greg Weaver, and Kyle Neumeier), John Chapman (another co-organizer of SEMjs and the NodeBots precompilers), and I could test and finalize kits and components, review and update documentation, and give some of the challenges and components a dry run in the process. Participants at CodeMash will be able to take part in one of two competitions with their NodeBots; a sumo-inspired Battle Bots competition where bots can compete for supremacy in the ring, or a line racing time trial where bots must follow a track in the fastest time2. My main efforts during the hack day were to create a sample line-following bot and provide some example code as a starting point for our precompiler hackers. The examples for both the basic line follower and basic sumo bot, as well as some other examples for specific components, can be found on GitHub in the CodeMash NodeBots Docs repository. Instructions on getting started are available on the official CodeMash NodeBots website.

Healthcare and NodeBots?

CareEvolution logo

Some of you may have been wondering: "why would a healthcare IT company like CareEvolution chose to sponsor an event hacking robots?" If you would like to know more, please come to our vendor session at CodeMash (2 p.m. on Thursday, January 8) where I will be presenting "We're Not All Robots: Hacking NodeBots, Healthcare, and the Workplace".

The Line-Following Hardware

Before hacking the code, I needed to work out how the hardware worked and build my bot. I started out with the IR (infrared) reflectance array component; an array of six IR emitters and corresponding receivers that will be the eye to see the line.

IR array and cable
IR array and cable

In the image above, you can see the front of the array as well as the cable to attach the array to the controller (we are using Arduino Uno clones for the precompilers). Using the pins already attached3, I connected the array to the board.

Rear of array showing attached pins
Rear of array showing attached pins
Wiring diagram of reflectance array connected to the controller
Wiring diagram of reflectance array connected to the controller

In the wiring diagram above, you can see each of the six analog pins on the Arduino going to one of the output pins (labelled 1-6) on the reflectance array4. Pin 13 of the Arduino has been connected to the LED ON pin of the reflectance array, which is used to activate the infrared LED's.

With everything connected, I used the usage code from the Johnny Five documentation to create a quick tester and verify that I was able to receive output from my reflectance array.

var five = require("johnny-five"),
    board = new five.Board();
 
board.on("ready", function() {
  
  var eyes = new five.IR.Reflect.Array({
    emitter: 13,
    pins: ["A0", "A1", "A2", "A3", "A4", "A5"]
  });
 
  eyes.on('line', function(err, lineValue) {
    console.log( "Line Position: ", lineValue);
  });
 
  eyes.enable();
});

After verifying the reflectance array was wired and working, I followed the reference kit build instructions to create a robot chassis on which I could mount the reflectance array.

Reference bot
Reference bot

I then mounted the array at the front, near the wheels, using some padded double-sided tape (the array must be within a quarter of an inch of the line, so a little padding was required). To avoid confusion, the array was oriented so that its left (pin 1, according to the documentation) was also the bot's left (assuming the wheels are the front of the bot).

Reflectance array mounted at the front of the bot. Pin 1 is on the right in this picture (the bot's left).
Reflectance array mounted at the front of the bot. Pin 1 is on the right in this picture (the bot's left).

The Line-Following Software

With the bot constructed, I needed to tell it what to do. My aim was not to create the best line-following bot ever (that is a task that possibly awaits you at CodeMash), I merely wanted to make something that demonstrates the basic concepts.

The first thing that the bot needs to do is to "see". Although we had a little code to check the array worked, we had not actually calibrated the array. Calibration allows us to show the array the extremes that it is to understand, i.e. the materials that represent the existence and non-existence of a line. Thankfully, the Johnny Five driver for the reflectance array makes calibration easy with the calibrateUntil function.

var five = require("johnny-five");
var board = new five.Board();

var stdin = process.stdin;
stdin.setRawMode(true);
stdin.resume();

board.on("ready", function () {
    var eyes = new five.IR.Reflect.Array({
        emitter: 13,
        pins: ["A0", "A1", "A2", "A3", "A4", "A5"]
    });
    
    var calibrating = true;
    
    // Start calibration
    // All sensors need to see the extremes so they can understand what a line is,
    // so move the eyes over the materials that represent lines and not lines during calibration.
    eyes.calibrateUntil(function () { return !calibrating; });
    console.log("Press the spacebar to end calibration...");
    
    stdin.on("keypress", function(chunk, key) {
        if (!key || key.name !== 'space') return;
        
        calibrating = false;
    });

    eyes.on("line", function(err, line) {
        console.log(line);
    });
    
    eyes.enable();
});

In my updated code, I also added keyboard input capture so that the calibration mode could be exited via the space bar. Running this with my bot, I was able to drag a piece of paper with a thick black electrical tape line under the array and calibrate it. After calibration, I could see from the console output that my bot recognised the line and in which direction it had last seen it5.

Next, I needed to be able to move the bot based on the line position. For this, I added some simple wheel commands and thresholds. The code is shown below.

var five = require("johnny-five");
var board = new five.Board();

var stdin = process.stdin;
stdin.setRawMode(true);
stdin.resume();

board.on("ready", function () {
    var wheels = {
        left: new five.Servo({ pin: 9, type: 'continuous' }),
        right: new five.Servo({ pin: 10, type: 'continuous' }),
        stop: function () {
            wheels.left.center();
            wheels.right.center();
        },
        forward: function () {
            wheels.left.ccw();
            wheels.right.cw();
            console.log("goForward");
        },
        pivotLeft: function () {
            wheels.left.center();
            wheels.right.cw();
            console.log("turnLeft");
        },
        pivotRight: function () {
            wheels.left.ccw();
            wheels.right.center();
            console.log("turnRight");
        }
    };
    
    var eyes = new five.IR.Reflect.Array({
        emitter: 13,
        pins: ["A0", "A1", "A2", "A3", "A4", "A5"]
    });
    
    var calibrating = true;
    var running = false;

    wheels.stop();
    
    // Start calibration
    // All sensors need to see the extremes so they can understand what a line is,
    // so move the eyes over the materials that represent lines and not lines during calibration.
    eyes.calibrateUntil(function () { return !calibrating; });
    console.log("Press the spacebar to end calibration and start running...");
    
    stdin.on("keypress", function(chunk, key) {
        if (!key || key.name !== 'space') return;
        
        calibrating = false;
        running = !running;
        
        if (!running) {
            wheels.stop();
            console.log("Stopped running. Press the spacebar to start again...")
        }
    });

    eyes.on("line", function(err, line) {
        if(!running) return;
    
        if (line < 1000) {
            wheels.pivotLeft();
        } else if (line > 4000) {
            wheels.pivotRight();
        } else {
            wheels.forward();
        }
        console.log(line);
    });
    
    eyes.enable();
});

The first thing I added was a wheels object to encapsulate the motor controls. Movement is provided by two continuous servos attached to pins 9 and 10. After defining left and right servos, I created the following methods:

  • forward
    Both servos turning such that they rotate toward the front of the bot
  • pivotLeft
    The left servo rotates in reverse while the right servo rotates forward
  • pivotRight
    The right servo rotates in reverse while the left servo rotates forward
  • stop
    Both servos stop moving

Next, I made sure that stop()  was called on startup to ensure the bot was not wandering around aimlessly. I then updated the space bar handling to act as a toggle that on first use stopped calibration and started the bot on its line following quest, but on subsequent uses merely stopped or started the line following. Finally, I added some thresholds to the line  event handler to determine when the bot should drive forward and when it should pivot in either direction based on the value sent from the array.

And with that, my simple line-following robot was complete. It does a fair job at following a course, but it is in need of fine tuning if it is to win any races. Perhaps you will be up to the task when you take part in the CareEvolution-sponsored NodeBots precompilers at CodeMash 2.0.1.5. If you wish to take part in our hacking extravaganza, you will need to register, so be sure to reserve your spot.

  1. which earned Brian the privilege of becoming a core committer []
  2. of course, you don't have to compete in either; you can just hack []
  3. thanks to the efforts of John Chapman, no one will need to solder pins to the reflectance arrays []
  4. pins 7 and 8 are unused as the reflectance sensors for those pins have been separated from the component []
  5. the `line` event from the array uses 0 to mean the line was last seen to the left and 5001 to mean it was last seen to the right; any value between 1 and 5000 means the line is under the array with the value indicating its position []

Corporate Dogma: Good Intentions, Bad Policies

Recently, a colleague wanted to update our corporate profile on a well-known website for sharing interview experiences; we will call them Brickwindow. When signing up for a free corporate account, he filled out the fields honestly, stating his name, his job title, and checking the box that stated he represented HR, which he does as part of his various duties. 24 hours later (or thereabouts), the response came back saying that Brickwindow were not permitting him to open the account as his job title wasn't HR-related. They would need a C-level employee or member of the HR department to verify his authority (or to open the account themselves).

Here's the issue. Our organization does not have an HR department or traditional C-level employees like CEO, CFO or CTO. Just as we are trusted to make good software engineering decisions, we are trusted to make good decisions in other aspects of the business, including who we hire. There are no managers, no Chief Gubbins Officers, and no HR departments. So, my colleague wrote back to Brickwindow outlining how our company structure just does not fit their rules. He assured them that he is authorized to make HR decisions. Shortly thereafter, they responded reiterating that he could not have the account and asserting that they are committed to the security of their users.

So, I signed up.

I have the same job title as my colleague, but since we can choose our own job titles, I temporarily promoted myself to Assistant to the Director of HR. After submitting my application, I pondered on how they might verify this and quickly updated my LinkedIn profile to state the same title1. About thirty minutes later I had an account. It was that easy. My colleague had just been too honest. As for the commitment to user security, Brickwindow sent me my new user name and password in plain text. Brilliant2. I quickly changed it and then forwarded the account details to my colleague so he could continue with the task he had attempted to do the day before.

I think this tale serves as a great example of how we can get bogged down in process and miss the purpose of an activity altogether. In trying to make sure that no one could just create an account for any old company, Brickwindow made assumptions about its corporate user base that meant they could not adapt when faced with something that did not conform. Not only that, but they were so busy trying to enforce those assumptions, they missed the glaring loopholes. All they managed to achieve was a huge waste of time; theirs and ours. This had been an opportunity for Brickwindow to demonstrate they are forward thinking and adaptable, but instead they made it clear they are stuck in the past with the monolithic corporate structures of C-level employees and middle management. In the end, they failed on three major points: identity, roles, and security. We only persevered because we appreciate the primary service provided by Brickwindow.

So, next time you are faced with a situation that does not fit the script, consider whether the script needs to change before trying to change the situation. These conflicts are an opportunity to impress, not stick to rigid rules that don't even achieve the goals they intend to.

If you have any similar tales of well-intentioned processes gone wrong, or corporate dogma that gets in the way, please post them in the comments.

As for me, I have since demoted myself back to a Senior UX Engineer (a title I had chosen when I found out I would be speaking at CodeMash 2.0.1.4). It turns out HR was just not a good fit for me.

  1. Apologies to anyone who was confused []
  2. sarcasm []

CodeMash 2.0.1.4

Adventure

It is almost nine years since I first set foot in the US. It was through that experience that I rediscovered the joy in challenging myself and embracing change, something I had not so strongly felt since I first started singing in a band. So, while I had faced challenges before as a result of my own decisions, none had been bigger. Even though the opportunity had been provided by someone else, it had been my choice to take it and to see it through1.

It took me a while to settle in to my new home (or even to acknowledge it as home), but I eventually joined the developer community in Ann Arbor and the wider mid-west region. The interaction with other developers has continued to provide challenging opportunities and encourage positive change within my career, as well other aspects of my life. It was through the basic act of attending one local Ann Arbor .NET Developers Group meeting and the people I met there that I learned about CodeMash.

CodeMash

CodeMash v2.0.1.4 logo
 
The CodeMash conference – a community-organized event held annually in Sandusky, Ohio – never fails to provide unique experiences or challenges. My first CodeMash, CodeMash v2.0.1.2 was unique because I had never attended a developer conference before (or any other conference), and CodeMash v2.0.1.3 provided a completely new experience when, after attending a fantastic workshop on public speaking, I went on to win the PechaKucha contest.

This year, I was guaranteed yet another unique experience when I was accepted to be a speaker. I am extremely grateful to friends, mentors and others for their support and encouragement leading up to speaking at CodeMash v2.0.14. It was a wonderful honor that I thoroughly enjoyed, and while it changed my CodeMash experience with the added anxiety of speaking and subsequent release when my session ended, I would definitely do it again if the chance arose.

To those that attended my talk on AngularJS for XAML developers, thank you. I  hope that you found it valuable. If you were there or if you have an interest, you can find my slide deck and code on GitHub (Deck|Code).

I am very grateful to the volunteers that organize and run CodeMash each year, as well as the many friends and mentors that have guided my own CodeMash experiences and the many other experiences within the developer community. Without these people, I would not have had such amazing opportunities, nor would I have learned how important it is to challenge myself and strive for new experiences. It is always uncomfortable to embrace change, but the rewards of doing so are often worth the pain.

To close, I encourage you to challenge yourself this year. Make sure to let me know in the comments below how you will challenge yourself and perhaps we can follow-up at the end of the year.

  1. Of course, there were many times in the weeks between being offered the position and setting foot in the US when I considered changing my mind, including just after the plane doors closed []