(that’s 50,000 feet, or 9.47 miles – if those units mean more to you)
Here are a JeeNode v6 and an Arduino Duemilanove, side by side:
Let me start by saying, tongue-in-cheek: it’s all Arduino’s fault!
Because – let’s face it – the core of each Arduino and each JeeNode is really 95% the same: an Atmel AVR ATmega328P chip, surrounded by a teeny little bit of support circuitry and placed on a printed circuit board. So part of the confusion comes from the fact that the Arduino introduced its own conventions, moving it further away from the underlying common ATmega technology.
The differences between an Arduino Duemilanove and a JeeNode v6 – which resemble each other most – are:
- the JeeNode has a “skinnier” shape, incompatible with Arduino “shields”
- the Arduino runs at 5V, whereas the JeeNode runs at 3.3V (this carries through to all I/O pins)
- the JeeNode includes a wireless radio module, called the RFM12B by HopeRF
- the Arduino includes an FTDI <-> USB interface, while the JeeNode relies on an external one
There are many other differences, of course – so let’s continue this list a bit:
- the Arduino’s “eco-system” is far, far bigger than the JeeNode’s (translation: everyone who finds out about JeeNodes probably already knows about the Arduino platform, and usually already has one or more of ’em)
- this carries through to articles, websites, books, and discussion forums – Arduino is everywhere
- you can do lots of stuff with an Arduino without ever touching a soldering iron, whereas the JeeNode is really not usable without some soldering (even if just to solder on a few pin headers)
- different pinouts… it’s one big conspiracy to confuse everyone, of course! (just kidding: see below)
My reasons for coming up with the JeeNode have been documented in the past on this weblog, and can be summarized as: 1) running at 3.3V for lower power consumption and to better match modern sensors and chips, and 2) supporting a simpler form of expandability through the use of “plugs” – little boards which can be mixed and matched in many different combinations.
On the software side, JeeNodes remain fully compatible with the Arduino IDE, a convenient software environment for Windows, Mac, and Linux to develop “sketches” and upload them to the board(s).
The biggest stumbling block seems to be the way pins are identified. There are 4 conventions, all different:
- Atmel’s hardware documentation talks about pins on its internal hardware ports, in a logical manner: so for example, there is a port “D” with 8 I/O pins numbered 0..7 – the sixth one would be called PD5.
- Then there is the pin on the chip, this depends on which chip and which package is being referred to. On the 28-pin DIP package used for an ATmega328P, that same PD5 pin would be identified as pin 11. That’s the 11th pin, counting from the left side of the chip with pin 1 at the top.
- The Arduino run-time library has software to control these pins. For a digital output pin, you can set it to “1” for example, by writing digitalWrite(5,1). This resembles PD5, but it fails for other pins (PB0 is “8” in Arduino-land, and PC1 is “1” if used as an analog input, or “15” if used otherwise – go figure…).
- The JeeNode organizes several pins as part of 6-pin “Ports” (no relation to Atmels terminology!), each of them having 1 digital and 1 analog-or-digital pin.
The thing about JeeNode Ports is that there are 4 of them, and they can all be used for plugs in the same way. To support this, there’s a Ports library which lets you define port objects. This is an abstraction layer on top of the Arduino runtime. The reason is that it lets you associate a port object with a header on the JeeNode:
Port myport (2);
Then you can connect your hardware / sensor / plug / whatever to the header marked “P2″ on the JeeNode, and access it as follows:
This happens to be the same pin as in the examples above, i.e. PD5 of an ATmega, pin 11 of the 28-pin DIP chip, and digitalWrite(5,1) on an Arduino. This also means that there are numerous ways to perform the same action of setting pin 11 of the chip to a logical “1” (i.e. 3.3V or 5V):
the “raw” C-level access, using Atmel’s register conventions and definitions (fastest, by far):
PORTD |= 1 << 5; // or ... PORTD |= _BV(5); // same thing bitSet(PORTD, 5); // same thing, using an Arduino macro
the Arduino way of doing things:
the JeeNode Ports library way of doing things, as shown above:
Port myport (2); myport.digiWrite(1);
… let’s throw in an extra bullet item, since every other list in this post appears to come in fours ;)
The one (minor) benefit you get from using the Ports approach on a JeeNode, is that if you attach your hardware to a different port, say port 3, then you only need to change a single line of code (to “
Port myport (3);” in this case). The rest of the code, i.e. everywhere where its pins are being read or written, can then remain the same.