Computing stuff tied to the physical world

Archive for the ‘AVR’ Category

Sending packets without battery

In AVR, Hardware, Software on Sep 2, 2010 at 00:01

Here’s a fun experiment…

After yesterday’s improved power-down current results, I wanted to find out how much power it really takes to send out a bunch of small packets. No acks, just periodically sending out a packet and sleeping.

Trouble is, I didn’t want to wait for a battery to run down, since that would take months or even years. Bit long to get results for this weblog, eh?

So instead, I used this little chap:

Dsc 1873

It’s a super-capacitor which can handle up to 5.5V and has a capacity of 0.47 Farad! That’s like putting a thousand 470 µF caps in parallel. Amazing stuff, in an even more amazingly small package.

Here’s a JeeNode, fitted with this new power source, to give you an idea of just how small this thing is:

Dsc 1874

The next step was to design a small sketch to test this. Here’s what I came up with:

Screen Shot 2010 08 29 at 11.57.38

Some of the code left out for brevity. Full source code can be found here.

What this demo does is send out a packet with a 2-byte payload, then sleep for approximately 1 second, then send again, etc. Until power runs out.

Sure enough, packets started coming in every second:

    OK 4 0 0
    OK 4 1 0
    OK 4 2 0
    OK 4 3 0
    [...]

I expected it to send out say 100 packets or so, before the charge in the 0.47 F supercap would run out.

Guess how far it went…

    [...]
    OK 4 178 28
    OK 4 179 28
    OK 4 180 28
    OK 4 181 28

That’s packet number … clickety, clickety … 28 * 256 + 181 = 7349 !!!

In other words, the JeeNode was able to send out well over 7000 packets, i.e. two hours of packets sent once a second.

This is fantastic. I think the secret – apart from the 3 µA powerdown mode – is that the RFM12B + RF12 driver require very little time to start up, send off a packet, and go back to sleep again. There is no ACK involved, the RFM12B is hardly ever in reception mode.

With real-world use, I expect power requirements to be considerably higher. First of all, a Room Board will draw around 50 µA, due to the on-board PIR sensor. And second, I’m going to want to use ACKs for at least the motion detector reports, so that the system has a robust mechanism for reporting motion whenever it is detected. This means putting the RFM12B in receive mode for a few milliseconds, waiting for the ACK. And repeating this process a few times if that ACK isn’t immediately received.

But still … over 7000 packets without a battery!

Update – with one packet per 5 seconds, the charge lasted 4523 packets, i.e. just over 6:15.

Update #2 – with one packet per 60 seconds, 771 packets got sent out, that’s 12:51 hours … looks like the self-discharge of the supercap is eating up the remaining energy.

Sleep!

In AVR, Software on Sep 1, 2010 at 00:01

The “powerdown_demo.pde” sketch in this recent post draws 20 µA, which surprised me a bit…

A while back, I got it down to a fraction of that, by turning off the brown-out detector (BOD) through a fuse bit on the ATmega. That’s a little circuit which prevents the ATmega from coming out of reset and doing anything if the voltage is too low.

As it turns out, you can turn off the BOD in software, but only for sleep mode. The reasoning being that there’s no point in protecting the processor from going berserk while it’s not doing anything in the first place…

Well, my code to turn off the BOD was wrong. You have to do this right before going to sleep. Here’s the updated powerdown_demo.pde sketch:

Screen Shot 2010 08 28 at 12.50.18

(correction – I mixed up my bits: change “PINB |= …” to “PINB = …” or “PORTD ^= …”)

The result?

Dsc 1872

Now we’re cookin’ again!

Fractional bits?

In AVR, Hardware, Software on Aug 28, 2010 at 00:01

To continue this little weblog series on bits, I’m going to go into bit fractions.

Yeah, right… there is no such thing, of course – unless you’re into probabilities or fuzzy logic, perhaps.

What I actually want to do, is describe “analog output” on the ATmega, using the Arduino library’s analogWrite() function. And throw in some bit manipulations along the way, to stay somewhat on topic.

The little secret with analogWrite() is that it doesn’t do what its name suggests. The ATmega has no way of generating an analog signal, i.e. a voltage level between 0 and VCC.

Instead, a pulse is generated, with a varying duty cycle. I.e. the “on” and the “off” times of the pulse will be different, the ratio of these times being proprtional to the 0..255 value passed as argument to analogWrite(). With “0″, the signal will be 100% off, with “255″ the signal will be 100% on. With “128″ the pulse will be on the same amount of time as off. With “1″, it will be on very briefly, and then off most of the time, and so on…

The neat thing is that you connect it to an incandescent lamp, or a motor, then the effect will be that these will light/turn at less than their full power, due to the time it takes for these devices to try and follow the pulse. So the effect is similar to a fractional adjustment: you can dim / slow down these devices by using analogWrite().

It even works with LEDs, although these turn on and off very fast. In this case, the reason is that our eyes can’t follow such fast changes, and so we perceive the result as dimmed as well. A whole industry was once created around this “persistence of vision” property of our eyes – it’s called TV…

Here’s a sketch which uses this pulsed output to control the brightness of a LED connected to DIO3 (i.e. D6):

Screen Shot 2010 08 27 at 16.44.38

Note that I didn’t have to define pin 6 as an output, analogWrite() does that.

What the above does, is ramp up gradually from 0 to 255, and then repeat:

Screen Shot 2010 08 27 at 16.49.06

Suppose we want it to fade in and out instead:

Screen Shot 2010 08 27 at 16.49.17

Try implementing this yourself.

Note that you’re going to need at least 9 bits of information to do this: 8 for the brightness level and 1 to keep track of whether you’re currently in the up ramp or in the down ramp:

Here’s one way to do it, using some bit trickery:

Screen Shot 2010 08 27 at 17.05.15

A few notes:

  • I’ve changed the “level” variable from an 8-bit byte to a 16-bit word
  • bit 8 toggles from 0 to 1 and back every 256 level counts
  • it’ll be 1 when level is 256..511, 768..1023, etc
  • when it’s 1, we flip the bits, i.e. 0 becomes 255, 1 becomes 254, etc
  • the analogWrite() function ignores all upper bits

If you think that was an obscure call to analogWrite(), try this one:

    analogWrite(6, level ^ -((level >> 8) & 1));

Maybe you can decypher it when written slightly differently?

    analogWrite(6, level ^ -bitRead(level, 8));

(hint: bitRead() always returns either 0 or 1)

It’s all pretty geeky stuff, and let’s hope you’ll never have to deal with code such as this again, but the point of this story is that there’s no magic. You just have to know what each operator does, and how to translate an integer from decimal to binary notation and back.

I’ll summarize my intuitive interpretation of bit operators below:

  • X | Y” = take X and copy all the 1′s of Y into it
  • X & Y” = take X and copy all the 0′s of Y into it
  • X ^ Y” = take X and flip all the bits where Y has 1′s
  • ~ X” = flip all the bits of X
  • - X” = arithmetic minus (same as “(~X) + 1″ !)
  • ! X” = 1 if X is zero, 0 otherwise
  • X << N” = multiply X by 2, N times
  • X >> N” = divide X by 2, N times

Some tricks based on this:

  • ~ 0” = all bits set to 1 (same as “-1″ !)
  • ~ 0 << N” = all bits 1, but N lowest bits set to 0
  • bit(N) – 1” = a constant with N lowest bits set to 1
  • X & (bit(N) – 1)” = the N lowest bits of X, the rest is 0
  • X & ~ (bit(N) – 1)” = X, but with the N lowest bits set to 0
  • !! X” = 0 if X is zero, 1 otherwise

An useful rule when writing logical expressions is: when in doubt, parenthesize! – see C operator precedence.

Sooo… use bit(), bitRead(), bitWrite(), bitSet(), and bitClear() wherever you can, since it usually makes the code easier to read. But there’s no need to get lost if you see ^&|~!’s in your expression – just slow down and decode such expressions step by step!

Flippin’ bits

In AVR, Hardware, Software on Aug 27, 2010 at 00:01

After yesterday’s post about setting and clearing bits, let’s explore reversing bits, i.e. changing them from 0 to 1 and back. And let’s do it by blinking an LED attached to DIO of port 1 – i.e. Arduino digital pin 4:

Screen Shot 2010 08 26 at 10.31.26

The “if (onOff = 0)” etc is the logic that toggles onOff between 0 and 1 on each pass through the loop:

    if (onOff == 0) onOff = 1; else onOff = 0;

But there are lots of ways to do the same thing, coded differently:

    if (onOff == 0) onOff = 1; else onOff = 0;
    if (onOff == 0) onOff = bit(0); else onOff = 0;
    if (onOff == 0) bitSet(onOff, 0); else bitClear(onOff, 0);
    onOff = onOff ? 0 : 1;
    onOff = (~ onOff) & 1;
    onOff = (onOff + 1) & 1;
    onOff = ! onOff;
    onOff = 1 - onOff;
    onOff = onOff ^ 1;
    onOff ^= 1;

See if you can figure out all of these.

Take your pick. Those last two use C’s XOR operator. I tend to prefer shorter source code, so I’d use that last notation (note that the resulting compiled code is not necessarily shorter than the other examples).

Now suppose you have a byte value “X” and you want to flip the 4th bit in it, while not changing anything else. That’s a bit more work. It could be done like this, for example:

    if (bitRead(X, 4) == 0) bitSet(X, 4); else bitClear(X, 4);

Or like either of these:

    X = X ^ bit(4);
    X ^= bit(4);

This shows clearly that the “^” XOR operator does exactly what we need: flip bits.

Back to blinking an actual LED, as done with the above sketch. Here’s a little mind bender – another sketch, doing the same using raw ports and the XOR operator:

Screen Shot 2010 08 26 at 10.58.10

The first example was doing things “the Arduino way”, using pinMode() and digitalWrite(). It compiles to 890 bytes of code. This second example goes straight to the hardware and uses 554 bytes of code:

  • Arduino digital pin 4 is bit 4 on the “D port” of an ATmega
  • “DDRD” is the “Data Direction Register”, where we set up pin 4 as an output
  • “PORTD” is the out “Port Register”, which controls the actual output signal

You can see the XOR in action in that last example. It takes all the output bits of port D (Arduino pins 0 .. 7), and flips just a single bit, i.e. bit 4.

Just for kicks, I’ll show you one more way to blink the LED:

Screen Shot 2010 08 26 at 11.03.44

This uses a relatively little-known feature of the hardware, which actually has “bit flipping” built-in. The “PIND” register is normally used for input, i.e. for reading the state of a pin as an input signal. But you can also write to that register. When you do, it will be used to flip output pins, but only for the bits which were set to 1. It’s essentially a built-in XOR.

That last example uses 550 bytes of code, most of which is overhead from the Arduino run-time library (setting up the milliseconds timer, etc). So what’s in a measly 4 bytes, right? Wrong. There is a minute, but sometimes important difference: the other approaches all had to read the register value first, flip the bit, and then write the value back. This last version only writes a (constant) value to a register. With interrupts, that can be very important: this last version can’t ever go wrong, it will always flip the requested bit. The other version could have an interrupt occur between the read and the write. It’s a known issue for the Arduino Mega. It can lead to code which runs for a week, and then fails mysteriously. Bugs like these are fiendishly hard to properly diagnose.

Bit-flipping can be quite useful for physical computing. Not only does it let you easily toggle specific bits, and change the state of some output pins, it can also be a way to clear a bit. Let’s say you need to generate a (very) quick pulse. Here are four ways to accomplish the same thing:

    bitSet(PORTD, 4); bitClear(PORTD, 4);
    PORTD |= bit(4); PORTD ^= bit(4);
    PORTD |= bit(4); PIND = bit(4);
    PIND = bit(4); PIND = bit(4);

That second one based on XOR works, because bit 4 is known to be one, so setting it to zero is always the same as flipping it. That’s also why the third PORTD/PIND example works, with PIND doing the XOR in hardware. Lastly, the fourth approach will only work if bit 4 was initially zero. It’s the fastest one, and does not suffer from the interrupt race condition mentioned above.

Ok, that’s enough flippin’ for one day!

Tomorrow, I’m going to go into, ehm… “fractional bits” (haha!) ;)

Update – see comment below on why “bitSet(PORTD, 4); bitClear(PORTD, 4);” are also interrupt-safe (mostly – but not on every pin of an Arduino Mega!).

Bit manipulation

In AVR, Software on Aug 26, 2010 at 00:01

Today I’d like to go into bit manipulation, ehm, a bit

You need bit manipulation when you’re dealing with the individual bits in a byte, such as on the I/O ports of an ATmega, for example.

First the easy approach – use these predefined macros from the Arduino library:

  • bit(N) returns an integer with the N’th bit set to 1
  • bitRead(X,N) – returns the N-th bit of X as 0 or 1
  • bitWrite(X,N,B) – sets Nth bit of X to B (0 or 1)
  • bitSet(X,N) – sets the Nth bit of X to 1
  • bitClear(X,N) – sets the Nth bit of X to 0

This is why you might see code such as the following:

    bitSet(WDTCSR, WDIE);

This means: “set the Watchdog Interrupt Enable to 1 in the Watchdog Timer Control Register”. The WDTCSR and WDIE terms are predefined constants. WDIE is 6, for example.

Note that some of these routines can be written in terms of the others, i.e.

  • bitSet(X,N) is the same as bitWrite(X,N,1)
  • bitClear(X,N) is the same as bitWrite(X,N,0)

But what does it all mean?

Well, let’s dive in. First make sure that you are comfortable with “bit shifting”. The expression “bit(3)” is the same as “1 << 3″, which in turn is the same as doubling the value 1 three times, i.e. the value eight. So “bit(0)” is 1 doubled zero times (i.e. 1) and “bit(7)” is 1 doubled 7 times, i.e. 128. Bytes have 8 bits numbered 0 to 7, so all you need for (byte-sized) hardware registers is to remember that bits 0..7 map to (specific!) integers with values 1 to 128.

Setting a bit, is like OR-ing the bit with the rest of the value. The following statements are all identical:

    WDTCSR = WDTCSR | bit(WDIE);
    WDTCSR = WDTCSR | (1 << WDIE);
    WDTCSR = WDTCSR | (1 << 6);
    WDTCSR = WDTCSR | 0b1000000;
    WDTCSR = WDTCSR | 0x40;
    WDTCSR = WDTCSR | 64;

This, in turn, can be abbreviated in C as:

    WDTCSR |= bit(WDIE);
    WDTCSR |= (1 << WDIE);
    WDTCSR |= (1 << 6);
    etc...

Or you could write:

    bitSet(WDTCSR, WDIE);

It’s all the same. So OR-ing is about setting bits (to 1).

Likewise, AND-ing is about not clearing bits (to 0). Whoa, that’s confusing. This expression returns a value which is what X was, but only for bit N:

    X & bit(N);

So this will change X to a value with all bits except bit N set to zero:

    X = X & bit(N);

To put it differently: X will lose its original bits, except bit N, which will be left alone. All the bits are set to zero, except bit N.

Usually, you want the opposite, setting only bit N to zero. That too is accomplished with AND-ing, but you have to flip all the 0′s to 1 and all the 1′s to 0 first. Hang in there, it’s a slightly longer story. This sets bit N to zero:

    X = X & ~ bit(N);

Let’s examine what’s going on here. First, “bit(N)” is a value with only the Nth bit set. Now, “~ bit(N)” is a value with all the bits flipped around (“~” is called the complement operator in C), so that’s a value with all but the Nth bit set. Everything is 1, but bit N is 0.

Now we can tackle the expression “X & ~ bit(N)”. Since AND-ing is about “not clearing bits”, that means that the result of this expression is all the bits of X unchanged where “~ bit(N)” was one, which is almost everywhere. The only bit that differs is bit N – it is zero in “~ bit(N)”, therefore that particular bit will “not not clear …” (a double negation!): it will be cleared (to 0) in the result.

Finally, we replace X by that result. So X will change in precisely one bit: bit N. That bit will be cleared to zero, the rest is not affected. In short: we’ve cleared bit N.

Confused?

Well, that’s why the bit/bitSet/etc macro definitions were introduced. These expressions are all identical:

    X = X & ~ bit(N);
    X = X & ~ (1 << N);
    if (X & bit(N)) X = X - bit(N);
    bitClear(X, N);

That last one is clearest by far, because it conveys the actual operation with a well-chosen name: clear bit N, leave the rest alone.

So why would anyone ever choose to use anything but the bit/bitRead/etc routines?

Many reasons. Habit, perhaps. Coming from another environment which doesn’t have these macros. Being so used to this bit-manipulation that the use of words doesn’t really look any clearer. Whatever…

But another more important reason is that you can’t do everything with these bit/bitSet/bitClear routines. Sometimes you just have to go to the raw code. Such as when you need to set multiple bits at once, or flip bits. That’s why the ATmega datasheet has examples like these:

    WDTCSR |= (1<<WDCE) | (1<<WDE);

By now, you should be able to decode such a statement. It’s the same as:

    WDTCSR |= bit(WDCE) | bit(WDE);

In other words:

    WDTCSR = WDTCSR | bit(WDCE) | bit(WDE);

Which in turn is almost the same as these two statements together:

    WDTCSR |= bit(WDCE);
    WDTCSR |= bit(WDE);

That in turn, can be written as these two lines:

    bitSet(WDTCSR, WDCE);
    bitSet(WDTCSR, WDE);

Much clearer, right? Except… it’s not 100% identical!

The problem is a hardware issue: timing. The above two statements will set both bits, but not at the same time! For hardware register settings, that difference can be important. There is a fraction of a microsecond between the WDCE bit being set and the WDE bit being set. Unfortunately, in some cases that causes real problems – your code won’t work as expected.

Tomorrow, I’ll continue on this topic, but it’ll be a bit more fun, because there will be LEDs involved!

Dsc 1385 2

(Please ignore the cable on the left, I snatched the above picture from this post)

Update – see this excellent Wikipedia article for more details about bitwise operations.

Simplified button interface

In AVR, Software on Aug 24, 2010 at 00:01

The Blink Plug has two pushbuttons and two LEDs. The buttons are simple miniature switches, but nothing is ever simple in microcontroller-land: reading out the state of a pushbutton reliably can be deceptively hard, due to mechanical bounce issues.

The Ports library has had a BlinkPlug class for some time now, including a “pushed()” function to do all the debouncing. Unfortunately, that function turned out to be a bit harder to use than I originally intended.

Time to add some more code to the BlinkPlug class!

I’ve added a new “buttonCheck()” member, which returns events instead of state. That makes it a lot easier to detect when people press a button, which is usually all you’re after anyway.

Here’s a new button_demo.pde example sketch, which illustrates the new functionality:

Screen Shot 2010 08 23 at 17.44.21

Sample output:

Screen Shot 2010 08 23 at 17.44.39

As you can see, it’s now a lot simpler to detect when people press or release one of the two buttons on a Blink Plug. Each time you call buttonCheck(), you’ll get one of the following events:

ALL_OFF, ON1, OFF1, ON2, OFF2, SOME_ON.

You have to keep calling “buttonCheck()” reasonably often, at least 10 times per second, if you don’t want to miss any events. Calling it all the time in the main loop is fine. Keep in mind that ON1, etc. will be returned only once for each actual button press.

You can still call “state()” whenever you want, to check the position of either button. But when you use buttonCheck(), you should not call the old – now deprecated – “pushed()” function, as these two will interfere with each other.

This code is now part of the Ports library (subversion and ZIP). Gory details are in Ports.cpp, near line 230.

Assembling the JeeSMD, part 2

In AVR, Hardware on Jul 9, 2010 at 00:01

Yesterday’s post was about assembling all the SMD components of the JeeSMD kit.

The last step is to program a sketch into the ATmega. This isn’t as straightforwards as with a JeeNode, because there’s no on-board FTDI or USB serial port hookup.

It’s fairly easy to create an FTDI connection, but even if you do, you’ll still need an ISP programmer to install a boot loader (see this recent post for some background).

So let’s hook up an ISP programmer first:

Dsc 1787

I’m using a somewhat weird setup: first of all, my cable connector was attached the wrong way around, so I always have to use this one in that weird folded-over position.

But a more important issue is that the ISP connection needs to use pins 1..6 of the 2×4-pin SPI/ISP connector on the JeeSMD. That doesn’t work with normal flat cable connectors, which assume 2×3 pins and are too wide to fit in a 2×4-pin header. My solution is to insert wire-wrap pins the wrong way around into the cable header. This effectively extends the connector, but now it won’t be as wide and it’ll fit just fine. Another solution would be to only solder 2×3 pins in the SPI/ISP position – you can always add two more pins later.

Once you’ve passed that hurdle, you can use any ISP programmer you like. There have been several posts about this on the weblog, as listed here.

Now, if you want to use FTDI, then presumably you just uploaded a bootloader into the ATmega, with all the proper fuse settings, etc. The next step then, is to somehow connect to a 6-pin FDTI header.

There are several ways to do this. The one I use nowadays, is through a Carrier Board, which includes the 6-pin FTDI connector:

Dsc 1786

The point about the FTDI connector, is that it’s almost trivial. All you need is 4 wires to GND, PWR, TX, and RX – plus a way to reset the board from the RTS signal. The clever way to generate a reset is to insert a 0.1 µF capacitor between the serial side RTS and the ATmega’s reset pin. Tiny trick, huge implications (does the name “Arduino” ring a bell?).

So how does the Carrier Board implement FTDI? Easy: it adds the capacitor. And you can easily do that yourself without a Carrier Board. Here’s how:

Screen Shot 2010 07 08 at 23.20.52

Note that what FTDI calls “RX” is connected to what the ATmega calls “TXD”, and vice versa. It’s all a matter of perspective… Once you have the FTDI connection set up, you can upload sketches using the Arduino IDE just as with any other board. All you need is a USB-BUB or some other equivalent USB-to-FTDI interface.

Congratulations: that’s all it takes to build and use the Arduino-compatible JeeSMD!

Assembling the JeeSMD

In AVR, Hardware on Jul 8, 2010 at 00:01

The JeeSMD is a kit with tiny “Surface Mounted Device” (SMD) components. SMD was designed for automated assembly with Pick & Place machines, but with a bit of patience it’s fairly easy to assemble a board by hand – see this post for an overview of what you will need.

You won’t be able to do this without at least a fine-tipped (0.4..0.6mm) soldering iron plus the following tools:

Dsc 1773

A magnifier lamp also helps, I know I couldn’t do this without one anymore!

This is a step-by-step guide on how to assemble the SMD kit, which consists of these parts:

Dsc 1772

The tiny ones (don’t sneeze!) are hardest to tell apart:

Jee smd Closeup

(thanks to Steve E for the macro shot – I just added some labels)

There are 2 10 kΩ resistors in there, although you only need one. That lets you get started without having to worry too much – if you mess up completely, just remove it and start over with the other one.

For a fantastic resource with detailed videos about hand-soldering SMD, see this Curious Inventor page.

So let’s get started. First thing to do is to apply flux wherever you’re going to solder things. The flux is essential because the flux in your solder wire will have evaporated longe before you can move your tip from the wire to the part.

I’m right-handed, so that’s how I hold my soldering iron. That leaves only my left hand for the tweezers – and no hand at all for the soldering wire:

Dsc 1774

Use your tweezers for all these parts, and don’t let go – once a 0603 part flies off or drops on the floor, your chances of finding it again are next to zero. Best is to work on a clean flat surface with everything around you removed.

The trick is to place the part and then push it down while you touch it with your iron with solder already on it. The moment a part is soldered down on at least one pin, it becomes a lot easier:

Dsc 1775

The matte “stain” you see around these pads is the flux, which has dried up but is still active.

(Remainder continued after the break…)

Read the rest of this entry »

Uploading? ISP? FTDI? Huh?

In AVR, Hardware, Software on Jul 4, 2010 at 00:01

There seems to be a fair bit of confusion in- and outside the Arduino world, and it’s spilling over to JeeNodes …

I’d like to go through some terms and buzzwords to try and clarify how to get your Arduino or JeeNode to do the thing you want it to do. I’m going to assume that you are familiar with the process of writing software (“code”), compiling it, and running it – at least on a Windows, Mac, or Linux computer (let’s call them all PC’s for now). With software for the ATmega, there are two approaches, depending on whether you use the Arduino IDE or not:

Screen Shot 2010 06 28 at 23.50.22

Both lead to the same result: a “hex” file with code that needs to be transferred from the PC to the ATmega.

The step which can be puzzling when starting out with physical computing and embedded hardware is how to get things across from your PC to that little Arduino or Arduino-like system you’re holding in your hand. And vice versa, since we often want to get results back or see some confirmation that things are working properly.

The confusion comes from the different conceptual levels involved, and things like:

  • do you mean how to connnect? – plug in a USB cable
  • do you mean how does the ATmega change its own code? – through a boot loader
  • do you mean via ISP (In System Programming)? – no, that’s normally not needed
  • do you mean via FTDI? – yes, that’s the name of the chip which is hooked up to USB
  • isn’t FTDI a connector? – yeah, that too, sort of… i.e. a 6-pin convention
  • isn’t a power + serial cable enough? – no, resets also play a key role
  • do I have to use the Arduino IDE? – no, you can also use a program called “avrdude”
  • what’s avrdude? – a program which can upload to a boot loader or an ISP programmer
  • do I need an ISP progranmmer? – nope, the boot loader does essentially the same thing
  • so why not just get rid of ISP? – because you need ISP to install the boot loader

Confused? Welcome to the club…

In case you’re wondering… the process is called “uploading” because the PC initiates this as outbound transfer:

Screen Shot 2010 06 29 at 01.51.50

To get your code (“sketch” in Arduino-speak) into an ATmega, you need three things, working together to make uploading happen under all possible conditions:

  1. An electrical connection – to power the ATmega, to communicate with it, and to restart the ATmega when it is stuck or busy doing something else.

  2. A common language / protocol – the communication must be understood by both sides, i.e. PC and ATmega.

  3. Software on both sides of the connection – Sending something when the other side isn’t listening, or listening while no-one is sending will not have the desired outcome.

Let’s go through each of these separately.

1. An electrical connection

There are several ways to make the connection. With an Arduino, or any similar board which has a USB connector, you can simply plug in the USB cable:

Screen Shot 2010 06 28 at 23.52.41

Some boards use a separate USB interface (“FTDI adapter”), allowing reuse of that interface for multiple boards:

Screen Shot 2010 06 28 at 23.54.08

The end effect is the same: a connection which powers the ATmega and allows communicating with it using a simple serial protocol. There’s also a trick in this hookup to let the PC reset the ATmega whenever it wants.

2. A common language / protocol

Ah, now it gets interesting. First thing to note is that there is no single common language / protocol!

That’s right. It all depends on what you want to do. Here we want to upload code from the PC to the ATmega. That requires exchanging “ISP commands” over the connection. But once uploading is done, we really want to reuse the connection as a regular two-way serial link.

The way it works is that the PC will reset the ATmega just before uploading new code. This activates a “boot loader” on the ATmega. Now both sides will be in sync (briefly) so they can exchange the necessary information to make an upload happen. IOW, right after reset the protocol is “ISP commands”. Once the upload is done, the connection can be reused for any protocol you like – as determined by the code that was uploaded.

3. Software on both sides of the connection

Back to the software now. We need to send ISP commands over the connection.

As you may have guessed, that’s exactly what the Arduino boot loader on the ATmega understands. When reset, the boot loader in the ATmega gets control. It waits and listens for incoming STK500 ISP commands. If none come in within a second or so, it relinquishes control to whatever was previously uploaded to the ATmega.

On the PC side, we need software which resets the ATmega and then immediately sends all the ISP commands needed to transfer and program the contents of a hex file.

This is what “avrdude” does. You can either use it implicitly from the Arduino IDE by starting an “Upload” from the menu, or you can launch it manually from the command line – avrdude needs a few options to tell it where the USB port is, what baudrate to use, the type of ATmega, the protocol to use (i.e. STK500), etc.

There’s more…

The above describes the different pieces and concepts involved in getting code into an ATmega. The beauty of it is that once it works, it really works well. Supplying power, uploading, communication, control, debugging … all with one simple USB cable. You only need to go back a few years to appreciate just how much this approach simplifies embedded development.

But there’s one important detail: the ATmega has to have a functioning boot loader. Placing a boot loader into an ATmega is a bit more complicated (and involves other things such as “fuses”). It’s a chicken-and-egg problem.

This is where the ISP programmer comes in. An ISP programmer is a fairly simple piece of hardware. In fact, you can make your own, as I’ve described in several posts on this weblog. See this and this post for some quick solutions which require nothing more than a working Arduino or JeeNode.

The good news, is that you usually don’t have to worry about installing the boot loader – it’s all done for you. Once. For the mechanism described above, you’ll never need an ISP programmer.

Some people actually prefer to use the ISP technique for uploading their sketches. In fact, sometimes you have no choice, i.e. when you need the serial port at all times, or when you can’t spare the 1..4 Kb required by the boot loader code, or when working with ATtiny chips which don’t support bootloaders.

In thoses cases, you’ll need a setup with an ISP programmer. But for most people doodling around with ATmega’s and the Arduino IDE, the above boot loader mechanism is usually very convenient and the easiest to get going.

Either way, it helps to understand the process. I hope the above was helpful in that direction.

Fixing a faulty ATmega (Arduino)

In AVR, Hardware, Software on Jul 2, 2010 at 00:01

After a recent post on how to repair an ATmega with a faulty (or even missing) bootloader and helping someone out with it, it occurred to me that this mechanism will work for any Arduino – not just JeeNodes.

Any 3.3V or 5V Arduino’ish system which lets you upload the isp_repair.pde sketch can be used to program any board with an ISP connector on it. The code is for ATmega328′s, because that’s all I use around here these days.

The trick is to hook up a few power and I/O lines in a specific way:

Screen Shot 2010 06 28 at 16.59.11

