Saturday, September 25, 2010

Something I'm Proud Of

Engineers are supposed to make things, right? You'll cruise the hobby blogs and read about all these cool projects that light up and/or tweet things - everyone seems to be making something nowadays. I'm not so great in that respect. I really haven't made anything apart from my job. It's a little embarrassing, but I don't really get off my butt unless someone orders me to do something. But then I'm great - I make scripts. PCBs, code, you name it.

Well it turns out that lately I've actually accomplished something - and it all started with a problem. While working on a microcontroller design at work I was readily infuriated by breadboards. You just can't get away from them and you shouldn't try. Everything really out to be breadboarded before it's finalized - otherwise you'll have loads of incorrect PCBs laying around and lots of wasted money. But breadboards are hard to work with: wires pop out, you can't put surface mount components on them, they don't have nice modular connectors and you can't always stick a probe in the holes to see what's going on. So I made something to fix that problem for me.


This little doohicky is a breadboard test point/connector adapter. It has a row of 8 pins that plugs into your breadboard and then connectors for the power bus (there's two different configurations of power busses that i've seen - .1" pitch and .15". It has holes for both). First, it has 8 surface mount LEDs for each of the pins making it very useful for status displays. Second, it has a 2x5 connector that will fit a standard IDC cable plug. I have plans to make an IDC to male pin cable that plugs into it. Third, it has two sets of test points - there are male headers for logic analyzer female plugs to fit onto (along with the obligatory 9th connection - ground) and then there are high profile test points that work great with scope probes. And also for the scope probes there are four high-profile test point ground connections. No more silly jumper wires to the ground bus on the breadboard. All of the test points are isolated from the breadboard by 10K resistors. That way, if you accidentally short two test points together (perhaps one that is connected to ground and another to +5V) you won't break whatever is connected to those pins. If, for instance, you do have the worst case scenario and +5V shorts to ground, you have an equivalent 20K of resistance between them and nothing short circuits - just 2.5mA flows through the connection. Lastly, there is a 1.5A resettable fuse between the breadboard VCC and the VCC on the IDC connector, so if something you accidentally connect the +5V from the IDC connector to ground the fuse will trip and not hurt your power supply on the breadboard.

I plan to sell these at... well, wherever will take them. Sparkfun, Ladyada, etc But not yet. There are several design problems that need to be ironed out. A bit more parts selection, maybe a few more components and this board will be ready to sell. I hope everyone else is as excited as me.

Anyone?

Anyone? Bueller?

Oh well.

Thursday, September 16, 2010

Don't Save Bad Code

As coders we're often asked to do things we don't know how to. Use a new library, use a new microcontroller, try a new compiler. So we start to experiment - make something 'just to see' if you can program your microcontroller or figure out how a library works or do simple socket communication. Then you think 'Wow! That worked! Let's try more things! I'll just start coding everything here in main()....' And then you get eaten by raptors.

You've made a mistake. You weren't thinking about organizing this mess or even making sure it was robust - you were just seeing what you could do. Your main() is 1000 lines and you're not sure what all of this code is supposed to. You didn't comment because it was all so obvious earlier, but now all you know about this line is that if you comment it out the program crashes. Whoa boy.

But still you feel the compulsion to try to work with this mess. You want to massage it, start breaking things off into functions, add a few defines, rename the variables and make it work again. But step back - is this what you're supposed to be doing? After all, you started this to learn the library or a framework and, well, haven't you? Isn't that information tucked in your head by now? Is this code even remotely close to your final product? Could it be? Does it work? Is it well-organized and robust? Didn't you have a real development plan somewhere here? Complete with projections and unit tests? And haven't you learned enough to start on the real work, rather than just trying to save this one .c file out of sentimentality?

You shouldn't try to save old code just because it's already written. Old code has no particular value over newly-written code for several reasons.

