Computing stuff tied to the physical world

Archive for June 2011

Self-imposed hiatus

In News on Jun 30, 2011 at 00:01

It’s time for a break. And this one was planned :)

But it’s only fitting that today is also a great time to celebrate. Because this weblog has reached…

800

That’s right. Eight hundred articles on this weblog, published on a daily basis – at midnight Central European Time. About all the fun in physical computing and the electronics, hardware, software, and mechanics surrounding it – collected as a stream of notes describing my adventures in this geeky world of techno-babble.

The posts on this daily JeeLabs Weblog are – by definition – organized as a timeline. Some of it will inevitably be wildly obsolete by now, other parts are timeless and still useful, but if you didn’t tag along from the beginning in 2008, then it might all be somewhat overwhelming – or ridiculously frustrating, depending on your expectations.

There are a few ways to find your way around here. First of all, there are six categories (some of them quite large by now): AVR, Hardware, Musings, News, Software, and the catch-all Uncategorized. A somewhat more fine-grained structure is available through 28 “tags”, shown at the top of each post. There’s an updated listing of them on the intro page.

Another approach to finding your way around here, is to use the Search box at the bottom right of each page. It works quite well, but don’t search too broadly or you’ll get a result with hundreds of posts.

The third place to look for interesting posts is on the “Café“, and especially the pages in the hardware wiki, many of which have a Related Weblog Posts section at the end. I’ve tried to add links to new pages there whenever I could, although there’s still lots of room for improvement.

And last but not least, there’s the forum area, which is getting more and more traffic these days, so it could be a good place to search and ask questions. I tend to participate at least once a day (although quite a bit less in the two months ahead).

If shopping for JeeNodes and other JeeStuff is your kind of thing, don’t forget that the shop will close for one month, starting two weeks from now, and that there’s a discount / sale right now for current customers and contributors. See this page for all the details.

I’d like to thank everyone who in some form or other voiced their appreciation and encouraged me to push further. Techie as it all may be, this weblog is still about people, creativity, and shared passions. Because without all that, there is no point.

Scattered over the coming two months, Liesbeth and I will break away and travel in Europe for a while, and I’ll fill in the rest of this long summer by relaxing, learning, tinkering, experimenting, working on top-secret stuff, and cooking up all sorts of crazy hardware and software for future JeeLabs projects and products.

These daily weblog posts will resume on September 1st.

Until then, for your entertainment, a tale of two worlds: Splitscreen.

Enjoy!
-jcw

Update – Full alphabetical and chronological index.

All about Easy Electrons

In Hardware on Jun 29, 2011 at 00:01

Long-time readers will probably remember the Easy Electrons series of posts on this weblog – as the first post says: “a series which will cover various aspects of electronics from the viewpoint of a technology enthusiast with a non-electronics background.”

There have been 14 posts so far, covering everything from resistors and capacitors, to the basics of power consumption and heat, as well as diodes, transistors, and MOSFETs.

It’s been great fun to write, and the response to it has been absolutely overwhelming. Never did I expect that so many people would enjoy reading about these topics…

I tried to write these posts to convey my intuition on most of the topics covered. There’s a lot of theory out there on electronics, with as much maths and physics as you’re willing to muster, even. But none of that is really needed, if all you want is hook up some circuits with say a few sensors, some display, and a microcontroller such as the JeeNode, Arduino, or chipKIT.

So the point of the Easy Electrons series was really to try and bring across that essential understanding which can help avoid damaging stuff. It should after all be fun…

I say “was”, because I’ve decided to stop writing Easy Electrons installments. First of all, there’s a summer break coming up, but more importantly, I don’t really want to go too deeply into topics which are well covered by other sites on the web.

There are plenty of getting started sites, but the one I’d like to highlight is All About Circuits – it’s a goldmine of information, and it has a very active discussion forum area. Best of all, it’s not aligned to any particular supplier (as far as I can tell), so I would expect the information in it to be generally useful (and much broader and deeper than what I could possibly come up with). There are some ads on the site – to which I’m usually allergic, but they tend to be quite small and unobtrusive, IMO.

There’s bound to be info for everyone. I particularly liked Volume IV of their extensive documentation – filled with interesting experiments, with all the details and background info one could possibly need.

If all you want is to get started in electronics, perhaps because you have a computer software background, then skimming through the first 5 chapters, such as this section on voltage and current, ought to go a long way.

I’m not ruling out new posts which might still get tagged as part of the Easy Electrons series, but don’t wait for full-scale coverage of all electronics aspects one could think of. There’s no point duplicating what others are doing, and doing better and more thoroughly, in fact.

I’m delighted that there are such good resources, freely available to anyone with an internet connection. Would have loved to have had that access as a teenager!

So now I can focus my energy on exploring and blogging about all the new adventures ahead :)

JeeNode with a 32 KHz crystal

In AVR, Hardware on Jun 28, 2011 at 00:01

Another experiment: running a JeeNode on its internal 8 MHz RC clock while using the crystal input to run timer 2 as an RTC. This would allow going into a very low-power mode while still maintaining a much more accurate sense of time.

To this end, I modified a JeeNode SMD, by replacing the 16 MHz resonator with a 32 KHz crystal:

Dsc 2599

I didn’t even bother adding capacitors, these are probably not needed with this crystal (same as on the RTC Plug) since there is probably enough parasitic capacitance already.

The tricky part is the code, since the ATmega is now running in a not-so-Arduino-like mode. Could almost have used OptiBoot with this setup, but the only internal RC clock build for it is the LilyPad, which has an ATmega168.

I ended up using the ISP programmer. IOW, I now compile for “LilyPad w/ 328” and then bypass the bootstrap and serial-upload. Less convenient, but it works.

Here’s a quick test sketch which writes a dot on the serial line exactly once a second:

Screen Shot 2011 06 24 at 15.51.49

So this setup is working. It draws 4.10 ma, consistent with the recent current measurements: slightly less than with the 16 MHz resonator pre-scaled by two.

In idle mode, current use drops to 1.71 mA, not bad!

Now let’s power down with just the timer running as real time clock. There’s a special “power save” mode which does just that. The difference is that timer 0 will now be off, so there won’t be interrupts waking up the ATmega every 1024 µs (as side-effect, the millis() function will start to lose track of time):

Screen Shot 2011 06 24 at 16.15.04

A small adjustment is needed to make sure the serial port is finished before we go into low-power mode, hence the call to delay(3).

Hm, power consumption is still 0.67 mA – quite a bit, given that we’re really powering down most of the time.

Ah, wait. I forgot to turn off the radio. Doing that brings the reading down to 0.15 mA – and I forgot to turn off the ADC and other sub-systems. Now we’re down to … 0.05 mA, while still printing dots:

Screen Shot 2011 06 24 at 16.39.15

Note that these 1 second interrupts are very accurately timed, more so even than with the standard 16 MHz resonator. This could be used to perform time-domain tricks on the wireless side, i.e. waking up just in time whenever a “scheduled” packet is expected to come in – as described in yesterday’s post.

There’s probably more left to try. The delay is running on full power, waiting for the serial output to clear the USART. It could be done while in idle mode, for example. Anyway… that entire delay becomes superfluous when we stop sending out debugging output over the serial port.

So there you have it – a JeeNode running at ≈ 8 MHz, with a precise 32,768 Hz pulse feeding timer 2, in a way which supports low-power sketches while maintaining an accurate sense of time.

Wanna make a clock?

Time-controlled transmissions

In Hardware, Software on Jun 27, 2011 at 00:01

Receiving data on remote battery-powered JeeNodes is a bit of a dilemma: you can’t just leave the receiver on, because it’ll quickly drain the battery. Compare this to sending, where nodes can easily run for months on end.

The difference is that with a remote node initiating all transmissions, it really only has to enable the RFM12B wireless module very briefly. With a 12..23 mA current drain, brevity matters!

So how do you get data from a central node, to remote and power-starved nodes?

One way is to poll: let the remote node ask for data, and return that data in an ACK packet as soon as asked. This will indeed work, and is probably the easiest way to implement that return data path towards remote nodes. One drawback is that if all nodes start polling a lot, the band may become overloaded and there will be more collisions.

Another approach is to agree on when to communicate. So now, the receiver again “polls” the airwaves, but now it tracks real time and knows when transmissions for it might occur. This is more complex, because it requires the transmitter(s) and receiver(s) to be in sync, and to stay in sync over time.