I’m using an Arduino Pro as example, but that’s just one of many you could use. Now connect these six wires:

  • ISP pin 1 = BLUE = Digital pin 4
  • ISP pin 2 = RED = VCC (+5V)
  • ISP pin 3 = GREEN = Analog pin 0
  • ISP pin 4 = PURPLE = Analog pin 3
  • ISP pin 5 = ORANGE = Digital pin 7
  • ISP pin 6 = BLACK = GND

Note: if your working board operates at 3.3V, then you should connect the RED wire to +3.3V, not +5V (that way signal levels and power supply will match). Also: the target board should not be connected to anything, since it will be powered through the ISP connector.

The only thing left to do is to upload the isp_repair.pde sketch to your working board, and open up a console window. You should see something like this:

That’s it – disconnect all the wires. The ATmega on the target board now has a boot loader and the standard pin 13 blink sketch. Ready again to accept whatever sketch you upload to it!

Uploading without avrdude

In AVR, Software on Jul 1, 2010 at 00:01

In the future, I’d like to upload new firmware to JeeNodes, Arduino’s, and other AVR boards through channels other than a serial port or USB. Uploading to a “slave plug” via I2C would be neat, for example.

That means the standard avrdude won’t do. Besides, after having coded various types of ISP sketches recently, I realized that the upload mechanism is really quite simple. If all you need is STK500 compatibility (as used by several ISP programmers and by the Arduino boot loader itself), then avrdude is overkill.

So here’s a demo “rig” for JeeMon which does the same thing as avrdude, i.e. upload a sketch over a serial port:

Screen Shot 2010 06 27 at 23.19.45

That removes the need to compile and install avrdude. Better still, this should work as is on every platform supported by JeeMon.

(Note: the above code is now part of JeeMon, but the source code can also be found here on the web)

Onwards!

Update – the above code has been integrated into JeeMon as new Upload rig – with dudeLoader renamed to “stk500″ and readIntelHex now called “readHexFile”. Here’s a new demo “application.tcl” using this:

Screen Shot 2010 06 28 at 01.46.48

Now works with the Arduino boot loader as well as with the Flash Board ISP programmer (add “19200″ arg).

(Reminder: the Jee Labs shop will be closed from July 14th through August 14th)

TwitLEDs finale

In AVR, Hardware, Software on Jun 29, 2010 at 00:01

The TwitLEDs project by Myra and Jean-Claude Wippler (daughter and father) has come to a conclusion. It was great. I’ll just summarize by pointing to the six posts on the Jee Labs weblog describing the technical details, and some pictures and videos, showing the results.

Here you can see the finished TwitLEDs robot:

Dsc 1741

This is the, ehm… print head?

Dsc 1749

And last but not least, some videos. First a trial run for the print mechanism:

Next, a trial run for the vehicle, trying to stay out of trouble:

And here the result!

And one more:

Ok, that’s it. Myra and I both had oodles of fun building this and trying things out – hope you did too :)

Onwards!

(If you can’t view the videos on vimeo, see 1, 2, 3, and 4)

TwitLEDs robot – action shots

In AVR, Hardware, Software on Jun 25, 2010 at 00:01

As promised in the previous post, some pictures and movies of the TwitLEDs robot in action.

First another view of the robot, with the different pieces:

Dsc 1747

We don’t have the proper “arena” yet, i.e. a big fenced-off floor area covered with glow-in-the-dark paint. Instead, these first trials used two pieces of foam board, taped together. It’s not perfect because the robot keeps running off track, and because the hump between the two pieces is quite high. Foam board isn’t really suited for this: it curls up too much from the moisture in the paint. We probably should have waited a bit longer for everything to dry completely…

The inital test code just printed out its name (povGlow) and the compilation date. In the first tests, one of the LEDs wasn’t working (a software bug, not hardware), so the text isn’t quite right:

Dsc 2039

You can clearly see the fading of the letters over time. This happens very quickly, but those faded letters then remain visible for quite a while. That’s why you can still see several trial runs “printed out” on the foam board.

So the basic idea of printing with light works, as you can see!

Here is a video (sorry, not inline), showing how the robot veers to the right as I put my hand in front of it to prevent it from running off the track. Note that I’m not touching the robot, I just briefly trigger the distance sensor. The on-board LED lights up in red when the correction takes place. It’s not very smooth, but it works.

Another picture, showing the decay of the printed text brightness:

Dsc 2067

Maybe 7 pulsed blue lasers (from DVD writers, perhaps?) could be used to create even more intense blue dots. As it is, with these blue LEDs the writing is very clear – but only in a relatively dark room. With the lights on, the text becomes virtually invisible. Even though the LEDs are bright enough to be painful to look at:

Dsc 1749

The quality of this “printer” is actually pretty good, considering how simple its technology is:

Dsc 2056

Finally, a run where the robot happened to stay a bit longer on track, allowing it to display its brief message a few times. Again as video – you can see the wobbling foam board, and this thing driving like a drunken duck, leaving its trail of fading messages behind.

All that remains, is to try and get some tweets into it in real time. Stay tuned…

Several days of testing have now drained the 4 alkaline AA to the point where the robot advances noticeably slower. Looks like we’re getting no more than an hour or two out of these batteries. Which is not really surprising: the DC motors must be eating quite a bit of current, and the LEDs probably draw up to 200 milliamps or so. Self-powered autonomous motion is really hard!

TwitLEDs robot, part 3

In AVR, Hardware, Software on Jun 24, 2010 at 00:01

To continue on yesterday’s post, here is how we got a little autonomous robot going.

The main part was solved by picking the Asuro robot kit. It’s really low-end, but it has just enough functionality for this project, and at €50, it’s very affordable. In fact, Myra built a spare one because the first unit broke down. In the end, I was still able to fix it: a burnt out transistor (both H-bridges are done with discrete components!). So now we have two Asuro’s:

Dsc 1750

The nice bit about the Asuro is that it has an odometer on each wheel. IOW, there are IR LEDs + sensors to count the number of steps (8 per rev) made by the wheel, and the C library code includes logic to adjust the speed of the motor. It’s a bit crude, but because of this the Asuro can drive fairly straight. As we found out later, it has a bit more trouble doing so while driving slowly, so it’s still a bit wiggly.

But it works. Two small DC motors, some simple gears, motor axles soldered to the PCB (what a great low-cost solution), and room for an extension board. To give you an idea of how crude this thing really is: there is no on-board voltage regulator. When used with 4 alkaline AA batteries, you have to remove a jumper so the extra voltage drop over a diode gets the supply voltage down to under 5.5V …

The Asuro is full of such nifty cost-cutting tricks. It even includes a bidirectional IR link, over which new code can be uploaded. The IR link is very short-range, so it would have been insufficient for our purposes – but for quick code tweaks, the IR link works fine.

Speaking of code, here is the main avoider.c logic running on the ATmega8:

Screen Shot 2010 06 18 at 23.57.08

This is not an Arduino sketch, but I made it look a bit like one by using the same setup() and loop() functions.

This code has to be compiled with avr-gcc. The Asuro comes with several examples with Makefiles. I simply copied one and started extending it. A little optional USB-IR adapter is used to connect to the Asuro (an RS232 one is included with the Asuro kit, but I don’t have any RS232 ports). The whole setup works pretty well from the command line, especially considering that it’s a completely different setup than the Arduino IDE.

Anyway, back to the design of the TwitLEDs robot.

The challenge was to find a simple way to make this robot drive around without bumping into things. The Asuro has a row of switches at the front, but these are not very reliable, and besides: bumping and stopping and turning would mess up the LED strip being “printed” on the glow-in-the-dark paint.

So instead, we mounted a Sharp 10..80 cm distance sensor on top. It’s very easy to read out, since it produces an analog voltage, inversely related to the distance of objects in front of it.

The logic for collision avoidance is crude, but sufficiently effective: turn more and more right as you get nearer to an obstacle. The on-board LED turns from off to green to yellow to red as the distance decreases, so it’s easy to see what the robot is doing. I’ve tweaked it so that when it drives straight towards an obstacle, then turning will be quick enough to never bump into that obstacle.

Here’s the completed unit, with the Sharp proximity sensor on a little expansion board at the front, and the LED blinker glued to the side of the battery pack – the LEDs hover 1 .. 2 mm above the ground:

Dsc 1741

Myra’s idea was to have this thing drive inside a more or less circular “fence” made of corrugated cardboard. The whole area inside the fence will be made of some panels, covered with 3 layers of glow-in-the-dark paint.

There is a flaw in the current design, in that the robot can only evade an obstacle by turning to the right. If it approaches a wall obliquely from the right, it will do the wrong thing and drive straight into the wall. But we’re hoping that as long as it doesn’t over-correct, and by sending it off in a tangent, it will keep adjusting slightly to the right as it drives around and around in “sort of” circles.

More tests and tweaks will no doubt be needed.

But as it is, this thing really seems to stay out of trouble. We can let it loose in the room and it’ll veer to the right whenever it comes near an obstacle. Sometimes it veers to far, though. Again, I hope a more controlled “arena” will be sufficiently simple to keep it going.

When the robot does bump into its front switches, it turns both motors off, blinks for 10 seconds, and then starts off again. Time enough to pick it up and aim it in a different direction.

So that’s it. An autonomous unit with two independent computers, IR distance sensing, a short range IR link, and the JeeNode with a longer-range wireless RF link. Even including a JeeLink on the laptop side, the cost of all this was only slightly over €100.

Tomorrow, some pictures + movies. Gives me time to finish the Twitter link, and then on to the grand finale!

(Reminder: one week left for the June special in the Jee Labs shop!)

TwitLEDs robot, part 2

In AVR, Hardware, Software on Jun 23, 2010 at 00:01

Yesterday’s post introduced the robot Myra and I have been working on. Here’s the first part we built:

Dsc 1725

It’s basically a backplane for the LED blinker component. Or to put it differently: a simple persistence-of-vision (POV) unit, using a JeeNode, and Output Plug to drive a few LEDs. Only the output plug was soldered-in permanently. The removable JeeNode allows it to be easily programmed and re-used, and the removable LEDs allow trying out different units. This turned out to be important, because I only had a few green LEDs when starting this, and had no idea then as to what sort of LEDs would give the best POV results later on.

Myra did all the soldering. Here are the two LED mounts we ended up with:

Dsc 1745

The one on the left is the super-duper LED concoction we built as final version. The one on the right was great for initial testing.

Everything is held together with rubber bands, zip-lock ties, tape, and ample amounts of hot glue (once verified to work!) – hacking at its best, clearly:

Dsc 1742

Here’s the LED blinker with the final LED strip, side view:

Dsc 1743

Side view close-up – with the foam board cover:

Dsc 1746

Bottom view:

Dsc 1744

Seven blue LEDs, ready to shine very brightly and controlled by the JeeNode.

The software started out very simple, of course. Things like this, just to make sure it all works:

Screen Shot 2010 06 18 at 23.01.21

This is the main part of what is more or less the final twitLEDs.pde sketch:

Screen Shot 2010 06 18 at 23.03.06

I found a suitable font table by googling around a bit. This is needed to go from ASCII characters to dots-in-a-readable-pattern. No room for Unicode (don’t laugh: some tweets are in Japanese and Chinese, and they won’t show properly).

The amazing bit is that everything worked essentially on first go. It blinked! But does it blink in the proper pattern? Our first test consisted of Myra taking a long-exposure shot, as I waved this thing around in the air – with the lights off. Liesbeth tracked progress through all the shrieks and laughs… but from a safe distance :)

Dsc 1793

Yippie. It really works!

Tomorrow: driving around without bumping into things.

Something different…

In AVR, Hardware, Software on Jun 22, 2010 at 00:01

Ok, so I’ve got tons of projects on my plate to do and to finish. And tons more that are still very experimental, or haven’t even been started. Plenty to keep me busy, with the summer vacation period nearing fast.

Yet here’s something different. The timeline for this project was imposed by external factors: my daughter Myra doing a project for the last quarter of her second year at the Design Academy in Eindhoven.

She wanted to do something which triggers human interaction, and she wanted to try something with Physical Computing. “Terrific, I’ll help!” – I shouted, completely ignoring all the pending work on my own plate…

So here’s the start of a few articles about the “TwitLEDs” project we’ve been working on recently. All the basic ingredients work as I write this, but we have yet to finish the final setup and go through a last rehearsal.

What is it?

It’s a mix between a matrix printer and a persistence-of-vision (POV) display.
It’s called the TwitLEDs robot. And it’s hooked up to the internet.

Get it? No? Ok, then let me try again. I think this picture tells it best:

Dsc 2069

The idea is to have a little autonomous robot driving around, leaving messages behind on a floor covered with glow-in-the-dark paint. The messages are collected off Twitter using a configurable search term. This is done from a laptop and then sent to the robot by wireless.

There were several fairly non-trivial problems to solve here, with some experimentation needed to find a workable mix – as well as some time contraints. A few days of work would be the most I could set aside for this. Luckily, I didn’t get lost in too many dead alleys, so it worked out nicely.

Here are the pieces we used:

  • A low-cost robot kit called Asuro – based on an ATmega8, so I had all the software ready for it. In fact, I played around a bit with it a while back – as reported here.
  • A JeeNode for wireless connectivity.
  • An Output Plug to drive some LEDs.
  • Seven blue LEDs. I picked a bright one with a very focused beam (C503B-BAN-CY0C0461).
  • Glow-in-the-dark paint. Green stuff. Three coatings.
  • Some panels to create a floor. Covered with the green stuff.
  • Some cardboard to create an “arena” on the floor to contain the robot.
  • JeeMon running on a MacBook, with a JeeLink to send out the messages.
  • A fairly dark room. This just won’t work with the lights on, unfortunately.

As with every project, the first part is the hardest and the most critical success-factor: figuring out what to do, what not to do, and finding solutions within the many constraints we had to operate under. I’ll spare you the ideas that didn’t make it, and the (really neat) ideas we simply didn’t have time for.

Being the sole programmer on the team, I got to deal with all the software. Yummie! :)

The most important insight for me was that we could implement this project with three completely independent subsystems:

  • The LED blinker, driving 7 LEDs in the proper pattern, basically a POV unit (plus receiver).
  • The robot, moving around while continuously trying to stay out of trouble.
  • The server process running on the laptop, connecting to Twitter and sending messages into the air.

We started off with the LED blinker because it was a major component with few unknowns, i.e. we picked the low-hanging fruit first. Here’s a picture of it, still under construction:

Dsc 1726

More on the LED blinker tomorrow…

Battery savings for the Pressure Plug

In AVR, Hardware, Software on Jun 20, 2010 at 00:01

Reducing power consumption is fairly tricky, as you can see in the many previous posts about this topic. And to be honest, I haven’t quite gotten to the point where I want to be with the Room Board. My first “major” (ahem) setup with about a dozen nodes around the house didn’t quite go as I had hoped. Most batteries were empty within a month. A few nodes are still going, but those are hooked up to power adapters…

I’d like to revisit this issue and try to improve things a bit. To make the rooms sketch perform better, and also to make the code structure a bit clearer. The current rooms code is quite complex and hard to follow.

But before messing with the rooms.pde sketch, let’s tackle something simpler: the wireless sensor node based on the Pressure Plug, as described here, and then simplified here. I’ll use that last version as starting point.

The first point to note is that to get a substantial first power reduction, you have to focus on the portion of the code where it’s spending most of the time. Which, in the case of “bmp085demo”, is here:

Screen Shot 2010 06 17 at 01.55.06

That’s right: it’s waiting for the next second to “happen”. And even with a slow’ish sensor such as the BMP085 at maximum resolution, it’s spending more than 90% of its time there… waiting!

I’ll use an approach which might be a bit surprising: let’s not change any of the current logic. The idea is that once we’ve done our thing for the current second, we can go into low power mode, as long as we make sure to get back to normal operating conditions in time for the next second.

So what we’re going to do is add some code to the end of the loop() function. It’s functionally equivalent to adding it at the start, since loop(), eh, loops – but I think it makes a better point.

The end of loop() used to look as follows:

Screen Shot 2010 06 17 at 02.01.01

I’m changing it to this:

Screen Shot 2010 06 17 at 01.43.00

IOW, at this stage all the hard work has been done. We wait a bit for all interrupt-driven I/O to complete (serial and RF12). And then we need to figure out how much time remains until the next second. The power saving happens by spending that time in power off mode.

But this requires some preparation. When inducing a comatose state like this, you have to make absolutely sure that something is still able to get you out of coma and back up and running again. This is what the ATmega’s “watchdog” is for: we set it up to wake us up in 16 milliseconds, just before entering sleep mode. And then we keep doing that until it’s almost time to take another reading. The actual watchdog interrupt handler does nothing, btw – all we want is to get back out of power down.

Note that the radio also needs to be turned off and back on again. It’s the biggest power consumer when enabled. Turning it off and going into power down mode is what lets us go from a tens-of-milliamps current drain to a tens-of-microamps current drain.

All the logic for this is located in the loseSomeTime() function, which was adapted from a slightly different version in the rooms.pde sketch:

Screen Shot 2010 06 17 at 01.42.33

And that’s about it. The average power consumption of this sensor node will go down by an order of magnitude. It’ll still be 1..2 mA, but it’s a major improvement: this node should now run 2..3 months on AA batteries. The source code for bmp085demo.pde has been updated.

I’d like to stress that such gains require very little effort for many types of sketches. All you have to do is figure out where the sketch is spending most of its time, and deal with just that part of the code. Getting into yet lower power consumption levels would require more work.

IR trigger for Nikon camera

In AVR, Hardware, Software on Jun 12, 2010 at 00:01

Here’s a fun project: sending out infrared remote codes to takes snapshots :)

This is the code:

Screen Shot 2010 06 10 at 17.19.44

This sketch is doing everything in software, and it’s sort of pushing the limits by pulsing a TSKS5400S IR emitter LED at 38.4 KHz using software delay loops.

The timing diagram on this website was a great help to get this working in no time. Here’s another site.

With the 33 Ω resistor in series, total current through the IR LED should be somewhere between 20 and 50 mA. Since the latter is beyond the ATmega’s current sourcing capapbility, I suspect that the pin voltage will actually drop quite a bit below VCC. A transistor or MOSFET could be added for more power. As it is, this seems to trigger reliably up to about a meter away.

Here’s the setup, triggering my trusty D40 Nikon:

Dsc 1692

a self-portrait!

Lot’s of people have already done this ages ago, btw. Here’s a sketch which uses assembler to get the timing more accurate. But the above does work – the main point is to avoid digitalWrite(), which is relatively slow.

A Happy Ending!

In AVR, Hardware, Software on Jun 10, 2010 at 00:01

The multi-ISP programmer I built and started using some two weeks ago, turned out to be quite a nightmare. Not only were incorrectly programmed ATmegas sent out to about two dozen people, I also had to go through about 70 kits, prepared as new stock just days after I started using this programmer. Twice!

Yes, twice. Because the first “fix” turned out to be insufficient. Doh.

This was a clear case of one bug hiding another, and another, and another. Yep, four bugs: a bug in the MemoryStream class in the Ports library, a timing problem exposed by fixing that bug, and two incorrect assumptions about how the “avrdude” utility works. I’ve now got an explanation for everything that went wrong.

There’s no doubt some interesting psychology at work here … I was so proud of my idea op programming multiple ATmega’s! The main idea was to create an AVRISP-compatible unit which stores everything sent through it and then just replays the saved stream as often as needed. Trouble is, I jumped to conclusions the minute a first “run” worked. Roll the presses! Print it! Tell it to the world!

Anyway. There is a happy ending to all this!

The latest version of the isp_capture.pde sketch in the Ports library has been working properly for over a week now, programming well over a hundred ATmega’s (and it now does auto shut-down a few minutes after use):

Isp Capture Output

The last bug was a very puzzling one: everything worked, but sometimes the fuses wouldn’t get programmed. It turns out that avrdude first reads the fuses, and only sends out commands to program them if the fuses don’t match the new value. Since the programmer needs to work with brand-new as well as previously-programmed chips, the replay mechanism would have depended on the prior state of the chips: not good.

The solution is very simple: I now always program each fuse twice, with two different (valid) values. The second one will remain in force, evidently. Since the replay code was already ignoring fuse mismatch checks, this now means that even if the first setting is skipped by avrdude, the second will always be emitted.

Here is the shell script to prepare the Flash Boards:

Screen Shot 2010 05 30 at 01.35.40

So this has now become a very useful tool at Jee Labs:

Dsc 1432

I love the on-board LiPo battery: I can grab it, use it where I need it, and put it back – no wires = freedom!

For pre-loading the fuses, boot loader, and RF12demo, it already saved me a huge amount of time. Its “burn rate” is up to 500 chips/hour. And Mr. Murphy taught me some valuable lessons along the way…

And now it’s time to move on!

Repairing a faulty ATmega

In AVR, Hardware, Software on Jun 9, 2010 at 00:01

This post is being written after a pretty nasty foul-up on my part w.r.t. sending out badly-flashed ATmega chips. It’s probably too late to be of use to anyone involved in that little débâcle, but I thought I’d describe a DIY fix here in full detail anyway. I’ve simplified the code to make it even easier to use than what was described here.

So what is this about, eh?

The ATmega328 chip used in JeeNodes (and Arduino’s, and various other similar board) comes with a serial boot loader pre-loaded into the high end of its flash memory. This is arguably one the most important features that made the Arduino popular: it lets you upload a new “sketch” into the ATmega over the serial or USB port.

Lots of little details, but the point here is that the boot loader itself can’t easily be damaged, even if you load a non-functional sketch into the ATmega. Just resetting it will let the boot loader overwrite the flash memory with a new version – hopefully a better one. Basically, no matter what goes wrong, there’s always the boot loader in the ATmega to upload a new sketch to it.

There’s a chicken-and-egg problem, though: how do you get that boot loader into the ATmega in the first place? Well … you don’t. It’s normally placed there by the supplier of your ATmegas.

Since Jee Labs is one of the suppliers of JeeNodes (for Europe, and Modern Device for the US), I do need to do a little more. I use an “ISP” programmer to place that boot loader there, along with the RF12demo sketch.

But there’s really not much to all this, and this whole boot loader / ISP stuff can easily be performed by anyone. Keep in mind that’s it’s just about getting that first step right: proper fuses and the boot loader stored in flash memory. Nothing more.

All you need is a working unit and a second target unit with the ATmega that needs to be repaired (or initialized for the first time – same thing). For Arduino’s, it’s all explained at http://arduino.cc/en/Tutorial/ArduinoISP.

As it so happens, there’s now even simpler software to do this, so I’m going to describe the process in terms of using one (working) JeeNode to repair another JeeNode (note that this still should work for Arduino’s as well).

The basic idea is still the same: we need to connect 6 wires. There are 2 wires for +3V and GND and 4 wires connected to ports 1 and 4. On the target JeeNode, the wires will be connected to the ISP connector:

Screen Shot 2010 05 29 at 01.37.23

The target JeeNode will receive its power from the working JeeNode, so don’t plug it into anything. Note that this can also be done with JeeNode USBs. All we need, is to make a few connections for power and I/O.

The working JeeNode should be plugged into a USB-BUB, or something similar. Do that now, because the following wiring step can be a bit sensitive to movement.

The following six connections need to be made:

Screen Shot 2010 05 29 at 02.57.58

On the working unit, the wires or wire jumpers can be inserted into the 6-pin port headers.

On the target side, you’ll probably just have gold-plated holes for the ISP connector. The nice thing about gold plating is that it easily makes contact. So one way to hook up the wires is to insert all six as shown above, and position the whole thing in such a way that there is a slight tension on the wires – just enough to make contact.

Ok, you should now have the working unit powered up, and the target unit receiving power and signals through these 6 wires. Good, leave them alone now.

To do the actual reflashing, I’ve added an isp_repair.pde sketch to the Ports library, which does everything. Upload that sketch to the working JeeNode, and open up the console. Here’s what you should see:

Screen Shot 2010 05 29 at 02.24.05

That’s it. The target ATmega has been set up with the proper fuse settings and a boot loader. You can remove all the wires, and hook up the JeeNode to a USB-BUB. It’ll now accept sketches like any other JeeNode. Fixed!

EtheRBBBreadboard

In AVR, Hardware, Software on Jun 7, 2010 at 00:01

Please excuse the crazy title. This picture probably tells you more:

Dsc 1509

You’re looking at an RBBB from Modern Device, hooked up to the Ether Card from Jee Labs. The hookup is trivial, it need 6 wires: 2 for power and 4 for SPI:

Screen Shot 2010 05 29 at 04.18.26

And that’s all you need to create a webserver!

Here’s a sample screen (yep, it’s been running for almost 12 hours):

Screen Shot 2010 05 29 at 00.03.48

And here’s the code for it:

Screen Shot 2010 05 28 at 12.05.03

It presents a self-refreshing page with the “uptime”, i.e. how long the server has been running since power-up.

The code is available as “rbbb_server.pde” example sketch in the EtherCard library and is a simplified adaptation of the etherNode sketch, omitting the RF12 driver and calls, of course. It compiles to 6 Kb of code.

As with the etherNode sketch, the MAC address and IP address have to be set to suitable values in the source code before uploading it to the RBBB.

BTW… did you notice anything?

The RBBB is running at 5V. And it works. Because the Ether Card is compatible with 3.3V and 5V signals!

Which also means that the Ether Card can be used with any Arduino board. It’s not specific to JeeNodes and it’s not limited to being used with the Carrier Board, either.

The generic software for the Ether Card is contained in the “EtherCard” library, listed on the software page in the Café. It doesn’t depend on Ports or RF12 libraries, so this thing really is a completely independent product.

It just “happens” to fit gorgeously into a box alongside a JeeNode :)

So there you have it – the Ether Card can be used with just about any microcontroller setup. All it needs is a power supply of 3.6V or more, 4 SPI I/O pins, and the proper software to make it sing of course…

Onwards!

JeeNode as web server

In AVR, Software on May 31, 2010 at 00:01

The new Ether Card add-on makes a lot of new fun stuff possible. Even with a measly 8-bit ATmega chip, it’s possible to create some pretty neat things. Like a little webserver for displaying the last received RF12 packets.

I’ve added an EtherCard library to the subversion repository, next to the Ports and RF12 libraries, etc. It’s now listed on the software page in the Café.

This is mostly the Ethernet code by Guido Socher and Pascal Stang, but I’ve moved some stuff around a bit, and kept the changes added by Andras Tucsni to make this work together with the RF12 driver.

A new “BufferFiller” class has been added, to help create web pages and such:

Screen Shot 2010 05 22 at 00.04.55

What it does is expand a PSTR given to it, by replacing $S, $F, and $E with strings copied from RAM, flash, or EEPROM, respectively. A bit like “printf” in standard C. It’s eaasiest to just show an example of use:

Screen Shot 2010 05 22 at 01.42.00

The $D code is expanded as integer, for convenience. And since BufferFiller derives from the Arduino’s “Print” class, all the usual “print()” and “println()” members are also available.

The above code will generate the following web page (and yes, it’s been up and running more than 3 days):

Screen Shot 2010 05 25 at 09.55.06

It’s part of the etherNode.pde sample sketch in the EtherCard library – a little web server which shows the last few incoming RF12 packets and continuously self-refreshes to present the latest info.

There’s also a configuration page:

Screen Shot 2010 05 21 at 18.46.32

The whole etherNode demo sketch is under 10 Kbyte, including both EtherCard and RF12 drivers, leaving plenty of room to implement more features.

Dear Mr. Murphy

In AVR, Hardware on May 28, 2010 at 00:01

Dear Mr. Murphy, you must have had a ball these past few days…

I goofed. Again. Big time. Well, not Toyota- or BP-scale big time, but still. It’s all your fault, Mr. Murphy!

About two dozen faulty ATmega’s were shipped as part of the JeeNode Kits. And another five dozen or so were packed into kits-in-stock:

Dsc 1505

What happened? Well, that “flashy” new multi-ISP programmer I was so proud of has a bug when the “isp_cpature.pde” sketch is used in replay mode: it doesn’t program the fuse bits properly. Whoopsy daisy. I thought I had all the scenarios covered and tested, but clearly I didn’t. Those ATmega’s are shipped running at 1 MHz, and the pre-loaded RF12demo is initializing the serial port to a totally useless 57600 / 16 = 3600 baud.

This morning (i.e. yesterday by the time this post comes out), I went through the stock of ATmegas, including those in already-packaged-and-labeled JeeNode kits, and redid the fuses and uploads. Not quite my idea of fun.

Anyway. The good news is that everyone has been contacted, and that I’ve sent out replacement ATmega’s to those people who I’m quite certain have the botched version. A few people will have run into the problem (that’s how I found out!), but most kits are probably still in transit, and will now be followed by the fixed ATmega(s) shortly.

In case I missed anyone, here are the symptoms: the LED on the USB-BUB stays on relatively long when a JeeNode kit is plugged in, there is no greeting from the pre-loaded RF12demo or there are only garbled characters, and you can’t upload to the JeeNode. The problem is only with ATmegas sent out in the past few days, no more than perhaps a week ago. JeeNode USBs and JeeLinks are not affected. If you run into exactly this problem, please email me and I’ll send you a replacement ATmega.

To make matters worse, I also mixed up some of the early Carrier Board and Ether Card orders, fogetting to include this or that. All issues reported to me have now been resolved.

Oh well, live and learn.

Now go home, Mr. Murphy, and don’t come back. Please? :)

Meet the Ether Card

In AVR, Hardware, Software on May 24, 2010 at 00:01

Yesterday’s post was a sneaky way to show you a glimpse of an exciting new addition to the always-evolving Jee Labs product range – meet the Ether Card !

Dsc 1454

It’s a low-end Ethernet extension card, with a form-factor specifically made for the Carrier Board + Box:

Dsc 1467

It is based on the good ol’ trusty ENC28J60 chip, with all the components needed to hook it up to a JeeNode (or any other unit running the SPI bus at 3.3V).

I’ve started working a bit on the software side. The Ether Card is pretty standard in every respect, with the GPL2 code by Pascal Stang and Guido Socher working just fine with it. All it needs is a different chip select pin (PB0, Arduino pin 8) and proper interrupt guards to prevent the RF12 driver from interfering.