First, there is no cost to writing new code in place of old code. When working with physical objects if you make a mistake with a material you have to pay to replace the material. If I were whittling wood and I shaved off a little too much I would try to work with it. But with software we have source control, so if I make a mistake I can revert it or even start over without losing anything. I still have access to the important things: my old code and the knowledge I've gained from writing that code.

Second, new code presents an opportunity for a more correct solution. So you've sat down and written a lot of bad code. You feel like deleting it would mean deleting the progress you've made towards a correct solution. But surely you haven't been asleep this whole time? Your mind has been watching the code you're writing and doing its own work - pondering the patterns behind the madness, taking note of vulnerabilities, seeing patterns that could become functions, etc. You've gained a lot of experience just by doing it wrong and at the very least you have a better idea of what NOT to do once you start over. A fresh start allows for a more pure expression of the solution that can't be shoehorned into your ill-conceived beginning.

Third, you will improve your tests by trying things different ways. If you use a FOR loop then you won't encounter errors that you might if you used a WHILE loop. If you're using dynamic memory allocation instead of static you have more things to worry about. Each new method of solving the problem before you opens up new areas for failure. Will this sub-function I just started using return 0x00 for any reason? Because I return its value without checking it and zero would not work well for a return value. So write a unit test to ensure that the return value is never 0. That's one more level of certainty that you're writing correct code, not just code.

Fourth, writing new code allows you to follow best practices more closely. So after a few hours of hacking together your test program-turned release candidate you decide to see what happens when you run splint on it. Turns out it produces so many warnings that your ego crawls into a hole and hides. What's the right course of action? Fix the warnings one by one until the splint output is clean. What do most people do? Turn off splint and wait for it all to be caught in integration. It's much easier to run splint on a 5-line function than 1000. Starting over gives you the chance to comment, run analysis tools, develop unit tests and format your masterpiece when it's a much more manageable size. This will only help you in the long run by front-loading much of the work that leads to clean, well-running and tested code at integration time.

Whenever you are writing - be it code, a short story, a joke, a play, a manual on annoying your cat remember this: the measure of how well you have written isn't the number of words - it's whether you accomplished what you wanted with those words. Eliminating incorrect code instead of massaging it back to life costs you nothing, lets you write more correct code, expands the range of your unit tests and helps you follow process more closely. So don't save that crufty old code, replace it and move on.

Friday, June 25, 2010

Just How Awesome is Batman?

Unlike my usual practice of the title of the blog post having nothing to do with the content I have posted a relevant title today. And also, there's nothing about electrical engineering or computers or code or controls or math in this post (except insofar as Batman can do any/all of those things awesomely) - just Batman.

Truly, Batman is amazing - he's crazy prepared at all times. (Note: I reference the Justice League cartoon when I'm talking here - haven't done much comics reading). When AMAZO stole Superman's powers, Batman nonchalantly whips out kryptonite from his belt and fends him off - prompting Wonder Woman to ask "You carry kryptonite around with you all the time?" Of course he does - he's the Goddamn Batman. If Supes suddenly went rogue (as opposed to going rouge which involves cross-dressing) then Batman would be on it. His utility belt is like Schroedinger's cat. While the cat is both alive and dead at the same time, his belt does and does not contain every single item in the universe - particularly the one that would be most useful. He's just lucky enough that when he opens a specific compartment the probability waves collapse into the exact item he needs. Or not - he'll just MacGuyver up something from whatever he finds in there. I mean, it might be pocket lint and somehow he'll defuse a nuclear bomb and give everyone ice cream cones (with sprinkles).

It's a well-known fact that Batman has a way to defeat every single Justice League member if they turn evil. But this brings us into the barber paradox of the day: Can Batman defeat himself? The logic of the situation is similar to the barber paradox but instead of shaving it involves death served cold. We start from several assumptions:

1) Batman is always prepared. Always.
2) Batman doesn't want to die
3) Batman has plans to kill every member of the Justice League himself
4) Batman is in the Justice League
5) Batman is the Goddamn Batman