Note that both approaches imply a difficult trade-off between power consumption and responsiveness. Maximum responsiveness requires leaving the receiver on at all times – which just isn’t an option. But suppose we were able to stay in sync within 1 ms on both sides. The receiver would then only have to start 1 ms early, and wait up to 2 ms for a packet to come in. If it does this once a second, then it would still be on just 0.2% of the time, i.e. a 500-fold power saving.

Let’s try this out. Here’s the timedRecv.pde sketch (now in the RF12 library):

Screen Shot 2011 06 24 at 20.54.37

It listens for incoming packets, then goes into low-power mode for 2 seconds, then it starts listening again. The essential trick is to report two values as ACK to the sender: the time the receiver started listening (relative to that receiver’s notion of time), and the number of milliseconds it had to wait for the packet to arrive.

There’s no actual data processing – I’m just interested in the syncing bit here.

The sender side is in the timedSend.pde sketch:

Screen Shot 2011 06 24 at 20.58.17

This one tries to send a new packet each time the receiver is listening. If done right, the receiver will wake up at just the right time, and then go to sleep again. The ACK we get back in the sender contains valuable information, because it lets us see how accurate our timing was.

Here’s what I get when sending a new packet exactly 2,096 milliseconds after an ACK comes in:

Screen Shot 2011 06 24 at 20.39.33

Not bad, one ack for each packet sent out, and the receiver only has to wait about 6 milliseconds with its wireless receiver powered up. I’ve let it run for 15 minutes, and it didn’t miss a beat.

For some reason, send times need to be ≈ 2.1 s instead of the expected 2.0 s.

Now let’s try with 2,095 milliseconds:

Screen Shot 2011 06 24 at 20.37.17

Something strange is happening: there’s consistently 1 missed packet for each 5 successful ones!

My hunch is that there’s an interaction with the watchdog timer on the receiver end, which is used to power down for 2000 milliseconds. I suspect that when you ask it to run for 16 ms (the miminum), then it won’t actually synchronize its timer, but will fit the request into what is essentially a free-running counter.

There may also be some unforeseen interaction due to the ACKs which get sent back, i.e. there’s a complete round-trip involved in the above mechanism

Hmm… this will need further analysis.

I’m using a standard JeeNode on the receiving end, i.e. running at 16 MHz with a ceramic resonator (specs say it’s 0.5% accurate). On the sender side, where timing is much more important, I’m using a JeeLink which conveniently has an accurate 16 MHz crystal (specs say it’s 10 ppm, i.e. 0.001% accurate).

But still – even this simple example illustrates how a remote can receive data while keeping its wireless module off more than 99% of the time.

Current measurements

In AVR, Hardware on Jun 26, 2011 at 00:01

Wanted to check a few things w.r.t. current consumption of a JeeNode. The old way of doing this was a bit inconvenient, so I made a new test setup:

Dsc 2597

(old one on the left, new one on the right)

Sturdier, no need to disconnect the multimeter to short it out, and most importantly: high-side current sensing! That’s quite important, because multimeters can add a small voltage drop when used in current measurement mode, and that voltage drop will affect the serial I/O on the FTDI pins when placed in the GND line. Silly me, should have been on the PWR line all along!

The back side of the new connector is trivial:

Dsc 2598

The multimeter attaches to the top pins, bent apart for easy connection. The jumper shorts it out so this contraption can still be used when the multimeter is turned off.

Ok, time for some simple measurements:

  • ATmega full speed, doing nothing: 6.84 mA
  • ATmega full speed, with the RFM12B receiver on: 18.42 mA
  • ATmega powered down, only the RFM12B receiver on: 11.53 mA
  • ATmega full speed, with the RFM12B tranmitter on: 29.92 mA

Idle mode is a simple way to reduce power consumption without changing the logic of the code. It turns the MPU off until an interrupt occurs. Basically, you’re telling it “I’ve got nothing to do until something new happens”. It’s a pretty safe change, and well worth doing in any idle loop which isn’t directly polling I/O pins. The ATmega’s current consumption is slashed by more than half:

  • ATmega in idle mode, doing nothing: 2.80 mA

Another way to reduce power consumption, is to slow down the clock at which everything takes place, by setting the “clock pre-scaler”:

  • ATmega @ 16 MHz, doing nothing: 6.84 mA (as before)
  • ATmega @ 8 MHz, doing nothing: 4.35 mA
  • ATmega @ 4 MHz, doing nothing: 2.96 mA
  • ATmega @ 2 MHz, doing nothing: 2.02 mA
  • ATmega @ 1 MHz, doing nothing: 1.55 mA
  • ATmega @ 500 KHz, doing nothing: 1.28 mA
  • ATmega @ 250 KHz, doing nothing: 1.16 mA
  • ATmega @ 125 KHz, doing nothing: 1.09 mA
  • ATmega @ 62.5 KHz, doing nothing: 1.06 mA

Diminishing returns, clearly. Note that lowering the system clock in this way is not necessarily the best choice – getting something done N times faster and then powering down completely might be more efficient (see below).

One thing to watch out for: don’t go below 4 Mhz if you want to be able to use the RFM12B, or the processor will be too slow to process each byte.

When combining this, we get:

  • ATmega @ 4 MHz in idle mode, doing nothing: 1.48 mA
  • ATmega @ 62.5 KHz in idle mode, doing nothing: 1.03 mA

The advantage of this approach is that the clock is still running on the 16 MHz resonator (which probably draws most of that remaining current), so you’re still able to keep track of time – just more slowly.

A different approach is to go into real low power mode, and use the watchdog to get back out of this comatose state. The watch dog timer is less accurate, but depending on your application that may not be an issue.

Here’s the current consumption with the ATmega alternately in full speed and in power down mode:

  • ATmega 16 ms @ 16 MHz / 16 ms powered down, doing nothing: 3.49 mA
  • ATmega 8 ms @ 16 MHz / 16 ms powered down, doing nothing: 2.31 mA
  • ATmega 4 ms @ 16 MHz / 16 ms powered down, doing nothing: 1.39 mA
  • ATmega 2 ms @ 16 MHz / 16 ms powered down, doing nothing: 0.80 mA
  • ATmega 1 ms @ 16 MHz / 16 ms powered down, doing nothing: 0.46 mA

That last one does about the same amount of work as when running constantly @ 1 MHz, but with a third of the power consumption. Here is the corresponding sketch:

Screen Shot 2011 06 24 at 13.45.56

And it will continues to scale downward:

  • ATmega 100 µs @ 16 MHz / 16 ms powered down, doing nothing: 90.4 µA

Which still represents 100,000 active processor cycles per second…

And lastly, let’s take it into power down and run for just 1 ms per second, i.e. 0.1% of the time. I can’t measure this with the multimeter, because the power use jumps up every second, but the comatose period draws a mere 6.8 µA, which is consistent with what has been reported several times before (the watchdog is still active, and so is the brown-out detector).

Desktop power supply

In Hardware on Jun 25, 2011 at 00:01

Apart from a variable lab suppy (mine does 0..15V @ 0..3A), I’ve often wanted a simpler supply with just a few fixed voltages and say 500 mA. For experimentation, a weak supply which collapses under too much load is in fact better, because it can help avoid damage (which is almost always thermal and due to large currents).

Today, I decided to put something together, using parts which have been lying around here for some time.

It starts with an encapsulated switching AC/DC converter. I used a Traco 04115, i.e. 15V @ 4W. That addresses the AC mains side of things and limits the power involved in the circuit. Then I added 4 adjustable switching power supplies, which I got off eBay last year:

Dsc 2594

They are all running in parallel, using 15V as input. You’re looking at the bottom side of the box, BTW – the bottom plate of this particular box has nice little rubber feet.

The hardest part was deciding how to bring the power out of the box. I didn’t want large jacks – this thing is a dekstop power supply! But leaving wires with various valotages coming out and dangling all over the desk is also not such a good idea.

The solution I chose, was to bring out everything together via a 40 cm piece of 6-core cable:

Dsc 2595

The cable is squeezed behind one of the enclosure’s inner posts for strain relief (the AC mains cable has a knot in it for the same reason).

At the other end sits this thing – ready to take lots of jumper wires:

Dsc 2596

I still need to figure out how to attach labels to it. This is the pinout (with the cable pointing up):