The card has been running smoothly for days on end here. It gets slightly warm, I’d estimate some 20°C above ambient. The regulator stays cool when powered from 5V. Total current draw is ≈ 150 mA, incl. JeeNode.

The Ether Card only uses through-hole parts, no SMDs. It has been added to the shop as kit and as PCB-only version. Here’s the PCB – in glorious blue-and-gold:

Dsc 1433

Here’s a sample web server requiring under 10 Kb of flash and showing a page with the last 25 RF12 packets:

Screen Shot 2010 05 19 at 11.33.18

So there you have it. JeeNodes can now handle wireless and wired networking.

It’s going to be oodles of fun to develop software for / on / with this Ether Card!

Credits: I would like to thank Andras Tucsni, who started the ball rolling by prototyping a complete working system and implementing the chip-select and interrupt changes needed for inter-operation with the RF12 driver on SPI. Andras also wrote the demo sketch which generated the above output. Knowing that it can be done and having working sample code makes a huge difference!

Multi-ISP programmer

In AVR, Hardware on May 18, 2010 at 00:01

This is a project I’ve been meaning to do for a long time:

Dsc 1432

It’s a portable ISP programmer which can program four 28-pin ATmega’s independently. It takes about 12 seconds to program fuses, bootloader, and RF12demo sketch into each chip, so with this unit I can essentially keep going and program some 20 chips per minute. Just what I need for yesterday’s batch of fresh ATmega’s. For reference: a USBtinyISP needs a few minutes per chip! (update: but it can be speeded up, see comments below)

Not that I need to program 1200 chips/hour! The point is that at this speed, I can now flash ATmega’s just-in-time, i.e. with the very latest version of RF12demo, etc.

This multi-ISP programmer is built from 4 Flash Boards, 1 JeeNode USB, 3 JeeSMD’s, a 450 mAh rechargeable LiPo battery, and a couple of ZIF sockets, resonators, and resistors. I’ve got roughly a dozen more ZIF sockets for the shop of there is interest. Also some 6-pin IDC headers and flat-cable.

The unit uses the capturing ISP programmer sketch and is very simple to use: plug the JeeNode USB in and use it as a normal AVRISP programmer @ 19200 baud. Use as many programming steps as you want. When idle for 3 seconds, the process stops – blinking the LED twice. Then exchange its Flash Board with one of the others and repeat the process until all flash boards have been set up.

From then on it can also work in battery-powered mode: insert chip, press button, wait for LED to start blinking, then rinse and repeat. Total current draw will be well under 90 mA, so this programmer should get over 5 hours of autonomy on one charge – up to 6000 chips… :)

The programmers are independent, so I can upload different contents in each of them. I’ve labeled each flash board to be able to do this without mixing things up.

The JeeNode USB v3 powers all the boards and includes the LiPo charge circuit, so the battery can be recharged by simply plugging it in. There’s a slide switch to disconnect the LiPo battery.

Some more build pictures. As you may have noticed, there is no connection from the 2×3-pin ISP header to the ZIF socket. That’s because I wired those up from below by using stacking headers for 2 of the 4 ports:

Dsc 1422

Here is the other side, wired up manually with wire-wrap wire. I’ve since covered it up a bit to avoid accidental shorts. The risky one is a direct short between the LiPo power pins, the rest is probably harmless.

Dsc 1430

And here’s the side view:

Dsc 1431

I’m looking forward to using this thing: swap chip, push button, swap chip, push button, … how convenient!

New ATmega batch

In AVR, Hardware on May 17, 2010 at 00:01

At last, 250 new ATmega328′s came in from DigiKey:

Dsc 1419

You may not have noticed, but in these past months there has been a major shortage of ATmega328 chips – everywhere. Once that happens, people start stockpiling, driving the shortages and delays up yet further, etc.

That’s 250 chips to intitialize with a boot loader + RF12demo sketch! Kinda illustrates my need for a good ISP programmer setup, eh?

There’s a substantial amount of capital investment involved in this stuff, so I’ve been cautiously moving about while trying to keep all the essential items in stock for the shop. So far, so good, mostly. But this batch sure is welcome… one less thing to worry about.

Onwards!

Setting up the thermocouple node

In AVR, Hardware, Software on May 10, 2010 at 00:01

This is part 2 of my reflow controller series. Unlike what was announced yesterday, I’m going to first describe how to set up the temperature sensing wireless node. JeeMon hookup to follow soon.

Our very first step could be to connect the thermocouple via a JeeNode and USB to the PC, but I’m going to do something more interesting and go straight for a wireless hookup. One reason for this is due to a problem with direct connections, but since this is going to be used in un-tethered mode anyway, it’s a good excuse to use a wireless configuration right from the start.

Here is the “thermoSend.pde” sketch I’m going to use (code here):

Screen Shot 2010 05 09 at 14.29.35

This contains all the ingredients needed for a simple basic sensor node: all we do is set up wireless, and then read out the thermocouple value and send it off once a second.

The easy transmissions code works with broadcast packets, so we don’t need to define a destination for the wireless packets, just this sensor node’s ID (1), the choice of frequency band (868 MHz), and a group ID (6). That’s done with the rf12_initialize() call.

The readings are converted to an integer in the range 0 .. 3300, representing a temperature range of 0 .. 330.0°C. Then we send that 2-byte integer in binary mode over wireless. That’s what the code inside loop() does. The map function is part of the Arduino library code.

The easy transmit system will take care of re-transmission if a packet is lost. All the transmission details are handled by rf12_easyPoll(), which needs to be called often.

One detail of the easy transmit system to keep in mind, is that only changed values are sent. No packets will go out if the reading is the same as the last one. In this scenario, that’s fine – there’s always some jitter in the readings, so we should see new packets at least a few times a minute, even when the sensor temperature is constant.

Ok, let’s get going. If you haven’t installed the Arduino IDE yet, go do it now.

Create the above sketch named “thermoSend” in the Arduino IDE. On my Mac, it ends up as a folder named “Documents/Arduino/thermoSend/” in my home directory. Plug in the JeeNode via an FTDI adapter such as the USB-BUB (or use a JeeNode USB) and check your Arduino IDE / Tools / Serial Port settings to make sure you’re hooked up to it. With multiple nodes on USB, it’s easy to mess up the wrong one – happens to me all the time…

Now the node is ready. Unplug, hook it up to a battery, and power it up.

You’re sending packets into the ether now. Quick, let’s try and collect those packets before they falll on the floor!

To do that, hook up a JeeLink or a second JeeNode. It needs to be running the RF12demo sketch, which is what it does out of the box if you got it from Jee Labs or Modern Device.

We need to connect to the JeeLink. Easiest way is to use the Arduino IDE. Make sure you are connected to the proper USB port. So again, check the Arduino IDE / Tools / Serial Port menu and select the JeeLink serial port.

Now open the Arduino IDE’s serial console. You should see something like this:

[RF12demo] A i1 g212 @ 433 MHz
Available commands:
[etc]

You are now in direct communication with the JeeLink. We need to set it up to listen to the proper transmissions. Sort of like tuning to the proper radio station. So type the following line and press “Send”:

2i 8b 6g

This sets node ID = 2, frequency band = 868 MHz, and net group= 6.

If all is well, and the wireless node is powered up, you should start to see packets come in, something like this:

OK 33 212 0
 -> ack
OK 33 209 0
 -> ack
OK 33 212 0
 -> ack
OK 33 209 0
 -> ack
OK 33 212 0
 -> ack

That’s a header byte (i.e. 33, associated with node ID 1) and 2 data bytes.

There won’t be packets every second, because only changed readings are sent. But there will be packets, and if you touch the thermocouple end, you should immediately see the rise in temperature:

OK 33 212 0
 -> ack
OK 33 226 0
 -> ack
OK 33 24 1
 -> ack
OK 33 44 1
 -> ack

No, I’m not suffering from sudden hypthermia: that’s not 4.4°C :) – what you’re seeing is binary overflow of the first data byte. A byte can only hold values 0..255. Anything higher and it will wrap around. That’s why two bytes are sent. The second byte contains the reading divided by 256, i.e. the number of wraparounds. You’re looking at the binary representation of an “int” on Atmel AVR chips.

So the above readings are: 21.2°C, 22.6°C, 28.0°C, and 30.0°C.

IOW, the actual temperature is: (byte1 + 256 * byte2) * 0.1°C

The next episode will be about hooking up JeeMon to the Jeelink and using it to read out the data and do something more meaningful with it. Stay tuned.

Assembling the Flash Board

In AVR, Hardware on May 7, 2010 at 00:01

Here is a step-by-step instruction for assembling the Flash Board, starting from these components:

Dsc 1386

The 24M01 1 Mbit EEPROM is already on the board. The build proceeds essentially in flattest-to-higher order, so that when you turn the pcb around for soldering, you can push down the part properly.

We start with the 470 Ω current limiting resistor for the LED:

Dsc 1388

Try to make nice and shiny joints:

Dsc 1387

Cut off the excess wires:

Dsc 1389

Next is the little start button:

Dsc 1390

There are four pins to solder:

Dsc 1391

They are a bit long, so it’s best to cut them off:

Dsc 1393

Next, the LED. This one is polarized, be sure to put it in the right way:

Dsc 1394

The last component on the top is the 2×3-pin ISP header:

Dsc 1396

Again, make sure all pins have good solder joints:

Dsc 1397

Now, all we need to do is solder in the 4 6-pin headers. The easiest way to do so is to push these headers into a JeeNode for proper positioning:

Dsc 1398

The push the Flash Board on top and you’ve got a convenient way to solder them:

Dsc 1399

That’s it, done!

Dsc 1400

Now you can upload the isp_capture.pde sketch and use this brand new ISP programmer.

Happy programming!

Low-level development

In AVR, Hardware on May 6, 2010 at 00:01

I’m working on some ideas which require some low-level code, and fairly accurate timing. Serial or wireless I/O are not an option, and hooking up the logic analyzer is not convenient (I may have to, if the going gets tough).

For now, here’s a very simple setup which ought to be sufficient:

Dsc 1385

Two boards, hooked up via two USB ports. They are on the same computer, so there should be no issues with voltage levels when leaving them both connected at the same time (I’m not too worried about the ground loop).

The board at the top is the Flash Board as ISP programmer (I’m not using the new capturing features here). The board below is the “target”, a plain JeeNode hooked up to a USB-BUB. Nothing fancy.

I’ve added 8 bits of “I/O” by hooking up 8 LEDs with current-limiting resistors – red on the DIO pins, green on the AIO pins as debugger, as described here.

The target board also has the option to communicate over serial (i.e. through its USB connection), but that adds code and affects timing – something which I probably can’t tolerate in my specific tests.

Nothing very unusual here, but it’s worth pointing out that a couple of years ago, a setup like this could easily have cost over 1000 <pick-your-favorite-currency>, whereas this one is well under 100.

Let’s see how it goes…

A capturing ISP programmer

In AVR, Hardware, Software on May 5, 2010 at 00:01

Meet the new, improved, autonomous, self-guiding, hassle-free, portable ISP programmer!

Dsc 1381

It works as follows:

  • hook up a JeeNode or JeeNode USB to your computer
  • upload the isp_capture.pde sketch to it
  • insert the Flash Board and hook it up to the target
  • program the target, using this as a standard STK500/AVRISP programmer @ 19200 baud
  • wait for the LED to blink twice
  • done

And this is where the fun starts:

  • connect the JeeNode to a battery or any other power source
  • insert the above Flash Board again and hook it up to the target
  • press the button on the Flash Board
  • wait for the LED to first turn off and then start flashing
  • done

You’ve just programmed another target MPU … look ma, no hands!

The first hookup went through a normal programming cycle, but it also stored everything in the EEPROM on the Flash Board: code, data, fuses, verification bytes, everything. That’s why I’m calling this a capturing programmer.

When pressing the button, it essentially repeats all the same steps.

This works for anything you can program with an AVRISP programmer: ATmega, ATtiny, whatever. And it will even capture multiple programming cycles, as long as they are started before the LED blinks twice, i.e. within a few seconds. So you could set up a script to call avrdude with a few different things to do – e.g. set fuses, program the flash, program the AVR EEPROM, set the lock bits.

There are some tricks under the hood to make this work. First of all, the baudrate as ISP programmer is set to 19200, so that the bootloader in the JeeNode doesn’t accidentally take over after reset (it listens at 57600 baud).

Another trick, and the main reason this all works transparently, is that the entire serial communication session is stored in EEPROM as is. When pressing the button, it simply replays the input to the programmer code as if it was coming from the serial port (and matches the results, also against EEPROM). There is some logic involved to be able to store both input and output streams, and keep them properly apart.

The EEPROM is connected via I2C to port 3. I used the MemoryPlug and MemoryStream classes from the Ports library to access it.

Lastly, there is some debugging built in. While used as AVRISP programmer, the serial port is in use for programming @ 19200 baud. But when in replay mode, the serial port is set to 57600 baud and used to report what the programmer is doing. Here is a transcript:

[isp_capture]
ISP bytes: 39680
Code size: -32768
Page size: 128
Data size: 1024
Signature: 86 00 00 01 01 01 01 03 FF 95 0F
Programming...
Done in 13.9 seconds.

That’s it. There is visual feedback when programming succeeds in the form of a flashing LED, so that this setup can be used without serial link. I’d like to add auto power-down one day, for serious battery use.

I’m going to use a bunch of Flash Boards here, pre-loaded with the different contents of ATmega’s and ATtiny’s I’m constantly preparing here at Jee Labs. Will probably also dedicate a bunch of JeeNodes to this, but that’s optional – any available JeeNode can be temporarily turned into an ISP programmer by simply uploading the “isp_capture.pde” sketch to it and inserting a Flash Board.

Now I can easily reprogram all those Room nodes in the house!!

PS. There’s nothing JeeNode-specific about this setup. The on-board wireless isn’t used (yet?).

PPS. For your convenience, I’ve tagged all related posts on this weblog with ISP.

ATtiny 8-pin ISP programmer

In AVR, Hardware on May 1, 2010 at 00:01

Yesterday’s ISP programmer used a 28-pin socket wired up for ATmega328 chips (and the older 48/88/168 versions).

As it turns out there are enough unused pins available in that socket to also support the ATtiny 8-pin series (such as 25/45/85). The trick is to add a few extra wires so that the ISP programming signals have the proper setup for these smaller chips as well:

Dsc 1376

This allows placing an ATtiny in the socket at the top end, i.e. using just pins 1..4 and 25..28:

Dsc 1377

This trick works, because the I/O pins used by the ATtiny happen to be normal I/O pins for the ATmega, so it doesn’t mind having some logic signals there (pins 9..12 and 17..20 can probably also be used, but then inserting the chip becomes more error-prone).

And sure enough, avrdude can now program the ATtiny as well:

Screen Shot 2010 04 25 at 02.44.46

For other chips, you’ll need to wire up a chip-specific socket, but at least for these ATtiny chips an ATmega setup will work just fine!

ATmega 28-pin ISP programmer

In AVR, Hardware on Apr 30, 2010 at 00:01

The Flash Board presented a few days ago was only half the story. Here is the other half, i.e. the chip socket.

What you need is a board with a 10 kΩ reset pull-up resistor, an 8..16 MHz resonator for the clock, and – just to be safe – a 0.1 µF decoupling capacitor. I used an empty JeeNode v4 PCB to hook it all up:

Dsc 1372

I added the ISP connector in a slightly unusual way: with long pins bent sideways. The reason being that the ZIF socket won’t fit on the board otherwise. In fact, it won’t fit directly anyway because the holes are too small and the socket is too long. So I pushed it (hard!) into a 28-pin IC socket first:

Dsc 1371

Then I soldered the socket in, and there it is:

Dsc 1373

An ISP programmer for 28-pin ATmega’s!

Tomorrow, I’ll describe how I’ve modded this setup to also allow programming 8-pin ATtiny DIP chips …

Decoding a pulse train

In AVR, Hardware, Software on Apr 27, 2010 at 00:01

The (planned) Input Plug uses an ATtiny chip to decode a 16-channel selection code using a single I/O pin.

Here is the relevant part of the schematic:

Screen Shot 2010 04 19 at 19.50.37

The DIO pin is connected to PB4 of the ATtiny. The ATtiny PB0..PB3 pins in turn are hooked up to the A..D select inputs of the analog multiplexer. So all the ATtiny needs to do is decode an incoming “pulse train” on its PB4 pin, and send out the decoded value on its PB0..PB3 output pins.

My first attempt used a simple serial protocol: a start bit and 4 data bits, clocked at a fixed rate:

Screen Shot 2010 04 19 at 19.52.59

This worked, but it was a bit flakey because the internal clock of the ATtiny is not accurate enough to ensure everything stays in sync for the entire duration of the transmission, i.e. across 5 bit periods. This is clearly explained in the following image (from here):

async1

It’s better to use a self-clocking format, for example 5 pulses of varying width, because then only the length of each individual pulse matters. Above a certain threshold = 1, below = 0. And we can reset when there are no pulses.

Here’s the a transmit test sketch, which sends a 0..15 counter every 100 ms:

Screen Shot 2010 04 19 at 19.57.36

As you can see, the pulses are 4 or 8 µs wide, with one pulse every 12 µs. Roughly.

Note that interrupts have to be disabled during each “transmission”, since these pulses are very short and need to be fairly strictly controlled.

The decoder on the ATtiny (ATtiny85 in this test) is also quite simple. It waits for a pulse start and then counts in a loop until the signal drops to zero again. Counts above a certain value are treated as “1″. Missing pulses and pulses which are way too long cause the decoder to be reset and start from scratch:

Screen Shot 2010 04 19 at 20.01.21

This can be compiled with avr-gcc, and it’s of course just a few bytes (even an ATtiny is overkill here):

Screen Shot 2010 04 19 at 20.02.44

I’m using yesterday’s Flash Board for ISP programming. Makes a good test that it also works with ATtiny MPUs.

Here’s the test setup (with the ISP programmer disconnected):

Dsc 1362

And sure enough, the LEDs display a little running 4-bit counter, driven by data sent over a single DIO pin.

Should be good to go for the Input Plug!

Preparing ATmega’s with ISP

In AVR, Software on Apr 25, 2010 at 00:01

Here’s a second use of yesterday’s ISP plug: pre-loading ATmega’s with a fixed sketch and bootloader.

This uses a very nice trick from the Arduino Boot-Cloner: store the code to be sent to the target MPU as PROGMEM data inside the ISP sketch itself!

I’ve adapted that Boot Cloner so that it takes its data from a separate C include file, added a couple of other features, and speeded the whole thing up a bit.

The result is called “isp_prepare” (code here).

Here’s what you’ll see on the USB serial port when starting it up:

Screen Shot 2010 04 18 at 23.14.22

The list reports the files which have been integrated into this sketch at build time, using this C code at the top of isp_prepare.pde:

Screen Shot 2010 04 18 at 23.23.36

Here is the contents of that include file, with most of the data bytes omitted:

Screen Shot 2010 04 18 at 23.24.51

The data consists of “sections” of code, to be programmed into the target ATmega using ISP. In this case there are two sections, a RF12demo sketch starting at address zero, and a bootloader in high memory.

Here’s is isp_prepare in action:

Screen Shot 2010 04 18 at 23.14.47

So the steps to load RF12demo onto a JeeNode with a fresh ATmega are as follows:

  • upload this isp_prepare.pde sketch to a “master” JeeNode
  • insert the ISP plug described yesterday,
  • connect the target JeeNode to this master JeeNode via ISP
  • enter G to start programming and wait for it to complete
  • done: disconnect, now the target JeeNode is ready to run with RF12demo on it

I’ve also included a “data_blink.h” header file, if you want to preload the ATmega with the standard Arduino blinking LED demo. Just change the include in isp_prepare and upload the sketch again.

I can now use this setup for initializing all the ATmega’s here at Jee Labs, since it means I no longer have to start up the Arduino IDE or use avrdude.

Convenience!

ISP plug

In AVR, Hardware, Software on Apr 24, 2010 at 00:01

For one of my projects, I needed a quick way to reflash an AVR via ISP. Didn’t want to have to use any of the several ISP programmers around here, so I made my own “ISP plug” for use on a JeeNode:

Dsc 1353

The pins are connected as follows:

  • ISP pin 1 = MISO = DIO1
  • ISP pin 2 = VCC (+3.3V)
  • ISP pin 3 = SCK = AIO1
  • ISP pin 4 = MOSI = AIO4
  • ISP pin 5 = RESET = DIO4
  • ISP pin 6 = GND

Here the top view, made from a little JeePlug board:

Dsc 1354

Bottom side:

Dsc 1355

Note that this ISP setup draws 3.3V from the JeeNode and uses it to power the target, so the target board should not have its own power and it should not draw more than say 100 mA of current @ 3.3V.

The code for this is called “isp_flash.pde” and is derived from the “ArduinoISP” sketch. I added software-based (bit-banged) SPI communication for use with the above I/O pins, and did a fair bit of cleanup of the source code.

The nice thing about this ISP programmer is that it works out of the box with Arduino IDE 0018:

  • upload the ISP_flash.pde sketch to the JeeNode
  • insert the ISP plug and hook it up to the test circuit (or one of these …)
  • burn the boot loader using the Arduino IDE:

Screen Shot 2010 04 18 at 18.04.06

The result will be a properly initialized ATmega, with protected bootloader and the default blink demo pre-loaded.

It’s not terribly fast because it uses a 19200 baud connection, but it’s simple and can be a life-saver if you ever damage the bootloader on an ATmega, or want to prepare blank ATmega’s for use with a JeeNode.

This plug can in fact be used as ISP programmer for any type of ATmega or ATtiny with “avrdude”:

Screen Shot 2010 04 18 at 18.14.42

You’ll need to adjust the serial / USB port, fuse settings, and sketch as needed, of course.

Debugging with LEDs

In AVR on Apr 10, 2010 at 00:01

There was a problem in the RF12 driver with startup, with hard-to-reproduce behavior, unfortunately. I couldn’t make heads or tails of it, until more details started coming in via the Jee Labs forumlong live open source!

The problem, as originally identified: sketches don’t start reliably, when power is applied through batteries.

The diagnosis: it’s not related to battery power, it’s due to the RFM12B staying in some sort of “powering-up” limbo mode for several seconds.

Trouble with this sort of problems is that they can be very hard to reproduce, and even harder to debug. It all happens at startup, before any comms with the outside world is possible, and what’s worse: sending out some debug bytes over the serial port may affect the problem, due to the time it takes to do so, or the interrupts taking place, or even RAM memory being changed by the debugging.

They’re called Heisenbugs, and they’re the worst…

In this case, the breakthrough came when I had a “reliably failing” setup: running the lcd_demo.pde sketch and inserting a call to rf12_config() was enough to get a hang after each power-up. Good – now I can chase this bug!

In this case, there was an LCD hooked up, but it gets initialized after the rf12_config() call. All I wanted to know at first, is where the code hangs.

Time for the LED debugger:

Dsc 1331

Two LEDs, inserted in an unused port. Both with 1 kΩ current limiting resistors in series (470 Ω would be brighter). One between DIO and GND, the other between +3V and AIO.

The code to init this is quite simple:

pinMode(5, OUTPUT);
digitalWrite(5, 0);
pinMode(15, OUTPUT);
digitalWrite(15, 1);

I used port 2, i.e. DIO = Arduino pin 5 and AIO = Arduino pin 15. Due to the way these LEDs are connected, the one on the left will light when DIO is set high and the one on the right will light when AIO is set low. The above code starts with both LEDs off.

Now, all I have to do is turn DIO on at the start, and move the code to turn it off further and further into the initalization code:

digitalWrite(5, 1);
rf12_config();
digitalWrite(5, 0);

As expected, the LED never turns off again – rf12_config is going haywire.

Then I tried simplifying, replacing rf12_confg() by a call to rf12_intialize(). Same outcome: hangs. So it’s not the EEPROM code.

Tried out several things: delays, sending stuff to the RFM12B driver to try and initialize it better, or even twice – no difference: stil hangs.

Hm. The RF12 driver uses interrupts. Maybe it’s in there (yuck, even harder to debug). I called rf12_inititalize() with 0 as first arg, so attachInterrupt() would not be called – and bingo … no more hang.

So the RFM12B is generating interrupts, at a point when I don’t expect it: i.e. right after initialization. Interrupts should only happen when sending out data bytes (TX FIFO empty) or when receiving them (RX FIFO full).

To make a long story short: the RFM12B is pulling the IRQ line low for some eight seconds after power up. Since the IRQ line is set up as a level interrupt, that means it’s generating interrupts all the time!

No matter what I tried, I couldn’t make the RFM12B stop generating interrupts. But then, after about 8 seconds, it ended up going high and all was fine. Go figure.

So now I’ve added a loop which waits and polls the RFM12B in the init code, until it stops pulling IRQ low. On power up, that takes around 8 seconds. On reset, there is no wait. This should fix the remaining issue reported with hanging of JeeNodes, battery-powered or otherwise, i.e. any scenario which doesn’t use resets to restart the ATmega when the RFM12B is ready. If this affected you, get the latest code and re-compile / upload your sketch.

In hindsight, I’m surprised it worked before this fix!

Case closed. One more victory over bits and silicon. Onwards!

After-burner

In AVR, Hardware on Apr 3, 2010 at 00:01

To reply to a comment posted yesterday, this is the contraption I use to re-flash a JeeNode or JeeLink after the fact via its ISP connector:

DSC_1295.jpg

It has two diodes, dropping the incoming 5V power from the programmer to around 3.8V – this turns out to be needed in the case of JeeLinks, which has the VCC pin on the ISP header connected to 5V instead of the 3.3V driving the ATmega. The high voltage was causing problems with logic signal levels.

The other component on the board is a 100 µF capacitor, to reduce voltage fluctuations (it.s probably superfluous, I added it while debugging the setup).

Here’s this “after burner” in action:

DSC_1296.jpg

The long pins are at an angle, because that way they can be gently pressed into the holes and they will stay there during programming.

Like most hacks, it looks awful, but it works pretty well!

AVRISP mkII w/ 5V power

In AVR on Apr 2, 2010 at 00:01

I’ve been using the USBtinyISP AVR programmer for some time now, to set the fuses, burn the boot loader, and burn the RF12demo.pde compiled sketch into each ATmega.

Trouble is, it’s slow as molasses …

So I got the AVRISP mkII programmer a while back, but the problem is that it’s unpowered. Not good for my setup, which expects power from the USB programmer:

2937E56E-F019-4E55-99F4-60B1B15111DB.jpg

So I went looking around for tips on how to bring 5V to pin 2 of the 6-pin ISP connector. Found this mod which uses a 5-to-3.3V regulator, and this one which draws 5V directly from the board.

I decided to tap the 5V USB power, but after the polyfuse, so that a short won’t damage the computer or USB hub as easily:

DSC_1294.jpg

The connection is jumpered, so this can still be used in its original form when needed.

And then I spent ages chasing ghosts…

It turns out that avrdude needs a “-B 3″ time adjustment to reliably program the chips. Now how am I supposed to know that!

Anyway, here’s the shell script I’m currently using on my old PowerBook, which automates it all:

Screen shot 2010-04-01 at 23.08.28.png

That last character being echoed is a CTRL+G, i.e. an audible bell to signal when the process is done. It used to be essential, since the USBtinyISP took so much time for each burn. Now, it’s clocking in at 17 seconds, and that could probably be reduced even further by combining the three separate avrdude runs.

A roughly 10-fold improvement!

Meet the JeeNode USB v3

In AVR, Hardware on Mar 19, 2010 at 00:01

Just got a couple of new boards back (this was an experiment, expediting some of the boards to get them several days ahead of the rest of this prototype batch).

Meet the new JeeNode USB v3 (this unit was soldered by hand – phew!):

DSC_1248.jpg

As you may know, the main reason for this revision was to resolve a problem with the voltage regulator, but since I had to rework the design anyway I also added a LiPo charge circuit.

The good news is that everything seems to work fine so far. There are some cosmetic problems with this board, but no show stoppers.

And of course the big deal is being able to hook up a Lithium Polymer (LiPo) battery:

DSC_1249.jpg

There is an extra LED in the corner, left of the USB jack, which will be orange (once I get them in). It lights up while charging. The charge current is max 280 mA, so this board won’t draw more than that from USB.

Without LiPo connected, the current still goes through the charge circuit, so another major change is that the PWR pin on all the headers of this board never carries more than 4.2V – don’t use the JeeNode USB if you need 5V in your circuit (use a JeeNode + USB-BUB if you really need the 5V).

Two BIG honking warnings, since LiPo batteries can be quite dangerous: one is that they need to be charged with the proper circuitry, such as on this new board, so don’t hook ‘em up any other way. The other issue to keep in mind at all times, is that LiPo’s can discharge at a very high rate! That “20C” label above means that this particular little battery is rated to sustain a discharge @ 20 x 450 mA = 9 amps!

You can probably cause a fire with those wires shown above, by simply shorting out a fully charged battery!

And you will probably fry the circuit and vaporize PCB traces by connecting the battery in reverse!

I’m exploring some options to reduce these risks. Hard-wiring the LiPo would be one way to reduce the chance of loose wires shorting out something. Perhaps a small custom PCB glued to the battery, with a fuse or polyfuse and a switch, wrapped in heat-shrink tubing? The trouble is that battery sizes and capacities vary greatly.

Some first tests w.r.t. power consumption: it looks like the JeeNode USB v3 will draw about 120 µA when in sleep mode. With the above 450 mAh battery, it would last up to 5 months without recharging (and without doing anything useful, such as turning on the radio module once in a while). There’s probably still some room for improvement here, but for now it’ll have to do.

FWIW, I’m going to hand-assemble a few of these boards in the coming weeks, but unfortunately that means there won’t be many v3 units available in the shop, initially. I’m also having solder paste stencils made up right now. Once these are in, the new boards will be much easier to assemble – using the reflow grill that gets a lot of work done here at Jee Labs.

