Wednesday, May 13, 2009

Power Power Everywhere...

But specifically from the sun. We will never run out of power (never being equivalent to several billion years) because of the sun. Consider that most of our power comes from consuming things. Basically we burn things - we turn complex hydrogen-carbon chains into simpler ones and live off of the resulting energy output. Coal, wood, sugar - it's all the same. Combustion. The sun is better. The sun is powered by gravity itself. By the very shape of the universe! There's a lot more energy out there than sitting in every oil field, forest or coal mine. But how do we access it? The simplest method is by laying in the sun and getting warm. As much as I like a tan, I LOVE electrical power! So I use solar panels.

Let's talk about them for a second. Solar panels are a lot like batteries in some ways. You start out with solar cells which are maybe an inch square of real estate. They're made of silicon in an extra-special arrangement which causes them to produce voltage and current when light strikes them. But how much of each? There's essentially two main parameters that matter. The first is open-circuit voltage, the second is short circuit current. They're fairly self-explanatory: if you shine sufficient light on the cell and don't put an electrical load on it then you'll measure the open-circuit voltage across its output; if you shine a light on it and put a short circuit on the output then you'll measure the short-circuit current through the output. In between those points is not a straight line, but more of a graph with a knee. Take a look at the graph I show below and you'll see what I mean.



You'll notice that the cells are almost constant voltage sources except when you attempt to draw currents close to the short-circuit current. You can either use a simplistic model of a constant voltage source or you can use a more complicated model that accounts for the actual behavior more:



If my calculations are correct, Il is the short-circuit current and the open-circuit voltage is equivalent to Il*RSh. Props to Wikipedia for having such awesome images that I can steal for free. I like free.

So that's your single solar cell. They're a lot like the cells of a battery as I mentioned last time: to get a useful voltage out of them you have to put a lot in series. The difference between these and batteries is that you also typically have to put several sets of cells in parallel to get a decent current. I have an 18V solar panel made out of perhaps 32 solar cells - 8 in series and four sets of these in parallel. Its open-circuit voltage is 18V and short-circuit current is 300mA. This actually makes it rather useful for charging batteries!