So, some conclusions. From 1 and 2 we surmise that Batman will always have a plan ready to prevent his demise. This only makes sense - who wants to die? And by adding in 5 we can assume that this plan will always work. It always has in the past. In the 80+ years of his comics I don't think he's ever died. I mean, Bane broke his back but he didn't die - he healed up again and went on being Batman. That's about as close as it gets. Maybe in some alternate timeline or something he dies. I hear the Joker got reality-warping powers once somehow and might have killed him but that didn't work out for the Joker because the whole mess was cleaned up by the end of the comic and Batman was alive again. Yes you heard that right - when Batman and reality itself are in conflict Batman wins. That's tough.

From 2 and 3 we surmise that Batman must have a plan to kill himself if he goes rogue and by adding in 1 we can surmise that he's ready to follow it through. It makes sense. I'm sure he's been under mind control or something often enough to want to have a backup plan in case he starts acting all evil. Most likely if he really needed to die he'd just have Supes or WW pummel him to death or slice him in half with heat vision (or lasso him to death somehow - not effective, but kinky and I think he'd like to go like that. Plus he can't lie when the lasso is around him so he'd probably admit it turned him on).

So this gives us two contradictory conclusions: Batman can't be killed and Batman has a plan to kill himself that will succeed. Both of these can't be true. I'll throw out a few examples:

Batman knows that he needs to go down if he turns evil, so he tells Supes to beat him to death under a very specific set of circumstances - maybe some kind of mind control that can only be broken by blending his brain into a milkshake or something. But! We know that Batman really doesn't want to die AND he has a plan to kill Supes. What stops him from just going through with that plan? Not much - he's Batman. So Supes is dead, and then Wonder Woman, Green Lantern - pretty much anyone who gets in his way. That's not a very effective plan. Maybe the ENTIRE Justice League could jump him at once but hell I just thought of that in ten seconds - Batman probably considered that one when he was still in the womb. I'm sure he has a plan for the whole Justice League turning evil at once. In fact I'm sure there's a precedent for that somewhere in comics history. And I'm sure Batman resolved it with ice cream again. So scratch that.

Okay, so maybe Batman can just kill himself. If he was evil he wouldn't consciously want to do it but maybe he implanted some post-hypnotic suggestion triggered by a code word that would force his heart to stop or something. And then he makes himself forget about it somehow and only lets certain people know. People like... Superman again? No, because if he really fears Supes going evil (enough such that he keeps kryptonite on his person) then he's not going to give him a kill switch. And even if he did do that whole hypnotic kill switch thing and forced himself to forget about it what stops him from one day discovering that someone implanted a hypnotic suggestion in his mind somehow and rooting it out? He doesn't know that he put it there - it could have been Grodd or someone else's insurance policy. Just yell 'Steeplejack!' in their next battle and Batman makes tea for him instead of delivering a beatdown. Can't take that chance.

I wouldn't even put it past Batman to install a tiny computer with a tiny AI in his suit somehow prevents him from stabbing himself in the chest, or replacing his heart with a nuclear bomb (the Goddamn Batman needs no capacity to love, or circulate blood. The blood moves on its own because it fears what will happen if it doesn't) that goes off as a last resort and his consciousness transferring through the ether to a clone tank on the moon that he put there and made himself forget about so no one could sabotage it. HE'S FREAKING BATMAN PEOPLE! He put a space station with a fusion laser in orbit a week after Martians attacked Earth. The buses weren't even running but apparently Wayne Enterprises had orbital capacity. Fusion technology didn't even exist! He invented it and then did it and surprised the hell out of the rest of the league and was all like 'Oh you like this space station? Yeah of course I can afford it. I'm the Goddamn Batman. Go to your quarters - the mattresses are stuffed with money and I can flood your rooms with poison gas if you get out of line. I mean, strike that last part. I'm Batman.'