Meet the JeeSMD kit

In AVR, Hardware on Mar 18, 2010 at 00:01

Meet the new kid kit in the Jee family – the JeeSMD !

DSC_1246.jpg

At a glance:

  • Same pinout as a JeeNode – same 4 port headers, same PWR/SER/I2C, same SPI/ISP
  • No wireless, no FTDI, just an ATmega328 – all SMD (32-TQFP, SOT-23, and 0603)
  • Two extra pins on the right side (allocated to the RFM12B module on JeeNodes)
  • Has a 3.3V regulator, a 16 MHz resonator, and four passive components

What’s the point? Well, it’s going to be made available as an SMD kit, and it’s going to be low-cost. If you don’t care about wireless or FTDI, then this is a convenient and compact way to hook up some Jee Labs plugs.

Of course, all the other stuff fits as before, including the Proto Board, for example:

DSC_1247.jpg

Here’s the board in more detail:

DSC_1243.jpg

(don’t look too closely at this prototype PCB – there are some silly cosmetic mistakes…)

There are some trade-offs w.r.t. JeeNodes:

  • No FTDI on board – you have to either add the equivalent connections yourself via the left and right headers plus a 0.1µF cap, or use ISP for flashing the ATmega328 chip
  • No wireless, so this isn’t a “node” in the usual sense – just a tiny Arduino’ish board
  • It’s all SMD, so if you want to practice soldering SMD by hand – this is one way to get started!

I’ve got a few boards for people who want to get their hands on them. The kits will be ready in about a week.

Now the JeeSMD kit needs a detailed set of instructions and close-up shots on how to assemble and start using it – more work to do!

Plug shield on Arduino Mega

In AVR, Hardware on Feb 7, 2010 at 00:01

The Plug Shield can also be used on an Arduino Mega:

DSC_1175.jpg

Note the two extra wire jumpers, since the I2C interface is on pins 20 and 21 on the Mega board.

The above has an RTC plug and an LCD plug hooked up, so let’s to set up a simple clock with this – and use it to demonstrate the brand-new RTClib along the way:

Screen shot 2010-02-05 at 17.22.01.png

I’ve omitted the details of the Wire coding, but you can get the full sketch here.

New date / time / RTC library

In AVR, Software on Feb 5, 2010 at 00:01

Not so long ago, I had the opportunity to work a bit on something which has bugged me for a long time – the lack of date and time handling in connection with RTC chips. There are a few libraries out there, but I think I could do better – i.e. make it simpler, smaller, yet sufficiently powerful for real day-to-day use.

Seeing where this was going on the Arduino developer mailing list (and disagreeing with just about everything that happens over there), I decided to put my money time where my mouth is, and build my own library.

Here’s the header file of the new RTClib Arduino-compatible library:

Screen shot 2010-02-04 at 13.52.13.png

This lets you do date / time calculations, and it provides two different ways to implement a clock: via a hardware chip or using the built-in millis() timer.

RTClib has been checked into subversion, see the CODE page for details on how to get it.

It includes four example sketches:

  • datecalc illustrates how to do calculate with dates and times
  • ds1307 interfaces with a DS1307 RTC chip, connected via the Wire library
  • plugrtc interfaces with the RTC Plug, connected via the Ports library
  • softrtc demonstrates how to do the same with just software

One fun trick I added, inspired by a comment from Limor Fried, is to allow initializing a DateTime object from the DATE and TIME strings generated by the C compiler. That means you can run that “softrtc” sketch without hardware support, and it’ll automatically have its clock set to the compilation date of the sketch, i.e. fairly close to correct. Not good enough for general use, but great during quick debug cycles when you’re re-compiling your sketch all the time anyway.

Note that to use RTClib, you need to include the “Wire.h” library – even if you don’t use it!

The inability to properly deal with libraries, particularly in a resource-constrained embedded processor context, is one of the aspects of the current Arduino direction which irritates me – see an older post for more details.

Fascinating concurrency

In AVR, Software on Feb 4, 2010 at 00:01

There is a new language for the Arduino / JeeNode / ATmega328, called Occam-π.

I found out about it yesterday, at http://concurrency.cc/ – it’s high level, and it supports parallel programming. The current development environment release is for Mac OS X, with Windows and Linux coming soon.

Here is a complete program with 4 blinking LED’s, one on each DIO pin of the JeeNode ports:

Screen shot 2010-02-03 at 01.13.19.png

That’s it. Compiles to roughly 2 Kb. Each extra blink adds just 20 bytes, btw.

And yes, it really makes four LEDs blink at an independent rate:

DSC_1167.jpg

There is slightly more to it than that, but this is mind-blowing stuff. The “parallelism” is simulated, of course. Looks like the ATmega can do around 6000 context switches per second (i.e. parallel task switches).

There is a roughly 20 Kb interpreter part that needs to be uploaded once (which is why this requires at least an ATmega328). After that, the IDE will upload just the bytecode for your program, i.e. 2 Kb in the above case.

B R I L L I A N T .

Imagine hooking up the RF12 driver to this – there’s plenty of room for the extra 3 Kb or so. And for doing all sorts of things… in parallel! My earlier complaint post about how awful it is to do several things at once on an ATmega board might just have been wiped off the table.

Looks like I’ve got some very serious learning ahead of me to try and get to grips with all this.

Single AA room node

In AVR, Hardware on Jan 21, 2010 at 00:01

The range of things to try is just endless…

Here is a (v2) JeeNode with a (prototype) room board and a 1-cell battery:

DSC_0942.jpg

Note that this prototype board is turned 180° w.r.t. the official Room Board, to match the Rooms sketch.

This node uses a 1.5 => 5V converter from SparkFun, which I had lying around. It’s far from optimal, with one third of the energy eaten up by the 3.3V voltage regulator, but it’ll have to do for now. Let’s see how long it lasts…

The whole thing is mounted on a little piece of foam board with dual-sided adhesive tape. Just to try it out.

To give you an idea of what’s flying around over the 868 MHz airwaves around here:

Screen shot 2010-01-20 at 00.18.35.png

That’s some 10 room nodes, the OOK relay with a bunch of sensors, and the energy/gas metering packets. Note how the Linux system time is exactly in sync with the DCF77 atomic clock receiver (using UCT i.s.o. CET). Note also that the OOK relay data is currently reported twice: once through a direct USB connection, once over the air.

Lots of fun! And that’s just the beginning, as far as I’m concerned :)

On a related note: I’m investigating whether it would be feasible to bring out a complete kit for the Room Board – with motion, light, temperature, and humidity sensors all included. If I can find the right distributors and order in sufficient quantity, it might be possible to get such a kit in the shop for €39, incl. VAT. Let me just say that if it can be done, you’ll be the first to know!

Sleep mode fix

In AVR, Software on Jan 20, 2010 at 00:01

The Rooms sketch (latest code here) had problems with the sleep mode added about a month ago:

Screen shot 2010-01-17 at 14.05.55.png

The first value is the current consumption in µA.

For some reason or other, the node would stop working and enter a permanent-on mode, drawing over 7 mA and draining the battery in a matter of days. Not good.

It seems to be related to the way the power down mode was implemented. To get absolutely rock bottom power draw, I was using the RF12′s watchdog timer. The ATmega watchdog time draws slightly more current and isn’t quite as configurable.

I’ve now reverted to using the ATmega watchdog anyway. Here is the modified logic:

Screen shot 2010-01-18 at 12.09.39.png

The watchdog is set to interrupt every 16 milliseconds, constantly. When the node is powered down, this will wake it up again. What the new loseSomeTime() code does, is simply to power down a couple of times, until the target delay time has been reached. There is some inaccuracy in these timings since the watchdog timer is free-running, but this should not matter too much when waiting for a second or so.

The new code has been running fine for over a day on six nodes. Here’s a sample from my power tracker:

Screen shot 2010-01-19 at 16.56.22.png

That’s 110 µA right now, 265 µA in the last minute, and 230 µA in the last hour.

At around 250 µA average, the power consumption is a bit higher than before, but my main concern is first to get the nodes running reliably. Even @ 250 µA, the AA batteries should last several months.

The average power down current draw is 110 µA/sec, 40 µA of which is due to the PIR sensor. The total current draw while transmitting is around 29 mA – during reception it’s about half, i.e. 14 mA. Still, due to the very brief on-times, this current consumption averages to only about 400 µA during 1 second for a normal send + ack sequence. Under optimal RF conditions, the long-term average consumption of a node will be under 150 µA. I’m confident that further optimizations could reduce this to well under 100 µA.

But there is one known flaw, which can be observed to happen once in a while: the nodes always wait for an ack in full-power mode, i.e. with the receiver on. This will normally be within milliseconds, but if the connection is flakey or if the central node is unresponsive, then nodes can spend a great deal of time in full-power mode. This needs to be fixed one day.

I’ve started re-flashing all the room nodes and replacing their dead batteries, here at Jee Labs – let’s see how it goes this time around.

More C++ template trials

In AVR, Software on Jan 18, 2010 at 00:01

Here are some more results in trying to use templates for embedded software on JeeNodes. This time, it’s about using Jee Plugs with bit-banged I2C on one of the 4 ports and with built-in TWI hardware on pins A4/A5.

Let’s start with an extract of the Latest JeeLib.h header:

Screen shot 2010-01-17 at 11.50.27.png

I’ve omitted all the actual code, for brevity in this example. The full code is here. The previous version of JeeLib has been moved to the avr-jeelib-first branch in subversion.

The Port<N> class is essentially the same as in an earlier post. It generates efficient code for raw pin access, given fixed pin assignments known at compile time.

The above code adds a templatized PortI2C<N,W> class, where N is again the port number (1..4) and W is a constant which determines the bus speed. As with Port<N> class, this leads to a class definition which requires no state and which can therefore consist entirely of inlined static members.

A HardwareI2C<W> is also defined, with the same API as PortI2C<N,W>, but using the hardware TWI logic in the ATmega. The point is that in use, PortI2C<N,W> and HardwareI2C<W> objects are interchangeable.

You can see how all this templating stuff complicates the naming of even simple classes such as these.

The final class implemented above is DeviceI2C<P,A> – it does the same as DeviceI2C in the original Ports library, but again using templates to “bring in” the underlying port classes and the device I2C address.

Here is an example sketch built with all this new code:

Screen shot 2010-01-17 at 12.48.05.png

It supports two bit-banged I2C devices on ports 1 and 2, respectively, as well as a third I2C device driven by the built-in TWI hardware.

This compiles to 980 bytes (using Arduino IDE 0017).

The good news is that this generates pretty efficient code. It’s not 100% inlined – but quite a bit is, especially at the lower levels, so the result looks like a pretty good implementation of a high-level I2C driver which can be used for both bit-banged and hardware-supported I2C, all by changing one declaration at the top of the sketch.

But there are quite a few inconveniences with this approach…

First of all, note that the declarations at the top are fairly obscure. I did my best to simplify, but all this template mumbo-jumbo means you have to understand pretty well how to declare a port, and how to declare an I2C device object for that port. The “typeof” keyword in there is a GCC extension, without which these declarations would have looked even more complex.

The major trade-off is that the above example essentially generates separate code for each of these three I2C devices. There is virtually no code sharing. This can lead to code bloat, despite the fact that each version generates pretty good code. In practice this might not be so important – it is not likely after all that you’ll need all three types of I2C buses in the same sketch. Just keep in mind that you’re trading off efficient hard-wired coding against the need to generate such code for each type of I2C access you might need.

So would this be a good foundation to build on? I don’t know yet…

C++ templates do seem to get a lot more of the logic “into” the compiler. Instead of passing say an I2C device address as constant to an object, we generate a highly customized class which is special-cased to implement just one device at just one address. With the result that the compiler can perform quite impressive optimizations. In the above example, there are lots of cbi and sbi instructions in the generated code, just as if you were to dig in and hand-craft an optimized implementation for exactly what you need. All from a small general-purpose library!

But it comes at a price. There is no (non-template) “DeviceI2C” class anymore. Writing a class on top to implement access to the UART Plug for example, means this class has to use templates as well. It’s a bit like “const” – once you start on the path of templates, they will start to permeate all your your code. Yikes!

The other “cost” is that all templates have to end up in header files. The size and complexity of the “JeeLib.h” header file is going to increase immensely. Not so great if you want to get to grips with it and just use the darn stuff. On the plus side, I was pleasantly surprised that error messages are fairly good now.

These drawbacks may be acceptable if all the template code can indeed remain inside the library – I sure wouldn’t want to impose the need for all library users to learn the intricacies of templates. So maybe it’s all doable – but this approach has major implications.

Is it all worth it? Hm, big decision. I do not like big decisions, not at this stage…

New library experiments

In AVR, Software on Jan 14, 2010 at 00:01

Encouraged by the previous post, I started writing a bit more code based on C++ features such as templates and namespaces, in the form of an Arduino library (compatible with it, not depending on it):

Screen shot 2010-01-09 at 02.08.27.png

Things to point out:

Less #defines (none so far), I turned bitRead() and bitWrite() into template functions (getBit and setBit), so that they can be used with 1..4 byte ints, just as the macros.

The Port class is inside a new “Jee” namespace, so there is no conflict with the existing Ports library.

Atomic access hasn’t been solved. Some of this won’t work if I/O pins get changed by interrupt code. I’m hoping to solve that at a higher level.

There are compatibility definitions for pinMode(), digitalRead(), and digitalWrite() using the normal Arduino pin numbering conventions (only Duemilanove so far). These are in their own namespace, but can also be used without any qualifiers by adding “using namespace Jee::Arduino;” to the sketch.

Totally incomplete stuff, untested, and not 100% compatible with Arduino in fact.

The other thing I want to explore, is to treat the choice of what a pin does as a pin initialization mode. Hence the enum with Mode_IN .. Mode_PWM definitions. The underlying code is PortBase::modeSetter(), but it hasn’t been written yet. It’s all steamy hot vapor for now.

Update – I’ve placed the code in subversion, but the API is going to be in flux for a long time.

Update #2 – Atomic access is actually better than I thought. With constant pin numbers, setBit() will use the cbi/sbi instructions, which are atomic.

C++ templates

In AVR, Software on Jan 12, 2010 at 00:01

A recent post described the performance loss in the Arduino’s digitalRead() and digitalWrite() functions, compared to raw pin access.

Can we do better – i.e. hide the details, yet still get the benefits of raw I/O? Sure.

If you’ve used JeeNodes and in particular the “Ports” library, you’ll have noticed that there is a C++ class which hides the details of each port (i.e. JeeNode port, not ATmega port). Let’s look at that first:

Screen shot 2010-01-06 at 12.40.09.png

I’ve omitted the implementation, but there are still lots of secondary details.

The main point is that this is now C++, and uses a “Port” object as central mechanism. Each object has one byte of data, containing the port number (1..4).

Due to heavy inlining, there is almost no additional overhead for using the Port class over using digitalRead() and digitalWrite(), on which they are based. I verified it by running similar tests as in the recent post about pin I/O:

Screen shot 2010-01-06 at 12.48.50.png

Using the definition “Port orig (1);” – and sure enough the results are nearly the same.

There are two issues which make this approach sub-optimal: using the slow digital read/write calls, and storing the port number in a memory location which needs to be accessed at run time. There is no way for the compiler to optimize such calls, even “orig.digiRead()” should be the same as writing “bitRead(PORTD, 4)” in this example.

That’s where C++ templates come in. Check out this definition of a new “XPort” class (named that way to avoid a name conflict) and an example of use for port 1:

Screen shot 2010-01-06 at 12.54.02.png

(As you can see, I’m switching to a different, and hopefully clearer, API along the way)

There’s some funky <…> stuff going on. We’re in fact not declaring one class, but a whole family of classes, parametrized by the integer included in the <…> notation on the last line.

The big difference, is that each class now has that integer value “built-in”, so to speak. So we can define member functions which directly pass that value on to the corresponding bitRead() and bitWrite() macros. And then all of a sudden, all the overhead vanishes: since the member needs no access to object state, it can be made static, and since all the info is known in the header, it can be made inline as well.

So the above template is C++’s modern way of doing far more at compile time, allowing the optimizer to generate much better code.

Note that templates come with some pitfalls: first of all, it’s very easy to inadvertently generate huge amounts of code, so very careful inlining and base class derivation is essential. The second problem is that templates tend to be “instantiated” as late as possible by the compiler, which can lead to confusing error messages when the templates are wrong or used wrongly.

I’m still just exploring this approach for embedded use. The potential performance gains are substantial enough to give it a serious try. My hope is that the hard work can be done in a library, so that everyone else can just use it and benefit from these gains without having to think much about templates, let alone implement new ones. The “one” object declared above acts like any other C++ object, so using it will be just as easy as non-template objects.

Does the above lead to fast code? You bet. Here’s a test sketch:

Screen shot 2010-01-06 at 13.05.29.png

And here’s some sample output:

Screen shot 2010-01-06 at 13.06.14.png

As you can see, values 5 and 6 are virtually the same as values 7 and 8. We’ve obtained the performance of direct pin access while using a high-level port-style notation to access those pins. This is why templates are so attractive for embedded use.

The timings are different from the previous post because the loops are coded differently. In this case, only the relative comparisons are relevant.

Pin I/O performance

In AVR, Hardware, Software on Jan 6, 2010 at 00:01

There was a discussion on the Arduino developer’s mailing list about the impact of a small change to the digitalWrite() function, and for some time I’ve been hearing that digitalWrite() has a huge amount of overhead.

Time to find out.

Here is the sketch I used to measure how often a pin I/O command can be issued using various mechanisms:

Screen shot 2010-01-05 at 11.42.53.png

The logic is that I’m counting how often the same command can be called between timer overflows, i.e. every 1024 µs (one byte, incrementing @ 16 MHz / 64), before the timer tick count changes again.

And here’s the sample output:

Screen shot 2010-01-05 at 11.42.14.png

There’s a small amount of jitter, which tells me the loops are syncing up almost exactly on the timer ticks. Interrupts have not been disabled, so the timer interrupt is indeed being serviced – once for each loop.

What these values tell me, is that we can do about:

  • 10 analog 10-bit readings per millisecond with analogRead()
  • 128 pwm settings per millisecond with analogWrite()
  • 220 pin reads per millisecond with digitalRead()
  • 224 pin writes per millisecond with digitalWrite()
  • 1056 pin reads per millisecond with direct port reads
  • 1059 pin writes per millisecond with direct port writes

(I’ve corrected the counts by 1000/1024 to arrive at these millisecond values)

So the Arduino’s digital I/O in IDE version 0017 can do roughly 1/5th the speed of direct port access on a 16 MHz ATmega328.

But WAIT! – There’s a large systematic error in the above calculations, due to the loop overhead. It looks like the loop takes 1024000/1251 = 819 ns overhead, so the actual values are quite different: digitalRead() -> 3712 ns, direct port read -> 151 ns. Now the values are more like 1/25th!

So let’s redo this with more I/O in each loop iteration (all 4 ports):

Screen shot 2010-01-05 at 11.55.31.png

The sample output now becomes:

Screen shot 2010-01-05 at 11.56.59.png

With these results we get: one digitalRead() takes 4134 ns, one direct port read takes 83 ns (again correcting for 819 ns loop overhead). The conclusion being that digitalRead() is 50x as slow as direct port reads.

Which one is correct? I don’t know for sure. I retried the direct port read with 16 entries per loop, and got 67 ns, which seems to indicate that a direct port read takes one processor cycle (62.5 ns), as I would indeed expect.

Conclusion: if performance is the goal, then we may need to ditch the Arduino approach.

Update – Based on JimS’s timing code (see comments): digitalRead() = 58 cycles and direct pin read = 1 cycle.

Update #2 – The “1 cycle” mentioned above is indeed what I measured, but incorrect. The bit extraction was probably optimized away. So it looks like direct pin access can’t be more than 29x faster than digitalRead(). As pointed out by WestfW in the comments, digitalRead() and digitalWrite() have predictable performance across all use cases, including when the pin number is variable. In some cases that may matter more than raw speed.

Update #3 – Another caveat – Lies, damn lies, and statistics! – is that the register allocations for the above loops make it extremely difficult to draw exact conclusions. Let me just conclude with: there are order-of-magnitude performance implications, depending on how you do things. As long as you keep that in mind, you’ll be fine.

Arduino Duemilanove

In AVR, Hardware on Dec 30, 2009 at 00:01

Not everything is about wireless. Nor about nodes, ports, or plugs. Of course not – that would be boring :)

To offer more choices, I’ve added the Arduino Duemilanove to the web shop:

Duemilanove_HI.JPG.jpeg

Jee Labs is now an official distributor for these famous boards. Woohoo!

Carrier detection

In AVR, Software on Dec 26, 2009 at 00:01

Wireless communication is a complex process. The ISM bands used by the RFM12B module get used in various ways – some quite simplistic. For “serious” use, what you want is to avoid transmissions interfering with each other – which means at most one transmitter should be active at any given time for a specific frequency band.

Easier said than done. This is what CSMA/CA is all about. It’s quite similar to ethernet: you listen to the “ether” and wait until there is no carrier before starting to send yourself. If everyone does so, then there will be fewer “collisions” – i.e. messed up packets.

CSMA/CA isn’t perfect. It doesn’t scale all that well if there are lots of nodes, all trying to find a free slot to send their packets out. There is always a non-zero probability of collision, when two nodes decide at nearly the same time that there is no-one else transmitting. And then, BOOM! … as they say.

One solution for that is another acronym: TDMA. Basic idea: have all the nodes agree to only send in specific time slots allocated to them. This requires a central coordinator, as well as pretty accurately keeping track of time (which is non-trivial with RC-based watchdog timers for sleep modes used with low-power nodes!).

In the ISM band, at least the 868 MHz one used in Europe, a simpler solution is used: keep the air-waves more or less free. The rule is that each transmitting node should send no more than 1% of the time, on average. With one or two dozen nodes and a bit of randomness in timing, the idea is that collisions will be relatively rare.

I recently added the 1% rule to the easy transmission mechanism in the RF12 driver (for the 868 MHz band only). So with the rf12_easy…() calls, adhering to the 1% rule is now automatic.

The 1% rule is a very simple system, yet it works surprisingly well. I’ve got over a dozen nodes around the house, sending out packets whenever they feel like it. The off-the-shelf commercial weather station nodes I use are very simplistic – they just send, ignore collisions, and send new data again a minute or two later. Those nodes probably don’t even have receive capability.

The RFM12B transceiver module in the JeeNode is slightly more sophisticated, in that communication can take place in both directions. So the receiver can send back an “ack” packet, and the originating node will have some idea of whether its last data packet ever made it to the destination (note that ack’s can get lost as well – but that’s another story).

Still – the RF12 driver used in JeeNodes is just as careless as the other nodes: it starts sending the moment it feels like it – except if a packet for its own net group is currently being received. Sending packets with the RF12 driver can still easily mess up whatever is currently going on in the air.

Well, as of today, things will improve a bit further. I’ve extended the RF12 driver code to look at the RSSI status bit before starting to transmit. If a carrier is detected, even one that isn’t being recognized by the RFM12B, then transmission will be delayed a bit. Here is the latest code in the RF12.cpp driver:

Screen shot 2009-12-21 at 02.16.28.png

This isn’t perfect – nothing ever is – because most nodes will be polling very frequently and then start to send right after the carrier drops. So the chance increases that nodes two and three will both try sending when node one finishes. But let’s assume that the RSSI signal doesn’t drop to 0 for all nodes at exactly the same time. If that turns out to be insufficient, a timer-based exponential back-off mechanism can be added later.

And there is a substantial benefit: nodes will no longer mess up packets which are currently “on the air”. As more nodes are being added around here, I expect this change to cause less degradation due to collisions.

In summary: the RF12 driver is a very simple system. No CSMA/CA, no TDMA. There are definitely limits as to what it can be used for. There are some severe limits on how much data it can send, given that (on 868 MHz) each node can only send up to 1% of the time, but this is also why such a simple approach is actually quite effective. And why the RF12 driver is still just a few Kb on an 8-bit ATmega, leaving lots of room for application specific code. I happen to think that the RF12 approach strikes a pretty decent balance between simplicity and effectiveness – and I’m always open for suggestions on how to take this further.

OOK reception with RFM12B ?

In AVR, Software on Dec 25, 2009 at 00:01

Yesterday’s post described a setup to see the RSSI and DQD status bit reported by the RF12 driver in real time.

One of the interesting results is that I can see the RSSI light come on when pressing a button on the FS20 remote transmitter – even though that’s an OOK signal, not FSK!

When adjusted to run at 433 MHz, the RSSI indicator also lights up with the KAKU remote.

In both cases, the DQD signal appears useless – it just shimmers all the time.

The RSSI signal is encouraging, though. It turns out that getting it to blink reliably did depend on setting the threshold right. At -103 and -97 dBm, it was on all the time – only the -91 dBm value produced a usable signal. I hope that’s the case with all units.

Could this be used to receive FS20 or KAKU?

Well, I just had to try. My idea was to continuously poll the RSSI status bit and then “mirror” its value to a DIO output pin. Then use a second JeeNode to treat this as a normal OOK pulse train.

Here’s the “rssiMirror” sketch I used:

Screen shot 2009-12-20 at 17.07.34.png

Does it work? Unfortunately … no :(

Time to hook up the Logic Analyzer to see what’s going on. I connected the above digital output to the first channel, and a real OOK receiver on the second channel:

uuu.png

Guess what… the RSSI signal is indeed detecting the presence of a transmitted signal, but it’s way too slow!

Here’s the same sample, zoomed in on the real OOK pulse train:

ooo.png

As you can see, there’s a pretty good sequence of transitions, 400 µs and 600 µs apart. Oh well, so much for the RSSI status bit – it’s nice to detect the presence of a carrier, but not more than that.

Next thing I tried was the DQD signal. After tweaking the DQD threshold to 3, this is what came out:

eee.png

Yeah, sure, it seems to track the signal, but not reliably, and with a huge number of extra transitions. Note how the top timings are all multiples of 25 µs apart – that’s because it takes 25 µs to read out the DQD status bit. Coarse, but fine enough in principle to track 400 / 600 µs pulses from an FS20 remote.

So, again: nice, but no dice. Neither the RSSI nor the DQD status bits are fast and accurate enough to decode a slow OOK pulse train with.

Next attempt was to try and pick up the ARSSI signal, direct off the RFM12B module – as mentioned in this forum discussion. There’s a German forum which describes where to pick up that signal:

rfm01.JPG.jpeg

And sure enough, here’s a scope capture of an FS20 transmission:

www.png

Yeah, it’s there alright. But the signal is a bit weak. I’d rather not dedicate the analog comparator or ADC to it, and besides – that still leaves the need to compare against the average level – there’s a nasty 0.4V bias in that signal.

Here’s the same signal, AC coupled:

qqq.png

And here’s a zoomed-in area, showing what looks like pretty decent 400 µs and 600 µs pulses:

hhh.png

So yes, a small self-adjusting comparator can proabably turn this into a nice digital pulse train – but it’ll require some extra components, and I’m a bit out of my league on designing such a circuit.

Oh well – perhaps this information will help someone else further along. It’s been a good learning experience for me, even if the result is not quite what I had hoped…

Tomorrow, I’ll describe another – successful! – outcome from this RSSI / DQD exploration.

Power tracker – software

In AVR, Software on Dec 22, 2009 at 00:01

Yesterday’s post described a small circuit to track power consumption of JeeNodes to help optimize sketches for minimal power consumption.

Let’s put that circuit to use, with a bit of software to measure actual power consumption. The basic idea is to continuously measure current and then integrate these measurements to determine the sum of all power consumption intervals, regardless of levels.

The reason for this is that we’re not really interested in current draw but in the amount of charge consumed by the JeeNode. As far as the battery is concerned, drawing 1 mA for 1 hour is the same as drawing 100 µA for 10 hours (in the ideal case, anyway). The fancy way to say this is that we need to measure Coulombs, not Amps. Or rather micro-Coulombs, i.e. µC. That’s really easy once you realize that 1 µA is the same as 1 µC per second. Or to put it differently again: 1 mAh = 3600 mC. So a 1000 mAh battery is really nothing but a 3600 C charge.

Ok, back to the problem at hand: measuring average current draw per second.

Here is a simple sketch which does all the auto-ranging and integration:

Screen shot 2009-12-19 at 19.34.25.png

It reports averaged power drain in µA/sec (the second value is the number of samples per second). The 10% correction which I had to apply in my setup could be due to a number of factors – most likely it’s due to resistor tolerances (they are all 5%).

Here’s an interesting case with the latest rooms node:

Screen shot 2009-12-19 at 20.01.21.png

As you can see, the baseline power drain is a fantastically low 56 µA/sec in this case, but once or twice a minute it goes up to 14 mA/sec for several seconds. Not sure what’s going in here – need to investigate (now that I can!).

It would be nice to automatically detect the baseline, i.e. the average low-level sleep consumption, and things like the peak current and the percentage of the total consumption caused by such peaks. Extending the software to handle this is more work.

With slightly more elaborate software, it will be possible to place the power measurement plug between the measuring JeeNode and the JeeNode under test, and then leave it alone. A 1-day or 1-week average should give an excellent estimate of battery lifetimes.

UartPlug class

In AVR, Hardware, Software on Dec 20, 2009 at 00:01

Here is a utility class for the UART Plug:

Screen shot 2009-12-18 at 13.42.26.png

The interface is exactly the same as the Serial class, so it can be used interchangeably. Here is the updated “uart_demo” example in the Ports library:

Screen shot 2009-12-18 at 13.38.44.png

Here’s a test setup with a second JeeNode running RF12demo plugged in:

DSC_0866.jpg

Sample output:

Screen shot 2009-12-18 at 13.38.29.png

Both input and output are supported by this UartPlug class – this demo is essentially a serial pass-through.

The UART supports accurate baud rates all the way up to 230400, which is in fact beyond the current I2C rates of the Ports library. Even at 57600 baud, I’ve seen several serious overruns with the above demo. One reason is that it’s only reading out one byte at the time, going through a multi-byte I2C bus sequence for each one (!). Note also that the Serial class does not buffer its output, so it can easily bog down everything else.

The UART hardware can support both hardware handshaking and XON/XOFF throttling, so this would be another way to avoid buffer overruns.

Up to say 9600 baud the UartPlug class should work fine, even with several UART plugs on the same I2C bus.

Battery life – refinement

In AVR, Hardware, Software on Dec 19, 2009 at 00:01

Yesterday’s post described how to estimate the battery life of a JeeNode running the “rooms” sketch with the SHT11, ELV PIR, and LDR sensors. To summarize:

  • the code started out using 370 µA average current, i.e. roughly 7 months on 3 AA cells
  • of these, 200 µA were caused by the 1-second periodic wakeup “blip”
  • another 120 µA were due to the actual measurements and packets sent every 30 seconds
  • and finally, the remaining 50 µA come from the PIR + JeeNode current draw in sleep mode

Yesterday’s post was also about reducing that 200 µA blip consumption to somewhere around 20 µA.

Today, let’s tackle the other power “hog”: the 300 ms @ 12 mA spike. Here is that pattern again:

b1.png

The high peak at the end is the RF transmission of a packet, followed by a “knee” during which the node is waiting for the ack packet in RF receive mode.

Note that the main power drain is NOT caused by wireless communication!

This period of over 300 milliseconds is when the ATmega is polling the SHT11, waiting for a fresh reading. Twice in fact: once for the temperature and once for the humidity measurement.

So the explanation is very simple: we’re polling and waiting in full-power mode. Quelle horreur!

The fix requires a small modification to the SHT11 driver in the Ports library. Instead of a fixed delay, it needs to be extended to allow using an arbitrary function to waste some time. Here’s the modified code:

Screen shot 2009-12-18 at 01.00.53.png

A new second arg has been added, specifying an optional function to call instead of delay(). The code remains backward compatible, because this argument defaults to zero in Ports.h:

Screen shot 2009-12-18 at 01.02.45.png

So now all we need to do is define a delay function which goes into real power down mode for a little while:

Screen shot 2009-12-18 at 01.52.23.png

… and then adjust the two measurement calls to use this function:

Screen shot 2009-12-18 at 01.05.08.png

Does all this make a difference? You betcha:

b2.png

That’s a substantial fraction of a second in which the ATmega will draw considerably less than 12 mA. How much less? Let’s expand the vertical scale:

b3.png

Most of the time, the voltage is around 50 mV, i.e. 1 mA over 47 Ω. That’s the SHT11 current draw while active. There are two measurements – so everything behaves exactly as expected!

A couple of quick wake-ups remain, to check whether the SH11 measurement is ready. And so does the wireless TX/RX peak, of course. Here is an isolated snapshot of that RF activity (200 mV/div and 4 ms/div):

b4.png

Approximate current draw: TX = 35 mA, RX = 20 mA. Total time is about 10 ms.

Looks like we’ve reduced the power consumption of this once-per-30-second spike by perhaps 90%. As a result, the node now consumes about 20 (blip) + 20 (spike) + 50 (sleep) = 90 µA on average. Even with much smaller 800 mAh AAA cells, the battery life of these low-power nodes should now be over a year.

There are several conclusions to take home from this story, IMO:

  1. The biggest drain determines battery lifetimes.
  2. Measuring actual current profiles always beats guessing.
  3. A simple USB storage scope is plenty to perform such measurements.

If I had followed my hunches, I’d no doubt have spent all my time on getting the current draw of packet transmissions down – but as these experiments show, their effect on power drain is minimal.

There are more optimizations one could explore. There always are. But the gains will be limited, given that the ELV PIR sensor consumes 30..40 µA, and that it needs to be on at all times anyway, to be able to detect motion.

Sooo… end of story – for now :)