Screen Shot 2011 06 23 at 18.34.21

No idea how yet, but it would be best if this were placed as label on top of the experimenter’s board in the middle, hiding the solder joints and clearly indicating which pin is what.

As it turns out, this power supply is considerably more powerful than I expected. The 15 V AC/DC converter will in fact go up to twice its rated power, i.e. over 500 mA, before the short-circuit protection sets in.

Due to the nature of switching regulators, the other voltages provide even more current: I was able to pull well over 1A continuously from the 3.3V supply. Although at those levels, the voltage did drop to 3.1 V.

Efficiency was not a primary goal, since this desktop supply is relatively low-power anyway, but the entire setup draws 0.7 W unloaded, and about 10 W when pulling 15V @ 500 mA out of it. I don’t expect to be loading this power supply down much, let alone getting into heat problems, even though the box is completely closed.

Oh, and in case you hadn’t noticed – another baby step in dealing with AC mains…

Alternating current

In Hardware on Jun 24, 2011 at 00:01

I’m not only interested in high-power AC mains switching, but also in the low-voltage / low-power side of things. So here’s another little step towards experimenting with that:

Dsc 2592

A simple 6V @ 58 mA transformer, soldered onto experimenter’s board and wrapped in a couple of heat-shrink layers. What comes out is a safe 6V @ 50 Hz signal.

Eh…

Open

Make that over 15 VAC (half the peak-to-peak value) and nowhere near a clean sinewave!

I suspect that this is what you’ll often get with low-grade / low-cost transformers. Even without any load, the transformer draws about 1.1 W and heats up to around 50°C, yuck!

Actually, the shape isn’t as bad as it looks. If you look carefully, you can see that it’s more or less one harmonic superimposed on the main sine wave. I won’t go into details (and risk exposing my ignorance), but that’s where Fourier transforms come in. The idea is that any repetitive waveform can be constructed from a set of sinewaves at a multiple of the original frequency (these are the harmonics, same as in music). By calculating the Fourier transform, you can decompose any repetitive waveform back into a sum of those basic waves.

Cool, now I have an excuse to try out the FFT feature on my oscilloscope!

Fft

The purple line shows a graph of the intensities of the different harmonics. It’s not really a continuous graph, since FFT is a discrete algorithm, but what it does show is that there are harmonics. If the input were a pure sine wave, there would only be a single peak, at the frequency of the sine wave itself. But in this example there’s a very strong second peak. Which produces this severely distorted waveform.

Here’s a better transformer for comparison (rated at 17 VAC):

Better

You can see that the harmonics are much weaker. Which translates to a much cleaner sine wave. Well, up to a point, anyway.

One reason why these voltages are much higher than the ratings, is that AC is specified as average – after all, the voltage is changing all the time, so it really is a matter of definition how you measure these values. For a sine wave, the average (or RMS in techno-speak) is about 0.7 times the peak value, or equivalently: the peak value is about 1.4 times the rated voltage.

For 6V, we should get 6 x 1.4 x 2 = 16.8 Vpp (a far cry from the above measurement!), and for 17V, the peak voltage should be 17 x 1.4 x 2 = 47.6 Vpp.

In both cases, the measured value is higher, perhaps because this is measured at no load. Although that first transformer really is way off.

Welcome to the world of alternating current, analog effects, distortions, and conversion losses!

TRIAC trials

In Hardware on Jun 23, 2011 at 00:01

To start some tests with TRIAC control of 220V AC mains devices, I’ve built a trivial setup – based on the S216S02 TRIAC, which goes up to 16A and includes a built-in opto-isolator and zero-crossing detector. That last part makes it unfit for dimming (that requires phase-controlled switching) but it should be fine for turning lights and heaters on and off.

The circuit is very simple, but I really wanted to have something that wouldn’t expose me to 220V no matter how much I start goofing around. Here’s the basic idea:

Dsc 2556

There’s a small heatsink on the TRIAC, since the datasheet says that it’ll only go up to 2A without one.

Now just Splice, Solder, and Seal:

Dsc 2558

And voilá – nothing fancy:

Dsc 2557

Trivial stuff, I added a 220 Ω resistor in series with the LED, making it switch reliably on 3.3V, with under 10 mA current, i.e. fine for an ATmega.

The ends of the power wire are attached to a plug and a receptacle, respectively – making this an extension cord.

Baby steps, as I overcome my fear of the unknown, eh I mean 220V AC mains…

Latching relays

In Hardware on Jun 22, 2011 at 00:01

The traditional relay looks like this (thank you Wikipedia):

Relay

A spring pulls on the vertical lever on the right (above its pivot), keeping the contact pushed agains the “NC” contact – hence the name: normally closed.

An electromagnet can pull the (iron) lever towards the left, against the “NO” contact – i.e. normally open, but closed once the electromagnet is powered.

Great invention. Perhaps the first example of electric amplification: using a small amount of electricity to switch a potentially much larger voltage or current.

For ultra-low power devices, ordinary relays have a drawback: you have to keep them energized as long as you want to keep the “NO” contact closed. With the Relay Plug, things are no different – the latest relays used on it have a coil resistance of about 125 Ω, and each of the two requires 40 mA @ 5V to stay “on”:

Dsc 2591

That amount of current consumption is not so convenient with batteries – when turned on, they wouldn’t last more than a day or two on a bunch of AA batteries.

Fortunately there’s an alternative, called a “bi-stable” or latching relay. It uses two coils to move that lever back and forth, with weak magnets in the relay set up in such a way that they’ll stay in place without using a spring as counter-force.

The benefit is that latching relays don’t need any power to stay in their current state (be it open or closed), you only need to give them a pulse to change their state from ON to OFF or from OFF to ON.

There are actually two types of latching relays:

  • dual coil, usually with a common pin which should be tied to ground
  • single coil, where changing the state is done by applying reverse voltages

Most dual coil latching relays can also be used in single-coil mode, by simply leaving that common pin floating.

In principle, the circuitry for a dual-coil latching relay is simple: you just need two relay drivers and then turn one or the other on briefly to make the relay change its state. The point being that you only need to pulse them very briefly, 10..100 msec should be enough.

Unfortunately, the Relay Plug isn’t usable for bi-stable relays, because it assumes a common PWR pin, not GND. It turns out that these relays are polarized. Thinking about this a bit more, this is actually quite logical: the force of the little latching magnet(s) need to be overcome with a magnetic field with a specific opposite orientation.

But there’s a surprising way out…

With single-coil plugs, the trick is to let current flow in different directions to set or reset the relay. IOW, either connect one pin to PWR and the other to GND (briefly), or vice versa. Hm, that sounds awfully like running an electric motor forwards or backward…

Now here’s the trick: instead of a Relay Plug, use the DC Motor Plug!

Dsc 2310 Large

It contains two H-Bridges which are intended to control two small DC motors (or one stepper motor), allowing them to run in either direction.

You even get 4 additional general-purpose I/O pins thrown in…

Now, instead of hooking up a motor, just hook up a relay, and only pulse the power briefly (by making both sides GND or PWR the rest of the time). With as added benefit that the DC Motor Plug will support two latching relays, and being an I2C device, it’ll also allow daisy-chaining with other I2C plugs.

Note that the chips used on the DC Motor Plug require at least 4.5V to operate, according to the data sheet. Maybe a slightly lower voltage will work – I haven’t tried it.

Update – DC Motor Plug is confirmed to work. The 5V relays I was testing this with appear to switch reliably with pulses down to 4 ms, using this test code (modified from the dcmotor_demo.pde) sketch:

Screen Shot 2011 06 22 at 16.33.58

MCP1702 current draw

In Hardware on Jun 21, 2011 at 00:01

The MCP1702 used in JeeNodes and other circuits here at JeeLabs is a nifty little voltage regulator. It’s not particularly good for high voltages (limited to about 13V), but it has a very low idle current. That’s very useful for low-power circuits, especially when trying to get months or even years of service out of one set of batteries.

Let’s find out how it’s performing. I’ve set up this little test circuit:

Screen Shot 2011 06 20 at 00.39.11

Well, it’s not really a test circuit at all – it’s in fact exactly what you need to use one of these things.

Putting 5V on the input (Vin), and leaving it a few minutes to settle, gives me a reading of 2.2 µA. Great, just what the specs say. It doesn’t really go up much with input voltage: 2.8 µA @ 12V. This is at no load.