Does anyone have a logical resolution to this mess?

Quick question: In a fight between Batman and Chuck Norris who wins? Answer: No one wins - there are only losers. Specifically, you and everyone you love.

Tuesday, March 9, 2010

New Unoriginal Idea

I don't think that I learn much at my job, but I was surprised the other day to learn something new about microcontrollers. Well, coding in general anyhow. You see, when working with microcontrollers I use a finite state machine to control program execution. No, wait, what does that mean? That's technical gobbledy gook. It means that I have a variable and I define a bunch of different values it can take. When my program starts it goes into INITIALIZE mode and it initializes stuff. Then when its done I usually put it into IDLE where it doesn't do much of anything and usually waits for user input like a button press or something. Then depending on what happens I put it into other modes like DO_STUFF_1 or DO_STUFF_2. Different events can change the mode it's in and that produces different behaviors. The idea is that it will be a nice and orderly flow from one mode to the next and that depending on what mode you're in you won't handle certain inputs, or you'll handle them differently. The goal is predictable behavior.

But microcontrollers are anything but predictable. You see, there's these awful things called interrupts. They are what they sound like - they interrupt your program and do something else. They happen usually when hardware has done something - say a button has been pressed. When that happens, whatever you were doing previously stops and this new code executes. That's not usually so bad, but you almost always want to change the mode you're in based on what happens in that interrupt. Okay, so change the mode. Fine, whatever. I don't care.

Except I obviously do. This might happen:

CODE ALERT! CODE ALERT!

do_special_stuff_for_different(modes)
{
mode1:
easy_command();
easy_command();
---OOOOPS INTERRUPT HAPPENED HERE!----
change_mode_to(mode2)
---INTERRUPT OVER BYE BYE NOW!--------
command_that_checks_mode(); //Oops, doesn't run, wrong mode!
command_that_depends_on_the_above(); //fails, above didnt' run!
...
} //Always close your braces!

You see what happens there. Ideally, you want all the commands for a mode to run regardless of whether the mode changes halfway through.

This can be done. Just use a queue data structure to change the mode. A queue is a list of things. I can put things into the back end and take things out of the front. So when I want the mode to change, I can just put the new value for mode into the queue and then handle it in one and only one place in the program:

is(empty(mode_queue))
{
no:
mode =new_mode_from_the(mode_queue);
yes:
//Do nothing!
}
do_special_stuff_for_different(modes)
{
mode1:
easy_command();
...
}

So you only change the mode before you handle events for that mode, and never while you're handling them. This eliminates confusion for the poor code.

But, my unoriginal idea improves this - I think. Say that you're in MODE1 and you have an interrupt that wants to change the mode to MODE2. Ok, it puts the new mode into the queue and we'll handle it when the time comes. But now, before it can be handled you get another interrupt that tries to change the mode to MODE3. Well, put it in the queue and we'll handle it. When everything is said and done, you have the mode change from MODE1 to MODE2 to MODE3 right after one another. It seems OK, but wait! When we designed the system, we never intended to move from MODE2 to MODE3 because in MODE2, we set things up to get ready for MODE4 which we intend to follow MODE2 directly. But that doesn't happen. When you're in MODE2 you try to put MODE4 on the queue, but it gets in line behind MODE3. And meanwhile, if MODE3 attempts to put MODE5 next, it also fails. So you've got two different things trying to happen in sequence at the same time.

It might work, but it might not. We intended in our design to move right from MODE2 to MODE4 but we didn't do anything to ensure that it actually would. That's where my unoriginal idea comes in. These modes are stored on a microcontroller. That means they're stored with bytes, and bytes are made of bits - eight of them to be precise. Eight bits can store 256 different modes if you encode it that way, or it can store eight if you use something called one-hot encoding. One-hot encoding means that only one bit is ever a '1' at a time - the rest are zeros. Wherever the '1' is determines what the value is.