All source changes checked in. The entire rooms sketch still compiles to under 8 Kb of code.

Battery life estimation

In AVR, Hardware, Software on Dec 18, 2009 at 00:01

To get an indication of battery power drain, I measured the voltage drop over a 47 Ω resistor in series with the 5V supply, using a JeeNode with Rooms Board and the latest version of the “rooms” sketch.

Here’s the blip I see, once a second (100 mV/div and 20 msec/div):

on-time-1.png

That’s a 40 msec pulse of about 5 mA, in other words: 5 mA during 4 % of the time, which averages out to around 200 µA current draw continuously. Not bad, but not stellar either: it’s 4 times the sleep mode current.

Every once in a while, a much longer and bigger spike shows up:

occasional-peak.png

Which looks like roughly 350 msec @ 12 mA.

Let’s assume the big one is a real transmission. It sort of fits: the spike at the end is a brief transmission at ≈ 35 mA total, followed by a 20-ish mA period of reception (waiting for the ack to come in).

Very roughly speaking, the area of that extra spike at the end is about the same as the 5-to-10 mA step at the start of this period. So as an estimate, we’re consuming about 12 mA during 350 msec – let’s round down to 300 msec.

Let’s also assume these bigger current patterns happen every 30 seconds, when the node is reporting changed values (everything other than motion gets reported at that rate in the latest “rooms” sketch).

So 1% of the time (300 ms every 30s), power consumption is 12 mA. This averages out to 120 µA continuous current consumption.

In other words: a JeeNode running this latest rooms sketch with the SHT11 and ELV-PIR sensors, is consuming roughly 200 (blip) + 120 (spike) + 50 (sleep) = 370 µA.

Using a 2000 mAH 3-cell AA battery, this should lead to a 225-day lifetime – over 7 months.

Can we do better? Sure.

It’s basically a matter of figuring out what’s going on during those 40 and 350 msecs, respectively. Interestingly, more can be gained by improving non-transmitting “blips” than twice-a-minute high-power RF packet exchanges.

Do those 40 ms @ 5 mA every second look a bit suspicious? Yep – that’s the “idling” power level. What happens is that I was a bit too pessimistic in the time spent in sleep mode. This was the code:

Screen shot 2009-12-17 at 00.51.26.png

Looks like this is about 40 ms off, and so the code ends up waiting for the 1 sec timer to expire… in idle mode!

Let’s change this to end up closer to the desired time:

Screen shot 2009-12-17 at 02.59.16.png

Here’s the new blip (different scales):

better-blips.png

We’re down from 40 to 10 msec blips – tada!

That translates to an average 50 µA current draw from the blips, bringing the total down to 220 µA. Which translates to a 375-day battery life: over a year!

Now we’re cookin’ … but could we do even better? Sure.

Note that only the 2 ms spike at the end of the 5 mA blip is the actual active period. The time up to then we’re just waiting in idle mode – and wasting power.

We could shorten the sleep timer to 994 ms, since we don’t care whether readings are taken exactly 1 second apart. Now the RFM12B-based watchdog timer will wake us up just 2 ms short of the target time. And sure enough, the 5 mA blip is down to around 3 ms – shown here with an even further expanded time scale:

final-blip.png

But that’s silly. We’re tweaking a millisecond timer, and we’re not even interested in an “exact” 1000 ms cycle in the first place! It makes much more sense to just use the RFM12B wakeup timer to get us close to that 1 second cycle, and then immediately take a measurement. Here’s the corresponding code change in periodicSleep():

Screen shot 2009-12-17 at 02.35.36.png

Does this make a difference? Definitely:

best-blip.png

One final remark: the above battery lifetime estimates do not take into account the increased power consumption when motion is detected and more packets are sent (up to once every 5 seconds). On the plus side, when no light / temperature / humidity changes happen, the packet frequency will drop further, to once-a-minute.

The above changes have been checked into the source code repository.

Update – I just found out that the DSO-2090 scope has a high-pass low-pass filter option:

smooth.png

Sure wish I’d found out about that feature sooner… it’s so much more informative: the initial ramp is probably the clock starting up, and the little peak could well be the LDR pull-up during ADC conversion!

Rooms sketch, reloaded

In AVR, Hardware, Software on Dec 16, 2009 at 00:01

With the new easy transmission mechanism and the low power logic implemented, it’s time to revisit the “rooms” sketch, which I use for all my house monitoring nodes based on the Room Board.

I’ve wrapped the code used in POF 71 a bit further, with these two extra functions:

Screen shot 2009-12-15 at 22.25.44.png

With this, the main loop becomes very simple – even though it will now power down the RFM12B and the ATmega328 whenever there’s nothing to do for a while:

Screen shot 2009-12-15 at 22.25.57.png

The lowPower() and loseSomeTime() code is still the same as in POF 71 – this is where all the hardware low-power trickery really takes place:

Screen shot 2009-12-15 at 22.24.57.png

Note that these need an “#include <avr/sleep.h>” at the top of the sketch to compile properly.

I’ve also disabled the pull-up resistor on the LDR while not measuring its value. This drops power consumption by over 100 µA, depending on actual light levels.

A quick measurement indicates that power consumption went down from 20 mA to some 50 µA (much of that is probably the PIR sensor). These are only approximate figures, because my simplistic multi-meter setup isn’t really measuring the charge (i.e. integrated current draw), just the current draw while in sleep mode.

These changes have been checked into the repository as “rooms.pde”.

This code isn’t perfect, but since “perfection is the enemy of done” I’ll go with it anyway, for now. One difference with the original rooms sketch is that the motion sensor is not read out as often so brief motion events might be missed. Another issue with this code is that if the central node is off, a lot of re-transmissions will take place – without the node going into sleep mode in between! IOW, a missing or broken central node will cause all remote nodes to drain their batteries much faster than when things are properly ack’ed all the time. Oh well, let’s assume this is a perfect world for now.

With these levels of power consumption, it’s finally possible to run room nodes on battery power. I’ll use some 3x AAA packs, to see what sort of lifetime this leads to – hopefully at least a couple of months.

Will report on this weblog when the batteries run out … don’t hold your breath for it ;)

Update – I just fixed a power-down race condition, so this code really goes back to sleep at all times.

Re-flashing and ISP

In AVR, Hardware on Dec 11, 2009 at 00:01

This is the second of two posts about everything related to uploading, re-flashing, bootstraps, FTDI, and ISP.

Yesterday’s post described the process of uploading new sketches via USB or RS232 using a boot loader.

But how did that boot loader get into the ATmega328?

That’s a bit of a chicken-and-egg problem. Ya’ can’t use a boot loader to get the boot loader into flash memory!

This is where a lower-level hardware-based mechanism called In System Programming (ISP) comes in. ISP is a clever trick in the ATmega chip which in effect activates a special boot loader built into the hardware. This is done by holding the RESET line of the ATmega low, at which point the chip becomes essentially useless, since the reset prevents the chip from starting to run its firmware. The trick is that in this mode, some of the pins on the ATmega become an interface to that special hardware-based built-in boot loader.

So what we need to do, is to manipulate those pins to send commands which will store data into the flash memory. What we’re going to send in most cases, is the data for the boot loader in upper memory. With that boot loader in place we can then switch to “normal” uploading via the serial interface and USB.

ISP programming is also used to change “fuse bits” on an ATmega. There are a few configuration settings for the ATmega – what type of clock it uses, how it boots up, enabling a watchdog timer, etc. These are stored in “fuses” which can only be adjusted via ISP programming.

There are 3 I/O pins involved in ISP programming, plus the reset line and power. On the Arduino as well as on the JeeNode and JeeLink boards, these lines are available via a 2×3-pin ISP connector with the following layout:

ISP pins.png

The interesting thing is that you don’t even need an Arduino or JeeNode to set up flash memory and fuses. ISP is so low-level that it works directly on the pins of an ATmega chip. This is very useful to pre-load the boot loader (or test program – anything you like, really) onto a chip before soldering it permanently onto a board.

(continued…)

Read the rest of this entry »

Uploading and FTDI

In AVR, Hardware on Dec 10, 2009 at 00:01

This is the first of two posts about everything related to uploading, re-flashing, bootstraps, FTDI, and ISP.

First, our goal: what we want to do is get our software (“sketch”) from the PC/Mac into the AVR ATmega328 microcontroller on our Arduino or JeeNode. This is a fairly simple process once all the pieces are in place…

The effect is that the flash memory built into the ATmega is re-flashed. Being flash memory, your software will remain in the microcontroller even without power – ready to start again once power is applied.

There are two ways to get your software into the ATmega: In System Programming (ISP) and uploading. ISP will be described tomorrow, here we’re going to focus on uploading.

Uploading works with a “boot loader”. This is a small piece of software started after power-up (or a reset), which usually listens on the RX and TX pins of the serial interface for commands. These commands then tell it what data to store in which part of the flash memory:

Screen shot 2009-12-09 at 12.25.31.png

The surprising thing is that the boot loader itself is also stored in flash memory. It’s stored in a small (1..4Kbyte) area in upper memory, and the data it writes always goes to the lower part of memory. That’s why it’s called a bootstrap or boot loader – imagine lifting yourself by pulling on the straps of your own boots. In this case the ATmega is lifting its own functionality up by reprogramming its flash memory via its own boot loader.

(continued…)

Read the rest of this entry »

Low power mode again

In AVR, Software on Dec 9, 2009 at 00:01

After yesterday’s Wireless Light Sensor was announced, I wanted to push a bit more on the low-power front.

The POF described two simple tricks to get the power consumption from 19 to 3 mA, roughly. It turns out that a single extra step will get the idle consumption down to some 20 µA. That doesn’t mean we’re getting a 15-fold battery lifetime increase, because I’m measuring the current at idle time but not accounting for the brief periods of high-current activity which also occur. But it’s a major reduction in power consumption.

Here’s how … but this requires going a bit deeper into some low-level AVR/ATmega chip features.

First, here are some utility functions we’re going to need:

Screen shot 2009-12-08 at 10.04.31.png

The lowPower() routine disables the ADC subsystem and then enters the specified low-power mode in the ATmega. Once it resumes, the ADC subsystem setup will be restored to its previous state.

The loseSomeTime() does just what is says on the box: go into comatose mode for a more-or-less controlled amount of time. The trick is to activate the RFM12B watchdog just before passing out. This leads to larger power savings than we would have with the ATmega’s watchdog, btw – and it’s easier to implement.

The complication is that we risk losing all track of time. It’s a bit hard for an ATmega to count heartbeats when its heart has stopped beating – not only are there no beats, it’s also stripped of its counting abilities while in coma…

So instead, we estimate just how long we’ve been away from the watchdog time chosen for the RFM12B, and correct the milliseconds timer built into the Arduino. That’s what the “timer0_millis” stuff above is about. It will not be quite as accurate as before, but that’s probably acceptable for a sensor node like this one.

The last issue is that we need an indication about how long we can go comatose. I’ve added a “remaining()” member to the MilliTimer class to obtain this information.

Now, all the pieces are in place to change the code in the Wireless Light Sensor from this:

Screen shot 2009-12-08 at 10.14.23.png

.. to this:

Screen shot 2009-12-08 at 10.15.53.png

So there you have it. Most of the time between each measurement once a second, the node will now go into a very low-power mode of around 20 µA. My current measurement tools are inadequate to measure exactly what amount of charge is being consumed, which is what this is really about. So accurate battery lifetime calculations are not yet possible – but I expect it to be in the order of months now.

I’ve updated the Wireless Light sensor POF to point to this post and include this trick.

Wireless Light Sensor – POF 71

In AVR, Hardware, Software on Dec 8, 2009 at 00:01

After last week’s Hello World POF to get started, here is a new Project On Foam:

DSC_0824.jpg

A battery-powered wireless light sensor node. This is POF 71, and it’s fully documented on the wiki.

This project goes through setting up the Ports and RF12 libraries, setting up a central JeeNode or JeeLink, and constructing the light sensor node.

It also describes how to keep the node configuration in EEPROM, how to make a sensor node more responsive, and how to get power consumption down for battery use.

The POF includes code examples and uses the easy transmission mechanism, with the final responsive / low-power sketch requiring just a few dozen lines of code, including comments. The sketch compiles to under 5 Kbyte, leaving lots and lots of room to extend it for your own use.

All suggestions welcome. Anyone who wants to participate in these POFs, or in the wiki in general, just send me an email with the user name you’d like to use. I’m only restricting edit access to the wiki to prevent spamming.

FTDI Reset Supressor

In AVR, Hardware on Dec 5, 2009 at 00:01

Sometimes the simplest things are so obvious that it’s easy to miss them…

I occasionally do not want to reset a JeeNode when accessing it via USB. The reset is great for uploading, because the ATmega’s bootloader runs right after reset and intercepts such upload requests in a very convenient way. But sometimes, you just want to leave the ATmega running when re-connecting to it.

Meet the “FTDI Reset Suppressor”:

DSC_0827_2.jpg

All it does is break the reset connection between an FTDI interface such as the USB-BUB and the JeeNode.

Just to make this post a little longer, here are the steps to make one:

DSC_0827.jpg

And here is an action shot:

DSC_0828.jpg

Tada! And it’s totally voltage, baud-rate, and platform independent… :)

Update - it just occurred to me that this already exists, it’s a 5-pin stacking header! Or a 6-pin one, as follows:

DSC_0836

Hello World – POF 52

In AVR, Hardware, Software on Dec 1, 2009 at 00:01

The first Project On Foam is inevitably a blinking LED:

DSC_0814.jpg

Not very exciting, but it’ll allow me to go through the steps needed to set up the development environment, the first-time USB hookup, and getting a first sign of life out of a JeeNode in Physical Computer terms…

There is a new section on the Jee Labs wiki which I’m going to use for POFs. For rather obscure reasons, this POF is #52 (new POF numbers always increase).

Note that as Project On Foam, this Hello World example is rather silly – because it doesn’t really need a foam base at all. But bear with me – this step is intended to help people through the first (and sometimes daunting) steps of getting started.

The challenge for me right now is to provide the proper information as concisely as possible. These POFs are being placed on the wiki so they can be updated and improved. There will be a few more people involved in this, which again makes the wiki much more suitable to collect and maintain all the POFs than say this weblog. New POFs will be announced on this weblog, but updates are an ongoing process on the wiki pages themselves.

There have been a lot of experiments and projects at Jee Labs over the past year, in various stages of completion. From hooking up all sorts of sensors to the house-monitoring network currently running here at Jee Labs. It is my intention to redo a number of these as POF, in more detail and with more background information. Other POFs will be completely new, though – the list of fun stuff one can do with Physical Computing is endless!

Other news: since assembly and reflow soldering of the JeeLink and the JeeNode USB has been going a lot better lately, their price has been reduced to €29.50 (incl. VAT and shipping) – see the shop for details.

JeeNode comparison matrix

In AVR, Hardware on Nov 26, 2009 at 00:01

All the final boards are in now. It’s time to step back a bit. Let’s start with a picture:

DSC_0785.jpg

From left to right: JeeLink (v2), JeeNode USB (v2), and JeeNode (v4).

Here is a summary of the similarities and differences between these units:

jee-comparison.png

(this comparison matrix is also available as PDF)

So there you have it – one happy JeeFamily :)

Update – Nov 30: lower prices for the JeeNode USB and the JeeLink!

Update – Dec 1: added the new low-cost “JeeNode NoRF” kit.

Node, node, node

In AVR, Hardware on Nov 24, 2009 at 00:01

Ok, finally got around to building a bunch of JeeNodes for all those room boards I had waiting:

DSC_0775.jpg

Just for the heck of it, I decided to leave the boards joined together, as they come from the pcb manufacturer. This picture was taken just before separating these final units.

Small detail: on the left the original 10 µF capacitors, lying down, and on the right the new ones I will be using from now on, which are much smaller and leave the battery connection pads exposed.

The good news is that these units all worked out of the box. Great, eight of ‘em will go straight to their room :)

I’m not having quite as much luck so far with the assembly of JeeLink and JeeNode USB boards, both using SMT parts. There, I often have to debug 2 or 3 out of 10 boards before they work. Occasionally, even that doesn’t solve it so once in while a board gets set aside, awaiting further debugging some other time.

It’s called “production yield”, I think, and I’m not quite there yet… oh, well.

Arduino?

In AVR, Hardware, Software on Nov 23, 2009 at 00:01

What is it? Hype? Hobby? Hacker stuff? Here is the best overall introduction I’ve seen so far – by Dave Jones. It’s 19 minutes – plenty of time to get used to his accent :)

(view directly on YouTube)

I think he really touches on all the important aspects and inevitable trade-offs.

Me, I use the Arduino bootloader for JeeNodes and JeeLinks all the time, and the Arduino IDE to compile and upload stuff to them, as well as the serial console in many cases. I do use my own editor environment – which is easy to do once you disable Arduino’s built-in one (this is not well documented, Google for “Arduino external editor”). So for me the Arduino is really the bootloader, plus the IDE just as compile/upload system.

As Dave points out, the Arduino is a wrapper around the avr-gcc compiler + avrdude in combination with a convenient USB-based upload/console/power hookup. The rest is libraries, conventions, a Java based IDE (based on Wiring), and optionally a Java-based PC-side front end called Processing.

On the embedded software side, it’s really standard full-scale C and C++.

Which is great, IMO. I can keep going with the Arduino-compatible JeeNodes and JeeLinks, and their built-in wireless, port conventions, 3.3V operation, and all the add-on plugs – knowing that much of this will work fine with as well as without all the stuff going on in the Arduino ecosystem right now.

OOK unit

In AVR, Hardware, Software on Nov 21, 2009 at 00:01

Here’s an ELV 868 MHz OOK receiver, connected to the new JeeNode USB:

DSC_0771.jpg

Note that this plug can be used for any of the four ports, simply by plugging this thing in one of the four possible orientations. In this case, it’s hooked up to port 1.

The receiver is mounted on a JeePlug for stability:

DSC_0768.jpg

There really are only three wires: GND, +3V, and the received bit stream, which is tied to the AIO pin:

DSC_0769.jpg

You can clearly see the built-in pcb antenna on these last two pictures.

The code for this is similar to the one used in an earlier post and basically runs a couple of bit decoders in parallel to recognize FS20, (K)S300, and EM10 commands. It’s available here. Sample output:

Screen shot 2009-11-19 at 15.02.31.png

Or have a look at the OOK relay, with which this plug will also work.

I really need to clean up and merge the different OOK decoding sketches – they all have slightly different capabilities…

One thing which would be very nice to do with this unit, is a general sketch which reports incoming OOK packets but which also uses the OOK sending capabilities of the RF12 driver to send out such packets, to control FS20 devices for example. That mould make this a general-purpose bi-directional 868 MHz OOK unit, connected via USB and controllable via simple serial-port commands.

I’ll punt for now. Don’ have time to go into this. Or perhaps I should say… exercise left for the reader :)

And maybe one day we’ll get OOK input going without extra hardware ?

PS. Good news: everything is now in for the JeeNode USB, so I’ve started shipping them.

New RF12demo

In AVR, Software on Nov 19, 2009 at 00:01

An updated version of the RF12demo sketch has been checked in. Also available as ZIP.

This adds preliminary support for the 1 Mbyte dataflash memory present in the JeeLink v2.

The idea is very simple: the RF12demo app reports all incoming packets as before, but now also stores all valid packets in flash memory, if present. This is done by collecting packets into a 248-byte RAM buffer, and saving it to flash whenever it fills up. Small portions at the high and low end of flash memory are reserved for future use, the remainder is treated as a circular buffer of 256-byte pages – 3808 to be exact (i.e. 952 Kbyte).

The RF12demo commands have been extended accordingly, here is the startup screen on a JeeLink v2:

Screen shot 2009-11-18 at 18.33.06.png

There is a “DF” line at the top which shows that dataflash memory was found, with page #41 written to last, and that we’re in the 3rd reboot since the flash was wiped. This unit picks up incoming data in group 5 @ 868 MHz.

The new “d” (dump) command reports which pages contain data:

Screen shot 2009-11-18 at 18.31.34.png

At this point, I did a reset of the JeeLink, and then left it on to collect some more data. Here are the last few lines of a subsequent dump:

Screen shot 2009-11-18 at 18.45.14.png

The new entries were added starting on page 42, and the clock started at zero again (there is no RTC). Some 248 seconds later, new entries were logged on page 43. The last number on these lines is a page checksum, btw.

The new “e” (erase) and “w” (wipe) commands require specific constant values as input arguments so that these destructive commands are not activated by a mere typo.

So far so good. The JeeLink can now keep track of what is coming in. But that’s just half the story. We also need to be able to get data out again, “replaying” the log from a certain point. This takes a bit more work.

Firstly, whenever a page gets saved to flash, something like this is sent out to USB:

Screen shot 2009-11-18 at 18.45.52.png

This means that page 44 with seqnum 3 was saved with some entries starting at time 505 (seconds since the JeeLink was powered up). Here are the last few lines of a dump made right after that save:

Screen shot 2009-11-18 at 18.46.18.png

The sequence number is an integer which increments on each reboot, and whenever the flash memory buffer wraps back to the first page. So the combination (seqnum,time) is unique and monotonically increasing, over time and across reboots.

On the PC side, these DF “packets” should be treated as readings and stored like any other incoming packet.

To get the saved entries out of the JeeLink, the PC has to send a “replay” command when it connects to it. This replay command must contain the last sequence number and time stored on the PC for the above DF packets. The JeeLink will look for the location of this page in flash memory (or the earliest one thereafter) and will then replay everything stored from there on.

This code is still work-in-progress, but the plan is to replay these packets as lines starting with “R seqnum time” instead of the usual “OK” prefix. Replay takes place at full speed, but depending on the amount of data stored this can still take a substantial amount of time.

After the requested data has been replayed, the JeeLink resumes its normal mode of reporting “OK” packets, “?” checksum errors, and “DF S” save commands.

I haven’t finished implementing the replay command yet, but storage of incoming packets seems to be working, so an updated version will be able to get at that stored data later.

One last point to note is that this storage implementation has built-in automatic “wear leveling” and hence creates no “hot spots”: there is no page in flash memory which gets written to more often than others, so this memory will be usable for at least its full 100,000 rated cycles. This is done by scanning the entire flash memory on startup to determine the last page written to, and by erasing 4 Kbyte blocks only when needed, ahead of the write pointer.

Total size of the new RF12demo is under 10 Kb, so there’s still lots of room left.

Update – several fixes and replay code added. Not 100% right yet, but all functions are implemented now.

Arduino plug stack

In AVR, Hardware on Nov 13, 2009 at 00:01

You could combine all these …

DSC_0750.jpg

… and create an Arduino sandwich like this – with full access to all the Arduino pins:

DSC_0751.jpg

That’s a Plug Shield with, from left to right / top to bottom:

Each of the plugs can be accessed via I2C, i.e. using the Arduino’s “Wire” library.

Would all this work? Yes, I’m pretty certain it would.

Would it be useful? Probably not in this combination…

I just wanted to show off the I2C plugs and shield ;)

Build and pinout errors on older posts

In AVR, Software on Nov 8, 2009 at 00:01

There has been an unfortunate dependency between the Ports library and the RF12 library for some time now, causing the Arduino IDE to generate errors such as these:

ide-errors.png

(etc…)

The workaround right now is to include both in your sketch, even if you only need one:

Screen shot 2009-11-04 at 10.50.42.png

I’ve been planning to do a major overhaul of the library and software in general, but until then this is the way to avoid those pesky errors. It probably affects quite a few sample sketches on this weblog.

Another thing to watch out for (thanks, Ian!) is that some older examples on this weblog use the JeeNode v2 or even v1, which have a different pinout. To uses those examples with the latest JeeNodes, you have to swap pins 4 and 5, i.e. +3V and AIO.

Please let me know when examples from earlier weblog posts don’t work as described. A small fix and note added to these posts might be all that is needed!

LCD Plug

In AVR, Hardware, Software on Nov 1, 2009 at 00:01

Here’s the new LCD Plug:

DSC_0722.jpg

It’s a little piggy-back board for standard LCD modules with 16-pin connectors. The middle 4 pins are not connected, so that two 6-pin male headers are in fact enough to hook this board up to the LCD.

Here is a setup using a 2×16 character display:

DSC_0721.jpg

The interface uses I2C, so this “plug” can be daisy-chained like all the others. The plug uses an I2C expander chip with a fixed I2C address of 0×24. There are two jumpers to select the voltage level for driving the logic supply and the backlight, respectively. The backlight can be turned on and off under software control.

A generalized version of the LiquidCrystal library included with the Ardiuno IDE 0017 is used to redirect the actual interface through a bit-banged I2C bus, using the Ports library. This was described in an earlier post. Details about how this code works are also available, see this post.

The latest Ports library now includes the new code, including the “lcd_demo” example as shown above:

Screen shot 2009-10-31 at 16.06.14.png

The only difference with the LiquidCrystal example is the definition of port 1 as I2C bus, and defining the “lcd” object to connect to the display via this I2C bus.

Updated RF12demo

In AVR, Software on Oct 29, 2009 at 00:01

The RF12demo software which comes pre-loaded on all JeeNodes and JeeLinks has been extended a bit:

Picture 1.png

The new commands are:

  • l – to turn the activity LED on or off, if present
  • f – send a FS20 command on the 868 MHz band
  • k – send a KAKU command on the 434 MHz band

The new FS20 and KAKU commands were added so that a JeeLink can be used out-of-the-box to control the commercially available remote switches of these types. The updated demo is included with all new JeeNodes and JeeLinks from now on.

For example, to turn on channel 1 of a FS20 unit with housecode 0×1234, you can type in “18,52,1,17f” – i.e. the house code in bytes, the channel, and 17, which is the “on” command. Likewise, to turn on channel 1 of group B on KAKU, type “2,1,1k”.

The KAKU transmission range is not very high because the RFM12B radio used is tuned for the 868 MHz band, but even more so because the attached wire antenna is completely wrong for use at 434 MHz. If you want to use this for controlling KAKU devices and don’t get enough range, try extending the antenna wire to around 17 cm, i.e. double its current length. You can just attach an extra piece of wire to the end.

Which – unfortunately – is going to substantially reduce the range at 868 Mhz… so if you really want to use both frequency bands, you’ll have to use two JeeNodes or JeeLinks, each with their own properly sized wire antennas.