With a 10 kΩ load, current draw rises to 338.1 µA, i.e. 330 µA for the resistor and about 8.1 µA for the regulator (assuming perfect calibration). That’s only 6 µA more, i.e. about 2% of the load.

Now let’s take the input voltage down, and see how this “low-drop” regulator behaves:

  • 5.0 V -> 2.2 µA
  • 4.0 V -> 2.2 µA
  • 3.5 V -> 2.1 µA
  • 3.3 V -> 2.1 µA
  • 3.2 V -> 90.4 µA
  • 3.1 V -> 84.1 µA
  • 3.0 V -> 78.2 µA

Whoa… it sure doesn’t like being fed less voltage than it needs to supply a regulated output of 3.3V! The change is quite pronounced between 3.30 and 3.28V (I couldn’t get my power supply knob to adjust any more accurately).

For yesterday’s AA power board discussion that’s actually bad news, because it means that when the supply drops a mere 20 mV, it could cause the regulator to start wasting a fair amount of current (relatively speaking).

Let’s try something different: no power on Vin, but power on Vout instead.

This simulates connecting a battery to the +3V pin, and bypassing the MCP1702 voltage regulator altogether. Evidently, it’s not a good idea putting much more than 3.3V on there, since now we’re reverse feeding the regulator, something not all regulators are happy with:

  • 3.40 V -> 1000 µA
  • 3.35 V -> 500 µA
  • 3.30 V -> 90 µA
  • 3.25 V -> 90 µA
  • 3.20 V -> 90 µA
  • 3.10 V -> 84 µA

The conclusion seems to be: when using the AA Power Board in combination with a JeeNode, it might be better in certain cases to omit the regulator altogether if you’re aiming for minimal power consumption!

It’s not enough to short the regulator’s Vin and Vout, it really has to be taken out of the circuit. Fortunately, you don’t have to disconnect all three pins – just disconnect the ground pin (on the JeeNode v4..v6, that’s the one closest to the FTDI connector).

But if all you want to do is power the whole thing from some power source over 3.3V, such as a 3x AA battery pack or a LiPo battery, then all is fine… you’ll see that ultra-low 2.2 µA figure – as intended in this design.

Just beware of low voltages: weird things do happen!

AA boost ripple

In Musings on Jun 20, 2011 at 00:01

The AA Power Board contains a switching boost converter to step the voltage from a single AA battery up to the 3.3V required by a JeeNode.

Nifty stuff. Magic almost… if you take the water analogy, then it’s similar to pushing water up a mountain! Wikipedia has a schematic with the basic idea:

Boost Circuit

Think of the coil as a rubber band (I’ll use a gravitational force analogy here), then closing the switch is like stretching it from the current voltage to ground. Opening the switch is equivalent to letting it go again – causing the rubber band to contract, pulling the end back up and then exceding the original height (voltage) as it overshoots. The diode then sneakily gets hold of the rubber band at its highest point. The analogy works even better if you imagine a cup of water attached to the end. Well, you get the picture…

The trick is to repeat this over and over again, with a very efficient switch and a good rubber band, eh… I mean inductor. The way these boost regulators work, you’ll see that they constantly seek the proper voltage (feeding a storage pool at the end, in the form of a capacitor).

Enough talk. Let’s look at it with a scope:

Open

What you’re seeing is not the output voltage, which is of course 3.3V, but the variation in output voltage, which is measured in millivolts. IOW, 45 times a second, the regulator is overshooting the desired output by about 20 mV, and then it falls back almost 20 mV under 3.3V, at which point the booster kicks in again.

Let’s load the circuit lightly with a 10 kΩ resistance, i.e. 330 µA current draw:

10k

No fundamental change, but the horizontal axis is now greatly enlarged, because the discharge is more substantial, causing the boost frequency to go to 2.2 KHz.

With a 1 kΩ load, i.e. 3.3 mA current draw, you can see the boost working a bit harder to charge up, i.e. the slope towards ≈ 20 mV above 3.3V is more gradual:

1k

Keep in mind that the difference is also due to yet more magnification on the horizontal time axis. The boost converter is cycling at 21.1 KHz now.

With a 330 Ω load, i.e. 10 mA current draw, the wavevorm starts getting a few high-frequency spikes:

330

The total regulation is still good, though, with about 25 mV peak-to-peak ripple.

Now let’s simulate what happens with the RFM12B transmitter on, using a 100 Ω load, i.e. 33 mA current:

100

Looks like the regulator needs more time to charge than to discharge, at this power level. Still the characteristic “hunting” towards the proper voltage level.

With a 68 Ω / 50 mA load, the regulator decides to use more force, losing a bit of its fine touch:

68

The scope’s frequency measurement was off here, it probably got confused by the high frequency components in the signal. Repetion rate appears to be ≈ 65 KHz. But now the total ripple has increased to about 70 mV.

That’s probably about as high as we’re going to need for a JeeNode with some low-power sensors attached. But hey, why stop here, right?

Here’s the output with a 47 Ω load, i.e. about 70 mA:

47

Whoa… that’s a ± 0.05 V swing, regulation is starting to suffer. I also just found out that the scope software has peak-to-peak measurement logic built in (and more). No need to estimate values from the divisions anymore.

Note that a 70 mA current at the end will translate to some 200 mA current draw on the battery – that’s the flip side of boost regulators: you only get higher voltage by drawing a hefty current from the input source as well.

Until this point, I used a standard 1.5V alkaline battery, but it’s not fresh and showing signs of exhaustion at these power levels (the output was a bit erratic).

To push even further, I switched to a fully charged Eneloop battery, which supplies 1.2 .. 1.3V and has a much lower internal resistance. This translates to being able to supply much larger currents (over 1 A) without the output voltage dropping too much. In this case, the change didn’t have much effect on the measurements, but I was worried that continued testing would soon deplete the alkaline battery and skew the results.

To put it all in perspective, here is the output with the same 47 Ω load, but showing actual DC voltage levels:

47dc

So you see, its still a fairly well regulated power supply at 70 mA, though not quite up to 3.3V, as it should be.

One last test, using a 33 Ω resistor, which at 3.3V means we’ll be pulling a serious 100 mA from this circuit:

33dc

Measuring these values with a multimeter gives me 3.16 V @ 89 mA, while the resitance reads as 32.7 Ω – there’s some inconsistency here, which might be caused by the high-frequency fluctations in the output, I’m not sure.

But all in all, the AA Power Board seems to be doing what it’s supposed to do, with sufficient oomph to drive the ATmega, the RFM12B in transmit mode, and a bit of extra circuitry. A bit jittery, but no sweat!

Update – With a 10 µF capacitor plus 10 kΩ load the limits don’t change much, just the discharge shape:

Slow

The same, at higher horizontal magnification:

Cap

Note that AC coupling distorts the vertical position, it’s still ± 18 mV ripple, even if the up peak appears higher.

EtherCard library API

In Software on Jun 19, 2011 at 00:01

As you may have noticed in the last few weblog posts, the API of the EtherCard library has changed quite a bit lately. I’m not doing this to be different, but as part of my never-ending quest to try and simplify the calling interface and to reduce the code size of the library (these changes shaved several Kb off the compiled code).

The main change was to switch to a single global buffer for storing an outgoing Ethernet packet and for receiving the next packet from the controller. This removes the need to pass a buffer pointer to almost each of the many functions in the library.

Buffer space is scarce on an ATmega, so you have to be careful not to run out of memory, while still having a sufficiently large buffer to do meaningful things. The way it works now is that you have to allocate the global buffer in your main sketch:

Screen Shot 2011 06 15 at 09.32.45

This particular style was chosen because it allows the library to access the buffer easily, and more importantly: without requiring an intermediate pointer.

To make this work, you have to initialize the EtherCard library in the proper way. This is now done by calling the begin() function as part of your setup() code:

Screen Shot 2011 06 15 at 09.34.46

The ether variable is defined globally in the EtherCard.h header file. The begin() call also needs the MAC address to use for this unit. The simplest way to provide that is to define a static array at the top of the sketch with a suitable value (it has to be unique on your LAN):

Screen Shot 2011 06 15 at 09.37.18

Next, you can use DHCP to obtain an IP address and locate the gateway and DNS server:

Screen Shot 2011 06 15 at 09.39.27

The printIp() utility function can optionally be used to print some info on the Serial port.