So, when we want to change modes we don't put the next mode we want to move to into the queue, we XOR the current mode with the next mode and put that into the queue. The XOR operation works on bits and it says if two bits are the same, the outcome is zero. If they're different, the outcome is 1. Since all of our modes are encoded with one-hot encoding, there shouldn't be any same bits. Wherever there was a one in either of the modes' bytes, there will be a one in the resulted XOR'd byte. Using this method we don't only record the next mode we want to go to, but we record the mode the program was in when it wanted to go there. It says 'I want to go from MODE2 to MODE4' instead of 'I want to go to MODE4'. Then, when it comes time to look at the queue and change the mode, we can make a better decision. If the request is 'I want to go from MODE2 to MODE4' but we're in MODE3 right now, it doesn't happen. It goes on to the next request which was 'I want to go from MODE3 to MODE5' and that one happens.

Now, there's an obvious flaw in this: the request to go to MODE4 is lost totally. The upshot is that if I press two buttons at the same time only one thing happens. For buttons that's good enough, but for other inputs it's not. For some inputs what you really mean to say is 'No matter what mode I'm in now, I want to go to MODE8'. How do you do that? Simple, it's.. No, wait, how DO you do that?

Oh, wait, I know how. Assuming you followed all of the above steps, then when you XOR the information in the queue with the current mode you get out a valid new mode and just switch to that. If you don't, then you can assume that you want to perform one of these unequivocal mode changes. You just have to figure out what mode you want to change to. So, in order to handle that, you can do this: instead of putting the XOR'd mode into the queue, just put the next mode you want to go to. When the program attempts to XOR it again with the current mode it WON'T get a valid mode out of it. So, it will XOR the data again with the current mode and if you meant to do one of those unequivocal jumps, it will produce a valid mode from THAT XOR operation. If you didn't mean to do an unequivocal jump, then it will produce an invalid mode. Tada!

Monday, March 8, 2010

Debugging

This post isn't for me. I never have to debug. I follow a strict development process in which all of the documentation I read is perfectly accurate and describes all edge case behavior. I also follow code writing procedures so well that every exception is handled, every input is sanitized completely (even to the point of predicting accurately what the user meant to enter instead of what the user did) and every return value is checked. All reported errors (which are entirely due to... well, not me anyhow) have expository messages bordering on small novels that not only tell you what caused the error but actually fix it themselves in all known copies of the program, including those in the past. Yeah, that's right - my code is so awesome that it goes back in time and fixes itself before you even see an error message.

Well, I doubt you believe that. I'm not sure what to believe anymore - the full truth of the situation is caught somewhere in an unstable time loop that will someday tear reality apart. So in the meantime, I actually debug things. Yes, things that I created. This is because you can never get away from debugging. Because documentation is Just. Plain. Wrong. Because the user put international unicode characters that you didn't even know existed into your text box. Because every library you rely on has bugs and undefined behavior. And it's only worse with circuits: the EM spectrum is effectively infinite. Wavelengths you only see in your nightmares can ruin your life in an instant. It happened with the earliest digital computers - freaking cosmic rays would cause a single bit in memory to be changed and trash your machine state. Yes, the very fabric of nature hates you and wants to give you blue screens.

The best, the very best that you can hope for is that your code or circuit does what you designed it to do. Put all your effort into meeting the spec first - later, after you're almost done debugging and trying to figure out why the slave device won't respond to a perfectly valid message, well, that's when they'll tell you that the specs they gave you were wrong and you have to wipe out some code and start over.

In any case, when all you have is a spec, all you can do is implement it. Let's imagine a scenario that involves both hardware and software. I'll imagine a small embedded sensor that has to relay data to its gateway - probably an AVR based 8-bit microcontroller with firmware that I've made, communicating with a host system over TTL-level serial (8-N-1, 115200 bps) and it collects 0-5V data with the ADC. It uses a packet-based serial communication scheme (START, MSG ID, LENGTH, DATA, END sort of deal) to transmit data every second to the host.

