Interface your mote to a Force-Sensitive Resistor

An example On-Chip Software Development Kit project in which we integrate a low-cost force-sensitive resistor.





As a hands-on mechanical engineer by training, I need actual physical examples to help me understand software concepts.  The example applications in the OCSDK are good solid examples, but I find I am able to absorb these concepts better when I do something "real" with them.  One of the many approaches I took in my exploration of the OCSDK cookbook was centered on the Round Force-Sensitive Resistor (FSR) from Adafruit (https://www.adafruit.com/products/166).  This sensor is manufactured by Interlink Electronics. An FSR is a Force-Sensitive-Resistor. When nothing is pressing on the round pressure sensitive area, the resistance of the part is many MΩ (normally open). A firm press with your finger drops the resistance down to ~1kΩ. This behavior makes this an ideal digital input sensor for a mote. I used this sensor first to make the sample application 02-gpio a little more 'real'. Then I used this same sensor to trigger joining in one project. Finally I used this sensor in an analog sampling application to trigger the taking of a sample.

Circuit

The circuit I used for this sensor was a very simple voltage divider. Since it is just a resistor, the part has no polarity.  I soldered a 2-terminal block to a prototype board and used those screw terminals to connect the two legs of the FSR.  The Adafruit hookup guide advises that it is difficult to solder the FSR to your board without damaging the plastic of the part.  I ran the Vsupply pin through a 150 kΩ resistor and through the FSR in series.  The low leg of the FSR is connected directly to GND on my DC9003 mote.  I connected DP2 on my DC9003 mote to the node between the 150 kΩ resistor and the FSR.  When the FSR is not pressed, DP2 reads 3.6 V (Vsupply) and no current is flowing.  When the FSR is pressed firmly, DP2 reads a very low voltage (~25 mV) and about 25 uA of current is flowing. 

.

Project 0: Digital input with Mote in Master Mode


The DC9003 mote comes out of the box in Master Mode.  What you see is that the mote sends temperature packets once every 30 seconds, but that is only part of what that sensor application on the mote can do.  You can enable any of 4 analog inputs, any of 4 digital inputs, and any of 3 digital outputs.  So, the very easiest thing to do is to configure the mote to report a packet anytime the button is pressed.  I connected the FSR exactly as described above.  In order to configure the sensor application to send a packet anytime the button is pressed, I connect APIExplorer to the manager and send a packet to the mote.  I select the sendData command, and enter the mac address of my mote: 00170d0000600470.  I choose 'high' priority, and set both the srcPort and the dstPort to 61625.  The options field must be set to 0.  Finally the payload is:  050002ff020200000101030103.  The byte-by-byte breakdown of this command is as follows:

05 00 The 0x05 means this command should be acknowledged, and I want to start fresh with a new sequence number.  The 0x00 is the new sequence number that I want to start with.  

02 This is the 'put' command ID.  Think of this as a 'set' command or a 'write' command

ff 02 02 00 This identifies Digital 0 as the channel I am going to be setting.  0xFF is the tag for naming the channel.  0x02 is the length of the tag identifier, and 0x02 0x00 is the address for Digital 0, labelled as DP2 on the DC9003 mote.  

00 01 01 Tag 0x00 is the enable field.  The length is 0x01 and the value I am setting it to is 0x01 (1 = enable).

03 01 03 Tag 0x03 is the data-format field.  The length is 0x01 and the value I am setting it to is 0x03 (3 = send on falling edge)

Once I send that packet, I see an acknowledgement to the put command from my mote.  Every time I push the button, I see a data notification coming from that mote.  So, without doing anything to the mote software, I can set up a mote to react to a pushbutton by sending a notification.   

Project 1: 02-gpio

In the 02-gpio project, there is example code that interacts with one GPIO pin as an output and another GPIO pin as an input.  I compiled this project with no changes and flashed it to my mote.  The mote toggles the blue LED once per second, and arms a notification for any state change on the digital input pin labelled DP2 on the DC9003 mote.  The documentation for that example project advises you to connect to Vsupply or GND and observe the notifications printed out on the mote CLI.  For my first project I instead wired up my FSR circuit to DP2 on the mote.  Wired up as pictured I can run the 02-gpio project and it prints out a line of text every time I press the button.  From the time I took the FSR out of the package from Adafruit to the time I had this project running took about 15 minutes.  

Project 2: Using a pushbutton to trigger joining

In all the OCSDK examples, the code will either have the local module join automatically or not join at all.  Most of the projects in the 02: Devices chapter of the Sample Applications don't join, like 02-gpio02-adc, or 02-temperature.  Some of the Devices examples have a variant that does join the network, like 02-gpio-net or 02-spi-net.  Those two types of examples will set a single boolean variable in the local interface task to true or false.  JOIN_YES means join, and JOIN_NO means don't join at all.  There is an obvious middle-ground for our application projects.  Of course we want our mote to join a network at some time, but in many cases we don't want the mote to join right away.

There are infinitely many examples, but here are a few:

  1. The device is encapsulated in a way that allows no power switch.  The device may be left in an IDLE mote state for hours, days, even months.  Some user interaction from the outside is required to "kick" the mote into joining a network.  Maybe a shake, or a magnet, or a pushbutton could provide this trigger
  2. The device needs to perform self-test operations on the sensor(s) connected to it, and it is desirable to delay joining until these operations are complete
  3. There is a desire for an intelligent searching mechanism that searches at a high duty cycle for some time, a lower duty cycle for another period of time, and stops trying to join for another period of time. Joining in a more manual way opens up some flexibility for this type of approach.
  4. Your device logs a substantial quantity of data, but needs to deliver that data VERY infrequently.  Deliberately dropping off the network for many hours, and joining later to upload data can be a more power efficient approach, provided there is sufficient connectivity in the network to allow your device to join whenever it wakes up

These are just a few examples. I decided to use my FSR circuit as an example of #1 above.

I copied the 02-gpio project over to a new project file that I called join-button.  In my code I added one prototype function that checks if the mote is currently in the IDLE state.  The return value of that function is a boolean TRUE or FALSE.  I use exactly the same gpio notification task to fire anytime the state of the pushbutton changes.  In my code, anytime the button is pressed, I call my function to check if the mote is IDLE.  If the state of the button is PRESSED and my Idle check function returns TRUE, then I call the dnm_loc_joinCmd() function.  Here is a code snippet of that logic and the call of the join command:

// issue the join command if you are currently idle
if ((gpioNotif.level == 0x00) && (idleCheck())){
	dnErr = dnm_loc_joinCmd(&rc);
	ASSERT(dnErr==DN_ERR_NONE);
	ASSERT(rc==DN_ERR_NONE);
	// print
	dnm_ucli_printf("Start searching because level=%d.\r\n",gpioNotif.level);
}

That's it!  The dnm_loc_joinCmd() function call is a single line of code.  Now my demo mote can be powered up anytime, and it will sit there forever and never join and never consume more than ~1.5 uA on average (if the LED jumper is disabled).  Any time I like, I press the FSR button, and the mote joins right away.  Anytime I power cycle the mote, or any other way to make the mote drop off the network (like resetting the manager for example), the mote will still require a button press to make the mote join.  I might build a variant of this project that takes the button press to join now and persist a state variable that will cause the mote to join automatically upon future resets.  The important thing I wanted to demonstrate was how simple it is to take deliberate control of whether and when to join.  

Project 3: Using a pushbutton to trigger a measurement and sending a data packet

I've built a few motes connected to a soil moisture sensor from Sparkfun (https://www.sparkfun.com/products/13322). I will publish a different recipe with a hookup guide for that sensor.  In one instance, I'm sampling the moisture sensor once every 5 minutes.  In another version of that project, all motes in a network will simultaneously measure their moisture sensor once per hour.  I decided that I wanted to use my FSR as a user input.  If I want to check right now whether the plant needs watering, I want to press a button that causes the mote to take a reading and send a packet to the manager with that reading.

I based my project on 04-syncblink from the OCSDK.  In that project, the mote joins, and gets network time from the network.  It uses network time as the basis for a user settable interval to blink an LED.  Using that project with no changes, you can have all your motes blink their LEDs in unison, demonstrating that the motes share a very accurate synchronized clock.  I replaced the simple 'blink' function with a slightly more complex action.  When this function is called, it turns on a digital output to power on the sensor, takes an analog reading from the sensor, and turns the digital output off again.  The Voltage reading is then stuffed into a packet and sent over the air to the manager.  This measurement function gets called whenever a semaphore is set.  There is a separate timer task that sets this semaphore whenever a timer expires.  I used my FSR circuit with a very similar GPIO notification task to interact with that same semaphore.  Now my mote will measure the soil moisture once an hour, and will send an extra reading anytime I press the button.  

Summary

The Adafruit round force-sensitive sensor is an inexpensive product that allows you to very rapidly prototype pushbutton functionality to your mote project.  In addition to the ease-of-use, it lends itself to an extremely low power consumption setup.  Still, this is just an example of a pushbutton, which are all straightforward to include into your OCSDK project.  Once you have a pushbutton as an input to the mote, there are numerous things you could do with it.  This recipe describes a couple high-level examples of things I built to demonstrate the capabilities.