If you are going to set up a server, then a fixed IP address might be preferable. There’s a new staticSetup() function you can use when not doing DHCP:

Screen Shot 2011 06 15 at 09.42.55

The gateway IP address is only needed if you’re going to access an IP address outside of your LAN, and the DNS IP addres is also optional (it’ll default to Google’s “8.8.8.8” DNS server if you do a DNS lookup). To omit values, pass a null pointer or leave the arguments off altogether:

Screen Shot 2011 06 15 at 09.45.55

Just remember to call either dhcpSetup() or staticSetup() after the begin() call.

DNS lookups are also very simple:

Screen Shot 2011 06 15 at 09.47.32

The one thing to keep in mind here, is that the website argument needs to be a flash-based string, which must be defined as follows:

Screen Shot 2011 06 15 at 09.51.10

Note the “PROGMEM” modifier. See the Saving RAM space weblog post for more info about this technique.

This concludes the intialization part of the EtherCard library. Next, we need to keep things going by frequently polling for new incoming packets and responding to low-level ARP and ICMP requests. The easiest way to do so is to use the following template for loop():

Screen Shot 2011 06 15 at 09.59.01

The packetReceive() function polls for new incoming data and copies it into the global buffer. The return value is the size of this packet (or zero if there is none).

The packetLoop() function looks at the incoming data and takes care of low-level responses. The return value is the offset in the global packet buffer where incoming TCP data can be found (or zero if there is none).

As to what to do next: it really all depends on what you’re after. Check out the examples in the Ethercard library for how to build web servers and web clients on top of this functionality.

To get an idea of the code overhead of the EtherCard library: a simple web client using DHCP and DNS is around 10 Kb, while an even simpler one using static IP addresses (no DHCP and no DNS) is under 7 Kb. The fairly elaborate EtherNode sample sketch, which includes DHCP and the RF12 library is now ≈ 13 Kb.

IOW, lots of room for adding your own app logic!

Ping example

In AVR, Software on Jun 18, 2011 at 00:01

Another example of how to use the EtherCard library:

Screen Shot 2011 06 15 at 09.08.33

This example illustrates doing DHCP, DNS, and then periodically pinging a remote server to see if it’s alive.

Sample output:

Screen Shot 2011 06 15 at 09.10.11

As you can see, it not only pings others, but also reports when it’s being pinged by others.

Add a LED and you could make a trivial server status display. Or add a web page fetch to verify that the web server is also still alive. Or add a graphics display to show a graph of the ping times. Or add a relay and power-cycle the server when it’s not responding … endless possibilities, and very simple to implement!

Complete web client demo

In AVR, Software on Jun 17, 2011 at 00:01

After yesterday’s addition of DHCP to the EtherCard library, it’s only a small step to create a sketch which does everything needed for convenient stand-alone use on a local LAN.

Here’s a webClient.pde demo sketch which sets itself up via DHCP, then does a DNS lookup to find a server by name, then does a web request every 5 seconds and displays the first part of the result:

Screen Shot 2011 06 15 at 09.04.57

Sample output:

Screen Shot 2011 06 15 at 09.05.51

The total sketch is under 10 Kb, so there’s still lots of room to add the RF12 wireless driver, as well as a fair amount of application logic.

Who says a little 8-bit processor can’t be part of today’s internet revolution, eh?

DHCP support

In AVR, Software on Jun 16, 2011 at 00:01

Not long ago, Andrew Lindsay added support for DHCP to his EtherShield library, which is derived from the same “Guido Socher & Pascal Stang” code base as the EtherCard library. Fantastic work, hats off!

I’ve reworked the code to simplify things, and more importantly: reduce its code size. Many of these changes made it into Andy’s Github code base, but I’ve decided to take it quite a bit further and completely redo the way DHCP gets called in sketches.

It’s now based on just one call: dhcpSetup(). For completeness, I must mention that lease expiry and re-lease have been swept under the rug for now. Here’s the new testDHCP.pde demo I’ve come up with:

Screen Shot 2011 06 16 at 00.10.07

Sample output:

Screen Shot 2011 06 08 at 13.43.27

The entire demo sketch is currently 7732 bytes (6420 without the serial I/O). The DHCP part appears to require about 1200 bytes in all this. Note that the actual code to perform or serve web requests will add several more Kb to the total size, this merely illustrates the minimal code for doing DHCP.

There’s a “#define SELECT_BIT” in the enc28j60.cpp source which can be changed for boards which don’t use B0 (i.e. arduino digital I/O pin 8) as chip select. There’s also a “#define FULL_SPEED” setting which switches the SPI bus to 8 MHz during block transfers – it’s enabled by default and has a noticeable impact on performance.

So now any ENC28J60-based EtherCard with an ATmega328 can be connected to a local LAN and become usable as web server and/or client without having to configure an IP address, DNS server, or gateway!

Sale!

In News on Jun 15, 2011 at 00:01

Ok, here we go again…

1. The JeeLabs online shop will be closed from July 16 to August 15, 2011.

2. The JeeLabs daily weblog will be on hold from July 1st to August 31st.

3. Sale!

Discount 2011

Each order will be checked, if I can’t figure it out I’ll contact you by email (this may add to the delay).

Update – Similar conditions now also apply for JeeLabs products in the Modern Device – same discount code!

One last refinement

In Hardware on Jun 14, 2011 at 00:01

With the high-side DC power switch circuit working, there’s room to tweak things just a teeny bit further.

Summary: we’re switching DC power on and off through a MOSFET, and measuring the voltage drop across that same MOSFET with a bit of amplification to get better readout sensitivity.

Let’s add one more feature: the ability to detect whether a disk is connected. But first, the complete schematic:

Screen Shot 2011 06 06 at 19.06.57

The R1 resistor protects the op-amp from negative voltages, which occur when the MOSFET (Q1) is open and a device has been attached.

R2 and R3 put the op-amp in 11x amplification mode, referenced to VCC.

The C1 capacitor was added to smooth out the analog readings a bit (R1 + C1 form a low-pass filter).

The R5 resistor makes it possible to detect whether there is anything connected to OUT or not: when Q1 is open, R5 creates a pull-up, forcing the “+” side of the op-amp to VCC, unless there’s a device attached. At 1 MΩ, the pull-up is so weak that any device will pull it down to ground potential (keep in mind that Q1 is open). When Q1 is closed, then R5 no longer matters since it gets shorted out.

And lastly, R4 was added as pull-up to avoid a startup glitch as the JeeNode is powering up (i.e. while DIO is still floating). Note that Q1 will conduct when DIO is low.

Here are some readings under different conditions. These are referenced to VCC and converted to mV x 11, i.e. 0.3V under VCC on the op-amp “+” pin reads out as 3300. The three values are low, high, and averages, sampled 50 times over a 5 second interval:

  • OFF, no device: 0 / 16 / 6
  • OFF, device switched off: 9 / 48 / 16
  • OFF, device switched on: 3280 / 3287 / 3280
  • ON, no device: 0 / 0 / 0
  • ON, device switched off: 0 / 0 / 0
  • ON, device switched on, start: 1267 / 2761 / 2348
  • ON, device switched on, stable: 925 / 1096 / 983

When OFF, there’s a clear difference between a device waiting to get power and no device at all, or one which has been physically switched off. When ON, the readout becomes proportional to the amount of current drawn.

According to the lab power-supply readout, the startup current goes to about 1A, and then once stable it drops back to about 380 mA. The device is a “Green Power” WD 500 Gb hard disk in a no-brand external USB enclosure.

This concludes the “high-side” experiment (all related posts have been collected on the wiki). For a stand-alone setup, it should work fine, but after all this floating ground trickery I’ve come to the conclusion that a COMMON ground setup will be more useful if this were ever to be turned into a plug…

Better resolution

In Hardware on Jun 13, 2011 at 00:01

Yesterday’s high-side DC power control circuit was not able to measure current in a very exact way. Each ADC step is about 3.3mv, and with a 0.1 Ω sense resistor, that translates to 33 mA steps (a bit less, now that the MOSFET turns out to have a slighty higher “on” resistance).

So let’s add an op-amp, to amplify the voltage:

Screen Shot 2011 06 05 at 18.27.58

That’s a standard way to amplify an input voltage by a factor of 11, so a 0.3V input should generate a 3.3V output voltage, which is nicely full-scale for the ATmega’s analog input when running at 3.3V.