Ideally, you code everything, solder everything, hook up power and communication and it works. Then you go home to your supermodel wife/husband/plaything and sports car and sip scotch while listening to death metal. But the reality is that 99.9999% of the time it won't work. The questions you have to keep asking yourself:

'What might be wrong if it doesn't work?'
'What's the quickest way to test that?'


Before I begin, let me note that I said 'quickest' way to test things. When you think you're done and you're testing your code or hardware the actual system it's meant to interface and work with, then chances are your time is limited. You'll probably be close to delivery of the final product, or you'll have another group that needs to use the actual system to test. In either case, quickest is best - you want to front-load as much of this integration phase as possible into design as possible. Don't ever assume it's going to work and then attempt to throw debug capability into your design after you amazingly find that it doesn't 'just work'.

So, look at the host computer and see what it says. No communication with slave?

'What might be wrong if that doesn't work?'


You should know why specifically it shows that message - in this case let's say that it shows it because it didn't receive an answer to an initialization message. Maybe it's just not getting the message

'What is the quickest way to test that?'

I think the easiest way is to put an LED on my slave device and light it if it finds the message. So we'll create the light and lo and behold it doesn't light.

'What might be wrong if it doesn't light?'

If it doesn't light, then the serial port may not be working correctly.

'What's the quickest way to test that?'


I would create a wrap-around self-test mode. Just loop the TX lines of your slave to RX and send a test message, then light an LED if it receives what it sent out.

'What might be wrong if THAT light doesn't light up?'

At this point, if it can't communicate with itself then it's just not sending anything out (for one reason or another) or what it's sending out is gibberish and can't be read back.

'What's the quickest way to test that?'

Monitor the signal to see if it looks like a legitimate serial transmission. To do that, you'll need test points to hook up your logic analyzer or oscilloscope. So you'll either see a valid waveform, an invalid waveform, or no waveform.

So ask yourself again: 'What might be wrong if I see valid waveform or no waveform?'

If you see a valid or no waveform waveform then it's probably software: the receive or transmit buffer isn't being filled perhaps.

And then: 'What's the quickest way of testing that?'

What *I* would do is use a secondary serial port as a debug terminal so you can view the contents of the RX and TX serial buffers. Then you can see if they're being filled or not, and go on from there.

So look back at all that. Just by considering what might not work we added several things to our system: test points, a wrap-around self-test functionality and a debug terminal. If you have all of those things ready and you've tackled some of the other 'Why might this not work and what can I do to quickly test it?' scenarios then you're poised to quickly find the root of the problems you're seeing in minutes and hours instead of days and weeks. Integration (that is, combining what YOU make with what OTHER people make) is the most difficult part of any project. Specs aren't going to help you because no spec is ever complete enough to define a system. Everyone makes assumptions and doesn't tell anyone and that makes testing a pain. So save yourself some pain and plan ahead. You'll thank yourself later.

Tuesday, March 2, 2010

Wherefore Art Thou Sparkfun?

Did you know there's an angyee.blogspot.com? I think it's in Portuguese and run by a female. It's all pink anyhow, but pink can be manly, so I don't know. It might help if I read Portuguese.

I just read an interesting flame war over on Hackaday about whether Sparkfun is overpriced and, well, dumb. Overpriced is for certain, but that's the name of the game. Everyone who sells you something they bought from someone else will be 'overpriced' in that you don't have the money or storage to buy 1000 of anything and wait for others to buy them from you. You're buying the convenience of getting one and only one of something.

In fact, I just bought some ATMega328 DIP chips from Sparkfun. After the flame war I was feeling guilty about it so I checked DigiKey for their price. It's the same. The exact same. The only difference is that Sparkfun offers less of a volume discount. Their stock counter says they have over a thousand of them, so they got the nice $3.04/unit price and are selling them at $4.30 - just like DigiKey. Yes, they're making money, but why not just buy from DigiKey?

