The problem
Continuous Integration is great...
If any of you write code for a living, then you'll probably be familiar with Continuous Integration. This is where any code that you check in under source control is automatically checked out on a build server, it's compiled and any tests (you do write unit tests, don't you?) are run. This code is often deployed to a test server for anyone who wants to - such as a QA team - to check it out. Most professional development follows this procedure. If you're really ahead of the game then this may even be deployed automatically to production. To be honest, this (Continuous Deployment) is the holy grail. Everyone wants to get there but very few are brave enough!
... until it gets ignored
This all seems great - and it is. Everyone starts out enthusiastically and code is kept in top condition. If a test fails the usual path is for an email to go out to the person who broke the code or the team that is responsible for it, and someone gets right onto it. Broken code is rare and fixed quickly. However, things can start to slip. You start to get lots of "someone else broke it 5 minutes before me, so they should fix it" or "That test often fails. Run it again and it will probably work". If things get ignored then standard start to slip and the whole point of Continuous Integration breaks down.
We had this problem. As teams gets bigger and the codebase gets bigger and more complicated a lot of people have this problem.
The solution
Now, this is not a new problem. And this is not a new solution either. I didn't create this just for the Animatronics challenge. It was an existing project. However, when tariq.ahmad was asking for submissions I thought it deserved a write-up.
I decided that the solution to this problem would be to make sure we can see that things are going wrong. More importantly, if you know that your boss can also see things are going wrong then you'll make sure it's fixed quick! I'd had my eye on a large Lego mini figure for a while. (Can you have a large mini figure? Isn't that just a figure?) They just looked like they were itching to be repurposed. Specifically, I had my eye on a Darth Vader one. It's original purpose is as a torch. He has two white LEDs in his feet. He has a red LED at the base of his white plastic lightsaber. He has arms and legs that look sort of servo sized.
A build monitor
The idea was to convert little Darth Vader to monitor the builds of our code. If he didn't like what he saw then... well, let's just say you wouldn't want to get on the wrong side of him, would you? I would find a way to connect him up to our Team City build server and make sure everyone knew whether the code was good or bad.
Dremel please, nurse
So a fair bit of surgery was required. His chest contained a compartment for 3 AA batteries and a switch. This was used to control the lights in his feet. Much of the battery compartment was Dremelled away and the now unused button (his chest panel) was glued back in place. This left enough room to hot glue a servo in just the right place to operate his shoulder joint. More Dremelling and careful filing later has the servo horn slotted into the top of his arm. Some pictures probably show it better than I can describe.
Shoulder surgery
{gallery} Darth Vader's shoulder surgery |
---|
Back with battery connectors removed: We're going to make way for a servo |
Battery compartment removed: That should help! |
Front panel trimmed and button glued in place: Anything we don't need is being pared back to make more space |
Front and back panel butchered: Let's hope these aren't worth thousands on eBay one day... |
Servo horn attached to his arm |
...and trimmed to fit: That should let me get a servo in there |
Servo in place!: Enough glue, you think? |
Arm reattached: Ignore the RGB wires for now - that's later |
I'm doing nothing with his legs: I just sort of like the photo |
Before I go any further I should probably test to see if the servo works. Here it is being tested on a poor headless, one-armed Sith Lord.
Saber surgery
So, I know that he can move his arm, but there would be little point without a lightsaber to wield, would there? The toy has a single RED 5mm through-hole LED mounted at the top of the handle and the handle contains a single AAA battery, a small boost converter PCB and a switch. Who wouldn't want a colour changing lightsaber though? Gutting it and fitting an RGB LED was fairly easy. Routing the LED wiring through the handle, his hand, arm and rotating shoulder joint was a bit trickier though. Once again, pictures probably tell the story a little better than words.
{gallery} Adding an RGB LED to his lightsaber |
---|
Fitting the RGB LED: The easy bit |
Drilling a route for the wires: The hole in his hand and the lightsaber handle need to line up |
He's not putting that down again: It was originally removable - but not any more |
His completed arm: Ready to be reattached |
Major surgery finished: The patient is looking a bit off colour though |
Once again, I did a quick test to make sure the LED was working as intended before testing it along with the servo.
Tidying up
So the hard bit is done, but it would be a shame not to tidy things up a bit. You may have noticed he was a bit wobbly in the test video, so he got a nice laser-cut acrylic stand. The MSP430F5529 launchpad used to control him got a 3D printed case too. Popping his cape back on covered up the wiring into his back nicely too.
Making him do something useful
The plan
So, I now have Darth Vader under my control. I deliberately picked a USB capable microcontroller so that I could make some use of all that saber-waving and connect him through to our build server. Oh yeah - in all the fun I've been having I'd forgotten about that bit!
The microcontroller code
So the first part of the code required to make him useful runs on the MSP430F5529 LaunchPad you can see above. I've set this up as a USB CDC serial port that listens for various command to perform a few preset actions. This is a small snippet of the code. (You can see that lot at https://github.com/FredMurphy/Vader if you want.)
if (bCDCDataReceived_event){ // Add bytes in USB buffer to the string cdcReceiveDataInBuffer((BYTE*)pieceOfString, MAX_STR_LENGTH, CDC0_INTFNUM); // Append new piece to the whole strcat(wholeString,pieceOfString); // Echo back the characters received cdcSendDataInBackground((BYTE*)pieceOfString, strlen(pieceOfString),CDC0_INTFNUM,0); // Has the user pressed return yet? if (retInString(wholeString)){ // Compare to string #1, and respond if (!(strcmp(wholeString, "TEST"))) { vaderTest(); } else if(wildcardMatch(wholeString,"POSITION ?")) { parseAndSetServoPosition(wholeString[9]); } else if(wildcardMatch(wholeString,"COLOUR #???")) { parseAndSetColour(wholeString+8); } else if(wildcardMatch(wholeString,"ALL ?#???")) { parseAndSetServoPosition(wholeString[4]); parseAndSetColour(wholeString+6); } else { // Send the response over USB strcpy(outString,"\r\nNo such command!\r\n\r\n"); cdcSendDataInBackground((BYTE*)outString, strlen(outString),CDC0_INTFNUM,0); } } }
Firing up a terminal and typing "COLOUR #F00" or "POSITION 1" is all that's needed to spur him into action. "TEST" performs a nice 10 second routing of cycling colours and movement.
The PC code
Connecting to Team City was a matter of writing a C# service that polled Team City's Rest API looking for broken builds. If a newly broken piece of code is detected, Vader waves his lightsaber around a few time and it turns red. If everything's looking good then it's green. I added blue for "there's a broken build but someone's on the case" and purple for being unable to connect to the build server. This code is fairly specific to my own needs. I also wrote it at work so it's owned by my employer. Hence the fact that I'm not linking to it. It's nothing too interesting anyway. Suffice it to say that it does the job. Vader has a nice perch high up where everyone can see him and broken build are no longer ignored!
Alternative considerations
Of course, using a PC alongside a USB-capable microcontroller isn't the only way I could have tackled this. I thought about a Raspberry Pi. It would even have been possible to stick with C# on the Pi - as that's my colleague's skill set and I wanted it to be a shared project. Unfortunately the Pi doesn't do well with the PWM needed for both the servo and for dimming the LEDs. Not without adding more hardware anyway.
A BeagleBone was a contender for a while. It's quite capable of the PWM duties whether I decided to use the PRUs or not. Unfortunately the office policy was that nothing could be connected to the network unless it was virus scanned by our infrastructure team. Their standard solution wouldn't cover the BeagleBone and the time and expense to change this meant it wasn't going to happen.
Version 2.0?
So, I recently changed jobs. I left Vader with my colleagues as a parting gift. They're quite capable of maintaining and extending the PC side of things. They shouldn't have to touch the MSP430 at all. It just wouldn't have seemed right to uproot him and take him with me.
My new employer seems to have a far more relaxed attitude to these things. The office is no stranger to a Raspberry Pi and although BeagleBones have yet to make an appearance I think they'd be welcome. Once the thing they actually hired me for is a bit more out of the way I may turn my attention to improving their GitLab-based Continuous Integration setup. (It's there but it could be better and doesn't handle notifications.) I already have a couple more Lego figures hanging around. The question is... should it be Superman or Batman? Or do you have a better suggestion?
Top Comments