But there’s a little mistake in this setup…

The voltage we’re measuring is not a small voltage above 0V, but a small voltage below 3.3V, so we’re in fact feeding the op-amp a voltage between about 3.0V and 3.3V. Amplified by 11 you get… something the op-amp can’t handle when powered from 3.3V, so it’ll simply return 3.3V all the time. Overflow!

Simple to fix though. Instead of tying that lower resistor to ground, we tie it to 3.3V as reference level. And lo and behold, I’m seeing a roughly 11x larger reading with the same setup as yesterday:

Dsc 2563

Now, the input voltage swings between about 2.4V and 3.3V, which is just fine as analog input.

The one thing to watch out for is that we’re sailing very close to the edge, or in op-amp speak: “close to the rail”. This circuit is working with an input voltage which is very close to the +3.3V power supply “rail”, and the output of the op-amp also needs to be able to swing up to that same +3.3V level. This requires some care in selecting a “RRIO” type op-amp (i.e. Rail-to-Rail Input and Output) – the chip I used here is the TLV2373, a dual op-aamp. It does fairly well, but the output can’t quite totally reach 0V or 3.3V. I suspect that most op-amps will have this problem: a tiny residual voltage on both sides of the output swing. Such is life, no op-amp is perfect.

Here is the test sketch I used for this experiment:

Screen Shot 2011 06 05 at 18.22.28

It’s set up for 4 channels, although this circuit only has one. This could be used as the basis for a 2-channel plug, since both the MOSFET and the op-amp are dual-channel.

The output measurements come in via wireless every 5 seconds, and a simple “1,21s” sent out to it (since this is node 21) will turn on the disk.

But this code doesn’t even come close to what I’d really like to implement: it needs to track power use, only switch off when a device is consistently below a preset level (could be different for each device), implement encryption to prevent unauthorized control, store settings in EEPROM, support configurable behavior after power loss, and power devices up in a staggered mode to reduce the load on the power supply, oh my – not there yet!

DC high-side control

In Hardware on Jun 12, 2011 at 00:01

Good news: the “high-side” DC power switch works!

Dsc 2561

On the bottom, a DC jack getting 12V power, on the right a cable with a DC plug powering an external USB disk.

The little board in the middle is sort of a breakout board for two SMD chips: a dual P-MOSFET and a low-drop -3.3V linear voltage regulator to power the JeeNode. The rest is boilerplate stuff, i.e. the JeeNode Experimenter’s Pack, a couple of resistors, and some electrolytic caps.

I’ve only tested it with a load of about 1A, but it should work up to 3A without any problem. What’s also nice is that as a high-side switch, it doesn’t really care what voltage is being used as power supply – anything between 3.5V and 16V should work just fine. That means this can also be used for 5V devices and even with devices powered off 1..4 LiPo-batteries. This simply fits between a DC power plug and its device – convenient!

The current consumption is 21 mA with the ATmega and receiver permanently on. Could easily be lowered a few mA by putting the ATmega in “idle” mode.

The current sensing capabilities are definitely working, but the resistance of the P-MOSFET is not quite 0.1 Ω: with a 390 mA current, I see about 90 mV across the MOSFET, indicating that its internal resistance when driven from a 3.3V JeeNode is more like 0.23 Ω. That’s on the high side (pardon the pun), because this would mean a 1A load will get about 0.23V less out of the power supply than it would with a direct connection – and 0.7V less when drawing 3A. Oh well, it’ll be ok for most devices, cheap power bricks don’t always supply exactly 12V anyway.

The question of course is how consistent this MOSFET resistance is. I suspect that there will be quite a bit of variation across different units. But that’s not necessarily a problem: we don’t really care about absolute currents, we just need to see how the device’s current consumption is relative to full power and idle modes, basically. And we can always calibrate the value with a multimeter or power resistor.

The other weak spot in all this is that the voltage levels measured with this setup are very low, and only cover a few percent of the ADC range. It would be nice to have a bit more resolution there.

Ok, let’s throw an op-amp into the mix…

Controlling the Dimmer Plug

In Hardware, Software on Jun 11, 2011 at 00:01

The Dimmer Plug contains an I2C chip which can control the brightness of up to 16 individual LEDs using hardware PWM. The advantage over the ATmega’s PWM is that there is no limitation to use only the DIO2, DIO3, or IRQ pin (the only ones which support hardware PWM), and of course that 16 individual LEDs can be controlled. In fact, since there are 3 solder jumpers, up to 128 LEDs can be controlled from a single I2C port (by daisy-chaining eight Dimmer Plugs).

Note that the output of the Dimmer Plug is only suited for driving single low-power LEDs with a series resistor. The default setup assumes that these LEDs are tied to 3.3V or 5V. For higher voltages and higher power, additional driver circuitry must be added (transistors, MOSFETs, or the ULN2803 8-wide driver, for example).

Here’s a demo setup:

Dsc 2559

(it’s not visible here, but the test LED has a 470 Ω resistor in series)

Although software PWM can handle more I/O pins, that does place a fairly high load on the ATmega, and the dimming takes place at a much lower frequency, which can be visible to the naked eye (and quite annoying).

The disadvantage of the Dimmer Plug is that it’s based on a fairly complex chip, the PCA9635. I’ve extended the DimmerPlug class in the Ports library a bit further to make it somewhat easier to use.

There’s also an updated dimmer_demo.pde sketch:

It exercises several of the PCA9635’s features:

  • all 16 output are set to maximum brightness
  • the “group blink” mode is enabled, using a specified blink frequency and blink duty cycle
  • the sketch waits 10 seconds, while blinking
  • the chip is reset to its default “group dimming” mode
  • then gradually make all channels dim at the same time
  • and lastly enter a loop, which illustrates how to do per-channel dimming

The setMulti() call takes a start register number, then a variable of arguments 0..255, and then a “-1” value to mark the end. It is shorthand for calling setReg() with successive register values, but more efficient.

The code in loop() does some tricky bit fiddling. Figuring out what it does is left as exercise for the reader, but you can simply ignore it if you don’t care about such trickery. The main thing to note is that indiviudal LEDs can be controlled by setting their corresponding register: dimmer.PWM0, dimmer.PWM1, …, up to dimmer.PWM15.

As you can see, the PCA9635 can control individual outputs, but also several outputs combined via the “group” modes. There are other options, i.e. only controlling a subset of the outputs in group mode, inverting the output signal, using open-collector mode instead of the default totem-pole configuration, and more. You will need to go through the datasheet (PDF) to take full advantage of all this. All registers in the PCA9635 can bet read and written using the getReg() and setReg() calls, respectively.

But for simple uses, the above should be sufficient!

RF12 broadcasts and ACKs

In Software on Jun 10, 2011 at 00:01

In yesterday’s post, the general design of the RF12 driver was presented, and the format of the packets it supports.

The driver also support broadcasting, i.e. sending packets to all interested nodes, and ACKs, i.e. sending a short “acknowledge” packet from receiver to transmitter to let the latter know that the packet was properly received.

Broadcasting and ACKs can be combined, with some care: only one node should send back the ACK, so the usefulness of ACKs with broadcasts is limited if the goal was to reliably get a packet across to multiple listeners.

Broadcasts and ACKs use the HDR byte in each packet:

Rf12 Packets

There are three bits: C = CTL, D = DST, and A = ACK, and there is a 5-bit node ID. Node ID 0 and 31 are special, so there can be 30 different nodes in the same net group.

The A bit (ACK) indicates whether this packet wants to get an ACK back. The C bit needs to be zero in this case (the name is somewhat confusing).

The D bit (DST) indicates whether the node ID specifies the destination node or the source node. For packets sent to a specific node, DST = 1. For broadcasts, DST = 0, in which case the node ID refers to the originating node.

The C bit (CTL) is used to send ACKs, and in turn must be combined with the A bit set to zero.

To summarize, the following combinations are used:

  • normal packet, no ACK requested: CTL = 0, ACK = 0
  • normal packet, wants ACK: CTL = 0, ACK = 1
  • ACK reply packet: CTL = 1, ACK = 0
  • the CTL = 1, ACK = 1 combination is not currently used

In each of these cases, the DST bit can be either 0 or 1. When packets are received with DST set to 1, then the receiving node has no other way to send ACKs back than using broadcasts. This is not really a problem, because the node receiving the ACK can check that it was sent by the proper node. Also, since ACKs are always sent immediately, each node can easily ignore an incoming ACK if it didn’t send a packet shortly before.