For more info about FS20, see these posts on the weblog. For KAKU, see these.

Four generations

In AVR, Hardware on Oct 26, 2009 at 00:01

After one year, I thought it’d be nice to compare all the JeeNode versions which have come out – up to and including the latest v4:

DSC_0581.jpg

Here is the back side of each of them:

DSC_0582.jpg

The back side in particular illustrates the evolution which has taken place this year.

In version 1, there were no labels – mainly because I hadn’t figured out how to do those and I was eager to just see the darn thing work

Version 2 added some minimal labeling (in copper, to save on production charges!) and a ground plane. Port pairs 1+4 and 2+3 were moved 0.1″ further apart. The mounting holes were dropped.

Version 3 was really the first production-ready one. It added lots of text on the component side, plus a bit of eye candy by going for blue solder masks. I switched to yellow wire for the antenna, to help remind me that this is the version with the final port and pin layout – the one which matches all the new JeePlugs. Version 3 did get the silkscreen for the regulator wrong, but it also made it to the Make Magazine weblog – cool! :)

Version 4 now takes this evolution to its logical conclusion: a clear visual “identity” in the form of blue-and-gold color choices and lots of labels on both sides of the board. No more guessing! The PWR/I2C connector moves a bit and is augmented with two more pins. This JeeNode is the narrowest of all, it now has precisely the same width as all the plugs (21.1mm / 0.83″). This is the grown-up version at last, focusing on actual usage convenience along with a proud & pleasing appearance.

It’s time to move on. The JeeNode is done.

Assembly service

In AVR, Hardware on Oct 24, 2009 at 00:01

It’s time to try something new!

Sometimes, this DIY electronics stuff can be a bit daunting. Maybe you’ve never soldered microprocessor circuits before. Or maybe you’re worried about that RFM12B “SMD” module on the JeeNode. Or maybe you just want to get going fast, and not spend your time on the hardware side of things.

Meet the new Assembly service option:

DSC_0676.jpg

For a small fee, I’m going to offer to assemble JeeNode kits for you, as well as soldering headers onto any of the plugs available from the shop.

This can help more people get started on this wireless and sensor hookup stuff. And it lowers your risk – you could get two kits, have one of them assembled, and build the other one yourself. Or if you don’t care about soldering at all, just get all the pieces you want to hook up in assembled form.

In fact, I’m going to extend this new service even further: if you get a kit to build yourself and it turns out that you can’t get it to work, then you can send it back and I’ll assemble / finish it for you. I can only do this if all the components are still undamaged, otherwise you’ll need to get a replacement kit. Since I don’t know whether this will work out, nor whether I can handle such a “return/repair” flow of items, I will only commit to do this until the end of November. If it works well enough, I’ll prolong this service.

The reason for doing this is not to add a massive amount of assembly to my workload, but to help people take the plunge with less risk. Especially if you’re new to all this physical computing stuff and electronics, I think you’ll find out that assembling kits can be a lot of fun and very rewarding. But hey, if you’re in doubt, just get a kit and some assembled parts so you don’t have to worry about everything at the same time.

OOK relay, revisited

In AVR, Software on Oct 21, 2009 at 00:01

The OOK relay to pass on 433 and 868 MHz signals from other devices has been extended:

DSC_0665.jpg

Spaghetti!

The following functions are now included:

  • 433 MHz signals from KAKU transmitters
  • 868 MHz signals from FS20 and WS300 devices
  • the time signal from the DCF77 atomic clock
  • pressure + temperature from a BMP085 sensor

Each of these functions is optional – if the hardware is not attached, it simply won’t be reported.

The BMP085 sensor in the top of the breadboard could have been plugged directly into port 3, but it’s mounted on a tiny board with the old JeeNode v2 pinout so I had to re-wire those pins.

Sample output:

Picture 1.png

There are still a few unused I/O lines, and additional I2C devices can be connected to port 3. Room to expand.

The source code for this setup is available here. It compiles to 10706 bytes, so there is plenty of room for adding more functionality.

This code includes logic for sending out the collected data to another JeeNode or JeeLink with acknowledgements, but I’m working on a refinement so it gracefully stops retransmitting if no receiver is sending back any acks.

As it is, this code will forever resend its data every 3 seconds until an ack is received, but this doesn’t scale well: all the “rooms” nodes do the same, so when the central receiver is unreachable every node will keep pumping out packets while trying to get an ack. It would be better for nodes to only re-send up to 8 times – and if no ack ever comes in, to disable retransmission so that only the initial sends remain.

I’m also still looking for a way to properly mount all this into an enclosure. There is some interference between the different radio’s, maybe all in one very long thin strip to maximize the distances between them?

An OOK relay

In AVR, Hardware on Oct 12, 2009 at 00:01

After having hooked up OOK radios in a few ways, I’ve decided to create an “OOK relay” – a little unit which listens for OOK-encoded data on the 433 and 868 MHz bands, and then re-transmits the decoded data as “normal” packets via the RF12 driver. OOK stands for “On-Off Keying” as opposed to the more advanced FSK – “Frequency Shift Keying” used by the RFM12B’s – i.e. AM vs. FM.

The benefit of an OOK relay is that OOK reception then automatically gets integrated into all the data collection from other JeeNodes that’s already going on anyway. Since an RFM12B can send both 433 and 868 MHz OOK signals, the end result is a pretty complete solution for all sorts of things going on over the air.

Here’s the hardware test setup:

DSC_0650.jpg

The 433 MHz receiver is seen from the side, standing almost straight up with the white antenna wire. It’s connected to DIO of port 1. The 868 MHz receiver is lying flat, with the red antenna wire, and is connected to AIO of port 1. Both receivers are powered from the 3.3V supply.

The reason for this particular setup is that I can use two different pin change interrupts for both: PCINT1_vec for 868 MHz and PCINT2_vec for 433 MHz. No need to decide inside the interrupt routine which is which – this saves some interrupt routine overhead.

The code was created from the two existing decoders for these receivers, and will be made available once everything is finished. Right now, the decoders work happily alongside each other:

Picture 3.png

Sample output:

Picture 2.png

I cheated a bit though by selectively powering the receivers, because there is a hardware problem… it looks like these receivers are interfering with each other. They only work when the other one is off. It’s not that surprising, given that one frequency is almost an exact harmonic of the other. Maybe placing the two receivers physically further apart, or adding better RF power supply decoupling will fix it. They should be able to work together, even receive signals on the two frequency bands at the same time.

More work left to do…

Experimentation setup

In AVR, Hardware on Oct 11, 2009 at 00:01

After coming up with the JeeBoard, which needs a PCB with at least an I/O expander and two LEDs/switches, I decided to go one step simpler and just wire up a version with no active components at all:

DSC_0565.jpg

It connects the same 3.6 .. 4.5 V battery pack through a slide switch, and ties a breadboard to the AIO + DIO pins of ports 1 .. 3, along with +3V and GND. With a few headers placed flat on the board for various plugs.

Wiring this up is simple – note the added rubber feet:

DSC_0566.jpg

Now it’s ready to go, with 3 rechargable NiMH’s:

DSC_0568.jpg

And here’s the final setup:

DSC_0571.jpg

Just to show how you can go nuts with plugs:

DSC_0570.jpg

The battery pack connection is removable to give me a nice spot to insert a current-measuring multimeter.

First demo of this board coming up tomorrow…

Expander Plug, revisited

In AVR, Hardware on Oct 9, 2009 at 00:01

Got some revised plugs. The Expander Plug now works:

DSC_0626.jpg

Here’s a sketch which blinks all pins on the expander:

Picture 3.png

I forgot to check the A0 solder jumper orientation, so I accidentally wired my first plug up for address 0×21 instead of 0×20. Each Expander Plug can be configured for I2C addresses 0×20..0×23, i.e. up to 4 expander plugs can be daisy-chained on each port.

Expander plugs work nicely with the Breadboard Connector, to hook up a mini-breadboard like this:

DSC_0627.jpg

The width of a mini-breadboard is slightly less than an Expander Plug + sideways headers, so daisy-chained plugs can each have their own breadboard.

In summary: the Blink, Expander, Memory, RTC, and UART Plugs all work. So do the unpopulated Proto Board and Breadboard Connector, of course.

More news about prices and availability in the shop tomorrow… once I finish my homework and figure out a few remaining pesky little details and logistics issues.

More serial ports

In AVR, Hardware on Oct 4, 2009 at 00:01

Here’s an easy way to add more serial ports via I2C:

DSC_0547.jpg

I got the wrong crystal size, so it’s mounted a bit awkwardly:

DSC_0548.jpg

There are two jumpers, allowing up to 4 serial ports to be added to each I2C bus – i.e. up to 16 on the bit-banged I2C buses, and 4 more on the hardware I2C line. Since the A0/A1 jumpers actually support up to 16 addresses with a bit of extra wiring, you could theoretically connect up to 80 serial ports to a single JeeNode!

Here’s some sample code:

Picture 5.png

It sets the serial port to 57600, 8 bits, no parity and then sends whatever comes in to the “normal” serial port. The default fast I2C bus rate of over 1 Mhz appears to work just fine.

The header of the UART plug is compatible with FTDI, so you can hook up another JeeNode to it:

DSC_0559.jpg

In this case, I used a JeeNode with a room plug prototype. Sample output:

Picture 3.png

This demo code has been added as “uart_demo” example in the Ports library and is also available here.

Voltage Plug

In AVR, Hardware on Oct 2, 2009 at 00:01

The Voltage Plug generates up to four 0 .. 3.3V levels using MCP4725 12-bit DAC’s controlled from I2C:

DSC_0546.jpg

This sketch switches between 0 and 4095, displaying as 1.2 mV and 3.295 V on my multimeter, respectively:

Picture 1.png

The cycle time was set to 5 seconds to give my auto-ranging multimeter time to adjust itself.

There is room for 4 DAC chips, which seems like a bit of overkill, but I couldn’t think of anything else to put there and the board looked so empty :) – perhaps some sort of voltage-follower op-amp or amplifier stage would make more sense? Anyway, I’ll probably remove two of those chips from the plug again.

The MCP4725 only has one pin to specify the lower address bit. There are in fact 4 different chips available from the manufacturer, to support up to 8 DAC’s on a single I2C bus. Since I got the “A3″ version – and since I mixed up high and low again – this particular test uses address 0×67. For the final version I’ll fix the low-address bit and use “A0″ versions, i.e. 0×60 and 0×61.

Analog Plug

In AVR, Hardware, Software on Sep 30, 2009 at 00:01

The second plug panel has arrived. I’ll document my test results in the coming days.

First, the Analog Plug – an 8-channel 12-bit ADC connected via I2C:

DSC_0545.jpg

It’s based on the ADS7828 chip. Here’s a demo sketch to read it out:

Picture 3.png

I hooked it up using various gimmicks lying around here – this ties a trim pot to channel 4, with range 0 .. 3.3V on the wiper:

DSC_0544.jpg

As you can see, the Breadboard Connector can be used to hook up to 8 of the 12 pins of this plug.

Here’s some sample output:

Picture 1.png

I slowly turned the wiper as you can see. It stops at 4095 counts, which represents the 2.5V of its internal reference. Appears to work fine in this test setup at the maximum I2C rate, somewhere over 1 MHz. The readings didn’t change by more than one count when touching various parts of the circuit, so as first impression it looks like it’s pretty stable.

This plug has two solder jumpers, to configure its I2C address to 0×48 .. 0x4B, which in hindsight is a bit overkill. Only minor nit is that I mis-labeled the A0 jumper – as shown in the picture, the address ends up being 0×49 i.s.o. 0×48. Oh well, a small silkscreen fix will resolve that later.

So there you have it – eight 3.5 digit voltmeters on one tiny blue-and-gold plug :)

LCD display via I2C

In AVR, Software on Sep 28, 2009 at 00:01

Ok, it’s working – always takes longer than expected, especially if you mess up in both hardware and software!

DSC_0534.jpg

There’s a miniature trim pot on the left to set the contrast level. I haven’t yet added the transistor to turn the backlight on and off.

Note that with an MCP23017 chip there are 9 I/O lines available for other purposes. On the upcoming LCD Plug, I’ll probably use the smaller MCP23008 instead.

This particular setup works at the maximum I2C bus speed supported by bit-banging, which should be well over 1 MHz – I haven’t measured it. If the bus is long or is shared with slower peripherals it can be lowered to 400 KHz or 100 KHz by specifying an extra argument in the PortI2C constructor.

The sample code is available here. It will be integrated with the Ports library later.

PS. There are a few days left for the special offer in the shop. If you’ve ordered before or have participated on this weblog or in the forum, you can get 20% off until the end of September. Email me for a discount code.

Generalized LiquidCrystal library

In AVR, Software on Sep 26, 2009 at 00:01

Let’s dive into some C++ code for a change…

The Arduino version 0017 IDE has a nice library for driving standard character LCD’s, called… “LiquidCrystal”. The nice thing is that it mixes in the print() / println() functionality which is also used in the Serial library.

That makes it very easy to change a sketch to use either the serial port or the LCD screen to display results. Here’s how – let’s say you used this code in your sketch to print a value to the serial port:

Picture 2.png

The first thing to do is to generalize this slightly:

Picture 3.png

Functionally, nothing has changed. That’s the whole point, because you can develop and extend the sketch while testing everything via the serial port, as usual. Just use “Output” everywhere.

To change the output to the LCD, replace that “#define” line by the following lines of code:

Picture 4.png

This adds a bit of logic to easily switch between serial and LCD, without having to change a thing in the rest of the sketch. The “(2, 3, 4, 5, 6, 7)” parameters have to be set to the pin numbers actually used for your specific setup, of course.

So far, so good, although none of this applies to the I2C-connected LCD I’m working on. But by extending and re-organizing it a bit, it is possible to re-use most of the code of the original LiquidCrystal library.

The first thing I had to do was to rip apart the general and the pin-specific logic. That’s where C++’s abstract base classes and virtual member functions come in. I created a new “LiquidCrystalBase” class which has all the original code except for the pin-specific parts:

FlySketchExport.png

The “virtual … =0″ is C++’s funny way of saying it doesn’t need definitions for these three functions yet. The result is an incomplete class – you can’t create objects of type LiquidCrystalBase, you can only derive other subclasses from it. Tricky stuff, but bear with me…

Note that all the pin-specific member variables have been removed as well.

The next step is to re-define the original LiquidCrystal class in terms of LiquidCrystalBase:

Picture 5.png

If you compare this to the original code, you’ll see that most functions member definitions are missing. That’s because they have already been defined in what is now LiquidCrystalBase, and the new LiquidCrystal inherits everything from it.

What LiquidCrystal does add, is a definition and implementation for each of the virtual config(), send(), and write4bits() members. It is sort of “filling in” the missing functionality. So the result is… a LiquidCrystal class which does exactly the same as the original.

That seems pretty useless, but it isn’t – what we now have is a generic part and a specialized part. Which means it is now very easy to implement a variant which works exactly like the original, but going through the I2C port interface instead:

Picture 6.png

Nice. Only a little bit of new code was needed to create a completely different hardware interface which is fully compatible with the original LiquidCrystal class.

Here’s the original example, using this new LCD-via-I2C library:

Picture 8.png

Note that the I2C port is available as “myI2C” and can be shared with other devices by defining them here as well. You could even daisy-chain multiple LCD displays on the same port if you wanted to.

That’s all there is to it. The sketch code itself remains the same. Welcome to the world of abstraction, à la C++ !

Update – the final version and source code are described in this followup post.

Clock Plug v1

In AVR, Hardware on Sep 20, 2009 at 00:01

The Clock Plug adds a real-time clock to a JeeNode:

DSC_0507.jpg

A demo for setting it and reading it out follows:

Picture 2.png

Unfortunately, there seems to be a problem with it – it does not start up reliably, and connecting the backup battery makes it stop?

Oh, wait – the DS1307 is specified for a 4.5 .. 5.5V power supply, and I’m driving it from the 3.3V line! And yes, sure enough, it works fine when powered from 5V.

Whoops!

Time to look for another chip. Ah, looks like there is a pin-compatible one which does work at 3.3V – here’s a post from someone who fell into the same trap.

Update – the DS1340Z works fine, see this followup post.

Memory Plug v1

In AVR, Hardware on Sep 19, 2009 at 00:01

The Memory Plug adds flash memory to a JeeNode:

DSC_0505.jpg

This particular one has 2 different brands of 512 Kbit chips on it: a AT24C512B by Atmel and a M24512 by STMicroelectronics, for a total of 128 Kbyte. By fully populating it with 1 Mbit chips, this plug can contain a whopping half megabyte of memory :)

Here’s small sketch to test reading and writing to it:

Picture 1.png

A value will be incremented each second. When restarted, the value will continue to increase since the last setting, demonstrating the non-volatile memory. The demo uses I2C address 0×50 to address chip #0 – chip 1 #is at 0×52, chip #2 at 0×54, and chip #3 at 0×56.

This demo is available as the eemem example in the Ports library.

Here’s the plug hooked up to a JeeNode:

DSC_0506.jpg

This plug supports daisy-chaining of more I2C-type plugs.

So there you have it – a Solid State Disk!

Boot loader problems

In AVR, Software on Sep 11, 2009 at 00:01

Whoops – I messed up with several packages I’ve sent out to people. Ouch.

The gory details are in the discussion forum, but here’s the short version:

  • I’m shipping ATmega’s pre-programmed with the Arduino bootstrap and the RF12demo sketch. Mighty convenient, since it can get you going a lot quicker.
  • And to simplify my work I, ehm… sort of tried to automate it a bit.
  • So I burn the bootloader with the Arduino IDE and the burn the RF12demo sketch using “avrdude” from the command line.
  • Cool. Except that the second step undid the work of the first step… doh!
  • So I ended with ATmega328′s which have the RF12demo but no bootstrap loader.

It turns out that avrdude erases a chip by default when re-programming it. So the bootloader, which is loaded in high-mem, got cleared when storing the demo in low-mem. And of course that doesn’t show in a quick test: the demo on the chip, which I always check, works just fine. Which is why I sent out a few bad JeeNode kits and JeeLinks.

All it took to fix this was one lousy little “-D” command option for avrdude!

So now I’ve decided to automate all the way, and burn the fuses, the bootloader, and the demo sketch all in one go – from the command line.

Here’s what it takes – I have these files in one directory:

Picture 1.png

The hex files were copied from the Arduino “bootstrap” area and the RF12demo “applet” build area, respectively.

The makefile contains these commands:

Picture 2.png

So all I need to do now is to plug in the ISP programmer and put a fresh ATmega chip in its socket, then type “make”. This works for both the JeeNode and the JeeLink chips.

Easy… once done right!

Smaller still?

In AVR, Hardware on Sep 9, 2009 at 00:01

Now that the JeeLink is a reality, and SMD has become an option, I’m already wondering how far to take this…

Because, well, there’s this neat USB stick case available:

DSC_0491.jpg

I suspect that the same FTDI + ATmega + RFM12B as on the JeeLink can be fitted in there, but at the cost of omitting all expansion. No ports, no headers, no reset, nothing – but nevertheless an Arduino / JeeNode / JeeLink compatible unit.

There may even be room for a few Mb of flash memory. So this could be used as central interface to a PC/Mac, and it could collect data while the computer is off – as long as the USB port is on (a powered hub perhaps).

Would it make sense to create a separate unit for this? Just for the wow factor? Let me know, please…

Final JeeLinks

In AVR, Hardware on Sep 8, 2009 at 00:01

After the goof-up of not heating the boards up enough for lead-free solder, I simply re-did the reflow with a 250°C temperature profile. This appears to be near the limit of what my reflow grill can do, btw.

Here’s a fully assembled JeeLink:

DSC_0490.jpg

Note that I soldered all headers in, including two which aren’t supplied standard with the JeeLink:

DSC_0489.jpg

As shipped, the JeeLink comes with the 4 port headers, not yet soldered in.

While it still takes me quite a bit of time to assemble these JeeLinks, all four of the ones I did are now working (ahem, that’s a lie: I shipped two JL’s without proper testing… impatient as I was!).

So this story has a happy ending – the JeeLinks are ok now, it’s time to move on …

Meet the JeeBoard

In AVR, Hardware on Sep 2, 2009 at 00:01

I hate wires. Wires to power up stuff. Wires to transfer data. What a mess.

I just want to try out physical computing ideas on my desk, next to my (wireless) keyboard and my (wireless) mouse – while exploring the possibilities of hardware + firmware + software running on my “big” computer.

So here’s to scratching my own itch: meet the JeeBoard – a little 8×10 cm unit with no strings attached – heh ;)

pastedGraphic.png

A first mock-up with real parts, here still using a green JeeNode v2:

DSC_0469.jpg

On the left, a couple of demo plugs have been inserted. Those that use I2C can be daisy-chained.

One port is permanently hooked up to an I/O expander chip with 6 digital I/O lines for the mini-breadboard, 2 LEDs, and 2 pushbuttons. The on-board battery pack provides 3.6V with NiMH or 4.5V with alkaline cells.

The little overhanging board on top of the mini-breadboard “feeds” 8 wires into the center of the breadboard: +3.3V, ground, and the 6 general-purpose I/O lines.

I’m going to mess around with the layout a bit and explore some actual hookups before designing a real PCB for this. But even just looking at the mockup makes me want to start trying out stuff with it. Wireless, of course!

JeeNodes now with 328

In AVR, Hardware on Aug 31, 2009 at 00:01

Starting now, I will be replacing the ATmega168 by the ATmega328p in all future JeeNode kits:

DSC_0467.jpg

Twice the memory: 32 Kb flash, 1 Kb EEPROM, and 2 Kb RAM – and twice the creative fun!

JeeLink issues solved

In AVR, Hardware on Aug 23, 2009 at 00:01

It turns out that there were two problems with the new JeeLink boards, one major and one minor.

The reason why my assembled JeeLinks wouldn’t show up as USB devices is that the FTDI chip’s TEST pin was left floating instead of being tied to ground. It’s trivial to fix: a small dab of solder between pins 25 and 26 of the FTDI chip does the trick. Now all but one of my 6 JeeLinks show up as USB devices – yeay!

The second problem is not as critical: the +3.3V pin of all ports isn’t actually connected to anything… whoops. But this too is relatively easy to fix – a small wire from the VR output to the +3V pin on port 2 will fix it.

Thanks to Paul Badger of Modern Device and Marius Kintel for helping out and coming up with suggestions. I’m regaining my sanity now…

DSC_0449.jpg

In the coming week, I’ll send out new JeeLinks to everyone who pre-ordered these units. I’ve run out of SMD LEDs, so I have to replenish my (limited) supplies before assembling and testing more boards.

But rest assured, they work and pass all tests. There are several JeeLinks on my desk right now, each of them running as intended.

To celebrate this milestone, all JeeLinks will be shipped with ATmega328′s instead of 168′s – including all the pre-ordered units.

Update – the above two issues and their fixes have been documented here.

Lots of nodes

In AVR, Hardware on Aug 22, 2009 at 00:01

I’m gearing up to install over half a dozen nodes around the house to monitor temperature, humidity, light levels, and to detect motion:

DSC_0444.jpg

The plug at the bottom is a one-off to check out the connections for the EPIR version.

These are my last JeeNode v2 boards, salvaged from various experiments, with all their port headers replaced by the new 6-pin-female-up standard.

Given that these are v2 boards, I’m hand assembling the plugs to match the “old” port pinout. Beyond these, I’ll use the new v3 boards with a little pcb “room plug” to be created later.

Back to soldering a few more of these little sensor critters!

JeeLink status

In AVR, Hardware on Aug 21, 2009 at 00:01

The plot thickens… and I’m pulling my hairs out along the way.

The good news is that I have assembled 6 boards now, and they all behave in (nearly) the same way. The on-board ATmega is working and correctly running the blink test sketch installed when setting up the boot loader via ISP.

So the basics work. The voltage regulator is probably also ok.

The bad news is that none of these 6 boards is showing up as USB device. Whoops.

I’ve gone through a couple of build techniques, from reflow to hand-soldering, as well as various combinations. But after some obvious solder bridge removals and a few loose connections after hand-soldering, at least 5 of these boards exhibit identical behavior. I’m either getting it right or consistently doing something wrong.

Also found a problem in the PCB traces, i.e. a trace between 3.3V power and the 3.3V pins on all 4 ports is missing. But this is relatively minor – a tiny extra wire should fix that.

I’m at the point where I really need to step back to re-think what else could possibly be wrong. It must be some silly / stupid oversight… I’m still hopeful that the aha-slap-on-the-head-erlebnis will come soon.

Meanwhile, I’m also exploring some alternatives. Today, I visited a nearby “Fab Lab”, which has laser cutters, CNC routers, 3D-printers, and more such mind-blowing geek stuff. Absolutely fascinating – I’ll never look at an object in the same way again. Any object.

One of the things I wanted to try out is to create SMD stencils like the big boys do. A first trial on cardboard, paper, and 0.5mm polystrol came out as follows:

DSC_0443.jpg

The layer on top was my first attempt, using thin cardboard. As you can see, it’s not quite perfect since the holes are too large – there is no vector adjustment for the 0.1mm laser beam overhead. Then again, the plain paper example in the middle shows decent separation, and having paste overlap is not necessarily a problem.

I’ll try some more adjustments next time and will get a bottle of paste with squeegee to play around with this stuff. Who knows, maybe even a 1-time use plain paper sheet can work?

LED polarity

In AVR, Hardware on Aug 17, 2009 at 00:01

Ok, first puzzle solved. I had the two 0603 LEDs reversed.

The silly part is that I had actually built a test rig to make sure this wouldn’t happen:

DSC_0433.jpg

As trivial as it gets: a battery with a series resistor. By holding the SMD LED against two copper contacts it’s easy to check which side is which. Here’s a green LED lighting up:

frame3.jpg

Then I got confused and placed all the LEDs exactly the wrong way around – doh!

There are three copper pads. The middle one is PLUS, the other two are GROUND.

Ok, now the RX+TX LEDs blink a few times when plugged in. Onwards!

JeeLink build woes

In AVR, Hardware on Aug 16, 2009 at 00:01

Ok, I’m back. The Jee Labs blog resumes…

This first post is a progress report on the JeeLinks. Here are three partial builds (the bottom one has some hand-soldered parts, the rest use reflow soldering):

DSC_0432.jpg

I had to remove some solder bridges from the FTDI chips, but apart from that everything looks pretty tidy now. The JeeNode-based reflow controller is working very nicely.

Here are a couple of extreme close-ups:

frame1.jpg

frame2.jpg

frame4.jpg

frame5.jpg

Unfortunately, I’ve not been able to get any of these boards working so far. The FTDI chip ought to be visible as a serial USB port, even if the MPU isn’t working properly, but it isn’t showing up.

I’m probably missing something but for now it’s bad news. I’ll continue debugging this, of course…

Building the JeeNode v3

In AVR, Hardware on Jul 15, 2009 at 00:01

The v3 boards are finally ready! Here’s a step by step overview on how to assemble a JeeNode v3 kit:

DSC_0427.jpg

You’ll need some basic skill at soldering but don’t worry, as there are only a few parts to solder on. The best way is to start with the lowest-profile part, that way you can place things flat on the table and press down to keep the parts in place. So let’s start with the 10 KΩ resistor:

DSC_0408.jpg

Turn the board around and solder the leads:

DSC_0409.jpg

Then carefully cut them off:

DSC_0410.jpg

Continue in a similar vein with the four 0.1µF ceramic capacitors:

DSC_0413.jpg

Next the IC socket, which is a bit more work. The best thing is to solder two diagonally opposite pins, then check that the socket is pushed in all the way:

DSC_0414.jpg

If not, reheat and fix it. Then solder the remaining 26 pins:

DSC_0415.jpg

The 10 µF electrolytic capacitor is polarized – there is a “+” marking to indicate which way it should be soldered in. I normally bend the leads first and then make it lie flat on the board:

DSC_0416.jpg

Next the voltage regulator IC. This one needs special attention because it has to be mounted differently from what the marking on the board says. The reason is that the board was designed for an LP2950, but the kit includes an MCP1702 which has a different pinout. Here is how it should be mounted:

DSC_0417.jpg

The 16 MHz resonator is next, it’s the tallest part on the board:

DSC_0418.jpg

You’re almost there now. The radio module is a surface mounted module, which needs a slightly different approach. Put a bit of solder on one pad, then place the module over it and reheat to stick it in place:

DSC_0419.jpg

Once correctly positioned, add solder to each of the remaining pads to make shiny round joints:

DSC_0420.jpg

The 6-pin male FTDI connector can now be soldered on, I usually mount it sideways, but the choice is yours:

DSC_0421.jpg

A simple wire acts as antenna for the radio – attach it to pin 1 of the radio module. You can bend it as needed afterwards. I used a red wire, even though the kit probably has a yellow one.

One more step and you’re done: add the four 6-pin port headers.

Good, the soldering is over. Now bend the pins of the ATmega microcontroller slightly inwards so it fits into the socket. Make sure you only press it firmly down after all the pins are in the proper position.

Voilá! Your finished JeeNode:

DSC_0424.jpg

If you have a USB-BUB adapter, you can now plug it in and try out the board (note the 3.3V jumper – the JeeNode uses 3.3V logic signals). The ATmega that comes with the kit is pre-loaded with the RFM12demo sketch to get you up and running in no time:

DSC_0428.JPG

That’s it. Congratulations with your new JeeNode v3!

Reflow controller

In AVR, Software on Jul 14, 2009 at 00:01

Yesterday, I presented my new reflow system. Here’s the temperature graph from a sample run:

graph.png

The purple steps are the different phases:

  • Preheat (50) is whatever time it takes to reach 140°C.
  • Soak (100) is a 30-second temperature ramp up to 170°C.
  • Dwell (150) is defined as whatever time it takes to reach 220°C.
  • Reflow (200) is defined as 20 seconds at 220°C.
  • Cool down (250) is where the buzzer goes off and I open the lid.

