Archive for September, 2010

h1

Getting started with nrf24: Hardware connection

2010/09/27

The nrf24 chips are all SPI-based, which means they use a bit clock (SCK), chip select (CS#), and two data lines (MISO, MOSI) to communicate with the host.  In addition, there is a chip enable (CE) that is used as an external control over the radio itself.  Finally, if your application calls for it, you can elect to connect the interrupt line (IRQ), which tells you when various events complete within the nrf24 itself, to save you from status polling.

I won’t cover the various non-digital connections at this point, but rather leave that to other sources such as the schematic for SparkFun’s nrf24l01+ module.  I’ll probably write a section on that eventually though, stay tuned.

Now, to connect it to your average microcontroller, you simply want to find the SCK/MISO/MOSI pins and connect them straight across.  The CS# pin may or may not go to one labeled on the microcontroller as such (or SS# for “slave select”), and in general it doesn’t matter because most microcontrollers do not maintain automatic control over the slave/chip select lines in master mode, since there could be an arbitrary number of them.  CE is even more loose as far as were you connect it, since it’s not actually part of the SPI interface itself anyway.  IRQ would ideally connect to a microcontroller pin that’s capable of actually triggering an interrupt, should you wish to use that functionality.

Here’s the nrf24l01+ connected up to an ATmegaXX8:

An Xmega is “better” since you can use any of the “serial” ports you want, and since every single pin is capable of triggering an interrupt you can wire IRQ anywhere you want as well:

However, if you are prepared to “bitbang” your interface, you can connect it any which way you want.  If communication speed and efficiency is not your main concern, this can make your board routing significantly easier:

A special case are the various nrf24 chips which also contain microcontrollers.  Examples are the nrf24LE1 and nrf24LU1(+).  The actually SPI interface is present inside the chip, but instead of having to wire it up, they’ve simply connected them inside the chip.  In that sense it’s almost the same as connecting up a nrf24l01+ to a regular 8051 microcontroller and using the existing SPI registers, except you’re just using a different SPI port.  Kindof.

Now another option to seriously consider in your PCB design is that of actually driving the chip’s power entirely from the microcontroller.  This gives you the ability to completely turn off the chip if you so desire (for power savings), or to hard reset the chip in case it goes wonky (which I seem to have happen on a regular basis):

Be sure that the maximum current of the nrf24l01+ does not exceed that which your microcontroller can supply.  In the above case, the Xmega is capable of driving 20mA on each pin, which is plenty of headroom over the 13.5mA max draw of the nrf24l01+.  If your chip doesn’t drive that hard, you can simply connect multiple pins together.  Just make sure those pins all turn on at exactly the same time, or you’ll short out your power supply and probably fry your microcontroller…

The next post will cover the software side of the physical connection: getting and setting registers, transferring actual packet data, and making the radio actually radiate.

h1

Getting started with nrf24: Introduction

2010/09/27

So anybody who’s been following my blog for the last few weeks will have noticed I’ve been fighting with the nrf24 series of chips, trying to get a wireless protocol in place I can use for program & debug capabilities.  Unfortunately, finding any kind of coherent and properly documented example code, or tutorials that make sense, has been rather hard.  I’ve found a few that at least got me partially started, in particular diyembedded‘s tutorials even though they’re based on the PIC and ARM.  However, the many and varied code examples all seem to say slightly different things, generally in less than straightforward ways.  Thus, I’m going to attempt to write my own tutorial series, as I bootstrap my way up through the available functionality.  It’s going to be very code-based, yet hopefully in a form that’s not too confusing.  This will also provide me with the opportunity to solidify my own understanding of the chip(s).

To start things off, the nrf24 series of chips from Nordic Semiconductor have gained a lot of popularity both in product and DIY circles because of their (relative) simplicity and low cost.  The radios themselves operate in the 2.4GHz band, and have a maximum air bitrate of 2Mbps in a 2MHz channel.  They use a GFSK encoding with a -82dBm sensitivity at 2Mbps, giving them a range in the 10’s of meters on average.  There are relatively few external components required, though I’ve had some problems there myself…

The tutorial sections themselves are [will be]:

  1. Hardware connection
  2. Physical layer communication
  3. Trivial transmission
  4. …[TBD]

The sections will be linked here as they are written, and this will eventually be the root document for the tutorial.

h1

Fun with nrf!

2010/09/25

So for the past while I’ve been trying to bootstrap some boards based on the various Nordic Semi nrf24 chips, in order to build a wireless program&debug setup for the product I’m working on.  Early on it took a lot of work to convince the SparkFun nrf24l01+ modules to talk in the first place, due to a lack of really understandable documentation, tutorials, and example code.  I really ought to write something up myself that’s more coherent, if I can get it fully straight myself.

However, the most recent struggle has been getting the nrf24lu1+ to work.  The difference is that while the nrf24l01+ is nothing but the radio and has to be interfaced to an external microcontroller, the nrf24lu1+ is an 8051 microcontroller with both a radio and a USB interface on-board.  This is great and all, but I’ve got all my toolchain stuff set up for the AVR/Xmega….  That means coercing SDCC into working, straightening out the register file, getting things linked, and overall understanding the ins & outs of the 8051 microcontroller (which sucks, BTW).  Then once I have a firmware file, I’ve got to program the beast.  That involved writing ioStack code running on my ATXmega256A3 “spider” that could speak the appropriate SPI commands to the chip (after getting it both reset and in programming mode), as well as writing a protocol layer on top of that that mimics the protocol the USB bootloader uses.  Finally, the actual programming code on the PC has to load up the IHX file (which coming from SDCC is an abomination) and do things in the right order.

Once I got actual code running on the nrf24lu1+, it took another painful chunk of work to port the general nrf24 code over to it.  The interface to the nrf24 is a “soft” SPI port, which bears very little resemblance to an actual SPI port.  The biggest “REALLY???” moment came when I finally found in the SDK that there is indeed a “transfer complete” bit, but it’s never referred to anywhere in the “internal SPI” section…  I’m finding the 8051, and particularly Nordic’s implementation, to be a really unpleasant thing to work with.  It’s making me appreciate the Xmega even more than I already did…

I still have to get a radio protocol figured out that makes ioStack work with multiple end-points, and I still need to figure out why my “bit-bang” PDI interface isn’t behaving right.  But when I get those two working, I should be able to both program and debug an Xmega target wirelessly, without Bluetooth going braindamaged about every 5 minutes.

h1

Abirtrary clock generation (with benefits)

2010/09/16

The product I’m working on right now has a load of very arcane requirements, forcing me to delve into areas totally new to me.  One of those is precision clocking, since the product requires synchronized capture of data across multiple units.  As such I went hunting for PLLs that would do the job I need.  The key is the ability to adjust the speed very slightly in order to synchronize multiple clocks on multiple units to the exact same speed over the long term.

TI’s CDCE9xx series of chips turned out to have all the right features.  Each chip in the series has an onboard VCXO, which allows me to tweak the exact speed of the crystal with a voltage input, up to +-150ppm.  The various chips in the line have differing numbers of PLLs, each with 2 outputs on separate dividers.  The 12+9 bit N/M divider and 7-bit predivider allow for almost any sane clock speed you can dream up.  Coupled with the right crystal, it does exactly what I need.

But, there’s the problem.  TI specifies a whole mess of arcane crystal parameters needed in order to make the pullable VCXO actually work.  The catch is that nobody selling crystals actually publishes most of those numbers.  That means that you can neither determine the pullability range of a given crystal, nor find a crystal that actually works.  They list a number of specific crystals that “should work”, but not only are those datasheets no more help, but nobody (Digikey, Newark, Mouser, or anybody else I can buy from) sells them.  Hard stop.

Well, as I was looking through the listed vendors hoping to get my hands on some at least some samples, I tried to focus on US-based companies so I could actually communicate with them (all the others are in China etc).  Turns out Pletronics is based in Lynnwood, Washington, just a couple hundred miles north of here.  I sent them an email asking if they could point me to a crystal that’s supposed to work with and be pullable by the CDCE9xx series, and got back an answer that surprised me, and made my week.  They happen to sell a part that’s a CDCE9xx and matching crystal in one package!

The FD77T is the biggest of that line, based on the CDCE949.  The package is all of 5x7mm, which is ever so slightly larger than the CDCE913 alone (5×6.4mm), and noticeable smaller than the CDCE949 (7.8×6.4mm).  Compared to the CDCE949, crystal, and related parts, it’s radically smaller and easier to deal with.  It takes VCCIO, VCCINT, I2C, and VCXO control and spits out 7 PLL outputs, end of story.  The smaller versions (FD7[345]T) have fewer PLLs and outputs, but in the exact same package.  Pletronics seems to stock the FD77T for at least sample quantities with 24MHz, 24.576MHz, and 25MHz crystals.

The kicker is that the 1,000 unit pricing I was quoted was in the $2.50 range.  That’s cheaper than either the CDCE913 or the high-spec crystal separately!

In order to do testing, I made up a tiny adapter board for the FD77T that brings out all the pins, supplies the 1.8V VCCINT, and adds an extra set of top-side headers for the I2C programming interface:

In order to program the actual chip, you have to set up a rather complex sequence of registers.  TI provides a program called ClockPro that does it for you, but it seems to be written in MatLab and is ludicrously slow.  To top it off, it’s Windoze only and doesn’t provide any easy way of getting the register values out in a form that can be programmed in.  I’ve had to resort to literally typing in hex from the binary show in the bit viewer, which is very error-prone and not much fun at all.  So last night I constructed a Python script that does the core PLL calculation, and this morning added code to use the BusPirate to set the clock.  So far it works like a charm!

The code uses an iterative method, but one I’ve already thought through as far as implementation in a microcontroller.  It works back from the target clock, first finding a Pdiv that results in a Fvco closest to the nominal 135MHz.  It then tries all valid Pdiv’s above and below that still fit within the 80-230MHz range.  For each Pdiv/Fvco combination, it tries all the N multipliers from 1 through the max 4095, checking if the multiplied frequency modulo the Fvco results in no remainder, producing a viable M.  From there it calculates the intermediate values required to shove into the PLL registers, and outputs an I2C string to the BusPirate to set the clock.

As useful as the above is, setting the clock speed can sometimes be something you want to do at run-time.  Or more likely, you just don’t want to have to go through all that trouble when prototyping requires you to change the clock.  To solve that problem, I also designed a board that includes a microcontroller:

Populating this board is lower priority, but it’ll happen sometime soon.  The Xmega32A4 on the right is intended to run a microcontroller version of the above algorithm, with some tweaks in place for performance.  Mostly that means trying to fit the calculation into common bit widths, and dealing with the cases where it can’t gracefully and efficiently.  The goal is to have a register set on the MCU accessible via the various available protocols (the upper row of the board is a straight copy of a “serial” port on the Xmega, providing hardware async serial, I2C, and SPI) that lets you simply say “I want xx.yyyMHz on pin X, go!” and get a clock out.  Things get a little bit more complicated when you ask it to deliver two different clocks on pins that share a PLL, but that’s only a matter of finding a common Fvco with which two Pdiv’s generate the requested clocks.

A more interesting feature of the code destined for the MCU is the ability to lock the crystal to an external pulse.  To do so you would designate one of the interface pins as a trigger, and configure it for a particular mode.  To start off, the MCU will switch its clock from the internal oscillator to one of the PLL’s outputs, thus creating a cycle counter based on the crystal.  When these pulses are detected on the pin, the MCU will compute the difference between the actual counter and the desired counter, and run a PID to generate the VCXO control voltage, thereby dragging the crystal back into alignment with the external source.

The trigger modes would be pulse-before-count, pulse-after-count, and pulse-per-X.   In the first, the controlling circuit is expected to provide a trigger pulse, and then set a register with the cycle count that it was supposed to be located at.  In the second, you would set the register before the trigger pulse.  In the last, you set the number of cycles that are supposed to occur between pulses that come at regular intervals.  This mode is ideal for interfacing with the 1PPS signal coming off a GPS receiver.  Run the MCU off Y1 at the base 24.576MHz frequency, set the register to 24,576,000, connect 1PPS to the right pin, and suddenly you have a locked atomic frequency.

I intend to sell both of these modules on my (still upcoming) webshop.  The bare module should probably run about $10, while the Xmega-based module will likely run around  $20-$25.  As usual, if you need one of these and can’t wait for the webshop, let me know and I’ll see what I can do.  Just remember the code for the MCU doesn’t exist just yet.

h1

I <heart> Xmega

2010/09/10

So I’m working on a developing the ioStack code (still need to write something useful about that…) and am repeatedly reminded why I love to work with the Xmega.  At the moment, I have a single XmegaA3 acting as the “spider” of my protoboard.  It has a USB serial link connected to port F in order to provide the control interface to everything.  There are currently 4x “PDI5” interfaces configured for D0, D1, E0, and E1.  The PDI5 interface is my own invention, and consists of a sync serial port that’s able to switch between the AVR PDI protocol and normal serial, and is designed to connect to the target via a micro-B USB connector.  There’s a NRF24 wireless chip attached to port C, and ports A and B are currently unused.  The next step in my development is to work on getting the NRF24 tied in and running a multipoint protocol, but that depends on having a debug serial interface.  For some reason the A3 is missing a second serial interface on port F, so I’m just going to shut off one of the PDI5 interfaces and repurpose serial E1 for debug.  A few changes to the #defines in the code and I’ll be good to go!  Try doing that on most any other microcontroller, and you’ll be in for a lot of pain.

I just completed early bootstrapping of my latest project’s target board, but realized that for some reason I set the VID to 2.9V instead of 3.3V.  Obviously this will reduce current consumption on the board, but I didn’t quite think about the part where at least for a while I’ll need to interface it to 3.3V electronics.  For now I’ve just hooked up its +5v supply and am relying on the ability of the I/Os in the devices to run slightly out-of-spec.  It doesn’t hurt that there are series resistors built into the interface anyway…

The next step is to develop a basic multi-point wireless protocol over the NRF24 in order to link my NRF24+Xmega interface board up and power it directly from the PDi5 interface on the target, thus breaking the 2.9/3.3V problem.  Now that I’ve got the “spider” directly connected to several NRF24 targets, I can program all the multipoint microcontrollers without having the process halted by non-functional wireless protocols…