When charging batteries you need two things at the same time: voltage and current. Well lucky for us voltage and current together are POWER! And we can get power out of our solar panel! Success! Just connect wires to things and make it go! Well, not that easy. You need specific voltages and specific currents to charge our batteries. I have some Ni-Cad batteries that need to be charged at a maximum rate of (off the top of my head - don't hold me to this) their total capacity divided by 10. So I have 5 batteries that have a total capacity of 6A-Hours, so the max rate I charge them at is 6/10 = .6 Amps. And for charging these batteries current is the most important part: as you push more current into them their voltage goes up and you stop putting current into them when they reach about 13.8V. So you need your voltage to be at least above whatever the battery voltage is at the moment. Just figure you'll need at least 13.8V to get this to work.

So we have a specific power IN from the solar panel and we need different power OUT. My first guess is to use an LM317 in constant current mode. However this has problems. The main one is that as you try to draw constant current out of the solar panel its voltage will drop. And the LM317 is a linear device. For linear devices the rule of thumb is that the current into the device is the same as the current out, and the voltage out is less than the voltage in. Thus, you will need to make sure that your solar cell voltage stays above the battery voltage. Good luck, because even if you do make sure of that you will be dissipating the 'extra' voltage from the panel IN the LM317 as heat - thus losing it. Solar panels aren't amazing power sources, so I'd rather not waste any of the power that it does generate.

You can also do power transformation with a switched-mode device. The rule of thumb for switched-mode devices is 'power-in equals power-out'. The only loss is due to efficiency. Another great thing about switched-mode devices is that they can produce nearly any output voltage off of its input voltage. So you can always keep your output voltage above the battery voltage even if the solar panel voltage goes below it. The trick is that switched-mode power ICs are usually set up as constant voltage supplies. They employ a feedback voltage to set the output to the right voltage. They're a little control system! I love control systems! SOOOOO CUTE! It's contained in a single IC! Adorable!

Anyway, I know about control systems and I reckon that I can modify the feedback signal so that it's based off of the current going to the batteries instead of the voltage at the output. I would current sense resistor to monitor that current and then use a differential amplifier to amplify and scale the voltage from the current sense resistor. This would be the new feedback signal to the switched-mode power supply. Thus it would regulate its voltage to make sure that the proper current goes into the batteries.

My fingers are yet again getting tired so I'll mention that this is just the battery charging circuit. You still need an output stage connected to the batteries to power things off of the batteries. Also, there's an improvement on the simple battery charging circuit I described here. It's called a Maximum Power Point Tracker that gets even more power out of the panel than before.

Thursday, May 7, 2009

Wherefore Art Thou, Camping?

Exactly how many doohickeys can you take with you camping and still be considered to be 'roughing it'? I know many people for who camping means 'in a camper', i.e. they need their flat panel TV and fridge full of beer or they're not going. I will sleep in a tent, so I consider myself somewhat superior to these people. But being an electrical engineer I just LOVE gadgets and I can barely stop myself from bringing them along. I know not to even THINK about bringing a laptop, but I'm still bringing our battery-powered fan. Of course, instead of batteries I'm using an emergency jumpstart car battery thingamajig with a cigarette lighter power adapter. If you want to power AC devices you'll need an inverter - just make it has sufficient maximum power (I've experienced the letdown of not having enough power firsthand when my friends and I figured out we couldn't run a smoke machine off of an inverter plugged into a car. Memories!) I haven't graduated to thermoelectric coolers yet but soon I will.

The question is how to you power all of your gadgets in the wild? A car battery is a good start but for a perfectionist like myself it just won't do. Car batteries are heavy. If you have to carry anything any distance you'll with you hadn't brought it. You can find better batteries than the lead-acid car batteries. Nickel-Cadmium, Lithium-Ion and Lithium Polymer are all better options (i.e. greater power density per kilogram). Technology is only one thing to look for when choosing a battery. There are four main things to look for in a battery: Voltage, Capacity, Current Capacity and Technology/Battery Type (Ni-Cad or Li-on or whatever).

Voltage is easy for the most part. Car batteries are 12V nominally and for the most part that is the magic voltage. Since your car runs on 12V everything that plugs into your car runs on 12V so there's lots of devices out there that will happily run on this voltage. Other popular voltages are 9V and 5V, but if you have a 12V source you're in luck because you can use dead-simple linear DC-DC conversion to get down to those voltages. Look up the LM7805, or in fact, everything in the LM78xx line (the last two digits are the nominal output voltage). They're really simple to use - for an electrical engineer anyhow. Fun fact: a battery is not a single unit - it's made up of cells. Depending on what the battery is made of, each cell has a different voltage. It's intrinsic - entirely dependent on the technology used in the battery. You get other voltages by stacking these cells up in series. Lead-acid is 1.5V per cell I believe, so a 12V battery has 8 cells in series. Another fun fact: it's not called a battery unless there is more than one cell used in it.

Capacity of the battery is also straightforward. It's measured in Amp-Hours. If my battery is rated at 7A-Hs then it can in theory deliver 1A for 7 hours before it's empty. Of course this is simplistic. Voltage degrades as the battery empties, so if you need 1A at 12V for seven hours you may not be in luck. After hour three the voltage may go down to 11.5V, then down to 11V next hour, etc. If you're using linear step-down conversion then you're out of luck for a couple of reasons:

  1. You need a certain minimum voltage difference between the input to the voltage converter. If your battery voltage goes too low then you won't meet this requirement and you won't get any power at all. This can be alleviated with a switched-mode voltage converter

  2. Assuming the power output is constant, lower volts means higher amps. As your voltage goes down your converter will draw more amps just to have the same amount of power and this will cause your battery to drain faster. Switched-mode voltage converters are not immune to this


The degradation in voltage is a function of the battery technology, so your mileage may vary.

Current capacity is distinct from the other capacity. Current capacity is the ability of the battery to source large amounts of current. Not all batteries are equal in this respect. As with any non-ideal voltage source a battery has a certain amount of internal resistance. This means as current flows out of the battery, power is dissipated in the internal resistance. This creates heat. Heat causes explosions, especially when it's applied to exotic chemicals. Remember when Dell's batteries were exploding? They got too hot. They got too hot because despite the fact that Dell spec'd the batteries with a peak current of say 5A for one minute, the manufacturer ignored that and went cheap on the batteries. This caused them to heat up when the laptop pulled the amount of power from them it thought safe. They got so hot that the chemicals got angry, and *POOF*! Exploding laptop. In general batteries are high-performers for current sourcing - that's the reason your emergency jumpstart kit works better than the alternator on your Yugo - current capacity.

Technology is a good one. I'm not into chemicals and ions and things but it's somewhat exciting to see the effect that all of that sciencey stuff has on actual performance and use. As I said before, technology affects all sorts of things on a battery: nominal battery voltage, voltage degradation over time, capacity to weight ratio, discharge capability, charging method, discharge behavior, etc. In general your newer battery technology has better capacity to weight ratio, less voltage degradation, higher capacity and greater current capacity. What it doesn't have going for it is simplicity and reliability. Simplicity in that they're more difficult to charge. Lead-acid is dead simple: apply 13.8V to a 12V battery and let it go for a while. It will charge completely. Lead-acid is surprisingly hard to damage as long as you don't exceed its recommended voltage. Newer technology is harder - it's rather finicky about how much current you push into it and what voltage and you must stop trying to charge it when it's done or else you'll break it. As for reliability consider that you can discharge a lead-acid battery almost down to 0V and it will still live - just charge it up again (deep cycle maritime batteries are the best for this). Most other battery types can't handle this. If you let them get too low then they're dead.

My fingers are tired so I'll leave until a different time the discussion of the solar-powered power unit I'm making. For my camping gadgets of course!

Monday, May 4, 2009

Firmware in all things

So today I'm home from work for a bit to wait for the repairman (or repairwoman) to come and take a look at my dishwasher. It has lights flashing on the front and won't do anything no matter how many buttons I press. You may be wondering why I don't just fix it myself. Despite all of the experience I have with fixing household appliances (none) and my familiarity with similar devices (huh?) I've decided that it's just not worth my time to try to fix the thing myself (although having to stay home from work to wait for the repairman somewhat negates that position). I tried some things. The manual says that it may be a bad heating element and to check the wiring. I checked the wiring (well, looked at it anyhow) and nothing. Some advice online said to try pressing a sequence of buttons in rapid succession - nothing. I gave up after that.

Why? Because it's obvious this isn't a hardware problem. And if it's not a hardware problem it's a just plain HARD problem. Mechanical systems are easy - they either work or they don't. No ill-defined states, no invalid inputs, no built-in tests. If something can't happen it physically can't happen. If one gear is moving then the gear in direct contact with it also has to be moving. If something sounds wrong it's probably directly linked to the problem - just follow the connections.

But somewhere in this dishwasher is firmware - code. Code breaks all of the rules. Impossible things happen in code all of the time. Jump to the wrong memory address? You could end up executing impossible code. 'This shouldn't happen! I never called this function! It's impossible!' Mess up with pointers or indices? You could start reading impossible values. 'Umm, an unsigned 8-bit integer CAN'T be 1024....' Use a case fall-through instead of explicit checks? 'That's IMPOSSIBLE! That value isn't handled! Why isn't it going to default...'

Code is arbitrary. I have a flashing light. That's not a symptom of the problem - it's an indication. I need a manual to tell me what it means, and if that doesn't suffice I need the REAL manual - the one they only give to the service technicians (well, sell anyhow). It means whatever they tell me it means. A mechanical device is not arbitrary. If my engine is overheating it doesn't do something illogical like lock the drive shaft automatically - it just starts heating up. All according to rules Mr. Newton figured out (differential equations baby!). You can track it and explain it with rules you find in your high school physics book. The code only follows the rules that Mr. Programmer set forth and he's not bound to adhere to any standards and even if he was he wouldn't tell you. Furthermore, the state of a machine is obvious and can be ascertained by observation (perhaps complicated observations, but still, observations). Code need not give any indication of state and typically doesn't, or it's not very useful (green light - good, red light - bad!)

And if you aren't rigorous in your code you can have undocumented behavior. It's entirely possible for you not to be able to reach one of your states or not be able to leave it if you make simple mistakes. And if your testing doesn't catch it then you'll have to reboot your dishwasher or some other such silliness.

Computers are very powerful, but simple. They execute instructions at memory addresses. Everything else is defined by the designer. If he or she is incomplete in the definition of the system then irrational behavior follows. Mechanical systems are bound by the laws of physics: they cannot perform physically impossible functions, they must move smoothly between states that are defined by their physical characteristics alone, and failures are characterized by smooth transition to a new state(one which is obviously broken). Software doesn't follow these rules and that makes it much more difficult to troubleshoot.

PS: It was bugs Living on the electronics. Dirtying them up. I'm not a dirty person I swear. It wasn't a vague error code or random impossible to get to state, it was just flat out broke. At least even computers have flat-out broke modes...

Thursday, April 30, 2009

Laziness Continued

I am a fan of taking steps out of processes. Before tonight in my TinyCAD library creation process I had to do a few things:

  1. Update my CSV file with new attributes and/or data

  2. Update the schematic symbols in TinyCAD

  3. Export the symbol library as XML to a certain folder

  4. Run a Python script to turn each symbol in that XML file into its own XML file

  5. Run my main library creation Python script

  6. Open TinyCAD to check for errors. If any symbols are wrong, repeat from the second step


I hadn't really used it earnestly yet but it seemed like too many steps. So I decided to add functionality to my library creation script to pull the symbol data from the symbol library file directly instead of XML files created from that library. Tonight I got it to work, so now the process is:

  1. Update CSV file

  2. Update symbols in TinyCAD

  3. Run library generation script

  4. Check for errors


This is a great improvement. I may actually get work done now!

Tuesday, April 28, 2009

Exceptional Programming

I grew up programming. My first computer was a Laser 128 - an Apple IIc clone. I learned AppleSoft BASIC. Those were the days when the command line was also the BASIC interpreter. I programmed everything on that computer. Well, if 'everything' is some science fair projects and cute programs with blocky graphics. I grew up and got an 8086 and cut my teeth on QuickBASIC, then eventually C. In college I was taught C++ and I also picked up Perl and PHP. But despite all of this I never learned about exceptions until I earnestly got into Python.

We see exceptions all the time on our computers. "Firefox caused an exception in blah blah blah blah." I didn't really know what it meant past 'the program screwed up'. I had done most of my programming in C which doesn't have exceptions (or if it does I've never used them). Sometimes I screwed up in my programs and all sorts of crazy things happened. Gibberish printing out on the screen, random lockups, the computer starts beeping and won't stop, etc. I can't be sure, but once I think I caused the gibberish to come out on the printer. I'm probably imagining that though.

But after working with Python I found out those screwups were actually called exceptions. And what's more, you could handle them. Just put everything inside a try statement and if something bad happens you can catch it below and go on your merry way. It's great to just be able to deal with it and continue. But I noticed something. Exceptions weren't always exceptional. Try to access element number -1 of an array? C would happily let you do it and you could go crazy trying to figure out why. But in an exception-driven language it would catch it for you and stop you. But some functions throw exceptions instead of just telling you that you did something wrong. Well, I suppose that's HOW they tell you you did something wrong. But if you have three statements inside a try block and you just get a generic exception back, you're going to need to do more work to figure out what went wrong. And imagine my horror when I learned that some people will use exceptions for something as mundane as input validation! Maybe I'm just old fashioned, but in C you did your own input validation. You didn't just accept whatever the user gave you and then throw a fit when it turned out to be wrong. But what's worse is that this wasn't on your run-of-the-mill PC, but on an embedded device!

Exceptions? On an embedded device?

I've always been told that embedded devices needed to be ultra-reliable. All failure modes had to be accounted for and handled. True, exceptions are one way of handling failure, but for a lazy programmer it's entirely too easy to wrap the entire program in one big try block and just restart in case something bad happens. It's too easy to not even plan for the failure modes because you have exceptions. That may fly for your DVD player but certainly not for your airplane.

So what's the alternative? For one, strict input validation for everything - not just user data. Don't even assume that your own code will always pass you valid values in functions - always check! But then how do you signal an error? In C many functions would return a non-valid value if there was an error. For instance, abs() might return -1 if there was an error (and you had better check!). But this scheme doesn't always work. For some functions there may be no possible invalid values. You can't take a chance on using a valid value as your error signal. Sure, you'll bury the true meaning of the return value somewhere in the documentation but honestly who's going to look until there's a problem? And by then they've already cursed you for being so tricky.

No, the solution is to return a status along with your return value. In some serial systems the receiving device will respond to any message with a status message to tell you that it successfully received your information. Typically zero is 'OK' and everything else has a specific value - either the byte as a whole means something or each bit has significance. This can be done with functions as well. You can either pass all of the parameters as reference and the status as the return variable, or return the status and parameters in a struct if you don't like pointers. Of course it may be more work to work with a struct (and it's dangerously close to object-oriented programmng!). In this way a function can tell you that it failed and why it failed. You can use an enum to define all of the different error messages and then handle each of them. Of course some errors cannot be handled by your code alone. If data shows up late in a control system there's not much you can do about it except not use it in calculations. And your status returned will tell you if it was late (assuming you check it).

Exceptions are very good form for PC applications but it's easy to be lazy with them. Embedded programming sets a higher bar for the programmer, so bring your A game when developing for embedded devices. Always check inputs, parameters and status returned to make sure that you are working with valid data. The passengers on your airplane will thank you.

Update: I had a conversation with one of my colleagues on this issue and we're of the same opinion - in a sense. In essence he agrees with me except but he thinks exceptions are a valid method of achieving the same goals. BUT - we both agree that in embedded development you shouldn't be catching general exceptions or just wrap your entire main() in a try block. You have to know what failure you expect to happen and exactly how to correct it in EVERY case - exceptions or not. The way exceptions work on PCs (Oops, Firefox caused an exception - it's quitting) is unacceptable for embedded development. I shudder to think that the same approach would be applied to an embedded device by an unaware programmer, but that doesn't indict exceptions in general. Just their misuse.

Saturday, April 25, 2009

Laziness (and Python)

I wrote enough last time to scare some of you about serial communication. I was going to write about the design of a simple serial messaging protocol to make all of you readers feel better, but my laziness got to me. I mean, it's all designed in my head, but I figured I'd need tables and diagrams and figures and such to really explain it well. That riled up my innate laziness, so I decided to write about that instead.

To put this in some perspective, I am supposed to be the library maintainer for TinyCAD. It's an open-source schematic capture program, and development on it just started again after a few years of languishing. My duties are to put together libraries of basic schematic symbols (resistors, capacitors, diodes, some ICs, etc) for other people to use.

I'm not doing a good job. I have released no libraries yet.

I do admit - I'm lazy. And this job requires a fair bit of tedious work. The libraries are stored in Microsoft JET database format and the symbols can only be edited with TinyCAD's built-in drawing tools. They're OK, but not if you want to make two dozen symbols at once. Or worse yet, make slight changes to two dozen symbols at once. Or just add a bunch of meta-data (part name, manufacturer, part number, etc). You have to create all the fields for every part, edit them manually, save, etc etc. The entire process was not made for batch creation and editing. I was in danger of getting absolutely no work done at all. Or worse yet, I was in danger of doing lots of tedious work and then re-doing it when I needed to make slight changes to every part I had already made. Something that realistically I should only have to do once and then forget about it.

I am no fan of manual operations, especially when they are tedious and repetitive. Humans are not geared towards that sort of work - we make more mistakes and are much less efficient than a small shell script. When I was making wirelists my brain would just shut off after a while and I would do all sorts of really wrong things. Or I would cut and paste things that shouldn't be cut and pasted because although I thought two things were the same they weren't. My wirelist had tons of errors that luckily weren't too expensive to fix. But the lesson is clear - don't use people for repetitive operations. They're bad at it.

So when I was faced with the prospect of doing just that for these libraries I said 'no' and started immediately with the laziness. Laziness is bad of course because it keeps you from getting work done. And since I wasn't required by force of law or paycheck to make these libraries I wasn't too insistent on starting a process I knew would be frustrating and error-prone. I did nothing until I learned about Python.

Python is a scripting language that is designed to be easy and do everything. It is very close to succeeding. As I said before these symbol libraries were made with Microsoft Jet Database. It's the back end of Microsoft Access. I am not entirely impressed with Microsoft products but I knew SQL queries and it supports those so I had some baseline. And I had Python. A little searching and I figured out which module I had to import to allow access to the database. A little more searching and I figured out how I could insert the BLOB (Binary Long OBject, or maybe Binary Large OBject? - it's how raw data is stored in fields in databases) for the symbol drawings. Then I said to myself, why don't I store the symbol text data in a CSV file so I can just type things out once? Python has an import for that too. TinyCAD can export the parts data as XML? Great, I can import DOM to access the XML and create a CSV out of the current libraries.

If you've ever used Matlab scripting you'll feel right at home. Heck, there's even SciPy - it mimics many of the functions of Matlab (graphic, matrix operations, basic math, etc) in case you're too poor to buy Matlab. You can use wxWidgets or any other GUI library to create GUI apps. You can access almost any database. You can draw with TKInter. You could lose your voice from listing all the things you can do. It's easy, comprehensive and powerful.

Python gave me a reason for my laziness. I can do more work, more accurately and faster than if I had tried to do everything by hand. Bottom line: if you're avoiding doing some tedious work, pick up Python or any scripting language and do yourself a favor by making a tool to do the work for you. You'll thank me.

Tuesday, April 21, 2009

The scary world of serial protocols...

Serial is one of those things that may seem easy at first glance but in reality is so complicated that you want to hang yourself. I used to see plenty of job descriptions that required something along the lines of 'knowledge of serial protocols'. What a joke! 8-N-1, 115200bps, nine pin serial connector DONE! And you get BITS out the back end when you're done. Are people afraid of BITS?

Some people are afraid of BITS (I'm looking at you CS majors), but that's not the trouble with serial protocols. The trouble is that 'serial protocols' is really vague. The first protocol you might think of is good old RS-232. It's a lovely standby, 8 bits per message, no parity, one stop bit and your choice of baud rate. Why would anyone want to deviate from that? But what do all of these settings actually mean? It's swell if you have a GUI to enter these values in, but it gets harder when you have to configure a microcontroller with nothing but assembly. And even then what actually HAPPENS when you send a message? What does the waveform even look like? These may be idle questions for you until the first time that something doesn't work and you have to dig deeper than the GUI to fix it.

For instance what are the voltage levels of RS-232? The answer - heh. There is no answer. According to the standard it's supposed to be +/- 15V. That'd be easy except that no one follows the standard!. You might get +/-12V, or 0 and 5V (TTL levels). The scary thing is that most of these work because transceivers are often not too picky about voltage levels. And then when you figure that out you'll be surprised to know that the voltage levels are the inverse of what you'd expect - a '1' is -15V, a 0 is 15V. If you don't know that you'll have at least 20 minutes of confusion.

Add to the fact that even if you've figured out your RS-232, there are MANY more serial interfaces out there - all different. I2C and SPI are synchronous - there's a clock signal transmitted unlike RS-232. You don't have to worry about addresses with RS-232 since you've only got two devices communicating, but not so with the others. And have you even thought about hardware handshaking? Unnecessary with RS-232 but crucial to the others. I hope you can figure out why you need an open collector output with I2C...

And don't even get me started about data representation. Do you think bits are just bits? That 0x35 is always equivalent to 53 decimal? Not so fast. That could be ASCII-encoded which would mean that it represents the digit '5', not a decimal value of 53. If you look at your serial data stream in HyperTerminal the output you are seeing is decoded from ASCII. That means that 0x35 will display '5', not 53 decimal. ASCII encoding is useful when data is being displayed on a terminal, but it's also used in other circumstances where you'll tear your hair out because of it.

For instance many serial buses have packets with headers, footers, checksums, etc. Packets are usually started with 0x02 hex and ended with 0x04. You can transmit the length of the data packet when you send it so that your device will know when to start looking for another one, or you could choose not to. In that case, what if the data you're sending has an 0x04 in it? That would tell the device to stop listening and would ignore the rest of the data. So, you encode all of your data with ASCII. If you need to send the value 0x04 (decimal value 4, obviously) then you encode it to ASCII and send it as two bytes - 0x30 and 0x04. When you receive it, chop off the 3's and push the nibbles together and get 0x04 again, there's your data.

And that brings up another point - nibble order. Do I send the least significant nibble first (the '4') or the most significant ('0')? What does the standard say? There isn't one. You have to be told how to interpret the data by whoever put it together, and God help you if you didn't do it yourself.

Suddenly 8-N-1 doesn't sound as simple as it used to. Yes, it's all just BITS, but they're scary bits. They're bits that mean whatever the person on the other end of the conversation wants them to mean. You have to parse them, reorder them, combine them, split them and take a magnifying glass to them to make any sense of it. Watch out kids - it's a jungle out there.