Skip to main content

An impExplorer Motion Detector

This example uses the impExplorer™ Kit as a movement detector: to wake when it is moved and send a small set of readings that are graphed in a web browser, which can also be used to obtain motion data continuously.

Note The code below was developed for the imp001-based impExplorer Kit, but can also run on the imp004m-based impExplorer if you make some minor modifications

This example is fairly simple, but it demonstrates some key features of the impExplorer and of the Electric Imp Platform:

  • The configuration of an imp GPIO pin to detect signals from an on-board sensor (‘motion detected’ and ‘readings ready’) and respond accordingly.
  • The two-part nature — device and agent — of an Electric Imp application.
  • Two-way communication between agent and device:
    • User commands sent from the agent to the device.
    • Sensor data sent from the device to the agent for processing.
  • Putting the imp to sleep to conserve power.
  • Detecting why the imp was started and re-configuring it accordingly.
  • Using Electric Imp free-to-use code libraries:
  • Serving an interactive web UI from the agent.
  • Using the agent for data processing so the device can sleep sooner and thus use less power.

The Application

The code allows the impExplorer to be set to deliver continuous motion readings, or to sleep and start taking readings only when its on-board motion sensor detects a short, sharp movement, such as a finger tapping the upper surface of the impExplorer . This latter mode, called ‘wakeup’, is particularly useful if your impExplorer is battery powered. In this mode, the impExplorer is put into deep sleep, which powers down its processor and WiFi radio (but not the accelerometer), preserving the unit’s battery life. When the impExplorer is woken by movement, it takes a short set of readings, which it relays to its agent (see below) and then goes back to sleep. It is set to wake after 30 minutes if it is not triggered sooner by movement; this allows the user to change the operating mode via a web UI.

The Device Code

Wakeup mode makes use of the impExplorer’s wake-up trigger pin, Pin 1, which we alias in line 16 as the variable wakePin. Pin 1 can be put to many uses, but here it is configured in the device code to wake the impExplorer when it is asserted. This signal comes from the impExplorer’s on-board LIS2DH12 motion sensor, which is set to send that signal when it detects that it has been moved, in line 93. Pin 1 is set for wakeup using the imp API call pin.configure():

wakePin.configure(DIGITAL_IN_WAKEUP);

Pin 1 is not configured automatically, but must be set up in code. Here this happens in response to a message from the agent, "wakeup", for which the code sets up a handler function that will be called in response to the arrival at the device of that specific message:

agent.on("wakeup", function(dummy) {
    ...
});

The function body, which you can view in code below, configures Pin 1 for wakeup mode and sets the LIS2DH12 to trigger Pin 1 if it detects a single tap. It then sets the impExplorer to sleep for 30 minutes (1800 seconds, as you’ll see in the code) when it next goes idle. The impExplorer will doze while waiting for the wakeup pin to be triggered.

Note The LIS2DH12 makes use of the fully compatible LIS3DH library.

While the impExplorer sleeps, its processor is powered down and no code runs, but the LIS2DH12 checks for movement. When a single tap is detected by the LIS2DH12, it asserts Pin 1, waking the impExplorer. When the impExplorer awakes, the device code runs afresh.

The reason for any given impExplorer startup is recorded and read in line 109 using the imp API method hardware.wakereason(). When it is woken by the wakeup pin being triggered (as opposed to being woken from sleep, say, or a power cycle) the code configures the LIS2DH12 to take a batch of readings and signal when it's done. The signal line is connected to Pin 1 so we need to reconfigure Pin 1 temporarily to detect this signal, ie. when Pin 1 goes High. When this is detected, the function readBuffer() will called — as set in line 119.

The function readBuffer() pulls the recent readings from the LIS2DH12, packages then up and sends them to the agent with a call to agent.send() (line 40). Depending on which mode the impExplorer is operating in, it then either re-configures the wakeup pin and puts the impExplorer to sleep pending a single tap trigger, or halts until it receives a subsequent signal from the agent to take a further batch of readings.

This latter mode is called ‘continuous' and is triggered by a message from the agent — that message’s handler function is defined in line 75. This handler sets the LIS2DH12 to grab a series of readings and assert Pin 1 when it’s done. The code configures the imp to call readBuffer() when Pin 1 is asserted.

The Agent Code

Every device has its own agent running in the cloud as its online virtual twin. Here, the impExplorer’s agent comprises code which handles motion data received from the impExplorer, and code which delivers a web UI that allows the user to operate the device.

The web app is stored as a web page that combines HTML page markup and JavaScript program code; this web page is stored in the constant HTML_DATA (lines 10 through 121). The agent makes use of Electric Imp’s Rocky library, which provides an easy way to define agent-hosted Internet APIs. Rocky is imported in line 5 and utilized in lines 166 through 197. Having created an instance of the Rocky code, called api, we configure this instance to send the web page when requested (lines 169-171). We also configure it to respond to clicks on two buttons presented by the web app, one to put the impExplorer into wakeup mode (lines 188-197), the other to get a 30-second burst of sensor readings (lines 175-184).

What happens to the data from the impExplorer? It is processed by a function set to be called when the agent receives the message "accelData" from the impExplorer. This function is registered and defined in lines 130-163. The data is converted to make it more suitable for graphing and then relayed to the web app running in the browser. The web app uses Google’s charting JavaScript module to render the data visually (lines 13 through 69).

Next Steps

This example simply retrieves motion data in one axis (x) and displays that data visually. However, it can easily be adapted to trigger actions based on the device’s degree of movement. For example, while the code detects when motion starts, it might also be coded to watch for movement coming to an end: when a washing machine’s wash-and-spin cycle has come to an end. You might then use the data stored to chart the degree to which the machine and the impExplorer taped to it move during this period, or to simply signal the agent, which then signals you to inform you your washing is ready for drying.

The agent code makes use of the Rocky library, but there are other agent-oriented libraries that are available to you to extend the functionality of your code:

Further Reading

Find out more about the impExplorer Kit’s many IoT-friendly features here.

To develop more advanced application code, you’ll need to keep the imp API reference close at hand. You can also look up specific Squirrel functions in our [Squirrel language reference](/squirrel/.

If you’d like to find out more about the Squirrel language itself, take a look at our Squirrel Programming Guide.

The pin mux page is essential reading for anyone wanting to wire components up to an imp’s GPIO pins and buses. The impExplorer also allows you to hook up additional peripherals using the Grove System.

Finally, the Network State Diagram shows you the lifecycle of an imp-based application in the context of the device’s connection to the Internet and its sleep states. A thorough grasp of the Network State Diagram is crucial to understanding the lifecycle of an imp application.

The Code

Device Code

Agent Code

imp004m-based impExplorer Modifications

In the device code, you will need to change lines 16 and 17 so that wakePin and i2c point to imp004m objects: respectively, hardware.pinW and hardware.i2cNM.

The agent code does not require modification.