The green bands indicate when the heater is on. The blue line is the target temperature which the system is trying to reach. The red line is the actual temperature. As you can see, the heater stops well before target temperatures are reached, and does a pretty good job of ending up in the desired range.

All in all, this appears to be ok. The 700-watt heater isn’t quite hot enough to ramp up 3°C/sec, more like 2°C/sec at best. Since the grill isn’t heating up quickly enough, the soak phase ends up taking 60 seconds instead of the planned 30, so the target stays pinned at 170°C a bit longer. This could probably be shortened by aiming directly for 170°C, but I don’t think this phase is critical. My only concerns are that it took about 80 sec to “dwell” from 170°C to 220°C and that the system is above 200°C for some 60 sec. This was shorter in other trials, but as you can see the heater is turning on a few times to nudge the system towards 220°C as things slow down a bit.

This plot was produced by a really nice free package for the Mac, called Plot (how original). The readings were obtained by logging the sketch output from the USB port and reformatting it to tab-separated numeric values.

Programming a 32-TQFP chip

In AVR, Hardware on Jul 11, 2009 at 00:01

With SMT parts, all sorts of things change. For the JeeLink, I’d like to set the fuses and flash the bootstrap code to the ATmega chip before soldering it to the board. Here’s how:

DSC_0399.JPG

This is a zero-insertion-force socket for 32-TQFP chips. You put the chip on, press down, and the whole thing presses these 32 gold-plated contact fingers onto the chip. There are several alignment edges in there making it relatively easy and quick. It’s no doubt made for machine operation but it works nicely by hand as well.

And here’s the result – an ISP programmer which works with the Arduino IDE:

DSC_0401.JPG

I’ll start flashing a couple of ATmega168 chips, in eager anticipation of the JeeLink boards…

IO Expander

In AVR, Hardware, Software on Jul 7, 2009 at 00:01

Here’s a way to expand the number of digital I/O lines on a port:

3686066291_f856efcb63_o This is a JeePlug filled to the rim with tiny components and connectors. It’s based on a PCA8574A I2C 8-bit I/O expander. Each of 8 pins can be used either as inputs or as “mostly” open collector outputs. See the datasheet for details.

Here’s the bottom side of the plug:

3686871488_b2366a7459_o

Crowded indeed!

And here’s a demo sketch called “expander” which blinks the eight LEDs connected between PWR and the respective I/O pins:

Picture 3.png

As with yesterday’s example, this is running the I2C at maximum bit-banging speed, and seems to work fine. It’s used to make 8 leds blink:

3686871410_0e325c3a2b_o

The connector block on this plug has 8 sets of three connections: GND, PWR, I/O. Note that PWR is connected, not +3.3V. The reason for this is that I’d like to try driving a bunch of servos from this plug one day – it’ll load the JeeNode down a bit but it should be feasible.

The “expander” sketch has been added to the Ports library and is available as ZIP file and in subversion.

External memory

In AVR, Hardware, Software on Jul 6, 2009 at 00:01

For one of the projects in the Jee Labs, I needed a bit more “permanent” memory than the ATmega’s EEPROM or even flash could provide. Here’s what I came up with:

3683813851_d524fedae2_o

That’s a 64 Kbyte AT24C512B serial EEPROM memory which talks via I2C.

It takes only 4 wires to hook this thing up:

3684626986_c2c8f1119c_o

And this is the mess you get in when you don’t have the right connectors and need to deal with older boards:

3683813971_e00e924cb0_o

That’s the “regret plug” mentioned a few days back, to turn the downward pointing male header into an upward pointing female header, plus a “cross-over plug” to let me wire this thing up for the new JeeNode v3 pinout, yet use it on a (minimally populated) v2 board. Yuck!

Lesson: think about headers before deciding how to solder them on …

All future JeeNodes will be supplied with 6-pin female headers for the ports. Soldering them on pointing up is probably most convenient: it lets you stick little LEDs and wires in there, and JeePlugs can be placed pointing upright – such as this memory.

Back to the memory expansion. Here’s a test sketch:

Picture 5.png

Sample output:

Picture 4.png

As you can see, the count did not start with 255, as it would have if the EEPROM had still been empty. The JeeNode was powered off in between to demonstrate data retention.

This example code runs at full bit-banging speed – seems to work just fine.

The “eemem” demo sketch has been added to the Ports library and is available in this ZIP file as well as here.

There you go … a whopping half million extra bits of permanent storage :)

Ligthy power save

In AVR, Software on Jul 5, 2009 at 00:01

Getting the power consumption down of yesterday’s “Lighty” example turns out to be quite a challenge.

One thing to do is to separate out the logic for enabling the different sensors, and extending it to also support disabling all of them:

Picture 3.png

Powering down completely works best when all internal peripherals are also turned off, as implemented in the following code:

Picture 4.png

Now the trick is to enable some interrupt source to take us out of this deep sleep phase again. This could be the ATmega watchdog, but the radio watchdog uses even less power, so here’s how to stay off for about 4 seconds:

Picture 5.png

So far so good. This disables all power consuming sensors and internal circuits, preps the radio to wake us up in 4 seconds, powers off, and then reverses the whole process.

Bug there is a bug in all this – somewhere… From some earlier experiments, I would have expected to see a power draw of a few microAmps with this code. But for some reason, it never drops below 2.7 mA, i.e. still “burning” 1/10th of full power!

I haven’t been able to figure out yet where these milliamps are going :(

For the sake of argument, let’s assume this works properly. Then the next problem will come up, which is that measuring and sending packets every 4 seconds drains more power than I’d like to. It takes several milliseconds to measure all readings and send out a packet. But who needs readings every 4 seconds?

So the solution to this is to just sleep a bit longer, using the 4-sec wakeups to quickly read-out some sensors, and calculate their averages. Here’s is the final loop of the power-saving “LightySave” sketch:

Picture 8.png

This will integrate readings for 75x 4 seconds, i.e. 5 minutes, and then send out a single packet. Note how the power-hungry radio module is only enabled at the very last moment. All we have to do is make sure it’s ready to send, then send one packet, then wait again until the send is complete.

Then the loop restarts, sleeping in low-power mode, etc.

Only issue is to find out where the 2.6 mA are going! I’ll try to figure this out, and will post here once fixed …

Lighty

In AVR, Software on Jul 4, 2009 at 00:01

Let’s call yesterday’s mystery JeeNode “Lighty” from now on. As promised, here is the first sketch:

Picture 3.png

LightySerial reads out several sensor values each second and dumps the results to the serial port. Plain and simple – using the Ports library for most pins and Arduino’s analogRead() for reading out voltage levels on A4 and A5.

Sample output:

Picture 4.png

FYI, all the Lighty sketches are available for download as a ZIP file.

Now let’s turn that into a wireless version using two JeeNodes. The first step is to separate the measurement and reporting sides of things.

Here is the main code of LightyTransmit, causing it to send out its readings once a second:

Picture 8.png

It puts all values into a structure defined as follows:

Picture 6.png

… and then sends that off to the broadcast address, i.e. whoever is listening. No acknowledgements are used. If the packet arrives, great, if not then the next one will.

The receiver then takes it from there, here is the entire LightyReceive sketch:

Picture 7.png

Note that the Ports library is not needed here since the receiving JeeNode does not use ports, it merely picks up packets and reports them on the serial line.

That’s basically it. Each of these sketches compiles to some 3 .. 4 Kb code.

We’ve got ourselves a Wireless Sensor Network!

LightyTransmit uses about 24 mA. Tomorrow, I’ll go into reducing the power drain, because Lighty’s tiny 20 mAh LiPo battery won’t even last an hour this way.

Mystery JeeNode

In AVR, Hardware on Jul 3, 2009 at 00:01

Some more pictures from yesterday’s puzzle…

3681641100_900fdf0f6e_o

Added a second LDR on the left and a DS18B20 1-wire temp sensor. A 4.5V @ 35mA solar cell has also been soldered in.

The sensor is a TSL230R light sensor, as Milarepa correctly commented:

3679117790_f89f0caa7d_o

It has one frequency pulse output, with two other port pins used to control sensitivity (1x/100x) and frequency divider (2x/50x). The fourth I/O pin is used as power supply for the chip, so that it can be turned off completely in sleep mode.

Here’s the whole assembly from the side:

3681641152_3a6d49194e_o

And here the complete JeeNode (using a different solar panel which turned out to be too weak):

3679151344_f871517b7c_o

So what does it do? And what is it for?

Well, two things really – but I’ll be the first to admit that this isn’t truly general purpose and unlikely to be very meaningful for anyone else.

The first use is to help me take better pictures. The photos on this weblog are all taken using nothing but a white sheet of paper and plain old-fashioned daylight. Benefits are that it’s free and abundant, it needs no space for a light-box setup, and it tends to produce beautiful images.

The problem which you may have seen on this weblog, is that daylight ≠ daylight. Sometimes it’s too dark outside, and sometimes the light is too harsh. Worse still, many of the photos end up with a blueish tint. I’m having a hard time predicting this, so it seemed like a nice idea to just throw a bunch of light sensors together and try to correlate this to picture quality over a few weeks time.

The other purpose of this unit is to act as test-bed for long-term solar-powered use. That means getting the power drain down to very low levels of course. But I also added the ability to read out the voltage of the solar cell and of the battery, as well as temperature (solar cells are sensitive to that). And LDRs facing opposite directions, to try and detect sun vs. cloud cover weather info.

This seemed like an excellent project for JeeNodes and JeePlugs. Once it’s working well enough – auto-ranging the light sensitivity and such – I intend to put this up on the roof and just let it send out packets every 5 minutes or so, day and night. This will make an excellent yet non-critical test setup as well as allow me to track solar intensity over the entire year. Think solar panels…

Tomorrow I’ll post several sketches: one showing how to read out everything and report it over the serial FTDI connection, then two more to show how to turn this into a send/receive solution with two JeeNodes, and the last one showing how to get power consumption down.

Stay tuned!

Breadboard limits

In AVR, Hardware on Jun 29, 2009 at 00:01

Here’s something which isn’t a good idea with breadboards:

Breadboard limits

I used a socket with wire-wrap pins to be able to connect a few wires yet still be able to use the whole thing in a breadboard. If you look closely, you can see that the 5-pin metallic connectors inside the breadboard are pushed out – making the adhesive separate from the rest. Whoops.

Wire-wrap pins are clearly too thick to be pushing into breadboards…

Arduino Mega + shield

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

Got myself an Arduino Mega – an Arduino on steroids:

Arduino Mega + shield

Compatible with current Arduino shields, but extended to support a lot more pins.

Ordered it from NKCelectronics, along with their new extended shield for it:

Arduino Mega + shield

There’s a lot of them pins on there…

I decided to attach a solder-less breadboard to it, to be able to experiment with projects which need more I/O lines or comms than a standard Arduino:

Arduino Mega + shield

It fits, but just barely. Had to cut off the little hooks on the plastic. Using a breadboard in this way covers up all the identifying pin texts on the silkscreen, alas.

Actually, it doesn’t quite fit – couldn’t get all headers on:

Arduino Mega + shield

I’m using a mix of 4- and 6-pin headers, since I had them lying around. As you can see, the last 4-pin header makes it impossible to fit that other header in, so I left off pins 22 and 24. It might have worked with an 8-pin header i.s.o. 2x 4-pin.

And here’s the final “stack”:

Arduino Mega + shield

Conclusion so far? I’m not sure this is the way to go. I think it’s an abomination, to be honest. There are so many pins to connect that the two boards are very hard to separate once stacked up. You don’t want to pull too hard on one side and end up with bent pins when the thing finally comes apart.

And how often do you need that many I/O pins one one fixed board setup? Sure, the ATmega1280 has 128 Kb of flash memory, which is plenty to get fairly complex sketches going. But it also builds on that trend of using stacked shields – and let’s face it: a single shield is often great, but with 2 or 3 you end up with pin allocation nightmares (for designers) or conflicts (for users). Multi-stacking is tricky, requiring special stacking headers.

Nah, I’d much rather go with ports, and extensions for that, and connecting two or three independent units over a bus if need be. But then of course I would, that’s why I went for such an approach with JeeNodes after all.

Meet the JeeLink

In AVR, Hardware on Jun 24, 2009 at 00:01

I’m proud to announce a new board next to the JeeNode, called the JeeLink. Yes, there’s a pattern in the naming choices made for products on this site.

The JeeLink is very much like a JeeNode, but in the format of a USB stick and with a few small differences listed below. Here’s the layout:

Picture 2.png

As you can see, the JeeLink has basically the same headers as the JeeNode, but with a USB plug in the place of the JeeNode’s FTDI connector.

The JeeLink is useful in two different ways, I think: first of all, if you have a couple of remote JeeNodes, you’ll probably need a central node as well to tie the whole network to a personal computer. The second use case is that it can be used as a JeeNode with built-in FTDI-to-USB conversion – which is exactly what it is, technically speaking.

A major difference with the JeeNode also, is that the JeeLink is built with SMD parts. The intention is to make it available in pre-assembled form and as bare board. No kits with parts – that’s reserved for the JeeNode since I don’t want to stretch myself too thin.

There will be a more detailed description of the JeeLink once it is ready and working, but here’s a first overview:

  • the dimensions of a JeeLink are slightly different, obviously
  • the I2C and SPI/ISP headers are not in exactly the same position as on the JeeNode
  • there’s no battery connector (who needs one with USB?)
  • the FTDI-type USB connection includes two on-board activity leds

So there you have it – a new descendant in the Jee family. With on-board RFM12B wireless radio of course, and 4 ports to connect absolutely anything you like to. Just like the JeeNode.

The JeeLink is the initiative of – and was designed in collaboration with – Paul Badger of Modern Device. We’ve been having a heck of a time together, hammering out all the details and making sure the result will be as good as we can possible make such a new concept. I’m proud of the result, and hope you’ll like it as well. Should have properly working JeeLinks in my hands in July, assuming Mr. Murphy doesn’t barge in to spoil the party.

More SMD stuff

In AVR, Hardware on Jun 21, 2009 at 00:01

My adventures in SMD miniaturization-land continue:

SOIC chips

Those are two Atmel chips – an ATtiny85 (SOIC-8) and an ATtiny84 (SOIC-14).

Compared to 0603 parts, these are actually quite large. The distance between the pins is 1.27mm (0.05″), half of regular through-hole parts.

But you do need fine tweezers, and a ZIF socket to flash them or try them out without soldering is also nice:

SOIC chips

The lid snaps down, making a firm connection with each of the 14 pins.

Hm, I see now that the SOIC-8 dimensions are a bit wider than the SOIC-14 package. So the smaller package doesn’t fit in this (pricey) ZIF socket.

So not only is this stuff small – it’s also easy to overlook such differences!

Fortunately there are datasheets.

JeeNode headers

In AVR on Jun 17, 2009 at 00:01

More details about how to connect stuff to any of the four “ports” of a JeeNode. Each port has this pinout:

A few notes:

  • the DIO pin is for digital I/O only, the AIO pin can be for analog in or for digital I/O
  • a port has six pins, with both 3.3V (VCC) regulated and +V (PWR) unregulated power
  • with just a 4-pin header on pins 2..5, you still get the most important pins
  • if all you need is a single I/O line, you could even use a 2-pin header on pins 3..4
  • the IRQ signal is shared between all ports

Another thing to note is that the ports all have an identical pin-out, when looking from the outside of the board:

(the above two diagrams are from the JeeNode v2 PDF documentation)

And then there is the aspect of distances between the port headers:

headers.png

This is where the story gets a bit fuzzier:

  • JeeNode v1 uses A and B as distance between the port headers
  • JeeNode v2 and v3 use A and D as distance between the port headers

If you want your plugs to remain usable on all future JeeNode designs, then you will need to make sure that they can deal with separations between the headers as small as C and E.

I’m not saying there will be such JeeNodes any day soon, I just want to keep the option open to go there.

Prototyping with JeeNodes

In AVR, Hardware on Jun 16, 2009 at 00:01

Here’s a little board I used for a while with a JeeNode:

Pulse prototype

It has 6 female header underneath, which get plugged into a JeeNode with its header pins sticking upwards. It has an LDR, a diode I tried to use as voltage reference, a plugged-in SHT11 temperature / humidity sensor, a 3-pin connector to plug in a Parallax PIR sensor, and a 2-pin header (top right, behind the SHT11) which was used to connect a couple of 1-wire temperature sensors).

There are a couple of issues with this, though some are probably unavoidable for such one-off / ad-hoc solutions. For one: it’s a bit of a mess. One reason is that with this setup the 1-sided perf-board I used has to be mounted upside down to allow soldering in the female headers. That’s awkward, because it means you have to “surface mount” most components.

One option is to use perf-boards with plated-through holes. These are several times more expensive than single-sided boards, though. But more importantly, cheap one-sided boards are often based on “Pertinax” (SRBP) which is a lot easier to handle than FR-4 epoxy: you can simply break them on a sharp edge, with the row of holes acting as perforation.

The other problem with putting everything on a single board is reduced flexibility. In this case I had to add a second 4-pin female header on top to accommodate the SHT11 plug I had already made – which would have fitted just as well directly on the JeeNode.

One nice benefit of per-port prototyping is that it is easy to re-use this stuff in different configurations. In fact, as with the SHT11 plug showing in the picture, that’s precisely what happened.

So I’ve been thinking a bit about ways to use JeeNodes for experimentation. Which happens a lot around here. One simplifying convention is to always use male headers on the JeeNode. That leaves essentially two choices (ignoring sideways mounting for now):

Picture 1.png

I’m thinking of having a bunch of, ehm, “JeePlugs” made: tiny boards with a 6×8 “prototype” area containing plated-through holes, plus a 6-pin female header and connecting pads. Three ways to use these:

Picture 2.png

You’ll need male headers for use with a breadboard, but I’m assuming you’ve used the breadboard to figure out the connections with the bare parts, so this post focuses on using female headers for the JeePlugs.

In all cases, the orientation of the pins is the same, so once you have a plug set up with stuff on it, you could still use it in multiple ways. And plug them onto any of the 4 ports at will, of course.

One last refinement is to make these plugs around 20 x 25 mm – i.e. long enough to optionally plug onto two ports in that inverted 3rd example shown above. Here’s a first design:

Picture 3.png

It’s really not much more than a tiny perf-board of the proper size for JeeNodes with a couple of doubled-up connections. Using plated-through holes so components and wires can easily be soldered from either side.

The plugs are not labeled with pin numbers or signal names, because those depend on the orientation in which you use them. For that, use the markings on the JeeNode itself (starting with v3, that is).

These JeePlugs only makes sense in larger quantities, so I haven’t yet decided whether I really want to order them. I sure could use some, but it wouldn’t be practical to have less than a hundred or so of them produced.

New JeeNode v3 design

In AVR, Hardware on Jun 14, 2009 at 00:01

Here’s an – improved! – board design for the JeeNode:

Picture 1.png

The main two changes are: labeling of all the components and pins, and a change in the ISP/SPI pin header (pin 1 is now also pin 1 for ISP). All connectors are in exactly the same place, but the board is a tiny fraction wider.

For details, see the EAGLE files (jee-pcb-011.sch and jee-pcb-011.brd). The PDF of the schematic shows that the functionality is unchanged – other than the ISP/SPI header pinout change, this board should be 100% compatible with the JeeNode v2.

The v3 board was designed in collaboration with Paul Badger of Modern Device, to whom I’m most grateful.

I’ve just ordered a batch of these boards. Should be able to report here in ten days or so as to whether they are working properly. Let’s hope so!

JeeNode v2 kit notes

In AVR, Hardware on Jun 11, 2009 at 00:01

Just to make sure I didn’t forget anything – here’s the contents of a JeeNode v2 kit with parts:

JeeNode kit contents

For those of you who are about to receive the kits: they should match what’s shown above. If I forgot anything please let me know and I’ll take care of it right away.

The ATmega168 is pre-flashed with the standard Arduino boot loader and the RF12demo sketch.

As for assembling these kits, the main thing to keep in mind is the orientation of a few components and the ways things should be hooked up – see the recent post and the reference doc and close-ups on this site such as this one:

JeeNode v2

These are first-generation boards without silkscreen (I’m still learning about all this PCB design stuff!), although there are tiny markings on the top copper layer if you look really closely.

One important detail I forgot about is the antenna: for these 868 MHz units, I use a piece of 85 mm insulated wire. It needs to be connected to the ANT pin, which is the one in the corner as you can see in the above picture. You need an antenna, I’ve not been able to bridge even the shortest distance without one.

A tale of stand-alone builds

In AVR, Software on Jun 10, 2009 at 00:01

The JeeBot Duo runs off a Baby Orangutan controller by Pololu, which isn’t entirely compatible with the Arduino IDE. Well, it can be made to work with it but in this case it looks like just using avr-gcc and avrdude directly from a Makefile would be just as simple.

Boy, was I wrong.

I’ve spent nearly two days trying to understand why this thing wasn’t working. Or rather, it was. Sometimes. But with resets all the time, and the watchdog being tripped even though I never enabled it.

One problem is that the BOC has no other signaling on board than a single LED. So first thing was to set up serial communication. Well, that worked. But then it didn’t. And then things got really totally erratic…

The problem turned out to be in the highlighted portion of this Makefile:

Picture 2.png

Without the $(CFLAGS) on the linker line, everything   s o r t   o f   works.

Until you start using RAM for data, such as statics/externals and strings. Or C++ classes inside the Pololu libraries for example.

Then the system goes berzerk. Because the linker wrongly assumes that RAM starts at 0×0060. So strings and data variables end up being written into the extended I/O area. Want to know what’s at address 0×0060? The watchdog control register.

Anyway. It took me many hours of complete despair to figure this one out. Salvation came from “avr-objdump -h”, which clearly showed that the “.data” segment was in the wrong place compared to an Arduino sketch. With many thanks to Ben @ Pololu for nudging me towards the solution and for patiently responding to my emails, some of which must have been pretty weird…

I think that what baffled me most of all was the fact that the simplest bits of code worked just fine. You can get a lot of little tests going without ever using strings or allocating static variables. And the failures being random resets (from the watchdog) kept me looking for hardware problems – silly me.

At one point, I had figured out the incorrect starting RAM address and added this linker option: “-Wl,-Tdata,0×800100″. Unsure why it had to be specified but it got past the most erratic behavior.

But then interrupts wouldn’t work. Disassembly (with “avr-objdump -D”) showed that the generated code was using an incorrect set of vectors. And then it dawned on me: the $(CFLAGS) includes “-mmcu=atmega328p” which the linker needs to put things in the right place and to use the right vectors.

Doh. Totally obvious in hindsight.

Now I can finally generate and upload code without having to go through the Arduino IDE.

Building the JeeNode

In AVR, Hardware on Jun 9, 2009 at 00:01

Now that a few people have started building JeeNodes for themselves, here’s a close-up:

MCP1702 detail

Make sure you put that MCP1702 voltage regulator in exactly as shown. That’s the TO-92 package in the middle.

The board was intially designed for an LP2950, which has a different pinout. The MCP1702 does not have ground in the middle, hence the twisted positioning.

Note also how I use flat 6-pin headers, even for the FTDI connector. All the header pads are large enough to solder them on in any orientation you like.

FWIW, I’ve still got 9 JeeNode boards left (and probably all the parts needed as well). So if you want ‘em let me know. I can send bare PCBs for €5 each. Or the PCB with all parts including 868 MHz radio and pre-flashed ATmega168 for €17.50. Shipping included if you order more than one.

JeeBot Duo schematic

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

Heh – my most “sophisticated” robot so far. Here’s the plan for the electrical hookup of the JeeBot Duo:

Picture 1.png

There’s quite a bit of functionality in there, all the way to an on-board LiPo battery charger. Other things to note: the Baby Orangutan controller (BOC) can shutdown all power (to avoid running down the battery too far) and the JeeNode can reset the BOC if need be.

The two processors communicate with each other via an I2C bus. The on-board FTDI header connects to the BOC serial port and supplies power to the LiPo charger. The FTDI header on the JeeNode can be used for monitoring, control, and uploading, as usual.

JeeBot Duo – in progress

In AVR, Hardware on Jun 7, 2009 at 00:01

To continue this bot-craze, here’s another design, the JeeBot Duo

More JeeBots in progress

This design is considerably more advanced. From left to right:

  • two 50:1 micro motors with wheels and encoders (Pololu)
  • a 6-pin FTDI header
  • the Baby Orangutan 328 motor controller (Pololu)
  • underneath: a low-voltage boost regulator (Pololu)
  • at a 45° angle: IMU board with 2-axis accelerometer and gyro (SparkFun)
  • a JeeNode v2 with on-board RFM12B 868 MHz radio module
  • underneath: a 860 mAh LiPo battery

It’s called a JeeBot Duo because there are two processors on board. The plan is to put the self-balancing smarts in the Baby Orangutan – which has all the hardware needed to connect to all sensors and motors. The JeeNode is available for telemetry, remote control, and perhaps to connect to further gimmicks later on.

Initial tests show that the motors have plenty of speed and torque, and draw 40 .. 300 mA each, depending on load. The boost regulator can produce a constant 5.4 V for the motors, while the battery level gradually decreases. There’s a tiny bit of slack in the gears, which translates to about 1 mm of slack/travel on the wheels.

The remaining space is for a compass module and an on-off switch. That makes this a relatively complete autonomous unit, able to sense its vertical position and change, as well as the distance traveled and the compass heading. With the proper software, it should one day be able to respond to commands such as “go 2 meter north”, or “drive around in a 1-meter circle”.

But that’s a long way off. Lots of tuning and software development will be needed to get there…

JeeBot Mini – in progress

In AVR, Hardware on Jun 6, 2009 at 00:01

Here’s a second design, called the JeeBot Mini – no less:

More JeeBots in progress

The first JeeBot used servo’s but that’s not really such a great fit for self-balancing. This one uses miniature (and pretty weak) motors, directly driven by the ATmega’s I/O pins. The small socket is for the same Memsic 2125 accelerometer as on the original JeeBot, but placed at a 45° angle to use both X and Y axis together.

On the right is a tiny 100 mAh LiPo battery – plenty for simple trials. No gyro, no regulator, and no resonator (so far). No JeeNode either – just a serial FTDI interface and a bare ATmega168 chip running the LilyPad bootstrap @ 8 Mhz, straight off 3.7 V from the battery.

I’m waiting for some wheels for this thing. Am not sure the wheels will turn fast enough to regain balance once detected. If not, maybe raising the center of gravity by extending the “chassis” upwards will help. Or bigger wheels. Or both. Or maybe the design choices are hopelessly wrong already… we’ll see.

Telemetry

In AVR, Software on Jun 4, 2009 at 00:01

The JeeBot now has telemetry functionality, continuously sending real-time process data by wireless for analysis and display on a desktop PC.

It was quite simple to add this: send a buffer with the latest data every 200 msec, using the RF12 driver. No acks, no checking – the receiver grabs as much as it can off the air, and simply ignores invalid and lost packets.

Here is the essence of the code added to the JeeBot loop, which runs every 20 ms – in lock-step with the pulses it generates to control the servos:

Picture 2.png

A second JeeNode acts as receiver to pick up these data packets and transfer them to the serial port – here’s the complete sketch:

Picture 3.png

Sample output:

Picture 1.png

These values show what the JeeBot is doing while running on its own internal batteries … i.e. wireless telemetry in practice!

The next step will be to analyze and visualize this data to help me properly tune the PID control parameters. That’s more work.

Minimal motion

In AVR, Hardware on Jun 3, 2009 at 00:01

Now that I’ve been bitten by the robot bug, it’s hard to stop. Wanted to experiment with a minimal setup for self-balancing:

Minimal motion

These are 1.5 .. 3V motors with 1:96 gears from Conrad. What’s special about these is that they only need some 20..30 mA current, which is sort of within the direct-drive capability of an ATmega168. That means 2 I/O pins per motor can be used to create an H-bridge without any further electronics.

Here’s a small sketch to drive these from a JeeNode:

Picture 1.png

A couple of details show that this really is pushing the limit: without the capacitors, timing becomes erratic. Also, the delays between reversals seems to be needed to bring the motors to a stop. I suspect that there’s still some very bad stuff happening due to inductive kickback, so diodes to ground and VCC are probably required to avoid damaging the MPU chip.

But it does run. It’s all driven off a tiny 100 mAh LiPo battery in that picture above, and it kept going longer on a charge than I was willing to wait for. Probably over an hour – total power draw is in the 50 .. 60 mA range.

Anyway, this is even more spielerei than the JeeBot. Just wanted to find out whether these components might be used for a little baby balancer one day. This would also require wheels and at least an accelerometer.

Vertical JeeBot

In AVR, Hardware on Jun 2, 2009 at 00:01

Here’s a first example of the JeeBot standing upright:

Vertical JeeBot

When held upright on startup, it actually stands on it’s own two wheels very calmly, compensating immediately for slight imbalances for a couple of seconds. But beyond a minor error, it fails to regain its balance – so my hands are right outside the picture, ready to catch it :)

Have added a Memsic 2125 accelerometer to provide a sense of what’s up. It’s connected to port 1, with the X and Y axes each producing pulses at around 100 Hz.  The gyro kicks in when it’s falling either way. Having both near the center of gravity helps, as the counter force of the servo won’t disturb the accelerometer as much.

Here’s the main code. It has a crude low-pass filter and PID control loop:

Picture 1.png

The parameters were set using (much) trial and (much) error. I’ll clearly need to learn more about PID control to make this thing properly self-balancing. The loop runs 49 times per second on average, which also happens to be the servo pulse rate – maybe there’s some accidental interaction with the SoftwareServo library.

But still, a lot better than I had expected after one day!

Horizontal JeeBot

In AVR, Hardware on Jun 1, 2009 at 00:01

The JeeBot has made its first explorations, using a Nunchuk controller:

JeeBot baby steps