That brings me to the second thing that you get from Sparkfun - an explanation. When you search for ATMega328 on DigiKey you get five different chips in varying packages and a comparison table that's about a half mile long. If you don't know that you want the DIP version you're screwed. Lucky me, I do know.

But this totally avoids a more important point: How do you know you want an ATMega328 at all? Sparkfun spells it out for you: it's the Arduino chip but with more program memory. More is better right? Even if you don't know how much program memory you need, why not have more? Plus they tell you that it will work in place of the chip already in your Arduino but wait, don't change that chip yet! You need the bootloader programmed on there for everything to work properly. DigiKey would not tell you that. Heck, DigiKey will barely make it easy for you to give them money.

That's another thing Sparkfun has going for it: their web design is not straight out of 1995. It has pictures and a shopping cart and colors! Oh, and navigation. DigiKey has an awful Flash version of their print catalog. Yes, they thought it would be good to simulate turning pages on the internet. That hasn't been a good idea since Geocities. Of course, DigiKey started with its paper catalog and must really feel attached to it. I can't fault them for sticking with success, but the idea of even using a 1000 page catalog is... so, so unappealing. And a waste of paper.

So the second point is whether Sparkfun is dumb. And by dumb I mean facile. Childish. Dorky but in a bad way. The issue at hand was creating projects like '5 foot Nintendo controllers'. I must admit that so much of the hobby electronics seems like a big dick waving contest. Who can create the coolest steampunk doo-dad? I don't care. Or this gem recently featured on Hacknmod: 'Twitter Controlled LED IKEA Table using Bluetooth'

Let me just pause a minute to let that sink in.

...

...

Okay. Bluetooth is neat. My Wiimotes are Bluetooth and I think it's great I can hook them up to my computer and read their data. It makes a lot of sense as a Personal Area Network protocol. I like headsets. So I don't dislike Bluetooth. I also think RGB leds are interesting - with Red, Green and Blue we can make all colors! It'd be great for use as a status indicator - red is bad, green is good, orange is warning, etc. I like... coffee tables? I guess. I don't dislike them anyhow.

But I just picture this geek sitting at this table with his friends, itching to show off his new toy that he made. So in the middle of the conversation the whips out his phone and says 'Watch, I'm going to Twitter to my table and change its color! I made this! Hold on. I have to type out the message... almost there... Oh I don't have 3G, this might take a bit... Ok sent! Now it should turn green.. uh. any second... uh.. Maybe I have to reboot the computer... hold on...'

Or you have worse projects like TV-B-Gone. The sole purpose of that invention is to make yourself feel good at others' expense. In a bar? Football game that everyone else is watching too loud? Can't hear you and your friends talk about how counter-culture you are? Whip out your TV-B-Gone and turn off everyone else's entertainment! That TV wasn't doing anything for you!

So a lot of this hobby electronics community consists of everyone trying to outdo this month's steampunk widget or Twitter-using Ardunio-controlled status symbol. You know where it goes from here: What started as an honest effort to educate people, have a good time and share things turns into a contest. I saw it happen with LAN parties. Instead of having fun and laughs people started the biggest hard drive contest, or the most porn contest or the biggest monitor/best system specs contest. My friends and I held LAN parties in high school. Some we charged for. Despite lugging their system across town and PAYING to get in some people just wouldn't play computer games! They'd hang around, look over people's shoulders and slow down peoples computers by transferring porn while they were trying to play Unreal Tournament. It just wasn't worth it after a while and I fear the same thing will happen with this 'community'.

In conclusion: Overpriced - probably for some things, not for others. Do your homework. Facile? Childish? Lacking in true content? A bit. There's still plenty of good stuff over at Sparkfun and their top-selling items are components - not kits. But I worry about everyone else. When blogs just echo each others' postings of Twitter-controlled steampunk widgets instead of producing something... substantive, well, I get concerned.