tag:blogger.com,1999:blog-4759722329306337822024-03-13T03:16:09.225-07:00The Angry EEI seek to monetize my anger, thus I have a blog.Stevehttp://www.blogger.com/profile/12436983454045119515noreply@blogger.comBlogger64125tag:blogger.com,1999:blog-475972232930633782.post-6483757045269186322013-05-22T05:32:00.001-07:002013-05-22T05:32:58.235-07:00Serial Communication/Endianness PostI just posted a new article to my Embeddedrelated.com blog about endianness and serial communication. It discusses what endianness is and why it's important to serial communication. It also has a tutorial on transmitting data from a microcontroller to a PC an plotting it using Octave. This is part of the data processing aspect of my stoplight costume. I'm using Octave to develop DSP techniques to process the accelerometer data to determine whether or not the person wearing the costume is in motion - part of this is getting the data out of the microcontroller and on to the PC. That's what the article discusses. When I start documenting the software aspects of the costume I'll write about the actual DSP techniques used to process the data, but for now you can read <a href="http://www.embeddedrelated.com/showarticle/174.php">the article</a>.Stevehttp://www.blogger.com/profile/12436983454045119515noreply@blogger.com0tag:blogger.com,1999:blog-475972232930633782.post-31330804305157290862013-05-05T10:30:00.001-07:002013-05-05T10:30:14.468-07:00Redesign #1Several things about the overall design and approach for my Halloween costume have been bothering me lately:<br />
<h3>
Accelerometer Woes</h3>
The MEMS accelerometer I'm using to detect motion is not well-suited to the task which I'm using it for. I've come to the conclusion that MEMS accelerometers don't so much <i>measure </i>acceleration as they simply <i>register </i>it. Discerning what exactly is happening in the outside world from the output of the accelerometer is a bit of a dicey proposition. Still, I have made significant progress on the issue thanks to an Electronics Stackexchange <a href="http://electronics.stackexchange.com/questions/56623/analyzing-accelerometer-data-characteristics-and-designing-a-filter/57070#57070">post</a> by Olin Lathrop detailing a method to derive meaningful data from the cacophony a MEMS accelerometer produces. Using his approach I've been able to process the data to identify what I will call 'motion events'. It can't tell you how fast you're currently going, but it can pretty well determine if you've started to move from a stand-still. This is all the information I need from the accelerometer. Despite this success, the methods used to process the data will probably introduce significant delay when detecting these events - possibly on the order of 1 or 2 seconds. Still, it <i>is </i>just a Halloween costume so I'm going to try not to feel too bad about this.<br />
<h3>
Power Usage/Battery Life</h3>
The power usage of the board is still pretty poor - it will eat through a 9V battery pretty quickly. A costume isn't going to be impressive if it runs out of juice in a few minutes. To some extent there's just no way around this: LEDs are power-hungry. If I want any significant amount of light they have to draw 10-20mA each. Multiply that by 30 LEDs and that's a lot of power. Of course, they don't have to be that bright all the time. I built PWM into the design so that they could be dimmed when necessary - that's worth a bit of extra power. I will also get some gains my simplifying my power architecture as I mentioned in a <a href="http://angryee.blogspot.com/2013/03/oops.html">previous post</a> and I can also use low-power modes on the microcontroller and modify my design to allow the accelerometer to sleep when it's not used. I'll also be adding a battery monitor circuit so the microcontroller can read the current state of the battery and act accordingly (although I don't know yet what actions it might take). These fixes don't matter nearly as much as the LEDs though, which leads me into my next point...<br />
<h3>
LED Driving</h3>
<div>
My first instinct for driving LEDs was to use a linear approach and control the brightness with PWM. The reason for this was that it was simple and straightforward. It's also not the most efficient approach: a fair amount of power is dissipated in the biasing resistor. That's wasted power - it makes no light. This can be avoided by driving the LEDs with current instead of voltage. The benefit of this approach is that very little power is wasted: most of it is dissipated in the LEDs which is exactly where you want it. For best efficiency a switch-mode current driver should be used. There are many off-the-shelf ICs that can be used for this purpose but to minimize costs and maximize board space you can build your own switcher out of discrete components. In this case, it's worthwhile to use the ULN2803 as the switching element and the microcontroller to generate the PWM. The ULN2803 is designed to switch inductive loads and has most of the protection circuitry necessary. It would be nice to have some sort of current-sensing ability but this difficult to implement and isn't strictly necessary - the current system doesn't use any feedback and it doesn't suffer. A full description of the switching circuit can wait for another day but it's wortwhile to note that this circuit doesn't have to be on the main microcontroller board: most of the components can be located on the LED boards. This allows the microcontroller board to drive LEDs either using a switch-mode current approach or in the current linear approach. I prefer to let the microcontroller board be more versatile, so I think I'll modify the LED boards to use this new approach if it ever comes to it. With only minor changes to the microcontroller board it will be able to support both approaches.</div>
<h3>
Accelerometer Interface</h3>
This has proved more complex than I first imagined. Two main issues:<br />
<br />
<ul>
<li>Because they're not running on the same supply the microcontroller can't directly control the accelerometer pins. This means I can't set its measurement range, run a self-test or put the accelerometer to sleep with the microcontroller: I have to use jumpers instead.</li>
<li>I should have gotten an I2C accelerometer. While analog measurements are fun, they're prone to noise and I have high-currents running around this board (more on that in a second). It is possible to design the board such that the high-current paths and noise are isolated from the accelerometer signal path but if we're optimizing the signal path I vote for making it as short as possible by leaving it entirely inside the accelerometer. You can't get much shorter than that.</li>
</ul>
<h3>
Noise</h3>
<div>
Noise has been a significant problem with this design. The main issue is the high-current path used to drive the LEDs. The first time I tried to drive the LEDs <i>and </i>read the accelerometer I was surprised: the accelerometer data was garbage. The scope showed that there was so much noise on the accelerometer lines that they were worthless. Sure enough, turning off the LEDs made it all go away. After examining my layout I wanted to kick myself even more: the power supply for the microcontroller is drawn from the same trace as the power supply for the LEDs. The noise induced by the high-current PWM switching is not isolated from the microcontroller <i>at all! </i>Part of the reason for this is that the layout is so crowded that I couldn't really do it any other way. Why is the layout so crowded? Two reasons: </div>
<div>
<ol>
<li>It's a single-layer board so it was difficult just to get all the traces going to the right places. </li>
<li>I used through-hole components which are large and bulky. </li>
</ol>
<div>
I've been considering some approaches to minimize the noise but I don't think I will be able to remove it completely. One approach I considered was to filter the PWM coming out of the microcontroller to provide a smooth control voltage to the ULN2803 rather than a jerky square wave. One problem with this is that it will force the ULN2803 to work in linear mode rather than saturation mode - this will dissipate more power inside that IC and subsequently use up the battery quicker. That's not a tradeoff I'm willing to make right now, so I think I'm going to settle for a better layout and adding a large capacitor on the supply pins of the ULN2803. This will have the effect of minimizing the length of the traces that have switched high-currents on them and also separate those traces from more sensitive areas of the board.</div>
</div>
<h4>
Final Word</h4>
<div>
There are thankfully a small number of fixes which can remedy most of the problems I've discussed here:</div>
<div>
<br /></div>
<div>
<ul>
<li>Redesign the board and use all surface-mount components</li>
<li>Replace the voltage-mode accelerometer with an I2C accelerometer</li>
<li>Simplify the power architecture to power the LEDs from the battery directly and use a single switching 3.3V power supply to power the accelerometer and microcontroller</li>
<li>Utilize low-power modes on the microcontroller and accelerometer to save power</li>
<li>Physically separate the 3.3V and 9V portions of the board and place the ULN2803 much closer to the 9V battery. Add a large capacitor on the supply pins of the ULN2803. </li>
<li>Modify the ULN2803 circuitry to support both the current LED driver approach and the switch-mode current driver approach</li>
</ul>
<div>
Looks like I'll have to redesign the board and possibly upgrade to a two-layer, professionally-made board. More on this as I develop it.</div>
</div>
<div>
<br /></div>
Stevehttp://www.blogger.com/profile/12436983454045119515noreply@blogger.com0tag:blogger.com,1999:blog-475972232930633782.post-8979652082546989672013-04-01T18:41:00.001-07:002013-04-01T18:41:31.031-07:00Heartbeat LEDsI've started blogging at Embeddedrelated.com, so go over there and check out my post on <a href="http://www.embeddedrelated.com/showarticle/164.php">Heartbeat LEDs</a>. It's a bit basic but you'd be surprised how often they come in handy and how rarely I see people actually use them.<br />
<br />
Enjoy!Stevehttp://www.blogger.com/profile/12436983454045119515noreply@blogger.com0tag:blogger.com,1999:blog-475972232930633782.post-25625043366206426622013-03-14T15:00:00.000-07:002013-03-14T15:00:00.083-07:00OopsI messed up.<br />
<br />
Oooh it hurts to say that but it's true. I should say it again.<br />
<br />
I messed up.<br />
<br />
Ah, still stings a bit. Maybe it will get better if I explain just <i>how</i> I messed up.<br />
<br />
My last post linked to my overview of design considerations in voltage regulator circuits. In that writeup I staunchly defended the circuit I had designed to power my costume. Here's the block diagram:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://raw.github.com/angryee/light-costume/master/Wiki_Resources/Power%20Layout.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://raw.github.com/angryee/light-costume/master/Wiki_Resources/Power%20Layout.jpg" width="299" /></a></div>
<br />
The general idea is that a 9V battery powers two separate voltage rails (5V and 3.3V) which are generated from linear voltage regulators. The 5V rail powers the microcontroller and LEDs and the 3.3V rail powers the accelerometer. Hopefully some of you will have raised your eyebrows at this point regarding my design and noticed a few things:<br />
<br />
<br />
<ol>
<li>Two voltage rails? That seems like needless complexity. Why not drive the microcontroller from 3.3V?</li>
<li>The microcontroller and accelerometer have different voltage sources. Doesn't that make it difficult to interface them?</li>
<li>You're using linear voltage regulators in a battery-powered application? Don't they waste a lot of power? Isn't that bad for battery life? </li>
<li>Why drive the LEDs from a regulator? Aren't they high current devices? Won't that force you to choose a more capable linear regulator and dissipate a lot more heat through the regulator? </li>
<li>What's that cool graph paper you use? It looks all retro engineering-y!</li>
</ol>
<div>
I pretended I had good answers to these questions. There are two rails because I <i>need</i> the microcontroller to run on 5V because then it can use a 20MHz clock rate. Don't you want that extra performance in case you need it? You know... for the complex maths and large amounts of data this costume will be processing? And no, it isn't a problem to interface the microcontroller and accelerometer because it's an analog accelerometer, so the 3.3V levels it produces can be easily read by the A/D on the microcontroller no problem! Yes, I know I don't get to use the full range of the A/D (0-5V) to read the accelerometer because they're using different operating voltages. I could always connect the A/D reference to 3.3V and get that extra precision back. No, I didn't actually <i>do</i> that and <i>no</i> I can't directly manipulate any of the control lines on the accelerometer to change the measurement range or put it to sleep. I'm sure I'll never need to put it to sleep - this is a battery-powered application! How important could <i>that</i> be?</div>
<div>
<br /></div>
<div>
Linear regulators? They're <i>fine</i>! I've been using them <i>forever!</i> Why change now? My calculations indicate they're 80% efficient in this application! Why add all of those extra components like inductors and zener diodes for a mere 16% more efficiency? Oh, oops. I guess I did my math wrong and the linear regulator is only 55% efficient. But hey, <b>40%</b> more efficiency that... that can't be... worthwhile, right? In a battery-powered application?</div>
<div>
<br /></div>
<div>
But the LEDs - <i>those</i> need to be power from 5V! The green LEDs have a forward voltage of 3V - <b>way</b> too close to the voltage rail to allow me to properly bias them. I think. I didn't really check. Wait, power them directly from the battery and avoid the voltage regulators? I cant... I can't do that... because... because the battery voltage will decay as the battery drains! They LEDs will get less bright as that happens if I drive them directly from the battery! Of course, I am already using PWM to dim them, so as the battery dies I could increase the duty cycle to compensate. But I can't do that because I didn't monitor the battery voltage on the microcontroller via the A/D. Because... because...</div>
<div>
<br /></div>
<div>
Because I'm an idiot. There I said it. It hurts less now. Supposedly, scientists say that sometimes your brain subconsciously makes a decision and then only afterwards you consciously justify it. (I ate that pie. All of it. Because I had low blood sugar. Yeah I did kinda feel grouchy...) That's exactly what happened here. I wanted to start making circuits, soldering things and etching boards so I decided first and thought later. I pulled up an old circuit from my past, used it without thinking and paid the price for it. While testing the board I was always checking the 5V regulator to make sure it wasn't getting hot. I was tearing through 9V batteries during testing too (20 minutes of run-time? That will be an impressive Halloween costume!). I saw all the signs of a poor design but was able to justify them until I actually sat down and started writing an article about the decisions real engineers are supposed to make when designing circuits like this. The article just wasn't coming together - I couldn't make all of the pieces fit. Nothing seemed to make sense. Because it didn't - I hadn't followed my own advice.</div>
<div>
<br /></div>
<div>
At big companies with complex, involved processes for running projects they love to collect Lessons Learned. What did we do wrong on this project? What can we do better in the future? What worked? What didn't? While most processes and 'learning experiences' like this at big companies seem useless and painful, Lessons Learned is one tool that you should utilize everywhere you work. We're all imperfect and we all have a lot to learn. We all need to own up to our mistakes so we can correct them and become better engineers.</div>
<div>
<br /></div>
<div>
This means sharing - a perhaps uncomfortable amount of sharing. Honestly I can't say I'm comfortable admitting my mistake like this. I knew switching regulators existed, I knew microcontrollers could run from 3.3V. But I wasn't basing my design decisions on engineering - I was pretty much basing them on nostalgia (Ah, the LM7805! Reminds me of my childhood!) and inertia. This is a trap that all of us will run in to when we work on projects alone. With no one to watch our back and call us out when we make terrible decisions we will create<i> less awesome</i> stuff. Some of it will be downright embarrassing. All of it we will want to hide.</div>
<div>
<br /></div>
<div>
If we want to be better engineers and make <i>more awesome </i>stuff we're going to have to venture way out of our comfort zone and share our mistakes. Trust me, you haven't seen the last of mine.</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
Stevehttp://www.blogger.com/profile/12436983454045119515noreply@blogger.com0tag:blogger.com,1999:blog-475972232930633782.post-66850963781503757162013-03-10T13:25:00.002-07:002013-03-10T13:25:18.128-07:00Power Supply DesignI've started writing up the design of power supplies in my costume project. When I say 'power supply' I don't mean anything as exotic as designing a linear regulator out of parts or designing a 300KV supply for a Tesla coil but instead a more pedestrian 'which chip do I pick and why?' sort of writeup. There are an absurd number of potential voltage sources out there - more than enough to get confused. The writeup focuses on the criteria you would use to select a voltage regulator and discusses the differences between linear and switching regulators before discussing the reasons for choosing regulator I did. You can read it <a href="https://github.com/angryee/light-costume/wiki/Power-Supply">here</a>.<br />
<br />
<br />Stevehttp://www.blogger.com/profile/12436983454045119515noreply@blogger.com0tag:blogger.com,1999:blog-475972232930633782.post-86380252517278623602013-02-01T15:52:00.000-08:002013-03-12T16:46:31.111-07:00Schematic CaptureI said that the next post I made would be about the LED driver circuit - right? I honestly don't remember and refuse to read my old post. It's like hearing your voice on a tape recorder - or voicemail I guess. Tape recorders don't exist anymore. Anyhow that's not going to happen. You'd think I would have learned by now that every time I say the next post is going to be about something I'm usually wrong. I only do it to build suspense and try to get people to come back and read the next post. Of course, this isn't worth much unless people read my blog to begin with - and unless I <i>write</i> a next post...<br />
<br />
Instead I'm going to briefly discuss schematic capture and the schematic capture tool that I use. Briefly put, schematic capture is the process where you generate a schematic diagram for an electrical circuit. A schematic can serve several functions:<br />
<ul>
<li><b>Informational only</b> - A schematic is informational only if you just need to draw a circuit to show someone. You could do this with a 50K schematic capture tool, Visio or with a pen and paper.</li>
<li><b>Layout</b> - You may want to generate a PCB with your circuit on it at some point. To do this you need a schematic capture tool that can integrate with a layout tool. I'll discuss layout in a later blog post.</li>
<li><b>Simulation</b> - If you should need to determine how much power your amplifier is dissipating by simulating the circuit you'll need a schematic capture tool that interfaces with a circuit simulator like SPICE.</li>
</ul>
<div>
As you might image your choice of a schematic capture tool depends on which of these purposes you want to fulfill. Generally the very expensive Electronic Design Automation (EDA) packages contain all of the above: schematic capture, simulation and layout. You can do anything with them if you can afford them. In case you can't there are many open-source alternatives which also might suit your needs depending on what they are. If you want to start comparing schematic capture tools or even complete EDA suites some of the things you'll want to consider are these:</div>
<div>
<br /></div>
<div>
<ul>
<li><b>Basic Functionality</b> - Your schematic capture tool must be able to support the functionality necessary to do what you want with it. For example, almost every schematic capture tool can be used to generate schematics for informational purposes but even this is not strictly true - some online circuit tools may not offer an export function. To support layout and simulation functionality it must be able to generate a netlist appropriate to the purpose you intend. </li>
<li><b>Compatibility</b> - Following from the above, your schematic capture tool must be able to generate outputs that are compatible with other applications. This may be something as simple as generating a graphic or PDF version of the schematic for publishing and complex as being able to generate a SPICE netlist and stimulus in the proper format for your simulation tool. Ensure you know what types of outputs the other tools in your EDA toolset will accept.</li>
<li><b>Availability of parts/libraries</b> - The more pre-made parts that are made available with the schematic capture tool the quicker your design process will be. If a wide variety of parts are not available you'll have to generate them yourself - this can be tedious to say the least. However take note: not all parts are the same. Some part libraries are only for specific purposes such as simulation. You can't use those parts to generate a netlist for a PCB program. Vice-versa, parts that can be used to generate layouts may have no simulation information associated with them. It is also generally helpful if the parts are popular and freely available from a variety of sources - parts you can't find or are too expensive aren't very worthwhile.</li>
<li><b>Interface/Ease of Use</b> - There are some very awful schematic capture tools out there. I won't name names but when you use one of the bad ones it feels like the keyboard is made of needles. Don't tolerate poor software - there are very likely alternatives.</li>
<li><b>Neat features</b> - There are lots of features which are desirable to make your life easier: Bill of Materials generation is good, Design Rule Checks can help out a lot, integration with source control systems may be worthwhile, etc. While these features are fun and neat this bullet is at the bottom of the list for a reason: compatibility, library support and ease of use are definitely more important.</li>
</ul>
There are many options out there and I've used a few. Here's a few names you might recognize:</div>
<ul>
<li><b>Cadence OrCad/PSPICE</b> - Known by many names, this professional suite of EDA programs that let you design electronics from step 0 to product. It has everything: schematic capture, simulation, layout, a well-stocked component library and a huge price tag. Seriously, it's tens of thousands of dollars. This is only for colleges and businesses. While I used it in college and at some places I've worked I wouldn't use it for my personal projects.</li>
<li><b>Multisim</b> - National Instruments' answer to OrCad. I have very little to say about it. My university tried switching to it in my junior year and it really failed to impress anyone. I assume it's also expensive but I've never bothered to check.</li>
<li><b>gEDA</b> - An open source suite of EDA tools that aims to be <b>the</b> free software EDA toolset. I haven't used this one mostly because it's geared towards Unix/Linux and I use Windows.</li>
<li><b>KiCad</b> - Another open source suite of EDA tools. I just haven't used this one.</li>
<li><b>Eagle</b> - An EDA suite that is something of a standard in Maker circles. Everyone tends to use it or release libraries for it. Do you have a part from Sparkfun or LadyAda? They've released an Eagle library with that part. I also do not use this - mostly because the free version is restricted and it's not open source (although they have opened up their file formats).</li>
</ul>
<div>
If you want to peruse even more open source/free options take a look at <a href="http://www.semiwiki.com/forum/showwiki.php?title=Semi+Wiki:EDA+Open+Source+Tools+Wiki">this page</a> for a listing of many open source EDA tools of all kinds (schematic capture, simulation, layout, VHDL authoring, etc.). I've settled on a suite of tools that works well for me. Eventually I will document all of them but for today I'll focus on my schematic capture software: <a href="http://sourceforge.net/apps/mediawiki/tinycad/index.php?title=TinyCAD">TinyCAD</a>.</div>
<div>
<br />
TinyCAD is a Windows-based open-source schematic capture tool. While it doesn't come as part of a complete EDA toolset it is able to integrate with a wide variety of other EDA tools. It doesn't, for example, allow you to simulate circuits but instead allows you to export a SPICE netlist that any SPICE compatible simulation tool (which is the vast majority of them) can accept and work with. It doesn't have its own layout tool but it can easily export netlists compatible with a wide variety of available layout tools: Protel, Eagle, gEDA and PADS. It can also generate PNG graphics of its schematics for sharing. These options give me the basic functionality and compatibility that I need.<br />
<br />
As far as available libraries go it doesn't have quite the number of libraries and parts that Eagle has and is certainly nowhere close to professional-level tools like OrCAD. I don't view this as a large issue because I've found that no matter how much library support your schematic capture tool claims to have it never has the one part you really need. If you don't get familiar and comfortable with making your own parts and libraries you'll never go very far making things. TinyCAD has a good interface for making new parts and since everything is XML-based I could probably even whip up a script to generate rudimentary schematic symbols from information in the datasheet to save me time. There are also efforts out there to develop better libraries that incorporate more commonly-used parts and integrate with SPICE and layout tools.<br />
<br />
TinyCAD's interface is not fancy and modern but is straightforward and easy to use. The only feature I've never quite gotten the hang of is the busses but I'll learn someday. I've never felt confused or angry (well, any more angry than usual) when using TinyCAD. The workflow lets me quickly capture schematics without issue. You can't give a schematic capture tool a better compliment than that.<br />
<br />
TinyCAD has many neat features that keep me coming back. The open nature of the libraries, parts and schematics means I can create scripts to manipulate all of my design files to automate my work flow. It can export a parts list/bill of materials for a design. It offers a design rule check to make sure you don't connect two outputs and unlike other design rule checks this one has proved useful to me. It allows you to create hierarchical parts - you can create a 5V regulator circuit, save it as a hierarchical part and drop it as a block into any new design you want. TinyCAD is currently under development and not abandoned like some open source proejcts. Despite the fact that development has slowed down there is a bug list and feature request list on Sourceforge that is steadily being worked at. And of course since it is open source you can add in your own efforts at any time. There is also a large busy users' group on Yahoo which can help to answer all of your questions. <br />
<br /></div>
<div>
If you want to be like me and use TinyCAD I've documented the process of installing, downloading libraries, creating libraries, creating your first part and your first circuit. Find it <a href="https://github.com/angryee/light-costume/wiki/TinyCAD">here</a>. The next tool I'll document is the layout tool I use: FreePCB. But before that I'll discuss a few of the circuits I've created for the costume and some of the lessons I've learned in the process.<br />
<br />
Until next time!<br />
<br /></div>
Stevehttp://www.blogger.com/profile/12436983454045119515noreply@blogger.com4tag:blogger.com,1999:blog-475972232930633782.post-33914628149951535972013-01-08T18:45:00.003-08:002013-01-08T18:45:47.702-08:00Github Repo Up!I put all of the costume project files up on Github here: <a href="https://github.com/angryee/light-costume">https://github.com/angryee/light-costume</a><br />
<br />
There's not much explanation there yet but there is a wiki article on Github detailing what most of the files/directories are - see it here: <a href="https://github.com/angryee/light-costume/wiki/Directory-Structure">https://github.com/angryee/light-costume/wiki/Directory-Structure</a><br />
<br />
Take note everyone: open source or open design files by themselves are useless. There's so much information in any given project that at first glance to anyone it's all useless gibberish. Unless you take the time to thoroughly document the files, tools, directory structure, design decisions and other minutiae it really doesn't matter if you release your code into the wild and promise not to sue - if it's not well documented no one can use it or learn from it. It just makes you sick trying to figure it out.<br />
<br />
It makes me sick just looking at it and thinking how much documentation work I have to do. I'm going to bed.Stevehttp://www.blogger.com/profile/12436983454045119515noreply@blogger.com0tag:blogger.com,1999:blog-475972232930633782.post-14715579444939313572012-12-23T10:10:00.001-08:002013-01-29T16:30:13.257-08:00System Design and Parts SelectionA while back I said I was going to create a series of posts detailing how I go about building an electronics project from start to finish. That hasn't happened - until now!<br />
<br />
You see I'm usually pretty lazy on my off hours. And as lazy as I am about actually working on an electronics project in my spare time I'm lazier about writing about it. It turns out that I actually started working on a project months ago and haven't written anything about it despite having designed the electronics, fabricated the board and started developing the firmware. But since I have a good head start on actually making this project I figured I could do some backfill on the writing and show off some of my process.<br />
<br />
Here's the idea (on paper):<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-2tqh2FjlSGk/UNcnTn0E4cI/AAAAAAAABjk/tJI2GtO3JEY/s1600/Custom+Idea.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="http://3.bp.blogspot.com/-2tqh2FjlSGk/UNcnTn0E4cI/AAAAAAAABjk/tJI2GtO3JEY/s320/Custom+Idea.jpg" width="242" /></a></div>
<br />
So I have a shirt with a traffic light on it. The lights are several sets of red, yellow and green LEDs soldered onto a PCB and attached to the inside of the shirt with velcro or sewn on. The traffic light on the front is probably an iron-on applique or a custom shirt if I decide to get expensive. The lights are controlled by an accelerometer: if I sit still the light is red, when I move forward the light turns green and when I stop it turns yellow for three seconds then red again until the process starts over. It's a simple clear idea that makes for an interesting electronics project. <br />
<br />
The first steps in a project like this are to generate a block diagram and general system description so you can start finding suitable parts. That's what I'll discuss today. Here's the system block diagram I came up with:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-mdtq4QqqQwY/UNcpxrwMq4I/AAAAAAAABj0/L-un3JI04HQ/s1600/Costume+Block+Diagram.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="280" src="http://3.bp.blogspot.com/-mdtq4QqqQwY/UNcpxrwMq4I/AAAAAAAABj0/L-un3JI04HQ/s320/Costume+Block+Diagram.jpg" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Let's go over this briefly block by block. The most obvious are the LEDs - I need one set of LEDs in each color of the traffic light. There aren't many requirements for the LEDs. I don't think they'll need to be super bright or require heat sinking. I'm not dealing with any esoteric colors or optical properties - I just need colored light. The only requirement I can think of is that since these LEDs are going to be velcro'd to the inside of a shirt that I will be wearing I'd prefer that there not be metal pins sticking into me. In that spirit they should probably be surface mount LEDs. Since I can't keep my hand steady due to excessive coffee intake I'd like them to be the largest surface mount package I can find. Also I imagine I'll need a fair number of them - 30 or so. Thus, they should be cheap as well. This isn't a tall order for LEDs.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
I usually order my electronics on Digi-Key. Digi-Key is rather... old school. For example, they love their paper catalog. They love it so much that they created an app for their website that actually shows you the pages from their catalog. If you love the paradigm of paper please use this. If you love the Google paradigm then read on for a less-confusing way to use their website.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
When finding anything on Digi-Key you have to know what you're looking for and you have to be very patient. This is how I found the LEDs I would use for this project:</div>
<div class="separator" style="clear: both; text-align: left;">
</div>
<ol>
<li>Go to Digi-Key.com, type 'LED' in search in upper right corner</li>
<li>Browse through the categories until I find one that looks right - Opto-Electronics/Discrete LEDs. If you're looking for something common it's best to select the category that has the most items in it. In this case these should be common LEDs and the Discrete LED category has about 15K items in it. It's a good bet.</li>
<li>Now you have several columns you can use to filter all of the items in this category. Always <i>always </i>filter on 'In-Stock' before you do anything else. 95% of the time if something is not in stock you don't want it anyhow. </li>
<li>Now start filtering on what you know you need. Most of the columns you'll never touch. Dominant wavelength? Lens style? Size? No idea. Surface mount? Yes! Color? Green, yellow or red! Pick the things you know for sure first but select filters one at a time. If you don't you might end up with 0 results and have to work backwards to figure out why. </li>
<li>Guess with the rest. Look at the results - specifically the pictures - and determine roughly what you want, then try to apply filters to remove the other stuff. </li>
<li>Finally, look at price with an eye towards minimum quantities. Typically you won't be buying in such bulk that you get price breaks so look for minimum quantities of 1 and (generally) select the lowest price.</li>
</ol>
<div>
The filters I applied to find my LEDs were (in this order):</div>
<div>
<ul>
<li>Mounting Type: Surface Mount - For the reasons I discussed earlier</li>
<li>Colors: Red, Green and Yellow - This is obvious</li>
<li>Package/Case: 1206 - From experience I know this is the largest and most readily-available surface mount LED package.</li>
<li>Lens Type: Clear - I definitely don't want tinted and I've never liked the look of diffused (think frosted) lenses. Personal choice.</li>
<li>Test Current: 20mA - More current means more brightness. I'd like as much brightness as I can manage without too much work.</li>
<li>Lens Style: Rectangular - Honestly I have little or no idea about this one but the domed top lenses didn't sound like what I want and I didn't like the look of them from the picture, so I stuck with rectangular and flat top. It's worth noting that at this point I have 118 options remaining.</li>
<li>Price: Sort by lowest price with a minimum of 1 piece - If you click the up arrow in the Unit Price column it offers to sort by price with a specified minimum. Always use a minimum of 1 piece.</li>
</ul>
<div>
Now at this point everything's pretty much the same except for color. As long as there's nothing suspicious happening with price (ie, lowest price is $.01/unit but every other manufacturer is at least $.25/unit) you might as well select the lowest priced option. In the end I selected LEDs with a bit more brightness than the cheapest ones. Here are my selections for LEDs:</div>
</div>
<div>
<ul>
<li>Green LED: 754-1440-1-ND</li>
<li>Yellow LED: 754-1144-1-ND</li>
<li>Red LED: 754-1143-1-ND</li>
</ul>
</div>
<div class="separator" style="clear: both; text-align: left;">
The LEDs need something to drive them and there are two main options for driving LEDs: voltage or current. Ultimately LEDs are current-mode devices: the more milliamps you push through them the brighter they get. There are all sorts of methods to get this current through the LEDs in a controlled fashion - here are a few general ideas:</div>
<div class="separator" style="clear: both; text-align: left;">
</div>
<ul>
<li>Use an LM317 as a constant current source</li>
<li>Use a dedicated current-mode LED driver IC</li>
<li>Build a switch-mode current driver from discrete components</li>
<li>Bias the LEDs with a resistor and turn them on and off with a transistor</li>
</ul>
<div>
In the end biasing the LEDs with a resistor and controlling them with a transistor is the best choice for this application because it's the simplest. While it won't give me the most bang for the buck in terms of power expended vs. light produced it has the benefit of being simple and easily controllable compared to the others. I'm not out to prove how clever I am with this project and even if I were I'm not that clever when it comes to analog circuits. You can be as complicated as you want when it comes to controlling LEDs and have control over ever aspect of the system but realistically all this application calls for is to produce some light and wow a few people at Halloween. In that spirit I'm going with the simplest driver I can - a transistor switch. However, this requires a sanity check.</div>
<div>
<br />
Usually the transistor I would select would be an old standby: the 2N2222. I know as a rule of thumb that you get a current gain of 10 with the 2N2222: 10mA base current gives you 100mA collector current when the transistor is saturated. However, if I have about 30 LEDs all drawing 20mA I need to deliver 600mA. That's getting close to the current limit of the 2N2222 and it also means that I need to deliver 60mA base current to switch it. That will be more than a typical microcontroller can source from its pins. For this application I need something with more current gain - in this case a Darlington Array is probably best. A Darlington Array is basically two transistors connected together such that their current gain is multiplied - so instead of a current gain of 10 you have a current gain of 100. Also Darlington Arrays can usually handle more current than a single transistor. </div>
<div>
<br /></div>
<div>
And in fact there's a part that was made for this application: the ULN2803. It's eight separate Darlington transistors in one chip. The only rub is that each Darlington channel is rated for a maximum of 500mA. However, you can double up the channels and get a maximum of 1A. So if each LED color gets two channels that still only uses six of the eight channels. Also, the inputs are biased to allow TTL signals (such as those generated by microcontroller output pins) to be used so I don't have to worry about how much current they're drawing. The ULN2803 can switch the LEDs and I can bias them with resistors to control the brightness. In the end I selected a through-hole DIP version of the ULN2803: Part #497-2356-5-ND</div>
<div>
<br /></div>
<div>
As far as the microcontroller is concerned there are many options. The computation and timing requirements for this application aren't excessive so I won't need anything too esoteric. That still doesn't really narrow it down - there are plenty of good microcontroller options in the hobbyist market. To name a few that I've used: AVR, PSoC, MSP430, PIC and the ARM Cortex-M3. Of course, there's many potential chips in each of those families as well. </div>
<div>
<br /></div>
<div>
Since I don't intend to do anything fancy with the microcontroller so I'm going to use an ATMega328 - the microcontroller that powers the Arduino. The microcontroller is part of Atmel's AVR line of microcontrollers which are a good all-around choice for hobbyists for several reasons:</div>
<div>
<ol>
<li>The development tools are free - AVR Studio can be downloaded from Atmel and has everything you need to write C firmware for both Atmel's 8-bit microcontroller families and the AVR32 family as well. </li>
<li>The programmer is cheap - the Dragon is a full-featured In-System Programmer (and a less-capable debugger) that will program nearly all of Atmel's 8-bit for a cost of $50 (and I already own one)</li>
<li>The chips themselves are cheap and I already have several on hand.</li>
<li>Arduino-compatible so that others can easily reproduce the project if they want.</li>
<li>It has a wide variety of peripherals ready to use.</li>
</ol>
<div>
You can either find them on Digi-Key with this part #: ATMEGA328P-PU-ND or you can get it from Sparkfun with or without the Arduino bootloader pre-programmed. The prices are comparable at either place.</div>
</div>
<div>
<br /></div>
<div>
The accelerometer is a trickier question. I know I'm going to buy it from Sparkfun because they have a good selection of accelerometers with breakout boards. You can't really buy accelerometers in hobbyist-friendly packages like DIP so the breakout board is a necessity. I only really need one axis but I might as well get three so I can use this as a platform for other projects. I could use a serial interface but the ATMega328 has only one serial peripheral, so if I use it for the accelerometer I can't have a serial port for debugging. Given that, I'm going to try to find a three-axis accelerometer with voltage outputs. If you go to their site on the left they have their categories: choose Sensors/Accelerometers/3-Axis. There are about a dozen options. We can immediately ignore the ones that aren't breakout boards. Next, we can ignore the ones that have serial interfaces - that is, either I2C or SPI. That pretty much leaves one option: the MMA7361.</div>
<div>
<br /></div>
<div>
Power is the last issue, but there's a problem. The accelerometer is 3.3V. The ULN2803 prefers 5V. The green LED has a forwad drop of about 3V. The microcontroller could be either 5V or 3.3V. From this, it looks like the LEDs will have to be driven with 5V and the microcontroller will also have to be 5V so it can control the ULN2803. But we need 3.3V for the accelerometer as well. There isn't an easy solution to this: we need both a 5V and a 3.3V source. The 5V source has to be pretty hefty as well - each set of LEDs will draw about 600mA. Only one set should be on at a time - by design and because otherwise it will draw so much power that the battery will die quickly. For that sort of current draw I need another old standby - the LM7805. It can supply up to 1A at 5V and is more than enough to power the LEDs and all of the 5V components. If you search for LM7805 on Digi-Key you get the option of either a Texas Instruments version at $1.66/unit or a Fairchild version at $.66/unit. The difference seems to be that the TI part has no lead in it. I'm going to choose the cheaper version: LM7805CT-ND.</div>
<div>
<br /></div>
<div>
For the 3.3V regulator I just typed '3.3V regulator' into the Digi-Key search and selected the 'Linear-LDO' category. I know this from experience - the 7805, LM317 and other similar voltage regulators I've used are all linear so I stuck with it. After selecting 'In-Stock' I drilled down into the columns this way:</div>
<div>
<ul>
<li>Regulator Topology: Positive Fixed - I don't need adjustable or negative voltages</li>
<li>Voltage Output: 3.3V - That's all I need</li>
<li>Mounting Type: Through-hole - I tend to prefer through-hole</li>
<li>Output Current: 250mA - I need so little current, but in case I want to use this part again in the future I prefer to select a part that can accommodate more applications</li>
</ul>
<div>
That leaves part #497-7246-1-ND as the 3.3V regulator. </div>
</div>
<div>
<br /></div>
<div>
The last major thing I need is some sort of battery. I'd like to not screw around with some combination of AA batteries - they only go up to 1.5V (1.2V for rechargeables) so If I have to generate 5V that means at least 4, possibly more batteries. A 9V battery seems ideal - plenty of voltage overhead. Keep in mind though, 9V batteries tend to have about 500mAH of capacity. That's not a lot of time to run this costume, but it's the tradeoff I have to make to accommodate everything else. It's mostly for novelty anyhow. So I decided I wanted a nice 9V battery holder and not just a couple of wires and a connector. If you search Digi-Key for '9V battery holder' you're presented with the 'Battery holders, clips and contacts' category in which you can drill down the columns thusly:</div>
<div>
<ul>
<li>Battery Cell Size: 9V - Obviously</li>
<li>Number of Cells: 1 - Also obvious</li>
</ul>
At this point there weren't very many results, so I looked through all of the pictures to find this guy: BH9V-PC-ND. It's a through-hole full 9V cell holder. The other options were pretty much just the contacts. This will securely hold the battery and allow me to mount it on the PCB. <br />
<br />
All of the other parts are just miscellaneous: tactile switches, rectangular headers, resistors, capacitors, LEDs, jumpers, etc. All of that I have on-hand and don't have to order. With any luck I don't have to make any other supplemental orders to get more of anything or replace something I broke. When ordering parts make sure to note whether you're close to a price break. I needed about 30-35 LEDs (the number I thought I needed plus extras) and was able to get a slight price break by ordering a few more than I thought I needed. And of course, always always order extras - you WILL break something. I broke plenty of LEDs and perhaps a few microcontrollers during this process. <br />
<br />
Next time I'll talk about capturing/generating the schematics. For now I'll leave you with a bit of a teaser: pictures of the board after assembly.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-li8_uzkjL4I/UNdIQ8YOvPI/AAAAAAAABkM/LddQwRikE04/s1600/2012-10-28+11.51.55.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="191" src="http://4.bp.blogspot.com/-li8_uzkjL4I/UNdIQ8YOvPI/AAAAAAAABkM/LddQwRikE04/s320/2012-10-28+11.51.55.jpg" width="320" /></a></div>
<br /></div>
<br />
<br />Stevehttp://www.blogger.com/profile/12436983454045119515noreply@blogger.com2tag:blogger.com,1999:blog-475972232930633782.post-55039164484768073382012-09-15T11:42:00.001-07:002012-09-15T16:34:10.434-07:00Choosing data structuresI try to write tight, efficient code. This is very important when you're working on a small microcontroller with limitations on speed and memory. However, I also try to write code that is well-organized and safe (ie, preventing buffer overflows, recognizing and handling error conditions, etc.). Let me tell you that these two goals are often at odds: code suddenly becomes much less efficient when you have to constantly check for errors ("Is this passed pointer NULL? Am I outside the bounds of my array? Did I leave the oven on?"). Trying to write well-organized code just makes it worse - to achieve this I usually separate all functionality out into independent functions. Pretty soon you have a class with 18 functions and the call stack for any given publicly-visible function might be five or six calls deep. Say hello to stack overflows!<br />
<br />
It's an eternal struggle with no good solution. And since I don't have a solution, I'll just shut up and go to bed. Good night!<br />
<br />
Just kidding - you can't get me to be quiet so easily. While there is no universal answer to the problems posed above there are application-specific solutions that a good engineer can utilize to improve efficiency, readability and robustness. Choosing the correct data structure for your task gives you improvements on all fronts with no downsides. Let's discuss choosing between a circular buffer and a linked-list based on the application.<br />
<br />
(As always you can look on Wikipedia to find a good basic description of <a href="http://en.wikipedia.org/wiki/Linked_list" target="_blank">Linked Lists</a> and <a href="http://en.wikipedia.org/wiki/Circular_buffer" target="_blank">Circular Buffers</a> to supplement my descriptions).<br />
<br />
A circular buffer is a way to turn a linear array into a circular one. Say you have an array of bytes and it's 32 bytes long. These arrays are linear in that people think about them having a beginning and an end: the beginning is always 0 and the end is always size-1. Typically programmers will use a for loop to iterate over the whole range of the array from the first element to the last or perhaps use an enumeration to access specific elements in the array. Circular buffers are conceptually different in that they have no 'beginning' or 'end' but instead a 'head' and 'tail'. The head and tail can be any position within the array. When the head or tail reaches the last element they wrap around back to the beginning. Elements can be added to the bufer and removed during the course of program execution and the head and tail values change to match. In this way the buffer keeps track of which parts of the array are unread and which can be overwritten. Here's an example:<br />
<br />
I instantiate a circular buffer with room for 32 elements. At the beginning the buffer is empty, so the head and tail pointers both set to element zero. At some point I want to add data to the buffer. Data is always written to the tail and read from the head, so when I add data to the buffer it's written to the current position of the tail (element zero) and then the tail is incremented to now point to element one. I can keep adding data to the buffer and the tail will continue to increment until it's equal to 31. At this point I've added 31 elements to the buffer and read none, so the head pointer is still set to zero but the tail pointer is set to 31. If I incremented the tail pointer again it would be 32 and my array doesn't have 32 elements and that would be a buffer overflow. So instead of just incrementing the tail pointer I have to increment it then wrap it back around to point to the beginning of the array. So (31+1)mod 32 = 0. Doing that would cause the head and the tail to point to the same location. By convention I've decided that if the head pointer and the tail pointer are equal that means the buffer is empty, not full. So I've added 31 elements and I can add no more without disturbing my convention. In order to add more I have to remove some elements. As I said before elements are always read from the head pointer. So in order to remove an element I read the element pointed to by the head pointer and then increment the head pointer. Now the head points to position 1 and I can add another element at which point the tail will be equal to 0. As long as you maintain the state of the head and tail pointers you can reuse the same memory over and over again and hopefully not get too confused. <br />
<br />
Circular buffers are very useful for serial ports. Imagine for example you have a microcontroller and you need to monitor a serial port. You have an RX interrupt that tells you when a byte comes in. You have two options: you can handle the byte in the interrupt (which is not always a good idea depending on the amount of 'handling' you have to do) or you can just add that byte to a circular buffer and return. Then in your main loop you just check to see if there's any data in the circular buffer and handle it there outside of the interrupt context. <br />
<br />
I coded a nice circular buffer library with a focus on robustness and code clarity over efficiency. This meant that I had a function to add a byte, remove a byte, increment pointers, copy multiple bytes, etc. It ended up being a lot of functions and a lot of overhead: every time you wanted to add a byte it would check to see if the buffer was empty (one function call) then add the byte and call another function to increment pointers (two function calls, AH AH AH!). This was probably more function calls than I should have tolerated but the performance was acceptable for its intended application of handling serial traffic. It was so useful that when I needed a packet-based serial scheme I coded it utilizing my circular buffer as a basis: serial data would be pushed into the buffer and the packet communication functions would read the buffer looking for packets. Stacking these two libraries on top of each other caused more function calls and more overhead but it still wasn't unbearable because this arrangement was a pretty good fit for this application.<br />
<br />
But one fateful day I needed to handle TCP and UDP traffic instead of serial traffic. TCP and UDP communication doesn't piddle around with single bytes but instead can transfer hundreds of bytes at a time inside a packet. At the time I foolishly thought that code reuse was a higher priority than efficiency so I implemented the same scheme for TCP and UDP data as I did for serial. That meant that for every packet that came in called a function to copy <i>one byte at a time </i>into a circular buffer. And of course, that function called other functions which called other functions and suddenly my overhead just for copying data to the buffer was rather large. But wait, it gets worse. Even more foolish than copying bytes singly is copying them at all. You see, the TCP/IP stack didn't intend for me to copy that data to another buffer - it passed a pointer to the data and the length of the data and assumed I would work with it in-place without copying. But my circular buffer didn't work that way so instead I had to instantiate a huge circular buffer capable of holding multiple packets (we're talking a thousand bytes or so) and copy data into it one byte at a time at the cost of multiple function calls per byte when it was entirely unnecessary to do any of that!<br />
<br />
As you can see I was a fool. This system was not efficient in any way. It doubled the amount of memory I needed and made many useless function calls. There's no way this system could handle large amounts of data and sure enough my first attempt to handle TCP traffic produced an <i>astounding </i>data rate of<i> </i>8kbps at the application layer. This was over Ethernet by the way. <br />
<br />
I failed to produce efficient code because the data structure I chose was totally unsuited for the task. When I used my circular buffer for the serial port I gained the advantages of robust and safe code with a minimum loss in efficiency. When I tried to apply the same code to a different system I lost a significant amount of efficiency with no increase in robustness or safety. Different situations call for different solutions. What <i>should </i>I have implemented to better handle TCP/IP traffic?<br />
<br />
In this situation a linked list would have been preferable. Linked lists can perform many of the same functions as circular buffers but they arrange the data differently. Imagine a linked list as a bunch of Easter eggs connected by pieces of string. Each Easter egg has yummy candy inside of it. There's a string on one end of the egg that's secured so you can't remove it. On the other end of the egg is a place to tie another piece of string. In this example you're blind so you're doing everything by touch. You need to keep track of all of your eggs and not lose any. The first thing you do is secure one egg to the table and call it your 'head' egg. Unless you misplace the table it's unlikely you'll misplace the head egg. So someone (we'll call him Mr. TCP/IP Stack) hands you another egg and in order not to lose it you tie it to the ball that's secured to the table. When he hands you more, you just follow the string of eggs until you find the last one and tie the new egg there. You can keep adding to the string of eggs this way and be sure you'll never lose any because they're all secured to a single immovable point. At some point another person (Mr. Packet Parser) will ask for the first egg (called egg #1 hereafter) Mr. Stack gave you. Here's how you do it without losing all of your egg:<br />
<br />
<br />
<ol>
<li>Find the head egg </li>
<li>Move down the string of eggs until you find the egg <i>after </i>egg #1(call this egg #2)</li>
<li>Untie egg #2's string from egg #1 and keep ahold of it</li>
<li>Untie egg #1's string from the head egg </li>
<li>Tie egg #2's string to the head egg</li>
<li>Hand off egg #1 to Mr. Parser</li>
</ol>
<br />
As you can see this approach allows you to keep an unlimited number of eggs and give any particular egg away without being worried that you'll lose the others. This is the idea behind a linked list except that the strings holding the eggs together are pointers and the goodies inside the eggs are the payload. The TCP/IP stack would hand me the payload it received, but instead of putting the goodies into an egg I picked them apart one by one and put them in one of those pill boxes where there's a compartment for every day of the month. Thus, Mr. Parser had to open each compartment individually one eat one piece of candy at a time rather than opening the egg and dumping it all into his mouth.<br />
<br />
The difference between the two approaches is striking. With the linked list approach all I would have had to do when I received new data from the TCP/IP stack is to add the payload to the linked list. The performance of the circular buffer approach was dependent on the amount of data received where a linked list doesn't have that restriction. The linked list approach also reduces memory usage: there's no reason to copy all of the data into one large buffer to search through it. With TCP and UDP unless something goes horribly horribly wrong you won't receive half of your data in one packet and half in another - it's all or nothing. This means that you don't have to maintain two large buffers - just one. In addition with the linked list there's no overhead in maintaining the state of the circular buffer. This means fewer function calls compared to the circular buffer. For this application, using a linked list is superior to the circular buffer because it reduces memory usage, scales better and has lower overhead. <br />
<br />
But wait! I don't want your takeaway from this post to be that the linked list is superior to the circular buffer in an absolute sense. That's not true at all - the takeaway from this post should be that you have to choose your data structure to suit your application. Let's take a backwards look at this and see what would happen if we used the linked list in place of the circular buffer for the application of receiving serial data.<br />
<br />
You see, the circular buffer was fine for the serial application because it was designed to handle data that came in singly. All it had to do to add data was stick the new byte into the array at the location of the tail pointer and then increment that pointer. Incrementing the pointer is the hardest part and even that was fairly simple. The linked list is different. To add something to the end of the linked list first you have to <i>find </i>the end. This means starting at the head and working your way down until you find an egg that doesn't have another one tied to it. And you have to do this <i>every time </i>you want to find the end. In this serial application data comes in one byte at a time. That means each egg only contains one jelly bean. The efficiency of the linked list was due to the fact that you could put a lot of jelly beans in each egg. But if you're artificially limited as to the number of jelly beans you can put in each egg suddenly a linked list isn't very efficient. As the list gets larger you have to search longer and longer to find the end of the chain. And that list gets larger and larger with every byte that comes in. Not every ten bytes or every 100 bytes - every single byte. That gets very inefficient very quick. <br />
<br />
You can see that simply by choosing the correct data structure for your application you can improve performance without sacrificing robustness, stability or readability. By choosing your data structures wisely you can have your cake and eat it too!<br />
<br />
<br />Stevehttp://www.blogger.com/profile/12436983454045119515noreply@blogger.com1tag:blogger.com,1999:blog-475972232930633782.post-67953328357068157972012-08-30T12:38:00.001-07:002012-08-30T12:38:24.314-07:00C Gotchas - The Next GenerationI just got burned by this one. Here's the code:<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: Courier New, Courier, monospace;">modulus = a + (TRUE == display_warning_message)?1:0 + num_faults;</span></blockquote>
<br />
Let's say a is 1, display_warning_message is TRUE and num_faults is 16. What is modulus?<br />
<br />
If you said 18, you're wrong, it's 2.<br />
<br />
Let's try again. Same code, but a is 2, display_warning_message is TRUE and num_faults is 12. What's modulus? <br />
<br />
If you said 15, you're wrong - it's 3. <br />
<br />
But why? <br />
<br />
Because parenthesis man, parenthesis. Here's what C sees:<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: Courier New, Courier, monospace;">modulus = a + (TRUE == display_warning_message)?1:(0+num_faults);</span></blockquote>
<br />
Here's what you wanted:<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: Courier New, Courier, monospace;">modulus = a + ((TRUE == display_warning_message)?1:0) + num_faults;</span></blockquote>
<br />
You see, the C compiler follows the 'biggest chunk' rule for evaluating expressions: if there's ambiguity about what expressions get put together it grabs as large of a chunk of code as it can. This is the prototypical example:<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: Courier New, Courier, monospace;">c = a+++b;</span></blockquote>
How does the C compiler see this? Is it:<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: Courier New, Courier, monospace;">c = a + (++b);</span></blockquote>
<br />
Or:<br />
<br />
<blockquote class="tr_bq">
<span style="font-family: Courier New, Courier, monospace;"> c = (a++) + b;</span></blockquote>
<br />
The answer is to work left to right and apply the biggest chunk rule. The 'c=' is not ambiguous, so we don't need to worry about it. The next ambiguous part is the 'a+++b'. So, starting at the left, the biggest valid chunk of code we can pick is a++ - post increment on a. That means the second interpretation of the code is correct.<br />
<br />
But you should never have to learn the biggest chunk rule. Instead, just use parenthesis to de-ambiguate your code. Parenthesis always win in Order of Operations Paper/Rock/Scissors - this makes it a very boring game. Stevehttp://www.blogger.com/profile/12436983454045119515noreply@blogger.com2tag:blogger.com,1999:blog-475972232930633782.post-85810214279602663762012-06-10T14:34:00.001-07:002012-06-10T14:34:44.244-07:00A Suckers' GameYesterday I ordered five of my hookah widgets - prototype run. I plan to distribute them to my friends and family who smoke hookah and get some feedback. They may be entirely worthless, but like a overly-optimistic parent I'm going to choose to believe that my baby will somehow change the world for the better. <br />
<br />
Everything else aside - even if my widget absolutely ruins hookah smoking and I get run out of town I'm excited about having made something. Just seeing a physical objects manufactured to my specifications is worth every penny of the cost of the prototype run in my opinion. I will be more excited if it's useful to me and tickled pink if it's useful to anyone else. If it goes that well then a Kickstarter effort wouldn't be out of the question in my opinion. And that gets me thinking - am I going to get rich off of this?<br />
<br />
Please?<br />
<br />
Pretty please?<br />
<br />
We can all dream can't we? And I'm told that America is the place to make your dreams come true. With enough skill, tenacity, gumption and luck you too can live the American dream - the dream of living in a giant treehouse with a helicopter pad and an upside-down pool and complaining about people poorer than you. And I aim big - I want to complain about Mitt Romney. Come on Mitt! Your pool is rightside-up and it's lowering my property values because it's not awesome enough! Do I have to sue you?<br />
<br />
So how rich could this make me? Well I know a few things about business and I think that the more units I sell the more money I make. But I'm only one lazy person - the more widgets, the more I have to do. I'd rather get it over with quickly and ship my product than to draw it out months because I got greedy and tried to ship 1000 units. Plus, I've seen Kickstarter projects that were too successful - 10x the profit sounds good, but trying to handle that many orders without the trappings of a real business (returns department, quality control, lawyer, etc) while keeping customers happy turns out badly. With those things in mind, I decided to limit myself to 100 units only for a first run. I am considering a possible stretch goal of 250 though. <br />
<br />
Now the second thing I know about business is that I only make money on each unit if I sell it for more than I paid for it. Thus the next question I have to answer - how much does each unit cost? To answer this question I created a <a href="https://docs.google.com/spreadsheet/ccc?key=0AtoD08IjPwMSdF96UUoyT29LeFB3YUl6VWhEOVM5RXc" target="_blank">spr<span id="goog_2112019420"></span><span id="goog_2112019421"></span>eadsheet</a> that has all of the costs I could think of. Let's go over the per-unit costs before anything. The per-unit cost is the cost for each unit sold assuming a certain number are sold. My assumption is going to be that I will sell and ship 100 units as my Kickstarter goal. Kickstarter won't fund me if I don't make this goal, so I don't have to worry that it's about whether I'll make it.<br />
<br />
The first and most obvious cost is the cost of getting a manufactured unit shipped to me. Since I plan to go through eMachineShop.com I don't have to worry about separate costs for material and machining - they handle it all and ship it to me. That gives me one cost for each manufactured unit. I got several quotes from them and created a lookup table which you can see at row 12. This gives the ability to change the size of my production run and still get good numbers without guessing. The next cost is the cost to hard anodize each unit. I found a local place that gives me a significantly better deal on hard anodizing than eMachineShop.com did, so I'm going to receive delivery of the manufactured items from eMachineShop.com and then transport them to the local place to get anodized. That saves money. Next cost is shipping - this is easy if you want to ignore international shipping. Through USPS.com I just did a postage calculation knowing the weight and size of the item. It turns out to be fairly inexpensive. International shipping however is a whole different game that I don't want to get into right now. The next two costs get more complicated, so they get their own paragraphs.<br />
<br />
You might think it's odd that I'm counting labor as a cost. Do I plan on hiring someone? No, not in the least - I'll do it all myself. But since it's my business why pay myself? It's a good question. Not paying myself might seem like saving money but practically it's not. As the owner I can re-capitalize (read: give more money to) my business any time I want. So even if I pay that money to myself I can just give it right back if I feel like it (with the only downside being any potential tax costs). And in any case if this gets successful enough there will be a lot of orders and that means a lot of work. I may want to hire someone sooner than I thought, so it's good practice to start accounting for labor costs early. That being said it's not as if my labor is magically free. It's only free if you ignore my health, time with my family, friends and sanity. Plus if I don't pay myself now it will make it a greater financial shock later when I do have to account for the cost of labor. I prefer to keep costs out in the open.<br />
<br />
Overhead is perhaps the most interesting cost. The goal is to list every cost that is not directly associated with each unit sold and the amortize that total cost over every unit to recoup it. There are several costs associated with overhead:<br />
<ul>
<li>Business costs - licensing, insurance, web page, etc. Things that you have to pay if you want to stay in business even if you don't sell a single thing. Those costs are not included because I view this spreadsheet as a worksheet for this production run alone. However, these sorts of things probably run me around $500/year if my business doesn't do much except exist and have a website.</li>
<li>Prototypes - You never want to avoid having a prototype. There were several warnings given off by the Design Rule Check on eMachineShop's CAD software. The pieces could come out of the shop looking terrible - holes in the wrong places or with scratches, abrasions, etc. You need to know what you're getting before you order 100 of them and you have to know if your design even works. Perhaps not intelligently I ate this cost for now - it won't be recouped by the production run. If things turn out well I might sell any leftover prototypes as special gifts for generous backers to recoup the cost. </li>
<li>Refunds - Some people are going to want their money back and I want to give it to them. Too many Kickstarter runners seem surprised and terrified of requests for refunds - they prefer to think of their customers' money as a donation rather than a business transaction. I think that's dishonest. If I screwed up and I know its my fault I'm not going to try to hang on to a few more dollars. I do hope that it doesn't happen very often, but I don't have any real numbers. I included an assumption that 10% of the units sold will result in refunds and I'll have to give a full refund plus pay for return shipping. This turns out to be a very expensive cost, but I'd rather plan for the worst.</li>
<li>Fees - Don't forget about this! Kickstarter takes 5% of your total and Amazon takes up to 5% for credit card processing fees. Best to assume the worst and assume that you'll lose 10% of whatever you make to fees.</li>
<li>Unsold Units - This is a bit harder to wrap your head around, but bear with me. If I sell 100 units on Kickstarter, should I buy only 100 units from eMachineShop? Seems like a dumb question no? But what if they screw up machining just one of the units? I'm not going to ship a defective unit if I can help it, butI can't order just one more from eMachineShop. I should add some additional units on to the initial order to ensure that I receive at least 100 shippable units. The number of units above 100 that I order is the number of unsold units, and I have to recoup those costs by making everything else more expensive.</li>
</ul>
If you sum all of those costs up you get the cost to sell and ship one unit. Now all you have to do is arrange your Kickstarter such that you charge more for each of the units than they cost. The final Kickstarter goal is calculated in column H and is obtained by
multiplying the cost I plan to charge for each unit times the number of
units that I will sell. All I have to do is play with the price I charge until I see the level of profit that I would enjoy them most. Being a greedy capitalist I'm thinking my profit should be <b>$LOTS</b>.<br />
<br />
Of course, if I charge $LOTS some people just won't buy it. In that case I get nothing. Now, typical profits per unit for manufactured goods like this are pretty low - much less than 10%. And for this Kickstarter a profit of 10% still only gives me something absurd like $150 profit when all is said and done. That's not $LOTS. However, if I deliver 10,000 units instead of 100 then things get different. With 10,000 units my manufacturing costs get very low and even if I keep my profits very low (even as low as 1%) I get a lot of profit because 10,000 * $Anything = $Some. $3,000 in profit in one year is possible if my profit on each unit is $.30 and I charge around $30. Of course, why make $.50 when surely the market can handle a dollar of profit or even two? Now we're talking real money - if I can fulfill all of those orders on my own AND keep my actual job.<br />
<br />
That's pretty much the problem with manufacturing - it doesn't scale down very well. As it is I'll have to charge around $60/unit for a run of 100 units and I won't make a whole lot of profit. It's only when you get into high volume that it really gets to be profitable. But to handle high volume you need capital investment in automating processes, systems to track purchases, paying workers, etc. If I'm lucky I won't have to worry about this and I can just find an existing online shop to sell the widget - I deliver manufactured units ready to sell and worry about nothing else. <br />
<br />
So as you can see, there's a lot of thought that goes into deciding how much to charge for a product and plenty of pitfalls you have to watch out for. Once you start adding everything up it becomes clear that manufacturing things is a suckers' game - you either have to be fairly large or you're never going to make real money. Kickstarters beware....<br />
<ul>
</ul>
<br />Stevehttp://www.blogger.com/profile/12436983454045119515noreply@blogger.com0tag:blogger.com,1999:blog-475972232930633782.post-84157317257176655762012-05-19T11:08:00.001-07:002012-05-19T11:08:49.855-07:00Productively Slacking OffWe all slack off. I'm actually amazing at getting things done - despite the fact that I slack off nearly all the time. Remember how I was supposed to write about developing for microcontrollers? Yeah I didn't do that (yet). Wanna see what I did instead?<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://1.bp.blogspot.com/-648xECzt__M/T7e_IZv7VII/AAAAAAAAAOE/wm0rU2ULQ3M/s1600/Isometric.BMP" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="165" src="http://1.bp.blogspot.com/-648xECzt__M/T7e_IZv7VII/AAAAAAAAAOE/wm0rU2ULQ3M/s320/Isometric.BMP" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">This is an awesome... uh... thing?</td></tr>
</tbody></table>
You might be wondering what this thing is. Well, do you know what this thing is?<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://upload.wikimedia.org/wikipedia/commons/b/b3/Hukkah_nepal.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="320" src="http://upload.wikimedia.org/wikipedia/commons/b/b3/Hukkah_nepal.jpg" width="213" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">It's a hookah!</td></tr>
</tbody></table>
It's a hookah! It's also called a water pipe. This is because the bottom is filled with water and a pipe coming from the top extends beneath the water level. On top is a clay bowl filled with shisha - tobacco mixed with flavored molasses. Popular flavors include rose, mint, plum, apple and my personal favorite: guava. Lit coals are placed on top of the shisha and drawing air through the hose causes the shisha to be (theoretically) nicely and evenly burned to produce pleasant smoke. Hookah started in India and moved across Iran and into the Middle-east before it broke out into the world at large. <br />
<br />
Hookah used to be one of my favorite vices. But nowadays not so much. Tobacco is bad for you no matter how you smoke it - simply filtering the smoke through the water in the bottom of the hookah doesn't reduce any of the carcinogens to any level that could be considered 'safe'. Plus I started to just not enjoy it. I tried as hard as I could to get a great hookah going. I ditched self-lighting coals - the chemicals on them tasted horrible. I used natural, less-processed coals despite the fact you need to light them on a range burner. They tasted better and produced better, fuller smoke. The only problem is that they get so hot that they burn the shisha under them badly and quickly. Or the air flow would be so bad they don't really start burning well at all and <i>none </i>of the shisha gets burned at all. That's wasteful. A good, well lit and packed hookah can be enjoyed for maybe an hour. My typical experience these days is either everything burns up in 15 minutes and produces acrid, thin and disgusting smoke, or everything remains unburned and no smoke is produced at all.<br />
<br />
I don't enjoy that at all. The hot coals are theoretically good, but they require adequate air flow and some method to moderate the heat they produce.. That thin layer of tin foil separating the shisha from the coal typically has many small holes that produce good air flow (if the coals aren't blocking them completely) but don't moderate the heat at all. There are metal plates that can be used instead of or with the foil to provide a somewhat larger measure of heat moderation. The problem with them is that they are thin and have large air holes in them. Thin means they provide a low level of heat moderation and large air holes means that air flow isn't directed around the coals to keep them lit. <br />
<br />
In short, none of the available solutions is very effective. <br />
<br />
As an engineer I feel I can't let this situation stand. How difficult can it be to create some sort of metal grate that will distribute the heat of a burning coal while still providing good air flow - and additionally providing some means to ensure the coals don't slide off the bowl and leave burn marks in your carpet - such as this:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-v3sGM20LYb8/T7fKUiY-SFI/AAAAAAAAAOQ/i9K7dj5lagE/s1600/2012-05-19+12.27.08.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="http://1.bp.blogspot.com/-v3sGM20LYb8/T7fKUiY-SFI/AAAAAAAAAOQ/i9K7dj5lagE/s320/2012-05-19+12.27.08.jpg" width="191" /></a></div>
<br />
Well hard <i>is </i>it to design something like this? I'm an electrical engineer, so I don't really know anything about, well, I'll make a list:<br />
<ul>
<li>Materials - What kind of metal will have good thermal conductivity and has high machinability characteristics but not produce, say, any poisonous gases when exposed to the heat of a lit coal? Where do I even buy all this material? Aren't there a lot of different options? </li>
<li>Machining - How is such a thing as this made? I've seen a CNC mill, but I don't own one, know how to use one, or even know what sort of information I need to give someone to be able to make something using one. What sort of tolerances can I expect? Can I design something with .01" dimensions and expect that it will come out right?</li>
<li>Cost - How much will this be? How do I make it less expensive? </li>
</ul>
In short, I don't know a whole lot. So, I start with what I do know.<br />
<br />
I have three different hookah bowl types. I want this thing to sit nicely and securely inside the bowl and not move around. So, first step, measure the inside diameters of each of the bowls so I can figure out what sort of lip I need to design into them. For measurements like that you need every engineer's best friend:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-GnPPw3QQLrc/T7fNclmJQHI/AAAAAAAAAOc/8DJfTB2ECFA/s1600/2012-05-19+12.41.16.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="191" src="http://4.bp.blogspot.com/-GnPPw3QQLrc/T7fNclmJQHI/AAAAAAAAAOc/8DJfTB2ECFA/s320/2012-05-19+12.41.16.jpg" width="320" /></a></div>
If you don't own one of these, buy one. I'll help, clicking on this link makes me happy: <a href="http://www.amazon.com/gp/product/B0002JFMIO/ref=as_li_ss_tl?ie=UTF8&tag=thanee-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=B0002JFMIO" target="_blank">6 Inch LCD Digital Caliper with Extra Battery and Case</a> My favorite part about that one: the supplier is 'Generic'. I love China. You can measure anything with these very accurately. Saves your life when doing anything mechanical. They're great for PCB work - particularly for drawing your own footprints. <br />
<br />
So this starts me off with at least some idea of what I need to make. Let's start drawing something. I could go old school and start off with pencil and paper but this is the 21st century. We have computers with CAD software - but which to use? I've never had to do any mechanical design like this before. <br />
<br />
Lucky for me I've been at this a while. I can't even remember where I heard of it first, but I knew that <a href="http://emachineshop.com/">eMachineShop.com</a> existed. It's something like PCB123 or ExpressPCB but for mechanical parts. They provide you with free CAD software that is capable of:<br />
<ol>
<li>Drawing out what you want to make</li>
<li>Generating a 3D rendering of your design (very useful)</li>
<li>Deciding what machines/processes would be suit your widget </li>
<li>Presenting you with a list of materials with information on machinability, typical uses, cost and other information as well as making limited recommendations about which materials to use for your design.</li>
<li>Calculating the cost and delivery time for your part right from the program.</li>
<li>Placing an order for your part.</li>
</ol>
eMachineShop.com handles most of the hard stuff - ordering material, machining it, finishing it and shipping it to you. The software takes some getting used to, but since I have a limited mechanical design background (let's hear it for growing up on a farm and... playing with Legos!).<br />
<br />
I eventually decided on a design that looks a lot like the picture above. It will be made from 316 stainless steel (the same type as is used in pots and pans - that should be pretty safe) and fit three different bowl types. On the inside there are ridges that the coals sit on top of. In the troughs of the ridges the holes will be drilled. These holes in the troughs allow air to flow freely over the coals - the holes will never be completely covered by the coals because the coals can't fit into the trough. This fixes the airflow problem. The bottom plate is about a quarter inch thick still - this will spread the heat out and not just burn the top layer of shisha to cinders. And the walls are an inch and a half high to prevent coals from falling off (and helps to block drafts). Overall I'm rather pleased. I think I could use about 3-5 of these as a prototype - I'll hand some out to my hookah-smoking friends and get some feedback. So how much will it cost?<br />
<br />
Oh, only $500 for three of them? Well, at prices like that I might as well get a dozen eh? Now don't get me wrong - I think this idea actually has product potential. I'm up for investing in a prototype if there's a payoff, but no matter how many units I pretend to buy (I went all the way to 10,000 units) the cost/unit is still around $30. I'd have to sell it for around $50 and for that cost <i>I </i>wouldn't buy it. Something has got to give. Perhaps I can talk to local machine shops and see if I can get cheaper machining?<br />
<br />
This isn't a bad idea - there are plenty of local machine shops. I hate calling people, so I use email. I narrowed the list down to about five that I actually liked. What was my criteria? Basically, how amateur their web page looked. No, I'm not joking. Places that talk about machining parts for the space shuttle? No thank you. Places that talk about making awesome chrome instrument panels for your motorcycle? Yes please. Places that discuss ISO 9e8 quality processes and micron-level attention to detail? Sounds expensive. Places that have pictures of bearded men wearing leather gloves inhaling metal shavings? Now you're talking my language. Places that say they'll work with you and specialize in prototype production runs? Yes! Look, I'm an amateur, but I'm not unprofessional and I'm not looking for a disreputable machine shop. I'm looking for the one that will understand my plight the most - forgive my crazy unrealistic demands, help me decide what materials are safest, hold my hand through the difficult and unknown process of machining metal. I'm in unknown territory and I'm looking for the people that will have the most patience and tolerance of a difficult designer meandering his way through a low-profit job. I'm looking for someone humble and helpful. <br />
<br />
Luckily, the eMachineShop software can produce DXFs, and from what I understand about mechanical design, that's a thing. So I proudly send off my DXF, acting all professional with my talk of what materials and processes to use (entirely cribbed from the eMachineShop software mind you). And they get back to me very quickly!<br />
<br />
'Uh, we don't really use DXFs, can you give us a PDF drawing or something?'<br />
<br />
'Do you have an STL file? Or maybe a PDF with measurements?'<br />
<br />
'Can you maybe draw it out... and send us a PDF?'<br />
<br />
What?! Don't these people realize that we're in the 21st century?! That's practically the future! Fine - you know what? My dad taught me how to draw things out, I have graph paper, I've seen mechanical drawings and I know how to measure. So bring it on!<br />
<br />
I printed out a cross-section from the eMachineShop software, sat down with my ruler and mechanical pencil and started marking out measurements. And boy, was it a mess. My design was absurdly over complicated. I had angles other than 90 degrees all over the place (but they looked pretty!). I had about fifty different measurements to mark when only about 4 of them actually mattered. I just plain didn't align anything to anything else - wherever I had the choice to line up two lines I just didn't. It didn't matter - the software made it seem like all design decisions were equal and it's all getting built by machines anyhow. If the Design Rule Check doesn't complain, who cares?<br />
<br />
But now I was dealing with people. People who would have to do more work to handle my absurd design. People I would actually have to talk to. Most importantly - people I asked for help. Who might criticize my design. I wanted to try extra hard to do the best I could - you know, to avoid embarrassment. There will probably be plenty of that anyway given how little I know about mechanical design.<br />
<br />
So I go back to the drawing board. I have my important dimensions, so I start with those, but then I start aligning everything together to make it a more organized, simpler mess than before. I also do a bit more research into materials and find some interesting information. Did you know that aluminum is less expensive than stainless steel? Heck, most things are less expensive than stainless steel. More importantly, anodized aluminum is used in cookware - high heat tolerant and still people-safe! And wouldn't you know it - eMachineShop offers anodizing services and there are several local shops that will too. Now, with the less-complex design and different materials even the eMachineShop price per unit at 100 units is about $13. This is much more lucrative to sell. Plus, anodizing aluminum means you can color the metal. Everyone loves color and everyone loves choosing colors - very customer-worthy. Aluminum also cuts down on weight, which cuts down on shipping. It's a win-win-win situation. Here's the revised, simplified design:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://3.bp.blogspot.com/-2kflzFB6Q1I/T7ffojbmh1I/AAAAAAAAAOo/_WSwMLC4gjk/s1600/dimensions.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="264" src="http://3.bp.blogspot.com/-2kflzFB6Q1I/T7ffojbmh1I/AAAAAAAAAOo/_WSwMLC4gjk/s320/dimensions.JPG" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Look at that lovely handwriting!</td></tr>
</tbody></table>
I'm still waiting to hear back from everyone, but at this point I don't care if local places are less-expensive than eMachineShop.com - it's all pretty good. I can even buy material easily - you can buy aluminum stock from Amazon.com! If Amazon doesn't have it, <a href="http://mcmaster.com/" target="_blank">McMasterCarr</a> does - they're basically the Digikey of mechanical components and materials. This summer - one way or another - my beta-testers and I will have a product in our hands. If it's worthwhile, look for this on Kickstarter some time after. I'm hearing a lot of interest just around the water cooler. I'm told hipsters will love it. <br />
<br />
So, for any electrical engineers wanting to try their hand at mechanical design, here's some bullet points to get you started:<br />
<ul>
<li>Get a good set of digital calipers</li>
<li>Sketch everything out on paper to start with (use pencil, not pen)</li>
<li>Minimize the complexity of your part by minimizing the number of measurements it takes to describe it</li>
<li>Use the eMachineShop software for help with manufacturing processes and materials and a quick price-check</li>
<li>Use Google to look for local machine shops - they've been nothing but helpful to me so far and potentially less-expensive than online shops</li>
</ul>
See you on Kickstarter!Stevehttp://www.blogger.com/profile/12436983454045119515noreply@blogger.com0tag:blogger.com,1999:blog-475972232930633782.post-15934860684766516752012-05-06T14:29:00.002-07:002012-05-06T16:15:22.870-07:00Scientific ZombiesI used to think of lots of big ideas back in college. I'd think of things like 'Hey, let's use genetic algorithms to evolve a fuzzy logic model of a person's psychological makeup so that we can simulate what would REALLY HAPPEN in a zombie epidemic scenario! For science! And to watch a bunch of dots on a screen run away from other dots that are zombies! Realistically!'<br />
<br />
Yes, that was a real project I had. That was the goal anyway. A friend and I convinced a teacher to give us credit for a semester-long special project where we created a project titled "FUZZY DECISION MAKING IN A CELLULAR AUTOMATA-BASED EPIDEMIC DISEASE SIMULATOR". At least that's what the cut and paste from the abstract says. Yes, abstract - we presented this at a real symposium where real people (presumably professionals) nodded their heads and clapped. Now of course we didn't say it was a zombie attack simulator - we instead chose a real disease (you know, to promote <i>actual </i>science instead of <i>awesome </i>science). But they thought the idea had merit! I wasn't boo'ed off stage at an event where people are supposed to say smart things. I must have said smart things!<br />
<br />
I know what you're going to ask next. No, we didn't finish it. Not <i>finish </i>it finish it, but we had both parts of it. He could simulate the airborne dispersal of a disease and its incubation in people and I created a person who could have his own little day: When he's tired, he slept. When he was hungry he would either go home to eat if he was feeling antisocial or poor, or to a bar to eat if he was lonely. When he ran out of money he went to work - not exactly a perfect model, but for an automaton that basically just implemented the first three layers of <a href="http://en.wikipedia.org/wiki/Maslow%27s_hierarchy_of_needs" target="_blank">Maslow's Hierarchy of Needs</a> it showed some very human behaviors. I not only <i>said </i>smart things, I think I <i>did </i>a few too. <br />
<br />
I don't think I can say smart things anymore. Pretty sure I can't do them either. Not unless sitting on the couch watching Law and Order is a smart thing (geez, way to ruin my life Netflix...). Have I lost the knack? Hey, you don't know if you don't try right? So as a big idea pops into my head I think 'I wonder if anyone else has done this - if they haven't, I could get rich.' Let me tell you - if one thing can get me away from Law and Order it's a whole crapload of money. I'm just sentimental like that <br />
<br />
Let me explain the idea. One of the problems with linear controllers is that their performance
becomes much worse the farther you move away from the operating point for which they were designed.
The operational range of a linear controller is conversely tied to performance: smaller range - better performance, larger - worse. This is because plants tends to look more like a perfectly linear systems the smaller your operating range is. The more linear your plant is, the easier it is to control - but only within that range. If you can prevent the system from operating outside that range then you're fine. But no one is going to accept a solution that can perfectly control a piston - as long as its maximum extension is no greater than 1 inch.<br />
<br />
We can't avoid trying to span a wide range of operating conditions with a single linear
controller, but we always want better performance. How can these two be reconciled? My Big Idea is to use two linear controllers optimized for different operating points in the wider operating range and use a fuzzy logic controller to combine the outputs from both into one controller that has better performance over the whole operating range. When near either of the two operating points the fuzzy controller would largely cede control to the appropriate linear controller, but if it is operating between them the fuzzy logic controller would combine the outputs of both to some degree. Using two controllers in this fashion would theoretically give better performance over that wider range if you can tune the fuzzy controller to provide a smooth transition between the two controllers. So has anyone figured that out? Was it a smart idea? Do people like me?<br />
<br />
Truth is I have no idea. I started Googling and found <a href="http://cdn.intechopen.com/pdfs/34222/InTech-Tuning_fuzzy_logic_controllers.pdf" target="_blank">this</a>. It's very interesting but I can't at all tell if it's what I wanted to do. Is it just me or were textbooks always this hard to read? No, don't answer. If they were engineering textbooks then yes, they were always this hard to read. Teachers were just as difficult to understand, had the same propensity to stare off into space, to offer unhelpful explanations or simply not offer any at all. And <i>we </i>were the ones being graded. It mattered to us that we could understand those inscrutable papers and confusing textbooks. Our whole purpose for <i>being </i>in college was to leap those academic hurdles. Or, I dunno just run right through them. Whatever gets you to the finish line since (as we all know) 'C's get degrees'.<br />
<br />
I feel like I'm not going to get anywhere with books like that and quite frankly I don't <i>have</i> to care anymore even if I really <i>want </i>to. I have my degree so I'm off the hook. But it does make me ask: who is <i>right </i>here? Who <i>is </i>the smart one here? Does my idea have merit? Are those textbooks full of greek letters and dry mathematical drivel necessary, or is my frank yet wordy description above preferable?<br />
<br />
I think the most fundamental question here is was our zombie simulator <i>fake</i> science one second and <i>real</i> the next just because we changed a few parameters in the disease model, wrote an abstract and slapped together some PowerPoint slides? Was it because people nodded and clapped? What if they were just being polite? Why does polite clapping at a symposium make something more scientifically legitimate than a million 'Hells yes zombie attack simulator FTW!!!11!' comments on the internet? Can't those comments be coming <i>from</i> scientists? In fact I have a sneaking suspicion that if we <i>had</i> presented a zombie attack simulator at that symposium we would have had that exact reaction from the scientists present. And it didn't require foaming at the mouth about epsilons and solution spaces and lots of other mathy jargon. <br />
<br />
Can't normal people have good ideas? Ideas that smart people think are good? Can't we explain them without <i>trying</i> to confuse one another? With compassion and caring - compassion in that the person on the other side of your explanation is a poor person who probably isn't nearly as smart as you but is making every effort to try, and caring in that you do everything you can to help that person understand?<br />
<br />
There is an amazing opportunity in this country (and possibly across the world) for individuals - hobbyists, lay-people, the proletariat - to contribute to scientific progress in a real way. Never before have we had so many educated so well. A college degree doesn't make you a genius but it gives you something - no matter what you studied. It is far better than not having it and today <a href="http://en.wikipedia.org/wiki/Educational_attainment_in_the_United_States" target="_blank">more people have a college degree than ever</a>. Today, <a href="http://www.census.gov/hhes/computer/" target="_blank">more people than ever have a computer</a> - a computer that can calculate in hours or days what a computer fifty years ago could calculate in decades. A computer that can <a href="http://google.com/" target="_blank">look up almost any fact</a> for you. The same programming languages that run aircraft and space ships are free for you to use. Oh, you can't make an aircraft? <a href="http://www.velocityaircraft.com/" target="_blank">Yes </a><a href="http://www.zenithair.com/" target="_blank">you</a> <a href="http://www.lancair.com/" target="_blank">can</a> (top three hits for 'kit aircraft' on Google). It's expensive and I'm sure time consuming, but saying it's impossible? And who's going to tell you you can't <a href="http://hackaday.com/2011/10/10/22-miles-straight-up-in-90-seconds/#more-58067" target="_blank">build a space ship</a>. These are things that <i>hobbyists </i>are doing. There's more support than ever now to do whatever you want. Maybe you want <a href="http://batchpcb.com/" target="_blank">PCBs made</a>? Or you need help having mechanical <a href="http://ponoko.com/" target="_blank">parts</a> <a href="http://emachineshop.com/" target="_blank">fabricated</a>? Oh, but where will you <a href="http://kickstarter.com/" target="_blank">get funding</a> for all of these amazing ideas?<br />
<br />
The barriers to doing things that matter - like real science and technology - are lower now than they've ever been. But you still have sides. On one side you have hobbyists trying everything they can as hard as they can, filled with questions and looking for a place to make a real, helpful contribution to something greater than themselves. On the other you have symposium-goers. People who focus on publishing in peer-reviewed journals, double-checking results, navigating scientific political squabbles and generally becoming known and respected. But these two sides are not in opposition to each other. Both have the same goal: scientific progress and the betterment of mankind. The only difference is in their temperament (and how much they get paid). It's not a question of <i>real</i> science vs. <i>fake </i>science.<br />
<br />
As we go forward the ability of hobbyists and other scientific lay-people to contribute to scientific discussion will have nothing but positive benefits for both sides. Professional scientists should take steps to make their research more accessible by anyone with a passing interest. But we must not think that science can be handled by hobbyists alone. The rules of process that seem stifling to many hobbyists are a necessary part of the scientific method. Hobbyists need to respect the scientific process because that is ultimately what keeps us honest. The best case scenario for everyone is not to choose sides and see which wins, but to respect the necessity of both while finding ways to work together for greater effect. Stevehttp://www.blogger.com/profile/12436983454045119515noreply@blogger.com0tag:blogger.com,1999:blog-475972232930633782.post-80781070043834118122012-04-22T09:36:00.000-07:002012-04-22T09:36:10.990-07:00An idea blooms<br />
<div class="MsoNormal">
There’s all sorts of problems out there to solve but you
have to be careful. Not everything can
be fixed with a microcontroller.
Sometimes it seems like it’d be nice but then you hit hurdles – oops,
now I need wireless. Oops, there isn’t a
battery big enough to make this work.
Oops, this is physically impossible.
The truth of the matter is that there are few problems that can be fixed
cleanly with a microcontroller – and I’m all about clean. I hate kludgy systems grafted on to other
systems grafted on to Twitter. Sometimes
you just need to wait for a problem that is begging to have code written to
solve it. </div>
<div class="MsoNormal">
And I found that problem.
Here it is:<br />
<br />
</div>
<div class="MsoNormal">
</div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://4.bp.blogspot.com/-M33njDoAPCQ/T5QyPEPDxPI/AAAAAAAAANw/Q8YtE2nD9AE/s1600/IMAG0150.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="400" src="http://4.bp.blogspot.com/-M33njDoAPCQ/T5QyPEPDxPI/AAAAAAAAANw/Q8YtE2nD9AE/s400/IMAG0150.jpg" width="238" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">That wasn't like that before!</td></tr>
</tbody></table>
I know what you’re thinking – who could be responsible for
this heinous misuse of the trash can?
WHO WOULD DARE?! WHAT KIND OF
ANIMAL WOULD DO SUCH A THING!? As luck
would have it, we know exactly who the offender is. Here she is doing her hardest to appease us
with cuteness:<br />
<div class="MsoNormal">
</div>
<div class="MsoNormal">
</div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://2.bp.blogspot.com/-0MXPi-JPmls/T5Qyf3RGvDI/AAAAAAAAAN4/kjEDSF_52TM/s1600/IMAG0071.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="320" src="http://2.bp.blogspot.com/-0MXPi-JPmls/T5Qyf3RGvDI/AAAAAAAAAN4/kjEDSF_52TM/s320/IMAG0071.jpg" width="191" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Bad dog! Bad adorable dog!</td></tr>
</tbody></table>
Really, what kind of fool does this dog take me for? That’s only a half-windsor! Not bad for a creature without thumbs, I’ll
admit, but this does not excuse her bad behavior. Not at all.<br />
<div class="MsoNormal">
Naturally she only does it when we’re not in the house. And it doesn’t take long at all – this isn’t
a desperate gamble to get our attention, to force us to recognize that we are
abandoning her and she has to take measures to fend for herself. No, this is after perhaps a half hour of
being alone. That’s apparently all the
time it takes her to realize that there’s bacon grease in the trash. And boy does she love her bacon grease. </div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
What to do? Hide the
trash when we leave? Not bloody likely –
that sounds like work. Get a different
trash can – one that closes tightly and allows no dog to access its
contents? That’s also work – I hate
going to Bed Bath and Beyond. Plus,
neither of those ideas <i style="mso-bidi-font-style: normal;">trains</i> our dog
to be better. Who knows where all that
energy will be directed if not the trash – perhaps to the kitty litter? I want to train her so she leaves things
alone, not accommodate her bad behavior.
But she’s crafty – she only gets into the trash when we’re not
present. So how persuade her to stay
away from the trash when you’re not there?
This is a solution that begs for an automated approach! What are our options?</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Well, because I keep up on the latest in tools from <a href="http://kk.org/cooltools">Cool Tools</a> I have the inside track on a neat
little device used to train cats: the
<a href="http://www.amazon.com/gp/product/B000RIA95G/ref=as_li_ss_tl?ie=UTF8&tag=thanee-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=B000RIA95G">Innotek SSSCAT Cat Training Aid</a><img alt="" border="0" class=" nqvaddjkwvekswpwzihs" height="1" src="http://www.assoc-amazon.com/e/ir?t=thanee-20&l=as2&o=1&a=B000RIA95G" style="border: none !important; margin: 0px !important;" width="1" /> It’s
basically a can of compressed air with a motion sensor on it. You put it wherever you don’t want your cat
to be – usually up on counters or something like that. When the cat jumps up there and gets within
range of the motion sensor it releases a burst of compressed air that scares
the crap out of the cat. People say it
works rather well – it’s a consistent negative association for the cat. Best of all is that it’s automatic – it
doesn’t rely on a person being there and consistently disciplining the
cat. That sort of consistent training
helps the lessons stick. If I want to
train our dog to not get into the trash I need something like the SSSCAT. I could probably use the SSSCAT – it wouldn’t
be a bad idea for me to own one anyhow since we have two annoying cats. But damnit, it’s spring – when a young man’s
fancy turns to… engineering. Of
course. I want to make something and this is perfect for several reasons.<br />
</div>
<div class="MsoNormal">
First, it’s not too complicated. I’ve thought it out and it will only need one
or two sensors as inputs and one noise maker as an output. There are no complicated communication
interfaces, no zany analog front ends, and no high frequencies. You could code the whole thing in assembly if
you wanted. Second, nothing exactly like what I need
currently exists. The SSSCAT might work
– perhaps I could place it behind the trash can or inside of it somehow, but
that might just as easily not at all work.
Third is that I can add features that aren’t in any product I can
find. Inventing something that doesn’t
exist but would make your life easier is the reason I got into this engineering
racket. Some people write to make the
world a better place, some enter politics.
I find new ways to be lazy. Someday I dream of a world where everyone
can be lazy.</div>
<div class="MsoNormal">
So it’s decided – I’ll save the world by making something
that yells at my dog when she knocks over the trash. It’s a tall order, but I think I’m up for it.
Next time I’ll discuss high-level design: why it’s important, what sort of
documents you should produce as part of it and what kind of information they
should contain. We’ll also discuss
project organization and folder structure if you’re lucky. </div>Stevehttp://www.blogger.com/profile/12436983454045119515noreply@blogger.com2tag:blogger.com,1999:blog-475972232930633782.post-92024922656425839092012-03-08T05:30:00.000-08:002012-03-08T05:30:36.200-08:00An In-Depth LookI had someone ask to share the loops I was talking about in the earlier post for analysis. Ask and ye shall receive! Let's start with the loop that performed awfully.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://3.bp.blogspot.com/-YDXhSwYGXYY/T1ipW9dxJRI/AAAAAAAAANU/XI8N32D-U7A/s1600/load_log_file_data.vi+Block+Diagram+on+CAN_Log_Analyzer_2.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="226" src="http://3.bp.blogspot.com/-YDXhSwYGXYY/T1ipW9dxJRI/AAAAAAAAANU/XI8N32D-U7A/s320/load_log_file_data.vi+Block+Diagram+on+CAN_Log_Analyzer_2.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Stare into the belly of the beast...</td></tr>
</tbody></table><div class="separator" style="clear: both; text-align: center;"></div>Here's a quick walkthrough (roughly from left to right):<br />
<ol><li>Load a text file as a spreadsheet with a break on all newline characters - this gives me all of the lines in the file in an array of strings (there's probably an easier way but this was most direct at the time.</li>
<li>The array of strings is fed into the first FOR loop. The loop is auto-indexed on the array of lines.</li>
<li>Within the FOR loop there's a case statement that handles different lines in the text file differently. There's header rows and such at the beginning so basically the case statement allows the loop to ignore those and start with the data rows. </li>
<li>Inside the case statement there's a second FOR loop - this one loops over each field in the line. It is indexed by the array of integers. Each row of that integer constant contains offsets and lengths for a string subset call. (More on this in a second)</li>
<li>Inside the second FOR loop there's a case statement that has a case for each field. Every field except the last is handled the same.</li>
<li>Inside the case statement there's a string subset command fed with values from the constant integer array. These values provide offset and length for each string subset call except for the last. The last is the special case mentioned above - there's no length associated with the last call to string subset (not wiring the length causes it to read until the end of the line).</li>
<li>When each field is picked off, that text replaces one of the elements in the constant string array being fed into the loops near the bottom. The string array has an element for each field in each line, and the integer constant contains the array element within that string array to replace with the current field.</li>
<li>When a full line has been read and turned into an array of strings, that array of strings is appended to the list of lines already read. </li>
<li>The loops then continue with the next line.</li>
</ol> I hope most of you can already guess what the main problem is so far. It's the 'this loop inside this loop inside this case inside this loop inside....' yada yada ya. That's bad - for speed anyhow. At first I tend to try to make my code.. shall we say, robust? Able to handle even impossible situations? I also try to make it clear, and clear means verbose or at least, doing much more than you need to to promote uniformity and centralization of data. This often leads to unreasonable performance through over-engineering.<br />
<br />
Let me give you an example - I'll bet something like this has happened to you. Let's say you've got a program that communicates with another system. For what you're programming, you have to change your behavior depending on what commands the other system sends you. So as a hacker, you start hacking. You read the first command you need to implement:<br />
<blockquote class="tr_bq">"Set mode to passive - in this mode your system will only respond to messages sent to it by the external system." </blockquote>Ah, easy! I'll just make a boolean that tells me whether I've received that message! Then I can read that boolean and determine whether or not to send messages automatically. Great. Second message:<br />
<blockquote class="tr_bq">"Set mode to active - in this mode your system will automatically send the following messages at these rates:..." </blockquote>Perfect - when you receive this just toggle the same boolean from before to set yourself back to automatic mode. Third message:<br />
<blockquote class="tr_bq">"Set response delay to minimum - when you receive this message delay all automatically-sent messages by one frame." </blockquote>Okay... so I'll make a boolean for this one too?<br />
<blockquote class="tr_bq">"Set response delay to maximum: When you receive this message delay all automatic messages by three frames." </blockquote>Okay, okay, no, wait, I should make that last one an integer or something and not a boolean, I'll just go back and change that...<br />
<br />
And right about here my bat-sense starts tingling. "You're going to be doing this forever! Use a state machine! Otherwise you'll have a million variables and you won't be able to keep track of what combination of booleans and integers defines what state and what behavior! STATE MACHINE!" And a state machine sounds like a good idea - it allows you to be more rote, more design-oriented, more organized and more certain that your system works. Implemented properly they improve deterministic behavior in complex systems. So I add a state machine and start defining all the states I'll need: automatic, passive, umm, delay? No, so far it's just two states but I'm sure there will be more. Let's read the next requirement:<br />
<br />
"....."<br />
<br />
Ah, so we're done are we? So I rigged up a whole state machine architecture when all I really needed was one boolean and one integer. Sure, a state machine will WORK for this but it's certainly not efficient. It needs memory, time, special coding practices, etc. A boolean will do the same job much more efficiently.<br />
<br />
And that's my problem - that's why I build loops inside of cases inside of loops (<a href="http://knowyourmeme.com/memes/xzibit-yo-dawg" target="_blank">yo dawg, I herd u liek loops....</a>). I think I'm doing something to make my programs deterministic and robust. I'm actually making my programs robust, deterministic snails. Like a giant snail-tank that's crushes anything in its path and is always on-time. I don't think anyone wants that. Unless that's what you ride to work every... month?<br />
<br />
After much profiling of various methods of implementing this functionality, I settled on the below implementation:<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://1.bp.blogspot.com/-v1RloRlzSQE/T1ixY8FL_xI/AAAAAAAAANc/v7Wcc6DC8RE/s1600/load_log_file_data.vi+Block+Diagram+on+CAN_Log_Analyzer_final.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="226" src="http://1.bp.blogspot.com/-v1RloRlzSQE/T1ixY8FL_xI/AAAAAAAAANc/v7Wcc6DC8RE/s320/load_log_file_data.vi+Block+Diagram+on+CAN_Log_Analyzer_final.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">So fresh and so clean!</td></tr>
</tbody></table><br />
Yeah - look at that. ONE LOOP! Seven calls to string subset (running in parallel) and no Build Array blocks! Loading a 48000 line file used to take an hour. Now it takes two seconds. So how did I manage to rid myself of all of that cruft?<br />
<br />
<ol><li>First, I stripped off the header rows from the array containing each line. That removed the need for a case statement inside of the first FOR loop (the one that ignored the header rows). </li>
<li>Then I removed the inner loop that looped over each field and just put all of the string subset calls in the same place. This allows them to run in parallel instead of serially (if Labview is as smart at figuring out how to parallelize things as is claimed). </li>
<li>Since I'm not ignoring any rows any more I can replace the Build Array block with a simple auto-indexer on the output of the FOR loop. This significantly sped things up. </li>
<li>And finally, I configured the loop for parallel operation. To do this right click the FOR loop and choose 'Configure loop parallelism' or something like that. This lets different iterations of the loop run at the same time. If you think about it it makes sense. As long as the next loop iteration doesn't depend on the last loop iteration then you can just run them all at the same time. If I had 48,000 processors then I could have each of them process one line of text and have this job done in microseconds. When you use it though, pick a small single-digit number for the number of parallel loops. There is overhead associated with managing multiple threads so increasing the number of parallel threads starts to backfire after a while.</li>
</ol>The second block diagram is much better programming than the first simply because it's quicker. It's like I always say: any automated process is better than any manual one because it's consistent AND because once it works you can speed it up later. There's no way this program would have been useful to me if it took an hour to load one log file. So don't overcomplicate things!Stevehttp://www.blogger.com/profile/12436983454045119515noreply@blogger.com0tag:blogger.com,1999:blog-475972232930633782.post-63698491032162649272012-03-02T16:54:00.004-08:002012-03-04T08:38:23.626-08:00Boo Labview!So I'm not posting about the microcontroller stuff I swore I'd start last time. Well, this time I swear there's half a post sitting on Blogger ready to be finished someday. That one IS about microcontrollers. This one's about Labview - mostly because I had a fun little time with it today.<br /><br />We have a customer who has designed some rather interesting test equipment utilizing Labview Real-Time. This means that for months I've been working with Labview for all sorts of fun things. Since their test equipment is all National Instruments-based we've decided to double down and use TestStand to automate the testing that utilizes their equipment. This means that one of the fun things I invented to help our workflow along was a piece of Labview that reads in a CSV file containing descriptions of what inputs to apply to various VIs and what outputs to expect from them and turns it into a TestStand-compatible sequence. This has saved us more time than I can imagine - mostly because we didn't even try to write any of the sequences by hand. I was working with someone who works for our customer and he actually attempted to write a 500 steps sequence by hand. I don't think he got even halfway through. Keep in mind this is a rather tedious set of steps. Picture something along the lines of "Press '1' on the computer keypad. Verify that '1' appears on the computer display. Record the result. Now press '2' on the computer keypad. Verify purple monkey dishwasher. Hit self in head with hammer. Melons."<br /><br />You see? I couldn't even get through two steps without losing my mind and desiring to physically harm myself. When you use a CSV file you can search and replace. And copy and paste. Copy step 1, paste to step 2, search and replace 1 with 2. Presto! Extra nerd cred if you use regular expressions! Don't hire a person to do a computer's job. Use the right tools!<br /><br />In the spirit of using the right tools I wrote a lot of Labview today. You see, our customer gave their test equipment an option to log a LOT of CAN bus traffic. The only problem is that due to the (fast) way they write the log you can't be certain that everything is in order time-wise. I don't blame them - it's a real-time system. You do what's fast and leave the post-processing for a bigger computer (though do note an irony - I'm fairly certain that the real-time PC is more powerful than the host PC it's 'slaved' to). They suggested a rather cumbersome process to import the data into Excel and sort it but I say nay sir, nay! I hate things with more than one step. That's why I have an iPad - only one button. There's no question about what to do. The iPad is off? Step 1: push the button. Success! You'd be surprised how often it works. <br /><br />I wasn't happy about eight steps and I knew that in the future we would want to use this log to verify behavior of the system under test, so I decided to write Labview to read the log, organize it, search for certain messages, judge skew, rate, etc. So it made sense to write a Labview program to parse the log, organize it, search it and collect statistics. Now keep in mind that this log is distinctly not... how shall I say? It is distinctly not brief. The log for a 10 minute test is 20 megs. And it's all text. No pictures of cats whatsoever (not that they wouldn't improve things). Admit it - you're a little surprised that there can be that much text and that I can be interested in so much of it. But hey, we're not barbarians. We can handle this much text. It's no problem for a computer - especially the amazing computers we have today! Computers are information processing MACHINES. And a machine means I don't have to do the work for myself. That means less thinking. That are good.<br /><br />And all it takes is....<br /><br />Um...<br /><br />Theoretically it will take around six hours. <br /><br />Yeah, yeah, I know - that sucks. That's terrible. I should feel ashamed. *I* wrote something that take six hours to process 20 megs of TEXT? 20 megs of video is, what five minutes maybe? Naturally this depends on quality, but let's face it - you'll blow through 20 megs of high-definition video in much less than an HOUR let alone SIX. And I wrote a program that couldn't handle 20 megs of text in less than 75% of my work day.<br /><br />Hey, I like getting paid as much as the next guy but even I get bored. Plus, I want to get this log analyzing done quickly so I can do more of it and be DONE with everything quicker. I want to respond to our customers questions in minutes when they expect the answer tomorrow. I like to impress, I like to excel and what I've done here is not it at all.<br /><br />So I start profiling. So I load up a 5 meg text file (one of four in a typical log set). How long does that take? Milliseconds. Single-digits. Not worth mentioning. That is not the problem. I sort the data by timestamp - sounds intensive right? I have no idea what Labview's built-in sorting functions are like. Quicksort? Bubble sort? No idea. Could be a lot of room for improvement there. But... nope. Very brief - a small amount of the total time. Rather impressive actually. So I break it down; I limit the number of lines so I only have a thousand. Now the whole process takes a second and a half. I know it's not loading the file, I know it's not sorting the file so it must be loading all of the data line-by-line into a 2D array. One big ugly FOR loop in the middle of my VI that is slowing everything down. And no matter how much I profile, no matter how much I change the loop always seems to take about half a millisecond per line. My first attempt used one string subset block but it was inside a second FOR loop that ran once for each field in the line. Surely a FOR loop inside of another FOR loop significantly slows things down. After all, they keep telling me Labview is inherently parallel. Multi-processor, hyper-threaded blah blah blah. Putting that FOR loop inside the other one forces a serial process. If I used eight string subset blocks at once then it could thread it any way it pleased. That should help shouldn't it? No dice. No change. Ah, look! I'm indexing an array - if I can find a way to remove that from inside the loop.... no help. What if instead of string subset I used one Scan Into String block? That might.... provide no benefit at all. <br /><br />I suppose if nothing else I could remove this Build Array block and see if I can't just let the FOR loop auto-index the output but I doubt that would....<br /><br />....<br /><br />....<br /><br />Each iteration of the loop now takes 6 microseconds. Down from 500. <br /><br />This is why you can't trust Labview. This is why Labview Real-Time is an oxymoron. It does not encourage nor make easy optimization. Now, I will be the first to admit that I created - from scratch in one day - a program to process and analyze tens of megs-worth of text data and display it in a user-friendly way. This program will make me more efficient and productive and I have Labview to thank for that. And I do.<br /><br />But Labview just feels like a toy to me now. When you have ten lines of text data who cares about optimization? When you have a hundred it's a question of how much do you care about thirty seconds of watching a progress bar. If it's a thousand you go and get a coffee and when you come back it's done.<br /><br />But if it's half a million? You can't just say 'Well some things take a day to run.' That's silly. That's wasteful. Worse - it's unprofessional. Wall Street trading firms have gone so far as to implement their risk analysis algorithms <span style="font-style:italic;">on FPGAs!</span>. It used to take them the better part of day to process their data. Now? Something like fifteen minutes. And guess what? They win. Their competition still takes hours. Now they can act quicker or make better algorithms to work smarter. Better efficiency gives them more options. That's what a professional does. A professional does not shrug his/her shoulders and say 'I dunno. Let's just buy a faster computer.'<br /><br />So I can't trust Labview. I moved all sorts of blocks around trying to figure out which one was the culprit. They all looked the same. I had no idea what was under the hood. Was it linear complexity or exponential? National Instruments won't let me look at the code. As far as I know they haven't given me the tools to thoroughly analyze their entire architecture. Where's my gprof report? And was their Build Array block seriously doing something as absurd as copying a ten thousand element array each time it wanted to append one more line of text? <br /><br />If I had done it in C I could have utilized pointers and custom data structures to make a faster program. If I had done it in C I doubt it would have loaded the file in more than ten seconds to BEGIN with. Only in Labview are you encouraged to just plop down blocks without any regard for the cost in time or resources. Even if you cared there's no way to know other than tedious experience who the culprit in your bad algorithm is this time. Does that addition block break down into one assembly command or 100? You will never ever know with Labview. That makes it a toy. That's why you can't trust it.<br /><br />Edit: I realize that some people (among the many I'm sure who read my blog) will wish to argue with me and say that the problem I've outlined above with respect to Labview is a problem with EVERY computer language. Seasoned programmers know that you can't just call any function willy-nilly and assume it will be fast. I agree with this. It can happen in C - should I call printf in each iteration of a loop, or build a buffer and then print it afterwards? Building the buffer will be much faster than a function call which will then significantly speed up your loop. And this is, of course, not only something you need to keep track of in Labview but in C or Python or any other computer programming language I can think of.<br /><br />A seasoned programmer also knows that you adapt your approach to each unique problem you encounter. C provides you a nice framework to solve your own problems which includes pointers, function pointers, structs, a myriad of different loops, bit shifting and if none of these are sufficient you can use assembly. Nothing other than rolling your own co-processor with VHDL is faster than assembly. But with Labview you don't have these options. Pointers? Don't exist. Game over. That's your number one tool for optimizing code. For example, the block I had a problem with was build array with a 2D array. Essentially, I have an array in which each element represents a line of text with several fields. The line of text with fields is stored as an array of strings (which, if you want to get into things, are ultimately arrays of characters, null-terminated). That's a lot of arrays but the easiest way to imagine it is that I have an array where each element store several fields of information. What I would do in the innermost loop was parse each line of text to read the fields and shove it into a data structure and then append it to the array with all the data I had already collected.<br /><br />Well, it seems the Build Array block was to blame. The only way I can explain the terrible slowdown is that somehow Labview stores its arrays like strings - there's one pointer to mark the start of the array and where the array stops there's a special terminator entry. Just like a null-terminated string. So when I wanted to append the latest data to the array, I think it iterated through the whole array until it found the terminator entry and then appended the data there. For small arrays this isn't too bad, but I was getting to 48000 lines per text file (with four text files worth of data). Iterating through that much data every time you want to add another line gets expensive. And it was probably also re-allocating memory for the array each time too! In C I would at least have done the following:<br /><br /><ol><li>Allocate enough memory to hold all of the file data before I start the loop. I might count all of the lines in each file but that might take too long. It'd be better just to grab then length of each file and estimate what I needed.</li><li>Maintain a pointer to the last element of the array rather than have to iterate through the array each time I wanted to add something. It will not use that much memory and it significantly speeds up.</li><li>Don't use another loop to process each element in each line - unnecessary loops introduce unnecessary overhead.</li></ol>Those are the only ones I can think of right now (and #3 is kind of a stretch) but I already know that with those ideas I could make a much more efficient loop than Labview. If I had all that control then I could write something really fast. With Labview I simply don't. I have no idea how any of their blocks work or even how the auto-indexing on a FOR loop works. All I have to work with are the tools they give me and I have no indication how any of them are different. <br /><br />Many people will say that it's good I'm thinking about Labview in this way - no programming language is perfect, so learn its quirks and work within them. The only problem is that's not how National Instruments wants us to think of Labview. We can't judge it like we judge C because it's not meant to be C. It's supposed to be a magical language that frees us from worrying about the code and cycles and memory and instead focus on our ideas, our algorithms. Labivew, they assure us, will free us from having to think about how to efficiently implement our algorithms. They say anyone can be productive with Labview. I will give them this: almost anyone can use Labview and that is impressive. I've seen Labview created by Computer Scientists, Physicists, Electrical Engineers, Technicians, Chemists - you name it. And most of it works just fine for what they want it to. But it's generally badly written and inefficient. In some ways Labview makes it much easier to be badly written and inefficient - specifically because it essentially works so hard to figure out what you mean instead of what you said. From the viewpoint of someone who's picky about code that's despicable. From the viewpoint of someone who wants computers to make peoples lives better, that's laudable.Stevehttp://www.blogger.com/profile/12436983454045119515noreply@blogger.com3tag:blogger.com,1999:blog-475972232930633782.post-36611376340843878652012-02-26T17:57:00.004-08:002012-02-27T09:24:14.911-08:00Beyond ArduinoI own an Arduino. And why not? I've always liked the AVR - mostly because Atmel has always had a good focus on hobbyist-level tools. WinAVR is an excellent free toolchain and can interoperate with a wide number of IDEs due to the way it mimics the functionality of the GCC toolchain (THE standard C compiler). The Dragon is an extremely cheap ISP with debug functionality and HV/Parallel programming interfaces for when you screw up your fuses and it can program nearly all chips in the AVR line. The AVR architecture is similarly impressive due to its high MIPS/MHz ratio and hardware multiply functionality.<br /><br />Wow, that was in-depth, I hope I didn't lose anyone. Hey, vast majority of Arduino users: did you get any of that? I'm sorry, I'm sorry, I don't mean to be a jerk. No, the vast majority of Arduino users don't understand that. But that's okay. I'm an electrical engineer - trained and all! I've been programming microcontrollers for, oh.... Oh God - eight years now. I think I might be... old.<br /><br />So I'm old, and I'm an electrical engineer. That's why I know these things - to me it matters. If an AVR is a bad choice for a project I have to know why so I will be able to tell whether to replace it with a PIC, a 68K or ARM Cortex-M3. Most people who use the Arduino are not electrical engineers, develop embedded software for a living or necessarily have ever programmed before. Now, despite the fact that this causes some pretty hair-pulling <a href="http://electronics.stackexchange.com/questions/27218/heating-element-circuit-please-microcontroller%5C">questions</a> on Chiphacker (I'll bet that question is gone by the time I post) it's a good thing. Embedded systems have the potential to make our world a much smarter and better place in the hands of those with the right knowledge and world-view. I mean, the most basic application I can think of would be intelligent power sockets for everything - track usage of power, schedule things, auto-turn off of dangerous items, etc. You could make your house more efficient (power-wise) and safer (auto turn-off on a curling iron? Yes please!). Someday, the halting, uncertain steps taken by people who have never soldered before will lead to a better world through practical software.<br /><br />Which, to me, makes it all the more important that if you're going to have a good idea and succeed at making it ubiquitous you ought to know a thing or two about writing safe, deterministic software that will last forever and gracefully handle all errors. <br /><br />This is just as hard as it sounds. But worth every bit. <br /><br />You've seen it just as much as I have. I mean, look at the gas station - the electronic pumps that take your credit card. First off, they beep as if they have something to say and then it takes them three seconds to <span style="font-style:italic;">start</span> to update the display. And then it updates a little bit faster than molasses flows. So it asks you for your zip code. You punch it in the numbers and every time you hit a key you hear the beep beeps but don't see the numbers show up. No, for some reason that takes about 10 seconds per digit. So if you mess up you need thirty seconds or so to fix it. But that's only a little annoying - try this on for size: has your dishwasher ever crashed? Would it refuse to clean anything and spit out an error code you can't look up because you don't have the service manual? Did unplugging it and plugging it back in fix it? Do you know how many lines of code are in your car? Did you know I have a microprocessor in my PEN? <br /><br />While it's true that anything remotely dangerous with software in it is (generally) tested to some degree to make sure it doesn't kill you we have to ask ourselves - is the shoddy software we see in something so simple as a fuel pump with a display and a keypad something we want to put up with in (eventually) <span style="font-style: italic;">every single device we own? </span>What is so frustrating is that we know how to write software. We know how to read keypads, we know how to write numbers and letters on a display. We know how to dial a phone and ask a remote system whether that credit card number is valid. And if people would just write software correctly we could avoid creating a million devices that need to have their batteries removed every day due to blue screens.<br /><br />When I say 'we' know how to write this software I mean... I don't quite know who I mean. Dudes at NASA who couldn't rely on taking out batteries because the batteries were IN SPACE! Those dudes knew how to write software that worked - period. The stuff in cars, airplanes, medical devices is not perfect but as a friend of mine would say it's not a cell phone either. The quality is simply higher because otherwise people die. Right now, that sort of expertise costs money - you need the right people to design AND test your software so that it performs to the standards of whatever certifying body you need to satisfy. If there aren't any standards you need to satisfy then you don't bother - you hire someone who grew up on VBScript and PHP instead of someone who grew up on assembly language and eating rusty nails for breakfast. <br /><br />But the point is that the expertise is out there; the information is out there. Our collective knowledge knows how to write good software, so the goal should be to get the information out there and make it easy to use. <br /><br />So, back to the original point of this post. What does this have to do with Arduino? Well I'm sad to say that while Arduino is great it's pretty basic. It is somewhat brain-dead: it encourages blocking calls (ie, idling in a do-nothing loop until something happens) rather than use asynchronous interrupts. It skips over more advanced topics that form the basis of some of the techniques which ensure safe software such as callbacks/function pointers. It shuns even basic lessons such as parts selection (newsflash: you're going to use an Arduino. You will buy a shield - you don't need to know what's on it). You're certainly not going to learn anything about design for manufacturability (unless you're <span style="font-style:italic;">making</span> a shield). Ever heard of a state machine? Circular buffer? Process stack pointer vs. machine stack pointer? All very important!<br /><br />The Arduino is a good place to start, but if you're serious about making something worthwhile that has software in it, your attitude can't be 'I don't care about good correctness, suitability or efficiency. I just care if I can get it to run'. This attitude leads to terrible software and terrible products to boot. It can be avoided. Over the course of... the rest of my life I intend to write a series of articles/guides that instruct people on what the essentials of writing good software/good overall design are and how to apply them. This will involve every aspect of the process I can think of from microcontroller selection to getting a PCB made. I'm going to write the articles, publish the code, open-source the development kits and take a lot of pictures. Yes, there may be selling of things involved, but you only have to buy them if you're lazy. All of the tools (as far as possible) will be free to use and open source and all of the design files will be made available with an open-source license. <br /><br />If you want your software to be faster, more responsive, more efficient and just overall better, listen for a while. Even if I don't teach you something I may point you in the right direction.Stevehttp://www.blogger.com/profile/12436983454045119515noreply@blogger.com0tag:blogger.com,1999:blog-475972232930633782.post-42314179525051026692011-12-14T08:31:00.000-08:002011-12-14T08:48:37.100-08:00Labview is Actually Not All That BadIn stark contrast to the flurry of epithets I hurl at Labview on a daily basis at work I will now say good things about it - because it deserves it!<br /><br />The blocks are actually pretty old school. If you get stuck trying to decode a string in Labview your tools look surprisingly like what you'd expect from the C standard library. Granted - you don't need to worry about NULL termination or anything, but most of the basic building blocks (like string subset, search and replace, etc) promote code that acts (in form) like old-style C code. It's not like writing the routines yourself (iterating through each character, comparing, discarding, buffering, etc.) but the solution you come up with to manipulate strings will probably feel like an old-style C solution does. I also like the way the control structures work - you get nice features like shift registers (that teach you about instantiating a variable before the loop) or straight-through tunnels that just take the last value from the loop and pass it out. You can make complicated while or for loops with conditional terminations or conditional continuances. These are very welcome forms to have present. There's a lot of nice tools and abilities in Labview that don't feel new and gimmicky, but instead old and tried. <br /><br />Second, while most Labview VIs are just a mess plain and simple what I've found is that a messy VI usually means messy badly-organized code. A clean, well-organized VI means you've created sub-VIs in the right places, organized the right data into clusters, used the right type of loop, etc. If your VI is clean and organized, chances are your code is too. Thus, by seeking to visually clean up your block diagram you can actually write good code. Of course, the opposite is not true: you can have great code that still looks like a mess. Because you just can't get around that in Labview sometimes. But chances are if the block diagram looks good the reason is because of a highly-organized coding mind behind it. It helps people learn how to organize code by presenting it as a visual problem instead of an esoteric abstract one - and many people are simply visual learners.<br /><br />Third, I'm ecstatic as hell that whenever I Google anything related to Labview I come up with an answer - period. Someone has tried to do what I'm doing or for some insane reason National Instruments make a guide on how to manipulate TestStand sequences programmatically from Labview. Quite simply put I spent hours trying to figure out a problem on my own and when I get the bright idea to Google it the answers is invariably THERE. Done in five minutes. At this point in my career I'm a little more focused on results than banging my head against a wall to 'learn' so that feels really good. I have no idea why all of this support is out there but it is and it makes me happy. <br /><br />Fourth, Labview is actually free of a lot of the object-oriented crap that plagues many trendy languages today. Yes, Labview is actually a bit trendy by itself, but (and this impresses me because the more I think about it the more I realize it's true) Labview is actually pretty old-school. Some old-school hard core stuff you can't do (like function pointers - but then only kinda) but I'm pleased that I haven't seen the term 'inheritance' once when dealing with Labview. True, all the things that make me hate C++ might be in there but I haven't been forced to deal with it and I haven't seen anyone else's work that deals with it either. <br /><br />Don't get me wrong - I still find plenty to hate about it (and I may get to that later) but the more I consider it Labview feels like C but graphical. And that's not terrible.Stevehttp://www.blogger.com/profile/12436983454045119515noreply@blogger.com43tag:blogger.com,1999:blog-475972232930633782.post-65352087335799695762011-10-05T19:01:00.000-07:002011-10-05T19:40:58.709-07:00Good Coding Practices #...?I have a semi-ongoing series in good coding practices... to the extent that I ever update my blog anyhow. Lately I've taken up work on an iTunes Android Sync tool. Is anyone else amazed that there are very few good programs that will sync iTunes playlists to an Android device? There are some out there, certainly but for some reason each of them tends to have one or two major flaws: way too slow, randomly renames your songs to the titles of different songs, costs money - the usual complaints. So I looked into it and it turns out that iTunes maintains an XML version of its library information file. But then I discovered that the Android playlists are stored in a highly technical format called ASCII-encoded text files. Let me tell you, it took forever to crack that puppy. <br /><br />Well when all you have is a hammer every problem looks like a nail. When you have Python every problem looks... easy. So I decided to make a Python program to:<br /><br />1) Read the XML library file. <br />2) Figure out what playlists are in there<br />3) Figure out what songs are in those playlists<br />4) Figure out where those songs are<br />5) Make Android playlists from the iTunes Playlists<br />6) Copy the playlists and music files to the Android device<br />7) DANCE!<br /><br />So at first I tried using my favorite parser - SGML parser. But it turned out that SGML parser doesn't handle truncated tags. You know - the ones with nothing in them? With only a start tag that has a / in it and then it's done? Yeah, those. So I had to switch to expat which isn't so bad either. <br /><br />But enough of that! I'm going to show you what I did that's a good coding practice. The iTunes XML file has several parts in it: a general section that describes the library, a tracks section that describes each track and assigns it a unique ID, a playlists section that describes the playlist and lists the unique track IDs in the playlist.<br /><br />I wanted to start off by parsing all the goodness of the general library section and ignore the rest while at the same time planning ahead so I would... be able to figure out where to put the code to parse the rest of it as well. To that end I present a random code snippet:<br /><br /><blockquote><br /> def handle_data(self,text):<br /><br /> if self.current_tag == KEY_TAG:<br /> self.current_key = str(text)<br /> print "Key: " + text<br /> elif self.current_tag == INTEGER_TAG or self.current_tag == STRING_TAG or self.current_tag == DATE_TAG or self.current_tag==TRUE_TAG:<br /> if self.current_parent == LIBRARY_KEY:<br /> if self.current_key in libraryKeyList:<br /> print self.current_tag + "=" + text<br /> self.tempDict[self.current_key] = text<br /> <br /> elif self.current_parent == TRACKS_KEY:<br /> pass<br /> elif self.current_parent == PLAYLISTS_KEY:<br /> pass<br /> elif self.current_parent == TRACK_KEY:<br /> pass<br /> elif self.current_parent == PLAYLIST_KEY:<br /> pass<br /> else:<br /> pass<br /> <br /> self.current_key = ""<br /></blockquote><br /><br />Some explanation: this function handles data inside of tags. It handles key tags specially, but handles tags that contain data (integer, string, date, etc) differently still depending on which section they reside in. So you can see I've written the code that handles the data in the library section but left out handling data in all the other sections. But this is by design: if I wasn't planning ahead I wouldn't have put the if statement that checks what the parent is in that function. I would just have put the code that handles data for the library section without verifying that I was still in the library section - and then it would have handled a whole lot of data in the rest of the file. <br /><br />By putting the parent key check in there and explicitly listing the different situations that I want to code for I'm doing two things. First, I'm specifying the exact situation I expect this code to run in - putting my assumptions right out there in the code. Second I specify all of the other situations that I haven't yet coded for but want to in the future. I'm using the code to inform myself (in the future) that I need to put code there that does something different. That's the good coding standard. <br /><br />It can be used in a variety of languages. In Python use the above form but make sure that you put the pass statement in an empty case - otherwise it gets angry. In C you can use #warning directives to produce a warning when you know you'll have to write some code but just haven't yet. Like '#warning Will Robinson, you didn't handle the default case!'Stevehttp://www.blogger.com/profile/12436983454045119515noreply@blogger.com0tag:blogger.com,1999:blog-475972232930633782.post-64479060109648469132011-07-03T07:25:00.001-07:002011-07-03T08:18:49.076-07:00On ExcellenceI fancy myself pretty good at C. Not great, but pretty good. I can find my way around source code, I can write from scratch, I can debug with the most average of them. I'm handy in a variety of ways and I eat source code for breakfast. <br /><br />This didn't happen in college. This didn't happen in high school. This didn't happen in freaking <span style="font-style:italic;">grade school</span>. I have been programming since I was 6. I started off with AppleSoft BASIC on an Apple IIc knockoff (Laser 128c was the correct answer for those of you playing the home game). After AppleSoft BASIC it was GW-BASIC on the 8088 and QuickBASIC on the 286 and up. But roundabouts high school I decided I had to learn C - because that was the language that <span style="font-style:italic;">grownups</span> used. So I bought a C book (<a href="http://www.amazon.com/Programming-Language-2nd-Brian-Kernighan/dp/0131103628/ref=sr_1_1?ie=UTF8&qid=1309703441&sr=8-1">the right one</a> as it turns out - if you want to learn C <span style="font-style:italic;">get this book first</span>), downloaded <a href="http://www.delorie.com/djgpp/">DJGPP</a> and got to work!<br /><br />I'm having a computer weekend (putting a computer whose hard drive failed back into working order) so I'm going through old files looking for utilities and just plain reminiscing. I decided to see what my old C code looked like.<br /><br />Oh God, it's awful. <br /><br />It's terrible. Here's an example (with some helpful comments from future Steve):<br /><blockquote> i=-1; <br /><br /> fseek (readfile,0,SEEK_END); //Set starting point to end<br /> size = ftell(readfile); //Find file size<br /> fseek (readfile,0,SEEK_SET); //Set starting point to start<br /><br />//FS - Seriously? Is there no better way of getting the size of a file?<br /><br />//FS - Oh god, who gave me malloc?<br /><br /> readfiledata = malloc(size); //Allocate memory for char<br /> <br /> printf("Filename is %s\n", argv[1]);<br /> printf("Size is %d\n", size);<br /> printf("Copied %s to steve.tmp\n", argv[1]);<br /><br /> //FS - WHAT?! WHAT?! Index of -1? <br /><br /> i=-1;<br /><br /> do<br /> {<br />//FS - SERIOUSLY!? Is there no easier way to get all the data in an array? Did you not look?<br /><br /> readfiledata[i] = fgetc(readfile); //FS - OH GOD YOU ACCESSED INDEX -1 OF AN ARRAY!<br /> i++;<br /> }<br /> while(!feof(readfile));</blockquote><br /><br />In case you were wondering, I used malloc() and, no, there is no corresponding free() call. I relied on the fact that the OS would free the memory once the program exited. There were variables defined in .h files (no, not extern defines, plain old defines). There were what should have been arrays of constant strings were 'initialized' using sprintf (copy constant to string) rather than just initializing them when the array was defined (as any normal person would do). <br /><br />And the best part is that the whole program I made basically amounted to a regular expressions parser. All I needed to do was remove images and other formatting from HTML files so they'd be easier to print off and use less ink. That could have been done a lot easier. <br /><br />This was 1999. So, becoming average takes at least 12 years of constant use of a skill - and I still screw up. Looking at this I can see a lot of myself in new grads coming out of college - the same mistakes, the same assumptions, the same basic design assumptions that end up making bad code (even if it runs). It falls in line with Malcom Gladwell as he writes in <a href="http://www.amazon.com/Outliers-Story-Success-Malcolm-Gladwell/dp/0316017930/ref=sr_1_1?ie=UTF8&qid=1309704507&sr=8-1">Outliers</a>: if you do something for 10,000 hours you'll be great at it. It's not necessarily innate skill, it's practice, practice, practice. It's why I'm a professional programmer and not a professional trombone player - I just code a whole lot more than I play trombone. <br /><br />So knowing this I can see where new grads come from - hey, they haven't had 10,000 hours of programming, they probably haven't had 10,000 hours of anything engineering related from their college experience. 10,000 hours is 3.5 years at 8 hours a day and that's just for one skill. Engineering is a whole plethora and if you don't know where your career is taking you, why bother practicing one skill over another?<br /><br />That's my strawman argument - I don't agree with it. My question is - if you know you won't have you 10,000 hours in whatever you want to be good at by the time you graduate college (and by extension, be able to show some really awesome work to a prospective employer) <span style="font-style:italic;">why didn't you start earlier?</span> Did you <span style="font-style:italic;">plan</span> to be average? To be right in the middle of the pack, to not stand out? To be, essentially, replaceable by any other member of your graduating class? Did you plan to go out into the job market and have a big corporation tell you what you should be good at instead of deciding it yourself? Didn't you get into engineering for a reason? <br /><br />I see people on both sides of this question and you can tell them apart right away in an interview. The people who don't know why they're engineers - the ones who didn't start early excelling at something they loved and wanted to do - come to a job interview and basically want you to tell them what kind of career they should have. They hit the middle of the road for all of their classes - probably picked whatever electives were the most popular because they didn't really care about the difference, didn't have an opinion on what they wanted, didn't find anything particularly exciting and just followed their friends into a class. Their senior projects were whatever they were assigned and they just sort of did them. They don't speak about them with passion, they just wanted to graduate and they needed a project, so they did it. And they're not dumb - a lot of them have 4.0 GPAs for what its worth. But since they didn't know what they wanted to do they never got in-depth on anything. They never really put together the pieces that every single topic in electrical engineering is inexorably linked to every other. Analog circuits mean differential equations, considerations of bandwidth, frequency response, frequency content of waveforms, Fourier Series, linear algebra, matrix equations and any other number of fields of study. The coursework isn't a checklist, it's a symphony of learning. But if you don't have passion it is just a checklist. Mom and dad want you to be an engineer. You're smart, so you do well in classes and you graduate with a high GPA. You go for a job at a big corporation and they grind you into whatever kind of employee/engineer they want. Yay for you - you're average.<br /><br />But the ones who have passion and drive and love what they've done - they stand out immediately as well. They had a definite plan when they went to college. They'll tell you how they took apart TVs when they were a kid (good Lord it's dangerous - let your kids do it but make sure those capacitors are discharged) or how they wrote dumb little computer games in Visual Basic to entertain themselves. They just won't shut up about their senior project or whatever personal projects they have if they haven't started their senior project. Their eyes light up when you suggest ways they could improve their project ('Ooooh my God... I wish we could go back and work on that more - I'd make it so much better!') or they kept working on it themselves after they graduated. They've learned weird programming languages for fun. In essence, they love what they do and they just won't stop doing it. They don't ask you for direction, they tell you - I'm this kind of engineer and I love doing it, do you need me? And the answer is usually yes, we need you.<br /><br />So essentially the choice is yours: You can be average or excellent. There is certainly a long road between the two, but you have the choice to take the journey and practice practice practice. And if you find out that whatever you had your eye on doesn't really interest you then fine - move your target, pick something else. Excel at something. Hell, maybe you'll have 10,000 hours of random junk you've practiced. That's okay - it makes you an excellent generalist. Don't just sit around and play video games - ply your craft. I guarantee there's a payoff even though it's a long way down the road. Yes, a very long way. But it's worth it.Stevehttp://www.blogger.com/profile/12436983454045119515noreply@blogger.com2tag:blogger.com,1999:blog-475972232930633782.post-5653827012558587532011-06-20T07:26:00.000-07:002011-06-20T07:29:14.935-07:00Fathers DayI just read a nice article about someone whose father taught him how to build, use tools, make things. Reading that, it occurs to me that I've never heard a 'My father taught my how to code and I'm grateful for it.' story. It seems like everyone who codes well has been mostly self-taught - a loner. I wouldn't have wanted it then, but looking back now I would have liked to have been taught something so wonderful by my father. I hope we have these stories someday.<br /><br />That is all.Stevehttp://www.blogger.com/profile/12436983454045119515noreply@blogger.com0tag:blogger.com,1999:blog-475972232930633782.post-31831668439880427242011-05-25T18:37:00.001-07:002011-05-29T07:42:52.780-07:00DocumentationPeople say they hate writing documentation, but what they really hate is Word. And even Word would be okay if no one cared about formatting. Once you have to conform to these corporate styles things get so awkward - oh, you used 11 point font instead of 10, your margins are .05" off, you can't use a table here because it doesn't justify correctly. I've been in peer reviews where the only comments people have are formatting (and spelling errors). It's such an anti-pattern. <br /><br />Wouldn't it be much better if documentation were like wikis? Where anyone can find the document they want to edit? Where all you need is a web browser to edit it and it's just text? Sure you have to use *'s instead of bullets maybe, or -'s or something, but have you looked lately how many different options you have for bullets in Word? It's insane. I'd rather have one ugly bullet. <br /><br />So sure wikis are simplistic, but they're straightforward and you get to focus on writing instead of margins. But they don't work for real engineering, right? Real engineering documents are version-controlled, have complicated title pages, fancy diagrams and backgrounds that say things like 'UNCONTROLLED'. Wikis couldn't ever.... or could they?<br /><br />Step one: version control. Github now has wikis. But Github doesn't just do wikis - anyone can do wikis. Github does version-controlled wikis. Wikis are written in text-based markup: typically Markdown, MediaWiki, etc. But they're all text - just text. Github saves each page you create in the wiki as a text file in a repository separate from the project you're working on. The only non-ideal thing about this whole setup is that all of the wiki pages are stored in one directory - no structure at all. So if you want to create a block diagram for a sub-assembly in a sub-directory you'll have to figure out how to store that information somewhere. I'm considering storing the directory information in the name somehow, but this may be a bit unwieldy.<br /><br />So you'll end up with a bunch of text files with odd markup stored in a repository separate from your project. Surely there must be a way to take these text files, written with special markup, and turn them into something (dare I say) pretty? Well of course there is - Github takes the text files and creates web pages doesn't it? So yes, it can be done and it will be done. There's an open source program called <a href="http://johnmacfarlane.net/pandoc/">Pandoc</a> that describes itself as a swiss army knife for transforming markup formats. If you look at the list it can exchange between a lot of formats. Very neat, very useful. Now instead of text files you can get PDFs or... DocBook.<br /><br />Now with the PDFs you get PDFs that look like nice, printable versions of web pages. Basic but serviceable. But engineering documents from real engineering companies don't just look serviceable - they look complicated. They're full of revision history blocks, referenced documents, government standards and the aforementioned 'UNCONTROLLED' backdrops. You can still do this in this approach but you need a lot more finesse. Enter <a href="http://steves-wiki.wikispaces.com/DocBook">DocBook</a>. DocBook is used to create... books. You know all of those programming books with different animals on the front? Like <a href="http://www.amazon.com/Learning-bash-Shell-Programming-Nutshell/dp/0596009658/ref=sr_1_14?ie=UTF8&qid=1306679326&sr=8-14">this</a> one? If my history is correct, they're all written in DocBook and in fact O'Reilly invented DocBook so they could write their books easier. That's why the all pretty much look the same. That and I guess those folks are boring. <br /><br />The great thing about DocBook is that it's customizable. The input files are just XML, but the output is usually PDF - just print it off, bind it, draw a fish on the front and you've got a book. Or, if you want an engineering document, you describe some table layouts for revision history, title page, etc, fill out that information in your XML file, transform it and then you've got an engineering document. True, that will be a LOT of work, but so is trying to use Word to do the same thing. Best of all, Git <span style="font-style:italic;">is</span> version control, so your revision history is built-in: you can parse Git commit logs to fill out the revision history section. If your referenced documents are in version control (which would be a good idea) then you can link right to them. And DocBook has all sorts of other neat features built in: automatic table of contents creation, automatic figure referencing with hotlinks, you name it. It's worth looking in to.<br /><br />Text is great, yes, but we all scream for graphics. The Github wikis can reference documents from your project repository on the Github wiki, so including graphics in the online wiki is not really a problem, but what about on locally-produced PDFs? This might bet hairy. Pandoc has a different format for specifying image links than the Github wiki has. Luckily Pandoc is an open-source project so you can modify it to your heart's content if you so like. I might just figure out something else. So the workflow looks like this: <ol><li>Draw your tables, graphics, etc in whatever program you use locally. </li><li>Use command-line tools (as part of a makefile) to export the local graphics to a GIF or JPG format so they can be included in your documentation. </li><li>Save the newly-exported graphics in a common area of your project repository.</li><li>Commit your changes to Github.</li><li>Write your documentation in a Github wiki and reference the graphics you just committed. This will produce easily-accessible online documentation.</li><li>Retrieve the wiki changes from Github to your local wiki repository.</li><li>Modify the local copies of the wikis to allow Pandoc to run on them seamlessly.</li><li>Run Pandoc on the wiki text files to create either PDF output or DocBook output and copy it to the correct place in your project repository directory structure</li><li>If you just want PDFs, you're done. If you created DocBook output then there will be another step to distill the DocBook to PDF after running it through all of your custom stylesheets.</li><li>Commit your changes and you're done</li></ol>Tada! You have professional-looking PDF documentation derived from a wiki and various graphics. And what's great is that most of these steps are automated once you set up the makefiles. The only non-automated steps are actually writing the documentation, making the graphics and creating the stylesheets. Aren't you happy?Stevehttp://www.blogger.com/profile/12436983454045119515noreply@blogger.com0tag:blogger.com,1999:blog-475972232930633782.post-15102996377955187982011-05-18T04:52:00.001-07:002011-05-18T04:52:26.765-07:00Tool Vs. PatternsIt's hiring time where I work - mostly new grads. That means lots of confusion. The disparity between what new grads expect and what actually happens in industry is sometimes wide. <br /><br />For instance, my company might say 'We're looking for people with knowledge of VHDL to program FPGAs'. Plenty of students take a VHDL class or two - so you'd think that'd be a good fit, yes? <br /><br />Yes... and no. The tool is not the end product. Whatever is made will be made with VHDL, true, but the end product will not materially depend on VHDL being the tool used to create it. In fact you could use Verilog to achieve the same, or even schematic capture. Or even step back a bit: digital logic is fundamentally NAND gates or NOR gates. You can make any digital device from NAND gates - everything from a half adder to an iPod. But you won't get a job anywhere just because you memorized the pinout of an SN7400 IC - the important part is <span style="font-style:italic;">what</span> you're creating moreso than <span style="font-style:italic;">how</span>. Fundamentally, being familiar with common patterns used in your field of choice is the mark of a good developer moreso than a strict adherence to syntax.<br /><br />I'll illustrate with an anti-example that's more in my line. Let's talk C code. 'But it compiles!' has been long the defensive cry raised from many a young coder to defend their petty messes. Their unspoken assumption is that adherence to syntax is the sole qualification of a good C coder. This is patently untrue and a prime example is the anti-pattern of placing all of your code into main(). We've all done it - in fact it's the first thing you learn in class because they haven't taught you function calls yet. But is it a suggested practice? Not in the slightest. It produces code that's difficult to read, difficult to control (requiring the use of many <a href="http://xkcd.com/292/">gotos</a> (warning: <a href="http://www.cs.utexas.edu/users/EWD/ewd02xx/EWD215.PDF">considered harmful</a>) and just in general a pain. Of course the proper way to write code is the use of function calls to compartmentalize functionality and efficiently reuse it. The only people who deny this are defensive greenhorns more concerned about compiler errors than writing maintainable, readable and efficient code. Knowing syntax is a necessary condition for being a good programmer/engineer/developer, but certainly not a sufficient condition.<br /><br />What about a straight example of why you should pay more attention to patterns than syntax? Something that looks awful but is brilliant, effective and clean. I present to you <a href="http://www.lysator.liu.se/c/duffs-device.html">Duff's Device</a>:<br /><br /><blockquote> send(to, from, count)<br /> register short *to, *from;<br /> register count;<br /> {<br /> register n=(count+7)/8;<br /> switch(count%8){<br /> case 0: do{ *to = *from++;<br /> case 7: *to = *from++;<br /> case 6: *to = *from++;<br /> case 5: *to = *from++;<br /> case 4: *to = *from++;<br /> case 3: *to = *from++;<br /> case 2: *to = *from++;<br /> case 1: *to = *from++;<br /> }while(--n>0);<br /> }<br /> }</blockquote><br />(Code formatting is always iffy on this blog so you'll have to forgive me.) <br /><br />What manner of insanity is this? It's truly mind-breaking when you first look at it. So much so that when I show it to new grads/students the first words out of their mouths are more often than not 'Well that won't compile'. <br /><br />And at this point I get an evil, evil smile on my face. They've shown their hand - more concerned with syntax than patterns. I assure them that it does and the response follows 'But it's not right!' Oh but it compiles! So it must be right, no? Oh the joy I have at this point - I've defeated a mere child in a battle of wits (Ok, I'm not a great person). None of them attempt to figure out what's going on - which is sad. Because once you understand the purpose and function of this code you recognize at least two patterns right off:<br /><blockquote>*to = *from++</blockquote><br /><br />This is your basic memory copy with a twist - the destination address isn't incremented. If you're really smart and had a focus on embedded systems you might realize that's because it's meant for a memory-mapped I/O register so the address won't change between writes.<br /><br /><blockquote> switch(count%8){<br /> case 0: do{ *to = *from++;<br /> case 7: *to = *from++;<br /> case 6: *to = *from++;<br /> case 5: *to = *from++;<br /> case 4: *to = *from++;<br /> case 3: *to = *from++;<br /> case 2: *to = *from++;<br /> case 1: *to = *from++;</blockquote><br /><br />You <span style="font-style:italic;">might</span> recognize this as <a href="http://en.wikipedia.org/wiki/Loop_unwinding">loop unrolling</a>. Loop unrolling is used to minimize the overhead incurred from jumping around in a loop: instead of doing one thing n times you do four things n/4 times. Useful. <br /><br />Go ahead and read the full explanation of Duff's Device. If you can follow, you'll see why it's an amazing piece of code and why it vindicates the idea of patterns. Tom Duff understood assembly programming and knew how to implement loop unrolling in it - he was familiar with the pattern. He wanted to do it in C but couldn't think of a straightforward way so he <span style="font-style:italic;">abused the <span style="font-weight:bold;">hell</span> out of C syntax to make it work</span>. It makes you want to cry for joy and in pain because it looks like that poor, efficient program is being tortured to death. <br /><br />This is why patterns are more important than syntax. Patterns are like tools: if you're working too hard, chances are there's tool to help you be lazy. And new engineers usually work way too hard - most often at reinventing the wheel. They'll figure out some complicated method of ensuring single-access to a variable because no one taught them about semaphores. Oops. Patterns help us write efficient and correct code because they are distilled knowledge - the lessons of programmers before us given form. It pays great dividends to know about them.<br /><br />That's what 'x years of y experience' on a resume means: I know a lot of patterns, I have a lot of tools in my toolbox, I won't make stupid mistakes because I'm past that. If knowing syntax is intelligence then knowing patterns is wisdom (go D&D!). If you don't have both you will never be as awesome a programmer as Tom Duff.Stevehttp://www.blogger.com/profile/12436983454045119515noreply@blogger.com0tag:blogger.com,1999:blog-475972232930633782.post-43952031648357863832011-05-02T18:27:00.000-07:002011-05-03T18:44:04.353-07:00Offering AdviceI spend an inordinate amount of my free time on a site called <a href="http://www.chiphacker.com">Chiphacker</a>. It's a <a href="http://en.wikipedia.org/wiki/Stack_Overflow">Stack Overflow</a> for electronics, embedded software and general EE nerdiness. Sometimes you get wonderful questions like this one:<br /><br /><blockquote>Hey guys, I'm trying to properly bias the LM34476U chip (datasheet here) for operation in the saturated MODE. However, I want to be able to dynamically change the bias to on mode when my signal source changes. I've sketched out a design using the MAX4640AB 4:1 multiplexer that will switch out bias resistors but I'm getting a split second where both resistors are conducting and the feedback causes ringing in my output that I can't get rid of. Can anyone recommend methods to reduce the bandwidth of the LM3447 to eliminate the ringing? I've checked the app notes but the method they suggest there doesn't apply directly to my circuit topology and I don't know where to connect the feedback capacitor with my setup. </blockquote><br /><br />Wow, just wow. It's questions like that that I open up my circuits text book for.<br />Literally - check out this question <a href="http://electronics.stackexchange.com/questions/13592/diffusion-capacitance-approximation-for-bipolar-power-transistor/13598#13598">here</a>. I was even <span style="font-style:italic;">nice!</span><br /><br />But sometimes there are questions asked that... spawn blog posts. That spawn stand up comedy routines ('Hey guys did you hear about the guy that asked a stupid question on the internet?'). Questions asked by people with obviously little knowledge of engineering, analog design, programming, digital logic, etc. Out of respect for the guilty I will not post one of the questions here but instead show you a creation of my own twisted mind that makes me approximately as angry as the real thing:<br /><blockquote>Hey guys, I've just had a great idea that I'd like to follow up on but I don't know where to start so I was hoping you could give me some pointers.<br />It seems to me that a lot of disabled people have problems with picking things up, so I want to build a robot that will roll around and pick up the things that they need picked up and you can control it with voice commands.<br />I've got a lot of software experience with VB6 and I've been reading up on the PIC so I think I can write the code for it when I find an implementation of the .NET framework for the PIC. <br />What I don't know about is the motors and stuff and the voice control maybe. I need the robot to roll around with wheels and its hand has to be just like a persons hand so it can pick everything up. <br />It also needs to know what the words for things are and it should probably understand if you point at something too. <br /><br />My cousin is disabled and he has such a hard time... I really want to help him and think this is a good idea. Do any of you guys know a website or book that can help me figure this stuff out?<br /><br />Thanks guys, I know together we can work this out!<br /></blockquote><br /><br />This just makes me angry. Doesn't it make you angry? The first thing that pops up in my head is that this isn't really a question. If you had to distill it it wouldn't end up as 'Is this possible?' or 'What will be involved in doing this?' but instead 'Tell me how to do this'. It's like saying 'I want to get into Heaven - tell me how to do this.' Man, you'd be in for quite a discussion let me tell you....<br /><br />But what are the specific ways I hate this question: Oh, let me count them:<br /><br /><blockquote>Hey guys, I've just had a great idea that I'd like to follow up on but I don't know where to start so I was hoping you could give me some pointers.</blockquote><br /><br />First off, I hate it when you use any honorifics ('Dear sirs, I am many problems with this software having! For much to help please!') or really, any form of address. Don't call me 'guys', don't pretend like you know me unless you post regularly. Yes, I do check. Secondly the phrases 'I don't know where to start' and 'give me some pointers' indicate this person has no idea how to do what he wants to do. At all. Not even close. When the last time you had a great idea didn't you at least have some clue how it might be done? You think 'I want to know when I should stop pulling my car into the garage' and then immediately assume that this is a question you shouldn't even consider - that you should go consult a professional? Even if you start thinking about it and conclude you don't have enough specific knowledge to formulate a final solution that at least leaves you with some specific questions to ask. If for some reason you decided it needed to be electronic you'll quickly reach the question 'How can I measure distance electronically?' Then you ask THAT question to the professionals. Saying 'I don't know where to start' means you didn't bother to think through it even a little or you honestly don't understand what you want.<br /><br /><blockquote>It seems to me that a lot of disabled people have problems with picking things up, so I want to build a robot that will roll around and pick up the things that they need picked up and you can control it with voice commands.</blockquote><br /><br />This boggles my mind. Do I want to help disabled people? Yes. Do I understand some of the issues that may be affecting them? Yes - apparently they 'have problems with picking things up'. Could I design an apparatus that might help disabled people pick things up - via voice commands? Perhaps - but it would take years. You see, I'm a simple embedded software engineer (before this I was a controls engineer - before that an electrical engineer and before that? Farmer) and the request you just made involves at least four different fields of study (Mechanical engineering, embedded software development, computer science with a specialty in artificial intelligence, digital signal processing, analog design - all of the top of my head) and would require someone with a college education in each. I'd probably need one PhD as well - just for good measure. It's not as if I could do wonderful things to help the disabled but I just get drunk instead. This is HARD. <br /><br /><blockquote>I've got a lot of software experience with VB6 and I've been reading up on the PIC so I think I can write the code for it when I find an implementation of the .NET framework for the PIC. </blockquote><br /><br />Okay... this means you don't understand any of the potential tools you might be working with. Do you guys know what the PIC is? An 8-bit microcontroller that can't find its ass with both hands. Actually, scratch that - the PIC only implements one hand in hardware and requires you to emulate the other hand in software if you want to access it. This thing is dumb as sin. It most certainly doesn't have an implementation of .NET and even if it did the first thing he'd probably try to do is make 'Hello World' using console.writeline or whatever prissy function they use because they're not man enough to call it printf. You have to work with bits when you use this thing. Software people don't even know what bits are anymore - this guy is way out of his league.<br /><br /><blockquote><br />What I don't know about is the motors and stuff and the voice control maybe. I need the robot to roll around with wheels and its hand has to be just like a persons hand so it can pick everything up. <br />It also needs to know what the words for things are and it should probably understand if you point at something too. </blockquote><br /><br />Oh okay, what you'll admit you don't know about is maybe 3/4's of the entire thing? So at the very least it's only ten years of school? Do people seriously think that these matters are trivial? Many legitimate college graduates are simply lost as far as practical skills in their first job and even then a mechanical engineer (for instance) isn't a machinist - he may be able to design the mechanical parts but he can't make them. You need someone who works with his hands and hopefully still has all of his fingers - that means he's good! And I'm not even going to get into how difficult it is to 'make it understand words'. Suffice it to say the most advanced processing hardware in the world takes years to learn a language and usually doesn't learn it correctly anyhow. <br /><br /><blockquote><br /><br />My cousin is disabled and he has such a hard time... I really want to help him and think this is a good idea. Do any of you guys know a website or book that can help me figure this stuff out?<br /><br />Thanks guys, I know together we can work this out!</blockquote><br /><br />Oh of course - a book! Or website! All he needs is a website - one that tells him EXACTLY WHAT TO DO. Every step from A to Z to make this magical device that barely exists in his mind because he hasn't thought it through very much. Yes, I wrote that webpage - it's on Geocities. I dare you to find it. Face it - even if such a thing exists someone's selling it and they're not going to tell you how to make it. They're not going to document it completely and put it on the web for you to reproduce so you can not pay them anything. People like their effort to be rewarded - and this is effort<br /><br />People will try to defend this person. 'But Angry', they'll start, 'he just wants to know if it's possible!' Screw that - everything is possible. Period. It all depends how much you want to pay. And I can't tell you how much it will cost. Do you realize that real companies have people who are paid - full time, real money - to estimate how much jobs will cost? And (call me cynical) when you tell him that the price for development of this miracle is in the millions he'll say 'I don't understand why it needs to cost so much!!! You can't be for real!' You see, he has already demonstrated that he lacks the ability and knowledge necessary to judge the difficulty of the ideas he presents. Remember that as far as he's concerned he simply hasn't found the right website to tell him how to do it. After that it's easy.<br /> <br />'He just wants to know what it will take!'<br /><br />Seriously? Remember how he can't tell whether he's asking for something reasonable or something insane? When I tell him it's something insane guess what? That's not the answer he's looking for. He has every reason to ignore me and perhaps ridicule me. I can't say for sure whether he has a rigid mindset that won't listen to reason but I am saying for certain he has no facility to judge whether something is reasonable or not. So why even ask? Why not ask 'Am I way off base here?' instead of 'Show me how to do this'. <br /><br />'You should at least be nice to him'<br /><br />Well... I could. It's true. I don't have to do anything - so many questions simply remain unanswered, bereft and eventually die in obscurity. It feels so fulfilling to see no answers, no comments, no nothing on a question months after it's been asked. But I have my limits. I am the Angry EE for a reason. And that reason is that some things I just can't let go. On the internet anyhow - where all I have to do is type. Otherwise? Waaaay too lazy. But I will not refrain from essentially answering his question in the only way one paragraph can. I am not on retainer for more than one paragraph - no one on stackexchange sites should be. It will be pithy, it will be a little acerbic, but it will be right. If you choose not to believe it, I will follow up with comments that make fun of you more and more. <br /><br />The moral of the story is to do work for yourself. Do some, any! Then you can ask more specific questions - questions which I will be less hesitant to answer than blanket questions about topics you obviously don't understand and haven't thought about. I answer lots of questions on this site and there's plenty of good ones which means that plenty of people don't expect me to do their homework for them. I like those people. Yeah, don't expect me to do your homework. Homey don't play dat. <br /><br />(Does anyone get that reference?)Stevehttp://www.blogger.com/profile/12436983454045119515noreply@blogger.com0tag:blogger.com,1999:blog-475972232930633782.post-22955069280598548282011-04-23T19:05:00.001-07:002011-04-27T04:39:13.352-07:00THE FUTUREFor me, this weekend I realized that I was living in the future.<br /><br />I've always been bullish on the future. I read a lot of science fiction and science fiction loves the future Time travelers from our time go into the future for some reason and they see all of this cool technology: warp drives, transporters, ray guns, nanoconstructors - you name it. Science fiction writers love science but most of the time they skimp on the social aspects of the future. Do we have racism? Is there free love? Are drugs legal? Is religion abolished?<br /><br />Sci-fi writers are often less eloquent on these matters. Roddenberry wasn't. He showed us a world in stark contrast to the one that was developing around him. Racism: gone. Freedom: for everyone in every way. No one is sick because we all decided that wasn't going to happen in our world. No one is hungry because not a single person on Earth could bear to see a person starve. There's no war because we're way too grown up for that. There's no money because we're all so rich we don't feel the need to measure it anymore.<br /><br />But the uniforms he put his characters in were absurd.<br /><br />Seriously, go-go boots? Miniskirts? Captain Kirk is pretty much wearing pajamas. I mean take a look at military uniforms in our time. They've changed only somewhat in the past 300 years. They're full of creases, corners, polish, buckles and complication. Uniform maintenance is the primary method of making grown men cry in the military. I don't foresee a general relaxing of military culture to the point that you can chill in pajamas on the bridge of the flagship within Star Trek's timeline.<br /><br />Specific predictions about the future can get tricky. Very few people predicted even really obvious stuff like computers and cell phones. And clothes are worse. Fashion is unrecognizable year to year. The best rule I've figured out is the 20-year rule: whatever you're wearing now will be stylish again in 20 years (assuming it is currently stylish). It works well enough in a general sense, but I'm also quickly losing sense of what is fashionable right now anyhow.<br /><br />Which is why I was blindsided this weekend. We went to the beach (note to everyone in the frozen north: it is simply gorgeous out here and the water is plenty warm). I saw a bunch of surfers - many of them much much younger than I. And they were ripping up the waves and...<br /><br />Wearing war paint.<br /><br />Yeah, streaks of red, blue and yellow all over their faces, arms, chests, you name it. They looked like they belonged in Braveheart. I don't normally attempt to fathom the culture of kids these days but this one left me curious. The only explanation I could think of turned out to be the right one: it's sunblock.<br /><br />And of course it's sunblock. Let's do the math: you need to wear if you're going to be out in this sun and it pays to be generous with it. When I was bailing hay in summers on the farm I used pure zinc oxide - creamy, greasy and great at picking up dust and dirt. But you had to use it - normal stuff wouldn't get the job done and even with the zinc oxide you had to slather so much on that it was opaque. I looked like one of those nerds you see in movies who never goes outside - pure white nose peeping out from behind a wide-brimmed hat and long sleeves in the middle of summer.<br /><br />Oh if only I could have looked cool AND gotten sun protection....<br /><br />Oh, and now in THE FUTURE you can. You can cover yourself in sunblock and look like a warrior instead of a nerd. This is the sort of great idea that I never had or even considered, but seems so foreign when you suggest it:<br /><br /><blockquote>"In the future," the traveler started, "the kids wear war paint!" The pitch of his voice raised on the last half of his sentence as if he had made a particularly incisive statement. "They go to their sports games all painted up with their team colors, fancy designs on their faces to intimidate the other team - who of course have their own paint. Some wear it for every day pursuits too - go to the store and you might see some of them there."</blockquote><br /><br />How odd! How interesting! How different! THE FUTURE! Of course, in this case the future isn't foreign or odd. If you start from certain suppositions (you need sun block, sometimes you need it really thick, but it looks dumb) then it's not a far leap to the conclusion (non-dumb-looking sun block should be invented).<br /><br />Yes, THE FUTURE has arrived for me and it's a good thing: someone had an idea that seemed foreign and senseless to me but is in actuality insanely great (and it's making the world a better place). Kids are wearing more sunblock, protecting their skin and stopping cancer - but they don't look like idiots. Yes, in THE FUTURE the right thing to do is also the cool thing. I want more future please.Stevehttp://www.blogger.com/profile/12436983454045119515noreply@blogger.com0