It drives on two wheels plus a coaster ball to support the batteries – although not very fast and veering slightly to the right. It will also turn, by rotating the servos in opposite directions. The batteries push down hard on the coaster ball, making the wheels slip when turning if the surface is not hard enough. The control mechanism is somewhat proportional, although it seems to work best by just pushing the joystick to its limits.

Here’s the current primitive control loop:

Picture 1.png

Some more close-ups:

JeeBot baby steps

From left to right: the Wii adapter, batteries with coaster ball underneath, on-off switch, JeeNode, and the edge of the servos.

Not much wiring needed to get it going:

JeeBot baby steps

The two resistors divide the battery voltage in half, so it can be measured by an ADC pin. Note the use of wire to “bundle up” the Nunchuk I2C “bus”.

Port layout so far: 1 = unused, 2 = left servo + battery level, 3 = right servo, 4 = Nunchuk via I2C.

I’ve also mounted the gyroscope (not connected yet) in the proper orientation to sense rotations around the wheel axis:

JeeBot baby steps

Will need to add an accelerometer as well, no doubt.

The center of gravity is just about on the power-switch, between the battery pack and the JeeNode. Which is quite low when this thing is placed upright, not sure the servos + control loop will respond fast / accurately enough for balancing.

Current consumption is around 30 mA when idle, 160 mA with wheels turning freely, and up to some 300 mA under load – these 4 NiMH batteries give about 5.2V under no load when full, but I’ve seen it drop to 3.7 V under load after a bit of use – not so good…

Yet more AVR size comparisons

In AVR, Hardware on May 30, 2009 at 00:01

Ok, let’s finish off what I started yesterday – here are yet more tiny AVR boards:

Another AVR board line-up

From left to right:

Here is the previous line-up again for comparison:

More AVR size comparisons

See yesterday’s page for a description of what is what.

If you look closely, you’ll see that yesterday I used a JeeNode v1 board.

Update – same photos, higher resolution: first, second.

More AVR size comparisons

In AVR, Hardware on May 29, 2009 at 00:01

Here’s another comparison of little AVR-based boards:

More AVR size comparisons

From left to right:

Unfortunately, I forgot to show the RBBB (Real Bare Bones Board), and the new Strobit unit (also shown here) – they both deserve a place in this line-up.

These little boards are not entirely equivalent, but all of them are great for AVR-based fun DIY projects.

Measuring the AC line frequency

In AVR, Hardware on May 28, 2009 at 00:01

There is an interesting site in the UK called Dynamic Demand. The idea is to let the 50 Hz power-line frequency vary slightly to indicate the current load of the entire grid. Simple line-monitors can then track this locally and respond by voluntarily shutting down some power consumers (i.e. turning off freezers, A/C units, or electric heaters for a little while). With a bit of collaboration, the grid would then presumably recover as the load eases off – and overcome these demand peaks. I love the idea, it’s so beautifully simple.

The Dynamic Demand site also has a page showing the current frequency online, here’s a snapshot:

Picture 2.png

I don’t think this mechanism is being used – or even considered? – in the Netherlands but I couldn’t resist setting up a JeeNode to monitor the frequency myself. The sketch:

Picture 3.png

What it does is measure elapsed microseconds between 100 transitions of its input signal against the 1.1V bandgap reference voltage. That’s 50 ups and 50 downs, which should take 1 second.

The AIO pin of port 1 is connected to a rectified but unregulated AC voltage, coming from a 17 VAC power brick through a diode plus 1:10 voltage divider. The signal looks as follows:

ac.png

And here’s some sample output:

Picture 1.png

Note that for stable and repeatable results, the JeeNode will need to be fitted with a crystal as clock.

The accumulation over 100 transitions is a simple way to average all the pulse durations. Most of the code then tries to present a nice result, with sufficient accuracy to display minor variations.

Nice and tidy.

Meet the JeeBot

In AVR, Hardware on May 27, 2009 at 00:01

Here’s a fun new project, the JeeBot:

Meet the JeeBot

A little platform with two continuous-rotation servos, a JeeNode, and a (4x AA) battery pack. It’s all mounted and fixed together with what I had lying around: strong epoxy-based perf-board and lots of fasteners.

The electronics isn’t “quite finished” as you can see:

Meet the JeeBot

The JeeNode can be removed. There’s a small slide switch on the side to turn on power.

First task would be to get this thing rolling and steering – adding a small coaster of some sort on the right side under the batteries, to keep this thing off the floor.

The more ambitious plan is to make this thing stand upright and self-balance… who knows, one day, maybe it’ll be able to walk roll on two feet wheels?

RF size comparison

In AVR, Hardware on May 26, 2009 at 00:01

Here are four very similar wireless AVR-powered solutions side-by-side:

RF size comparison

From left to right:

  • Arduino Duemilanove with XBee shield (ATmega168/328) – 2.4GHz
  • JeeNode with RFM12B (ATmega168/328) – 433/868/915 MHz
  • Strobit board with RFM12B (ATmega168V) – 433/868/915 MHz
  • Busware CPM with CC1101 (ATtiny84) – 868 MHz

The XBee has more software on board, giving it more functionality. The CPM module, which is only marginally bigger than a DIL-14 chip – including antenna! – does not come with software loaded AFAIK, but there is open source software available for it. The middle two boards are compatible with Arduino IDE “sketches” and support the RF12 driver library by yours truly.

Gyro sensor

In AVR, Hardware, Software on May 25, 2009 at 00:01

Here’s the LISY300AL gyro sensor, mounted on a Sparkfun breakout board:

Gyro sensor

The sensor is not extremely sensitive, but works at 3.3 V. It has a single analog output, so readout is trivial:

Picture 1.png

Sample output:

Picture 2.png

The readout changes as this setup is rotated around the horizontal plane. Looks like the self-test (pin 5) to ground can be omitted, btw.

One (tiny!) step closer to a self-balancing bot…

Update – the Segwii website is a fantastic resource on how to accomplish self-balancing in a fairly similar setup.

Servo fun

In AVR, Hardware on May 24, 2009 at 00:01

Here’s some fun with a servo:

Servo fun

A slider drives the two servos in opposite directions, so you can make this thing turn on the spot.

Here’s the sketch:

Picture 1.png

Had to use SoftwareServo instead of the Servo library which comes with Arduino IDE 0015 – which didn’t work for me.

Turns out that only pulses from 1.4 to 1.6 msec actually have any effect on the speed of the servos, the rest of the 1.0 .. 2.0 msec range just makes them run at full speed. These ara Parallax (Futaba) Continuous Rotation Servos.

Note that the servos are driven from the PWR line, i.e. the full 5V – but the servo pulses are 3.3V, like the rest of the JeeNode.

It’d be nice to use a Wii Nunchuk controller as input. Even more fun would be an accelerometer / gyro combo to turn this thing into a self-balancing bot …

New RF12 sleep support

In AVR, Software on May 23, 2009 at 00:01

The RF12 driver has been extended to support power down as well as wake-up.

This example uses the RFM12B wake-up timer to generate an interrupt in about 1 second, then powers down, then leaves the radio off once power is back up:

Picture 3.png

That last call is important, because otherwise if the system happens to power up due to some other trigger, then the wake-up interrupt may happen later and cause problems. This way, regardless of why the system came back up, we make sure that the RFM12B wake-up interrupt stays off. The radio is still off at this point.

The argument to rf12_sleep() is a time value, in units of 32 ms. The maximum value is 127, i.e. 4 about seconds between wake-ups. If you need longer sleep times, change the logic to go back to sleep right away until the proper amount of time has elapsed.

To turn the radio back on, use “rf12_sleep(-1)” to start listening to packets again after the next rf12_recvDone() poll. Since the RFM12B consumes a fair amount of power, it’s best to wait with this right until you’re ready to send out a packet.

Here is the new code, which is now included in the updated RF12 driver:

Picture 1.png

The RF12 driver software is available over here or as ZIP, this is an Arduino-compatible library.

Strobit boards

In AVR, Hardware on May 22, 2009 at 00:01

Stephen Eaton, the guy behind Strobit, very generously sent me two of his boards and prototype boards:

Strobit boards

These units run at 3.3V by powering them off a corresponding USB interface, such as the boards from Modern Device and SparkFun. And it’s fully compatible with the RF12 driver and the RF12demo sketch – I’ve run a successful test with it. This particular unit has no crystal, so it’s running off its internal 8 MHz RC clock. Works fine, just treat it as an Arduino LilyPad in the IDE.

As you can probably see these well-designed boards are slightly shorter and wider than a JeeNode. Very neat to see the SMD stuff on there – clearly lots of room left. Note that the board doesn’t have a voltage regulator – it’s intended to run straight off a CR123 battery, for which connections exist on the back.

A really neat trick is that the holes for the header pins are slightly staggered. This means that when you push in a header, it fits snugly even before soldering – a huge convenience, considering how soldering those headers is always a bit tricky on the JeeNode, especially with 4-pin headers.

Lots of attention to detail, such as the silkscreen text where you can mark which frequency band module has been used. And two (pretty bright) red leds.

Another neat feature is the prototype board (“shield” in DuinoSpeak):

Strobit boards

Lots of room for some custom stuff. Room for 4 through-hole LEDs + resistors, a reset button, and an ISP connector. This could also be used to mount a LDO voltage regulator. Given that the Strobit board itself is so flat, I’m inclined to place this shield underneath to keep total height to a minimum – but that’s just me, and would not be optimal while trying out stuff.

Anyway: congratulations, Stephen – I’ll report further when I get to do more with these units.

JeeNode Pulse revisited

In AVR, Hardware on May 21, 2009 at 00:01

The JeeNode Pulse hasn’t fully materialized yet – it’s the configuration I’d like to use around the house. Here’s a new configuration:

Pulse revisited

PIR and LDR on port 1, BMP085 on port 2, and SHT11 on port 3. There’s obviously no point in having a BMP085 sensor in more than one node, but for now it’s easy to leave it in for testing.

Different PIR sensor (from ELV). That sensor draws 30..40 µA – this matters for battery-operated use because it’ll be permanently on.

Here’s the main part of a first sketch, using the new power-down logic:

Picture 3.png

The code compiles to around 9 Kb. This includes floating point calculations in the SHT11 driver and the serial port reporting, both of which could be jettisoned later.

Sample output:

Picture 4.png

The values are:

  • temperature x10, from BMP085
  • barometric pressure x100, from BMP085
  • relative humidity, from SHT11
  • temperature, from SHT11
  • motion detect, from PIR (1 = no motion)
  • light level, from LDR (high means dark)
  • the number of milliseconds spent measuring

That last value is way too high for battery use – this code is spending 0.316 seconds collecting sensor data… in high power mode!

Breaking down the time spent, it looks like the BMP085 takes 2x 7 ms, and the SHT11 takes 2x 70 ms. The odd thing is that the SHT11 seems to take 300 ms when taking both temperature and humidity readings.

The good news is that the power-down current consumption of this setup is around 40 µA.

What needs to be done, is to spend the waiting time in these sensor read-out periods in power-down mode as well. The BMP085 driver already supports low-power readout by splitting the start and end parts of the driver, so that the waiting time can be handled in the calling loop. The SHT11 driver will needs to be adjusted to allow a similar approach.

With a bit of luck, only a millisecond or two will have to be spent in high-power (10 mA, haha!) mode. Then perhaps 2..3 milliseconds with the RFM12B radio active, and that should be it.

With a 15..60 second reporting period, the node would stay almost entirely in power-down mode. An average power consumption of under 100 µA total should be feasible – giving well over a year of service on 3 standard AAA batteries.

But that’s not all. To effectively use the PIR module, the code must be set up to handle motion-detect triggers at any time, also in power down mode. One approach would be to wake up (i.e. use a pin change interrupt), note the change and power back down. A refinement would be to “preempt” and start transmitting right away when motion is first detected – and then re-schedule future transmissions so the average reporting period remains the same. This makes the central JeeHub aware instantly of motion detected by the various nodes.

Future JeeNodes – thoughts

In AVR, Hardware on May 19, 2009 at 00:01

After several months tinkering with the JeeNode v2 boards, I’m starting to make a list of things I’d like to change for a future design.

What I’d like to keep:

  • having 4 identical “ports”, both physical and in software
  • running at 3.3 V, with on-board regulator
  • the wireless radio module :)

What I’d like to change:

  • switch to SMD to create a smaller unit
  • add a PCB antenna, even though it’s frequency band specific
  • add mounting holes

This could perhaps become the layout:

Picture 1.png

Not 100% sure about the SPI/ISP and I2C/PWR pin headers – though I’m inclined to keep them, somehow.

No idea when or even whether this ever materializes, just some thoughts.

Trying to receive OOK data

In AVR, Software on May 18, 2009 at 00:01

Here is an experiment to try and (ab)use the RFM12B module for OOK reception, such as sent out by a FS20 remote control. First the complete sketch:

Picture 2.png

The interesting bit is that this appears to work – the LED flashes when I press a button on the FS20 remote:

OOK receive trial

Since the signal is made to come out on the AIO port 1 pin (A0), this whole unit can be plugged into a second JeeNode running the OOK decoding code from an earlier post. Like this:

OOK receive trial

The reason for using two JeeNodes is that the one receiving the OOK signal is 100% tied up in a loop polling the status register. No problem – we simply upgrade to a dual-core setup :)

Unfortunately, the combination isn’t working yet. I’ll need to use the scope or logic analyzer to figure out what’s going on. Perhaps the RFM12B’s RSSI circuit is not fast enough to faithfully reproduce OOK transitions.

Oh, well.

Power consumption – more savings

In AVR, Hardware, Software on May 16, 2009 at 00:01

Let’s get that JeeNode power consumption down

The no-savings baseline from two days back was 10 mA, with a few simple measures getting it down to 1.31 mA, i.e. waiting in idle mode with the pre-scaler set to 64 and turning the RFM12B clock off.

It turns out that the ATmega328 is quite a bit more power efficient in that mode, the same sketch consumes 0.67 mA, i.e. half that of an ATmega168. Great – that’s an easy gain. Unfortunately it doesn’t carry over as much to power down mode: 125 µA versus 137 µA. There is still some unexplained power use there – maybe some of the circuits need to be turned off explicitly, or some more output pins floated.

Anyway, the next idea to go beyond 1.31 mA is to use the watchdog timer for idling away in power down mode. The basic code structure will be as follows:

Picture 1.png

Ooh, wait – turns out that there is a simpler way, which doesn’t require changing the main application logic after all. We can let the watchdog generate an interrupt without resetting the system. Here’s the code I ended up with after some experimentation:

Picture 2.png

Note the added dummy watchdog interrupt routine. Without it, the code apparently enters a nasty infinite loop when the watchdog fires, which is hard to get out of – even after a hardware reset.

Usage: 139 µA while waiting – 99% of the time. Great.

The code can actually be streamlined a bit – simply leave the watchdog running to pull the processor out of power down mode once a second:

Picture 4.png

But there’s more. The ADC can be disabled to reduce the power drain even further:

Picture 5.png

Now usage drops to 24 µA while waiting. Cool.

One last change is to disable the brown-out detection, which in turn disables the internal voltage reference. Changing the high fuse from 0xDD to 0xDF drops total power usage to a diminutive 6.8 µA. Perfect.

So there you have it – 1500 times less power usage!

Update – see the discussion in this post for a change which gets this down to 3.7 µA …

Update 2 – changed the low fuse from 0xFF to 0xEE, i.e. 64 µs start-up i.s.o. 1+64 ms (ok for resonator, not ok for a crystal). This will help get the power up duration down once I start looking into it.

Power consumption – subtle bugs

In AVR, Software on May 15, 2009 at 00:01

Yesterday’s code has several bugs:

Picture 2.png

As already mentioned, a delay is needed to let the serial data leave the USART before the pre-scaler change messes up the clock and baudrate. But there are also two other serious problems:

  • the “limit = millis() + …” expression will overflow and fail (after about 49 days)
  • the “millis() == limit” condition can “miss a beat”, leading to an almost-infinite loop

Both bugs can be fixed by carefully rewriting the code:

Picture 1.png

The differences are subtle, but essential. Without it, the loop will get stuck within just a few seconds of starting the sketch. With the above fixes it’ll run properly forever… I think.

Power consumption – baseline

In AVR, Software on May 14, 2009 at 00:01

Ok, first step in lowering JeeNode power consumption is to establish a baseline.

Here is the original code, the first few lines of the loop that is – the rest is the actual sensor readout and calculations, which take about 10 milliseconds:

Picture 1.png

Usage: 9.80 mA (slightly different from yesterday’s post, hooked up to USB from now on).

First change is to make the delay loop explicit:

Picture 2.png

Usage: 10.05 mA – no idea why it’s slightly higher. Anyway 10 mA will be used as baseline – this is the current drawn before any power-saving measures are introduced.

First step: lower power use by putting the processor in idle mode while it’s waiting for the next readout time. Included “avr/sleep.h” and changed the loop to be as follows:

Picture 4.png

Usage: 5.58 mA – it works, cool!

Next idea is to lower the system frequency, but only while waiting – so that readout, processing, and serial I/O remain unaffected:

Picture 5.png

Usage: 1.99 mA – whee! But there is a small gotcha – the system now goes into slow mode before the serial port has finished transmitting. A “delay(3)” at the end (or start!) of the loop is needed to fix this.

For comparison: with just the pre-scaler and no idle mode, usage is 2.15 mA – so the bulk of the savings comes from slowing down the system clock. Idle mode saves roughly 10% at lower frequencies.

One more important saving is possible due to the onboard RFM12B radio module, which powers up with its 10 MHz crystal clock running. Adding a bit more code to access the radio and disable its clock lowers power usage from 1.99 mA to 1.31 mA.

So these three simple measures combined already lead to a 7.5-fold power reduction: “waiting” a bit more carefully and turning off the RFM12B. All without affecting the main application code in any way.

As for the bottom line: putting the processor in power down (from which this code won’t ever wake up) uses 137 µA – and removing the MPU chip brings it to 17 µA. Note that with 140 µA average usage, a JeeNode can run for two years on 3 standard AA batteries.

It ‘s possible to reduce the power consumption from 1.31 mA to the µA range by powering down the processor and using the watchdog timer to wake it up – but that requires another set of changes to code and fuses – stay tuned…

Update – see this more recent post for additional details.

Power consumption

In AVR, Hardware on May 13, 2009 at 00:01

This contraption:

Measuring power draw

… when connected as follows:

Measuring power draw

… makes it easy to measure the supply current, with a BMP085 pressure sensor hooked up in this case:

Measuring power draw

Just under 10 milliamps, as you can see. That’s just the JeeNode running the BMP085 demo at 16 MHz, sending a new reading over the serial port every second. The RF12 module has not been turned on.

If the JeeNode is to be used for a WSN, then it will have to get its power consumption down. Way down, in fact…

Something happened …

In AVR, Hardware on May 11, 2009 at 00:01

The electricity / gas metering monitor – which has been running for months – stopped working:

Picture 1.png

It just flat-lined, dead, nada. Power cycling everything and re-flashing the meter node did not fix it. I don’t see any packets from the meter node on the air when listening via an independent JeeNode.

The only packets right now are from a JeeNode pulse upstairs, which keeps resending – indicating that the central JeeHub isn’t replying with an ack. Weird.

I’ve adjusted all nodes to explicitly use netgroup 0×50, since there have been changes to the RF12 default netgroup and CRC calculation. Just to rule out a potential issue.

Still no go. I’m flabbergasted.

Update – uh, oh… the JeeHub 3.3V regulator is way too hot. It’s shutting down from time to time. Not good!

Time to switch to plan B – a JeeNode used as packet receiver connected to my “Bubba II” NAS. It’s been running all the time to collect weather data from the KS300 anyway. Still no electricity / gas metering data coming in, but at least all the remaining JeeNode and KS300/FS20 data gets logged again.

Update 2 – first there was one problem (JeeHub failing), then I created another one by re-flashing the metering JeeNode with the wrong node ID - doh! Anyway, metering data is coming in again now. Still don’t know why / how the JeeHub broke, but it was up for a hardware revision anyway…

New RF12 data packet I/O

In AVR, Software on May 10, 2009 at 00:01

Following up on yesterday’s new serial I/O layer, implemented on top of the RF12 driver, here’s another demo using the “<<” and “>>” operators to send data across. First the sample code:

Picture 5.png

Then the sample output:

Picture 3.png

Picture 4.png

(these are slightly older screenshots, not yet using “rf12_config()”)

The output is a bit mixed up because the nodes were not reset at the same time, but you can see the data coming in on both nodes. These are independent bi-directional transmissions, even though in this case similar data is being sent since the same demo is running on both nodes.

As with the “rf12serial” demo, there are still some serious limitations with this – I still need to debug and add more flow-/congestion-control logic in this new implementation (the code is in “RF12sio.cpp” inside the RF12 library).

Much of this sort of logic relies on timers: the “RF12sio.h” header defines a simple millisecond timer which is also available for general use.

New RF12 serial I/O layer

In AVR, Software on May 9, 2009 at 00:01

The new RF12 code is starting to work. I’ve added it to the RF12 library, along with a demo which sends characters across the wireless link in both directions. Here’s the code:

Picture 6.png

And here’s some sample output on two terminal screens:

Picture 1.png

Other side (the “transmittee” text is my typo):

Picture 2.png

There are still major flaws in the code:

  • it doesn’t properly pack/unpack small packets sent back-to-back
  • in fact, it chokes when too much data comes in
  • it seems to have trouble with the very first character sent

But it’s a start!

Teensies

In AVR, Hardware on May 8, 2009 at 00:01

The “Teensy” by PJRC is a tiny AVR processor with embedded USB device port:

Teensy

It’s similar but not quite identical to an ATmega168 Arduino (no analog inputs, no I2C, and some other diffs). But the basics are the same, and you can even adapt the Arduino IDE to feed it sketches.

Now there’s a “Teensy++” with 64 Kb flash, 4 Kb RAM / EEPROM, and analog inputs and I2C:

Teensy++

Plenty of oomph for much larger applications!

It’s still not quite what I’m after though, since these operate at 5V (although the Teensy++ can be made to run at 3.3V that only works when not tied to a USB port). I’ve all but abandoned 5V logic, because the RFM12B wireless modules require < 3.8V to operate and because battery power is simpler when in the 3 .. 4.5 V range.

Still, these look like nice little boards, and at a good price.

RF12 configuration in EEPROM

In AVR, Software on May 7, 2009 at 00:01

It’s becoming a bit tedious to set up and manage JeeNodes, each with their own RF12 configuration. Prompted by a recent request, I’ve created what I think is a much more practical configuration system using some of the ATmega’s built-in EEPROM.

The basic idea is to split the configuration and the setup code. The “RF12demo” sketch which is part of the RF12 library has been extended into a general EEPROM configuration utility. Here’s its new startup screen:

Picture 2.png

So now you can type commands on the serial port to adjust settings. These are stored in EEPROM along with a description string and a 16-bit CRC checksum. When launched later on, the last settings get re-used so this becomes a set-and-forget thing.

What’s more important though, is that the RF12 library has been extended with a new “rf12_config()” call which you can use instead of “rf12_initialize(…)”. It does a couple of things:

  • retrieve the settings from EEPROM and check that they are valid
  • if so, configure the RF12 hardware accordingly
  • display the current settings on the serial port

As a result, it’s now a lot simpler to set up a sketch with RF12 communication. All you need to do is upload and run the RF12demo once to configure things, then upload your own sketch and use “rf12_config()” to re-use the same configuration.

Here’s an example / skeleton:

Picture 4.png

The output from this sketch is:

Picture 3.png

It’s a bit cryptic to keep the code overhead small, but you can see that I configured this unit to act as node “Z” (i.e. 26), using network group 212, and operating in the 433 MHz band.

The RF12 configuration data is stored in EEPROM addresses 0×20..0x3F (this can be changed in “RF12.h” if it interferes with your own EEPROM use).

RFM12 vs RFM12B – revisited

In AVR, Hardware on May 6, 2009 at 00:01

Now that the RFM12 is working, here’s the list of differences between RFM12 and RFM12B I’ve come across:

  • The RFM12 works up to 5V, the RFM12B only up to 3.8V (but it won’t be damaged by 5V).
  • The RFM12 needs a pull-up resistor of 10..100 KΩ on the FSK/DATA/nFFS pin, the RFM12B doesn’t.
  • The RFM12 can only sync on the hex “2DD4″ 2-byte pattern, the RFM12B can sync on any value for the second byte, not just D4.

More differences, found by Reinhard Max:

  • The B version can be set to a single sync byte.
  • The “PLL setting command” (CCxx), which only exists on the RFM12B.
  • Different values for RX sensitivity and TX output power.
  • A slightly different formula to calculate the time of the Wake-Up Timer.

Here is the back of the module, RFM12 on the left, RFM12B on the right:

RFM12 vs RFM12B

(these also happen to be for different frequency bands, as you can see)

And here is the front view, with RFM12 on the right and RFM12B on the left this time:

RFM12 vs RFM12B

The RFM12 unit on the right has a pull-up resistor added on top – note also the exposed pads at the top.

Note how the alignment of the solder pads on the JeeNode PCB is a bit off – these are v1 PCB’s, the v2 PCB’s have better alignment.

JeeHub Lite

In AVR, Hardware on May 4, 2009 at 00:01

The current JeeHub includes a MMnet1001 Linux module, which is great for running JeeMon. But for an even more basic always-on system, it’s possible to forego the Linux part – here’s the idea:

Picture 1.png

The whole thing is powered from USB, which must remain on permanently. There is no need for the attached computer to be on all the time, because incoming data can be saved into the on-board DataFlash memory. Depending on data volume and memory size, it ought to be possible to have a few days of autonomy.

The 433 and 868 MHz OOK receivers make this thing suitable for receiving weather data from off-the-shelf components, as well as responding to KAKU and FS20 remotes (and others like them). And since the RFM12B is so versatile, it can also send out 433 and 868 MHz OOK commands to those systems.

One thing I forgot to add in the above diagram, is a DCF77 receiver – or perhaps using a crystal or RTC. As has been mentioned a few times, the JeeHub needs to have a fairly accurate sense of time to do its main job of collecting real-time readings.

Only a minimal number of signals/ports are needed for the main tasks, there are several pins left to connect a few extra sensors.

The main bottleneck will probably be the amount of code needed to make such a JeeHub Lite perform basic home automation tasks. An Atmega328 might help a bit.

The normal monitoring and reporting work is still done with JeeMon, but now running on the attached PC (which can be Windows, Mac OS X, Linux, whatever). In such a configuration JeeMon must catch-up and extract saved data from the DataFlash in the JeeNode whenever it is launched.

JeeNode in a bottle

In AVR, Hardware on May 3, 2009 at 00:01

When you have a hammer, everything looks like a nail. Or in my case, a potential enclosure for JeeNodes:

JeeNode in a bottle

This adjustable enclosure came with some small relays shipped to me a while back.

Now if only I could figure out a way to make JeeNodes run a while on these batteries:

3.7 V @ 100 mAh Lithium

That’s a 3.7 V @ 100 mAh Lithium cell. Three months endurance would be the minimum needed to make this practical, that’s about 40 µA average power draw (the RFM12B draws 30 µA in sleep mode, though that could be lowered tenfold by connecting it to a switchable regulator such as the LP3985). Hm, might actually be feasible.

Yet another PIR

In AVR, Software on May 1, 2009 at 00:01

Found yet another passive infrared module for around €10, by ELV:

PIR by ELV

Hooked up to port 1 of a JeeNode, and shown here with the USB “BUB” interface by Modern Device. Note that this uses a JeeNode with 6-pin port connectors, since the PIR module requires at least 5V. The output is open-collector, and therefore compatible with the 3.3V levels expected by the JeeNode (using the internal pull-up resistor).

Sample output, from a slightly adjusted version of the “pir_demo” example sketch which is in the Ports library:

Picture 1.png

Range and sensitivity seem to be ok. The signal is more jittery that with the ePIR and Parallax modules, it will have to be de-bounced it a bit in real-world use.

RFM12 vs RFM12B

In AVR, Hardware on Apr 29, 2009 at 00:01

Here’s an RFM12 433 MHz module from Pollin, hooked up to an Arduino Duemilanove:

RFM12 (not RFM12B) @ 5V

One major difference between the RFM12 and the RFM12B is that the RFM12 can run at 5V, whereas the maximum operating voltage for the RFM12B is 3.8V (it can withstand up to 6V, which is good to know).

Alas, there seems to be some other difference which eludes me, because the RFM12 hooked up in the above picture only seems to be able to send. The RF12 demo code, which works fine for send and receive on RFM12B’s seems to do something wrong. Same behavior with another RFM12 module – so it looks like this is not due to a broken module. Send works, but nothing is coming in other than occasional garbage data.

The transmit part works fine when sending to an RFM12B, also in OOK mode: the RFM12 successfully controls both 433 and 868 MHz units (KAKU and FS20, respectively). But as packet receiver for other RFM12 or RFM12B modules … no joy so far.

Weird. Tips, anyone? Please let me know.

Update – Thanks to R. Max’s comment below, the problem has been solved: the RFM12 does not support arbitrary 2-byte sync patterns, it has to be 0x2D + 0xD4 – then it works fine!

Update 2 - See also the RFM12 vs RFM12B revisited page for a list of differences.

RF12 protocol improvement

In AVR, Software on Apr 24, 2009 at 00:01

A small change was recently made to the RF12 wireless packet driver. This is the structure of a version 1 packet:

Picture 1.png

And this is the new structure in version 2:

Picture 2.png

Small change, big implications: the 16-bit CRC now includes the SYNC2 byte.

The SYNC2 byte is actually abused a bit by the RF12 driver, because it is set to the network group. Since RFM12B modules can look for a two-byte sync pattern with a configurable second byte, this is actually quite useful. By filtering on the network group, the receiver will completely skip packets which do not start with the proper group. This greatly reduces processor load when packets for different groups are being sent around in the same area.

There may still be some false syncs, since the RFM12B continues to look for the 2-byte pattern during the entire transmission, but it reduces overhead nevertheless.

The problem with version 1 packets is that a bit e