Note that both outgoing packets and ACKs can contain payload data, although ACKs are often sent without any further data. Another point to make, is that broadcasts are essentially free: every node will get every packet (in the same group) anyway – it’s just that the driver filters out the ones not intended for it. A recent RF12 driver change: node 31 is now special, in that it will see packets sent to any node ID’s, not just its own.

It turns out that for Wireless Sensor Networks, broadcasts are quite useful. You just kick packets into the air, in the hope that someone will pick them up. Often, the remote nodes don’t really care who picked them up. For important events, a remote node can choose to request an ACK. In that case, one central node should always be listening and send ACKs back when requested. An older design of the Room Node sketch failed to deal with the case where the central node would be missing, off, or out of range, and would retry very often – quickly draining its own battery as a result. The latest code reduces the rate at which it resends an ACK, and stops asking for ACKs after 8 attempts. The next time an important event needs to be sent again, this process then repeats.

RF12 packet format and design

In Software on Jun 9, 2011 at 00:01

The RF12 library contains the code to support the RFM12B wireless module in an Arduino-like environment. It’s used for JeeNodes but also in several projects by others.

Here’s the general structure of a packet, as supported by the RF12 driver:

I made quite a few design decisions in the RF12 driver. One of the goals was to make the communication work in the background, so the driver is fully interrupt-driven. An important choice was to limit the packet size to 66 bytes of payload, to keep RAM use low and still allow just over 64 bytes of payload, enough to send data in 64-byte chunks with a teeny bit of additional info.

Another major design decision was to support absolutely minimal packet sizes. This directly affects the power consumption, because longer packets take more time, and the longer the receiver and transmitter are on, the more precious battery power they will consume. For this same reason, the transmission bit rate is set fairly high (about 50 kbits/sec) – a higher rate means the same message can be sent in less time. A higher rate also makes it harder for the receiver to still pick up a good packet, so I didn’t want to push this to the limit.

This is how the RF12 driver can support really short packets:

  • the network group is one byte and also doubles as second SYN byte
  • the node ID is small enough (5 bits) to allow a few more header bits in the same byte
  • there are only three header bits, as described in more detail in tomorrow’s post
  • there is only room for either the source node ID or the destination node ID

That last decision is a bit unusual. It means an incoming packet can only inform the receiver where it came from, or define which receiver the packet is intended for – not both.

This may seem like a severe limitation, but it really isn’t: just add the missing info in the payload and agree on a convention so that the receiver can pick it up. All the RF12 does is enforce a truly minimal design, you can add any info you like as payload.

As a result, a minimal packet has the following format:

That’s 9 bytes, i.e. 72 bits – which means that a complete (but empty) packet can be sent out in less than 1.5 ms.

Tomorrow, I’ll describe the exact logic used in the HDR byte, and how to use broadcasts and ACKs.

How the JeeNode evolved

In AVR, Hardware on Jun 8, 2011 at 00:01

Thought it might be interesting to put the six JeeNode versions / designs next to each other. It nicely illustrates my progress in learning PCB design, and making some trade-offs and pinout choices over the past 2.5 years:

JeeNode v1:

Jlpcb 002

JeeNode v2:

Jlpcb 003

JeeNode v3:

Jlpcb 018

JeeNode v4:

Jlpcb 044

JeeNode v5:

Jlpcb 105

JeeNode v6:

Jlpcb 128

We’ve come a long way. And I think it’s now time to call this final v6 design… it!

Font tables – proportional

In Software on Jun 7, 2011 at 00:01

Unlike monospaced font tables, proportional fonts have character glyphs which all differ in size and relative positioning. This not only requires more storage, it also complicates the way these glyphs are stored in the bitmap image in flash memory.

In the GLCD library, I implemented this by storing two bytes for each character:

  • P: the horizontal start position of the glyph in the image (1 byte)
  • A: same as for monospaced fonts, but per-character pre-gap (4 bits)
  • B: same as for monospaced fonts, but per-character post-gap (4 bits)

The width of a glyph can be found by looking at the position of the next character glyph in the bitmap, which is placed right next to it.

Here is an example of a small proportional font:

Screen Shot 2011 06 01 at 17.24.37

I removed some parts for brevity.

So the “!” exclamation point for example, has width 2 in the bitmap (i.e. 3-1), with pre- and post-gaps of both 1 (i.e. 5-4). And the “#” numbersign charcter uses kerning, with a -1 pre-gap.

There is a problem, however. Most characters are fine, but after the “S”, the bit map position increments to a value greater than 255, which can’t be represented in a single byte!

Instead of doubling the position to use 2 bytes each, I implemented an “overflow” mechanism. This saves some memory, since most positions are just fine, if we ignore the top byte. We merely need to keep track of those few character positions where overflow actually happens.

This is what the “overflow position table” at the end does: for each character which straddles a 256-pixel boundary, it stores the offset of that character in the table. The result is that there is now sufficient info to locate each glyph, and this process only requires a few flash memory reads for any character code.

Note that for consistency, there are also two sentinels: one at the end of the per-character info, so that the width of that last character can be computed, and another one at the very end, to simplify the overflow calculation logic.

So there you have it: full font support, which easily fits in an ATmega!

Font tables – monospaced

In Software on Jun 6, 2011 at 00:01

The font support added yesterday works with compact byte tables stored in flash ROM to store all the “glyphs”, i.e. pre-computed bitmaps.

Here’s the entire table of the clR6x8 font:

Screen Shot 2011 06 01 at 16.31.53

All the characters are stored side-by-side in a very wide horizontal bitmap image. In this case, the height is 8 pixels and the width = 72 x 8 = 572 pixels.

In detail:

  • H: the height of the image, in pixels (1 byte)
  • W: the width of the image, in bytes (1 byte)
  • the image data, 8 horizontal bits per byte (H x W bytes)
  • F: the code of the first character stored for this font (1 byte)
  • N: the number of consecutive characters in this font (1 byte)

And then it depends on whether the font is monospaced or proportional. For a mono-spaced font, i.e. where all the glyphs have the same size:

  • P: the number of horizontal pixels per glyph (1 byte)
  • A: the “pre-gap” (value -4..11, encoded as 4 bits by adding 4 to it)
  • B: the “post-gap” (value -4..11, encoded as 4 bits by adding 4 to it)

The pre-gap defines where to start copying the glyph, relative to the current horizontal position. A negative value causes kerning. Likewise, the post-gap indicates where to start writing the next character. IOW, after a character has been processed, the horizontal position is advanced by P + B pixels (A does not participate in this calculation).

Proportional fonts

In Software on Jun 5, 2011 at 00:01

The GLCDlib library for the Graphics Board has been extended to support multiple fonts!

Dsc 2568

If you look closely, you’ll see that even kerning has been implemented – making italics much nicer.

The main use I see for this is not so much about going overboard with all sort of “roman”, “italic”, or “bold” mixes (although now you can), but to mix different font sizes on the same screen (large values, small labels, etc).

Here’s the new font_demo.pde sketch which produces the above display:

Screen Shot 2011 06 06 at 17.36.02

That’s just 7 of the 250+ fonts and variations now present in the GLCD library :)

To use a font, include the proper header in your sketch, and call glcd.setFont() to activate it. The thing to keep in mind is that fonts use up flash memory space. I’ve come up with a fairly compact way to store them, but larger fonts obviously need more memory than tiny ones, especially if they include all ASCII character codes. Also, proportional fonts need more space than mono-spaced fonts, due to extra per-character width / offset info.

Here is an overview of the amount of memory needed for each font, sorted by size:

    246   micro
    294   4x6
    294   clR4x6
    366   clR5x6
    426   5x7
    438   clR6x6
    486   5x8
    486   clR5x8
    582   clR6x8
    606   clR5x10
    ...
    7099  helvBO24
    7165  charB24
    7240  ncenI24
    7376  lubB24
    7478  lubI24
    7529  charBI24
    7595  ncenBI24
    7762  luBS24
    8148  lubBI24
    8627  luBIS24

The above sketch compiles to 12572 bytes, of which about 8 Kb are fonts.

One last note: these changes mean that you now always have to set up some font before calling drawChar() or drawString(), there is no default (it might not be the one you want, or you might not need any fonts at all).

Hard disk power – Mac OSX

