Setting up a remote node Feb 2017

To try out RF communications, we need to go through a number of steps:

  1. hook up two JeeNode Zero boards, so we can develop on both in parallel
  2. work out the code needed for the receive and send nodes
  3. lower the average power consumption of the send node
  4. install the send code in flash so it can run unattended
  5. add a coin cell, and turn the sender into a standalone unit
  6. as a bonus, we’ll also update the node with a modified version

Let’s jump right in… by the end of this one article, you’ll have it all.

1. Preparing two JNZ’s

Here is a 2-node setup, one via a USB-BUB type board, the other via a HyTiny-based SerPlus:

By running two instances of Folie, each in their own terminal session, and making sure that we can connect and easily reset ‘em with Ctrl-C, everything is ready for some Forth development.

2. Setting up RX & TX nodes

On the receiving end, it can’t get any simpler than entering “rf-listen”.

For sending, the first test is to manually send one packet with “123 rf-txtest”.

The result is that you should see one packet come in for each one sent out:

TX node, typed in RX node, printed out
123 rf-txtest
RF69 21EB2ACA01FDA0803D03 313233
45678 rf-txtest
RF69 21EB2AC401FD52803D05 3435363738
9 rf-txtest
RF69 21EB2AC301FDC0803D01 39

As you can see, the payload contains the ASCII representation of the number sent out, in hex.

Excellent! This shows that all the hardware involved is doing its job.

Next, let’s continuously send one packet per second, with an incrementing counter in it:

: blips 1000000 0 do i rf-txtest 1000 ms loop ;
rf-init 0 rf-power blips

It’s the same rf-txtest call, but now as part of a loop. The receiver output will be:

RF69 21EB2AC301FE60803D01 30
RF69 21EB2AC201FF42803D01 31
RF69 21EB2AC301FF4E803D01 32
RF69 21EB2AC301FF9A803D01 33
RF69 21EB2AC301FC92803D01 36

Not all packets are guaranteed to arrive. As you can see, we got packets 0, 1, 2, and 3, missed packets 4 and 5, and then got packet 6. That’s to be expected - it’s not that these sensitive radios are so unreliable, we’re simply placing them far too close together - even at minimal power, the radio waves from the transmitter will overload a receiver placed a few cm away!

To quit the infinite send loop, we can press Ctrl-C to get the Forth prompt back. Since this resets the JNZ, all code in RAM will be lost.

3. Low-power transmissions

The transmitting node is now sending one packet every second. The rest of the time it’s just twiddling its thumbs and wasting energy. Let’s fix that:

: blips 1000000 0 do i rf-txtest rf-sleep stop1s loop ;
lptim-init rf-init 0 rf-power blips

As before, running this should produce new output once a second on the receiver end.

Actual power consumption measurements will have to wait for another time, but the average current draw is likely to be under 10 µA, some three orders of magnitude lower than before.

Which means we’re almost ready to run the transmit node off a coin cell - but there’s a snag: the blips code lives in RAM, so the send node won’t start when simply powering it up.

4. Unattended operation

For such unattended operation, we need to save the blips code in flash and add logic to start it up immediately after power-up (or reset). Appending to flash is a matter of telling Mecrisp:

: blips 1000000 0 do i rf-txtest rf-sleep stop1s loop ;

Automatic startup is also easy: Mecrisp looks for an “init” word on startup, and launches it.

But it’s also a bit risky. What if there is a mistake in the code, or we want to change it later? Once a new init is installed, we lose the default command-line prompt! Even a hard reset won’t get it back, since it’ll simply launch that same init override again.

The solution comes in the form of a special unattended word, defined in board.fs. This is designed specifically for making init overrides safe:

: init init unattended lptim-init rf-init 0 rf-power blips ;

Some notes of what’s happening, since it’s fairly critical to get this right:

The unattended escape hatch is that when connected to a serial port, anything after it will be skipped. Instead, this init definition will immediately return to the Forth command prompt.

If you run the above and reset the board, you will see that nothing happens. You still have to start everything up by manually entering “lptim-init rf-init 0 rf-power blips”.

But that’s exactly the point. Even when a node has been set up to automatically go live without serial FTDI connection, the development workflow remains unaffected.

5. Running off a coin cell

And now the real test - we take the JNZ out of its FTDI connector and insert a coin cell:

(see the red glow? more on that in a moment…)

And here’s some sample output printed by the receiver, while moving away a bit:

RF69 21EB2AC201009C803D02 3231
RF69 21EB2AB801FF34803D02 3232
RF69 21EB2AA3020026803D02 3233
RF69 21EB2AB101FDA6803D02 3234
RF69 21EB2AB40100FE803D02 3235
RF69 21EB2AC0010078803D02 3236
RF69 21EB2A9E02002A803D02 3237
RF69 21EB2A9F02002C803D02 3238
RF69 21EB2A9F02002A803D02 3239
RF69 21EB2A9D020012803D02 3330

It’s alive!

But… whoops, there’s a silly little mistake in there: the LED is still on, drawing some 2 mA. Leaving that LED on would drain the coin cell within a matter of days…

6. Updating the code

So as last step, here is how to fix the LED issue by installing an improved version:

  1. Remove the coin cell (this is important, it cannot coexist with power from FTDI!)

  2. Put the JNZ back in its FTDI adapter, and it’ll show the normal welcome message again.

  3. Remove the code we added to flash by entering “<<<core>>>” to restore the flash memory to its previous state. This was explained in the previous article.

  4. Improve the code, i.e. we can simply add a call to turn the LED off on startup:

    : blips 1000000 0 do i rf-txtest rf-sleep stop1s loop ;
    : init init unattended led-off lptim-init rf-init 0 rf-power blips ;
  5. Now disconnect from FTDI again, put the coin cell back in, and we’re done.

That’s all. With a mean current consumption in the 10 µA’s (i.e. sleep mode + transmit power use), this node should be able to run at least a year or two on a fresh coin cell. Piece of cake!

Weblog © Jean-Claude Wippler. Generated by Hugo.