A high-resolution sensor node Dec 2016

The JeeNode Zero is intended as sensor node in a Wireless Sensor Network. This requires:

So far, all development has been performed through FTDI. To run unattended, we’ll need to cut that umbilical cord and make the node start up by itself from a battery.

Battery-powered operation is essentially just a matter of placing a CR2032 coin cell in the on-board coin cell holder, but – as so often – there’s a bit more to it than that:

A trick which can be quite useful during development, is to connect the JeeNode Zero to FTDI with all pins except the 5V power feed, using a modified 6-pin “stacking” header:

This way, a coin cell can be used as power source, while keeping the serial interface available for uploads, resets, and debugging (this is a JNZ rev1, which had a BME280 on top).

Mecrisp Forth supports auto-execution by re-defining init, which is always automatically started up after a reset. We might therefore consider implementing our node as follows:


: main
  <application code ...>

: init  init main ;

Note the call to init inside our redefined init. This is extremely important, since we have to make sure that all the original initialisations are still carried out. Within a redefinition of “x”, any reference to “x” is always treated as a call to its previous definition (not as recursion!).

But there’s a problem… what if the code has a bug, or we simply want to replace it?

With the above code, we have effectively shut down Forth’s default interactive interpreter. This code is no longer listening for incoming serial data! To make matters worse, adding a check using key? is not good enough: if the code crashes and hangs (which you can expect to happen all the time during development), then it won’t reach that key check either.

One solution is to include a special word called “unattended”, which is defined in board.fs:

: init  init unattended main ;

This has the following effect:

The end effect is that main will only run automatically when not plugged into FTDI. When plugged in, you will need to start it by typing main. In addition, when an unattended running JeeNode Zero is plugged in, it’ll react as if a key has been pressed, and exit its main loop.

It is probably still possible to lock yourself out of the command prompt, but the chance of this happening is now much lower. You can always get a JeeNode Zero back to interactive mode by re-flashing a new copy of Mecrisp Forth onto it, using Folie’s built-in “upload” command (!u).

The final step is to get the data into a packet and send it out using rf-send. The mechanism which is starting to become standard practice at JeeLabs, is to use a variable integer encoding which compresses ints to a fairly compact binary format. The utility words in flib/any/varint.fs make this relatively easy - although the API and code for this may look a bit dense:

: send-packet ( vprev vcc tint lux humi pres temp -- )
  2 <pkt  hwid u+>  n+> 6 0 do u+> loop  pkt>rf ;

Basically, we’re sending out a packet of type “2”, followed by the node’s unique hardware ID, followed by a signed int and 6 unsigned ints - all popped in reverse from the data stack. The result is then broadcast as RF packet. Further details will be covered in a future article.

The full implementation of this first sensor node can be found in jz3/main.fs – by changing the DEBUG value to 1, you can make it report sensor values over serial instead of over RF.

To load this application in flash for unattended remote use, send freeze.fs to the JNZ – this includes main as well as the special init override, with unattended taking care of the details.

Note: this was coded before the sleep mode power savings were ready. In this implementation, the node still draws about 1.7 mA, too much for long term coin cell battery use. But it worked fine as initial test for a fridge node and ran for two weeks before the coin cell went dead.

Here are some results from that early test run of the fridge node:

Temperature and humidity are both reported with an impressive resolution of two decimal places. The big dip is the cooler in action. The tiny blip was caused by opening the door.

Some more values - including the internal temperature sensor of the STM32L052 µC itself. It’s surprisingly usable due to the pre-calibrated parameters in ROM:

Another very useful feature of the STM32L052, is that it is possible to accurately estimate the voltage at which it is running - by measuring the internal bandgap voltage in reference to Vcc and then performing a little inverse calculation. Again, these values are of a surprisingly good quality, due to the µC’s built-in calibration parameters for the bandgap:

The first graph is measured right after coming out of sleep mode, when the coin cell has presumably recovered from the TX power drain, while the second graph shows the measurements made right after the TX packet send completes. As you can see, coin cells have a hard time with 15..25 mA current pulses. These tests were made with a rev1 JeeNode Zero, which had a 22 µF supply capacitor.

The glitches in the left-side graph might be caused by not waiting long enough for the ADC to stabilise after coming out of stop mode (it used the 16 MHz HSI clock). Needs investigation.

Note how the battery voltage pattern is almost identical to the temperature curve in the fridge. At these low temperatures, batteries tend to have a very difficult time generating electricity!

Weblog © Jean-Claude Wippler. Generated by Hugo.