In Hardware on Jun 4, 2011 at 00:01

Ok, quick manual test with Mac OSX gives me this pop-up dialog box when powering off a mounted disk:

Screen Shot 2011 05 30 at 11.19.42

The good news is that I can simply leave this message on the screen, since subsequent power cycling won’t create more dialog boxes. The disk mounts as usual, presumably after a sanity check. I’m using a journalled file system, so these checks should be quick and risk-free.

I can live with that on a “headless” server. Key issue will be to only power off when there really is nothing happening on the disk drive.

Server upgrade

In Hardware on Jun 3, 2011 at 00:01

The JeeLabs server is running out of steam…

No, not CPU load:

Screen Shot 2011 05 30 at 12.41.31

It’s idling at under 10%, and drawing 10..15W, exactly as planned.

It’s running out of RAM, all friggin’ 4 Gbytes of ’em!

There are 4 VM’s running so far, of which Drupal gets 768 Mb, and WordPress / Redmine each get 512 Mb. With Parallels, VM’s take up a bit more memory than the raw amount, I suppose there’s some caching going on.

It’s bordering on the ridiculous. The entire WordPress MySQL database is probably not more than a few dozen Mb by now (which in itself is silly, but that’s another story). Yet it needs more than an order of magnitude more RAM to serve it all up as web pages?

I can’t help but think that a fully RAM-based database (with disk image backup) could dramatically reduce the memory needs. But hey, I’m not in the business of redoing the database world – well, not these days anyway ;)

The shining exception is the nginx reverse proxy I use: it runs in 128 Mb, and would probably run just as fine with 64 Mb. It serves lots of static pages, and handles all the re-routing for the rest of the traffic. Brilliant software.

So I bought a fresh pair of 4 Gb memory sticks off eBay (thx, BWired):

Dsc 2541

With the latest Mac Mini models, memory upgrading is – at last – trivial. You might have seen the backSoon server for a few minutes, which is just a JeeNode USB with EtherCard presenting this (dynamic!) web page:

Screen Shot 2011 05 30 at 18.56.17

So there you go. All the JeeLabs .org and .net sites (and a few more) now run with a bit more breathing space. We’re solidly back in the green again:

Screen Shot 2011 05 30 at 19.01.55

Onwards!

Update – Looks like software always expands to consume all available memory: this time it is Apache, btw. I probably need to tweak it, it just grows and grows and grows! (the Drupal VM is now 1.5 Gb)

Screen Shot 2011 06 03 at 11.15.42

Hard disk power – bonus

In Hardware on Jun 2, 2011 at 00:01

Ok, there’s now a design for a high-side power switch which can power disk drives up and down at will.

Wait a minute…

You’re not supposed to power down disk drives just like that! It might be in the middle of a disk write. Even journaled disks are at risk, because journaling usually covers meta data (directories, files sizes, allocation maps, etc) … but not the data itself. So an unfortunate power down could leave the disk in an awful state: sure, the diks will be scanned and fixed on startup, but even then, some of the data blocks might contain inconsistent data. Whoops – bad idea!

One solution would be to add a JeeLink to the computer, and have it send out the power down command only after it finishes flushing and unmounting the disk. It’ll take some scripting, depending on the OS, but it’s all doable. Also, this isn’t really for disks which need to be online most of the time – for that, the normal hard disk spin down and idling modes will be fine.

But I’d like it to be a bit more automatic than that. I don’t want to have to remember to turn off the disks. Nor tie it to a specific time of day, or day-of-the-week. The whole point of these disks, is that I rarely need them. Some disks may stay off for weeks, even months.

Here’s an idea: by adding a current sensor to each disk power supply line, we could monitor disk activity and make sure that power is never shut off while a disk is “doing something”. By adding a bit of extra logic in the sketch, we could implement a timer so that the disk will only be powered down if the disk has been idle for say 15 minutes. Most operating systems have a periodic flush in place, so that changes always get flushed out to disk fairly soon after they have been buffered by the OS. If nothing has happened for a while, then we know there’s no important change pending.

OK, how do you measure the amount of current a circuit draws? Easy: insert a small resistance in series with the load, and measure the voltage drop. For the same reasons as before, we can’t do this “low side”, i.e. in the ground connection. But high-side would be fine:

Screen Shot 2011 05 30 at 02.00.54

With 1A of current, we get (using Ohm’s E=IxR law): E = 1 x 0.1 = 0.1V voltage drop across the resistor. And since the high side of the resistor is tied to “+”, all we need to do is connect the other side to an analog input.

The nice thing about the power control circuit presented yesterday, is that it has a MOSFET between + and the disk drive power pin. And MOSFETs are really very much like a small resistor when turned on. So we can simply use the MOSFET itself as a sense resistor:

Screen Shot 2011 05 30 at 01.54.25

Here are the characteristics of the P-MOSFET I’m going to try this with:

Screen Shot 2011 05 30 at 02.06.51

As you can see, at 3.3V, the MOSFET acts almost exactly like a 0.1Ω resistor: 0.1V drop at 1A – perfect!

There is still one problem though: when the MOSFET is turned off, the voltage on the low side will be at ground level, which is 8.7V below the JeeNode’s “ground”. So we can’t just tie it to an analog input pin, it would fry the ATmega. That’s is why I added a 10 kΩ resistor: it will still be a very “bad” input signal when the MOSFET is off, but the resistor will limit the current to less than 1 mA, and it will flow through the internal ESD protection diode. That amount of current should be harmless.

So now we have a way to sense the current. When the disk draws 1A, the analog input will be at 0.1V below 3.3V, i.e. 3.2V, which can easily be measured. Since the ADC resolution is 3.3 mV, this means that a change in power consumption as small as 33 mA could in principle be detected by this setup. Should be accurate enough to detect a disk spinning up or down and the seek actuator moving.

I’ve ordered a bunch of parts and will report when something useful comes out of these experiments.

Hard disk power #3

In Hardware on Jun 1, 2011 at 00:01

As promised in the previous post, here’s an improved design for controlling hard disk power.

The first conclusion is that we need to switch the positive +12V line, not the ground. Ground is inter-connected between all disks, the server, and this circuit – so we shouldn’t mess with it.

Here’s one way to do a “high-side” switch:

Screen Shot 2011 05 29 at 20.02.56

First problem: we don’t have a voltage higher than 12V available, so the N-MOSFET can’t simply be moved to the upper power line (it needs a few volts above its source to drive it, and when conducting, that source is at 12V). A P-MOSFET solves that, because it needs a few volts below 12V to drive it into conduction.

Second problem: we can’t drive the P-MOSFET high enough (12V) to make it disconnect, when driven from an ATmega output pin (which can’t go higher than 3.3..5V). So we need a resistor to pull the gate up, and a transistor to pull the gate down. And lastly, we need a resistor to limit the current into the transistor.

Quite a few parts, expecially since this circuit needs to be repeated for each hard disk.

For reasons which will become clear tomorrow, I’d like to simplify this circuit a bit further, and get away from handling 12V power levels. This “simplification” needs a bit of explanation, unfortunately:

Screen Shot 2011 05 29 at 21.05.13

To see what’s going on, this trick may help: look at the VOUT pin as being a regulated 8.7V voltage. In other words: the JeeNode “ground” is at +8.7V above ground, in relation to the power supply, hard disks, and server.

This means that the JeeNode is running with a 12 – 8.7 = 3.3V voltage difference between its 3.3V and GND pins, just as it always does. It’s merely floating a bit above ground, but that’s all relative anyway. As far as the JeeNode goes, it’s getting exactly the right power levels.

The result is that the output pins of that JeeNode will be at about 8.7V when “0” and at 12V when “1”. Which is just right to drive the gate of a suitable P-MOSFET (a “1” will turn it off, and a “0” will make it conduct).

So instead of making all the disk ground levels float, this setup places the JeeNode at an unusual 8.7V above ground level, which lets it turn on and off P-MOSFETs by controlling the positive supply line.

Now we need a regulated 8.7V supply. Eh, actually, no… we need a supply which is exactly 3.3V below the +12V line. That way, even if it fluctuates a bit from hard disk load changes, the JeeNode still gets a nice clean 3.3V.

The way to do that is to use a minus 3.3V regulator, such as an LM337. And from the perspective of that regulator, +12V is “ground” and ground is… -12V!

Perfect. You just have to look at voltages upside-down :)