Ship IoT with Particle.io's Photon and Bip.io
Getting Started with the Photon
The Particle Photon is a small open source WiFi dev board with an embedded STM32 ARM Cortex M3 microcontroller:
It supports a number of analog and digital inputs, and with some work can communicate with devices via TWI, I2C, or SPI. For this example, we're going to connect it to a triple axis accelerometer breakout board from Sparkfun:
This board has a Freescale MMA8452Q accelerometer which supports an I2C interface. The total component cost of these two prototyping boards is about $30USD, making it rather inexpensive.
For our development environment, we will need both the Particle Dev and Particle CLI tools. All of the device driver code will be developed in the IDE, and the CLI will be used to setup the web hook to send our event data to Bip.io.
Writing a Device Driver
The Particle firmware mimics the Arduino API in a lot of ways, but there are some significant differences. These differences largely take three forms:
- new methods specific to the Photon's hardware
- different header files which need to be included
- compiler is remote in the cloud!
The fact that your compiler is not local to your machine means you need to bundle your projects in a Particle Dev specific way. All of your files must live in the same directory and are sent via HTTP to the compiler via a multi-part mime document POST request. This means you must supply all of your library code each time you compile or make a change.
The code for this device driver can be found at:
https://github.com/WoTio/shipiot-photon-mma8452Q
And you can get it via git clone using:
git clone https://github.com/WoTio/shipiot-photon-mma8452Q
The data sheet for the MMA8452Q can be found at:
http://www.freescale.com/files/sensors/doc/data_sheet/MMA8452Q.pdf
And it goes without saying, but you should download and save the data sheet somewhere for future reference. This chip has a lot of features that we aren't going to use or cover, and the data sheet provides information on using it for a wide range of applications including: tap detection, portrait vs. landscape orientation detection, and freefall detection.
The first file we're going to look at is the mma8452.h file:
Here we define a C++ class that will model the state of our MMA8452 accelerometer. Our default constructor will set the I2C bus address to 0x1d. If you jumper the pads on the bottom of the accelerometer board, you can change the address to 0x1c. If you do this, you will need to supply that address to the constructor.
In our initial setup phase, we will call begin
which will initialize the I2C interface, place the board into standby mode, and then set the scale and data rate to their default values. Finally it will turn the data output on by exiting standby mode:
Setting the board to standby mode is done by clearing the low bit on the register 0x2a:
We start data flow by toggling this bit back to one:
The Freescale MMA8452 needs to be in standby mode to modify any of the control registers. To modify the data rate, we can write a rate factor to the control register 0x2a:
The rate factor defaults to 000 which per table 55 of the data sheet amounts to 800Hz. Our wire speeds on the Photon has two settings 100kHz or 400kHz, both of which are more than sufficient by a couple orders of magnitude to support the output data of our device. And since we're going to drive this off of a 5V 1A mains wired power supply, we're not going to worry about the low power modes. We could easily lower the sample rate, as we are unlikely to update the web API that frequently. Changing the output data rate to something closer to 2x your polling frequency should be adequate.
To configure the scale (multiple in G over which our 12bits represent) of the x, y, and z components, we need to write to the low two bits of the register at address 0x0e.
These bits per table 16 set 2G (00), 4G (01), or 8G (10). Currently the value of 11 is reserved, and should not be supplied. Since we're unlikely to swing this around like a dead cat, 2G is sufficient for testing. If you'd like to handle larger swings, feel free to bump the rate up to 8G!
Finally, we need a way to test for the availability of data, and a way to retrieve that data once we have some. To test for availability of xyz data, we check bit 3 of the status register at address 0x00.
If we were only interested in the fact that one axis changed, or only wanted to look for movement in one direction, we could query other status register bits, but this is good enough for now.
Then to read the data once available, we can make a call to read the 6 bytes starting at address 0x01. This will give us X,Y,Z in MSB order, wherein we need to trim the bottom 4 bits of the LSB byte (as the sample size is 12 bits).
The actual input and output is done by a pair of routines which simply write the request and destination register and a input or output byte array and length. The available
and read
methods use the in
method:
Whereas the standby
, start
, scale
and rate
methods use the out
method to update the register values:
Writing a Sketch
The application we're going to use to forward our accelerometer data to our web application will simply initialize the accelerometer and then publish an event every second with the most recent values of x, y, and z.
For sake of our sanity, we can also log the x,y,z values to the Serial interface, which will allow us to record the values as we see them. If you supply power to the Photon via your computer's USB, the Serial interface can be discovered as usb modem / serial device.
You can understand the setup()
and loop()
functions in the context of the main.cpp file from the firmware. The .ino files get translated to C++, it adds some header files, and is referenced in the main()
function. The activities taken by main()
are:
- setup the WLAN interface
- waits until WLAN is ready
- first loop through, it calls
setup()
- then it calls
loop()
each iteration forever
Should the WLAN interface fail to connect, the system will stay in the wait state, which means the LED will continue to blink green, and your application will not run.
Wiring up the Board
Now that we have our software ready for testing on hardware, it is a good idea to wire up the nets on a breadboard for testing.
For testing we connect the USB to our computer so we can watch the Serial output. For the pins we connect from the Photon to the breakout board:
- 3.3V to 3.3V
- GND to GND
- D0 to SDA
- D1 to SCL
Following Sparkfun's app note, I'm using 2 x 330Ω resistors between D0 and SDA and D1 and SCL. You should see roughly 3.3V on pins 4 and 5 of the breakout board when the application is idle (I2C is active low). If you have a raw MMA8452Q, look at figure 4 on the data sheet. To wire it up, you will need:
- 2 x 4.7kΩ pull up resistors tied to 3.3V from pin 4 (SDA) and pin 6 (SCL)
- a 0.1µF bypass capacitor attached to pins 1 (VDDIO)
- a 0.1µF capacitor tied to GND and pin 2 (BYP)
- a 4.7µF bypass capacitor attached to pin 14 (VDD)
As we're going to wave the accelerometer around, I am going to fix mine to a perma-proto board. We can use a fairly simple setup:
Here I'm using:
- 5 x 6 pin female headers
- 2 x 330Ω resistors for current limiting
- 22 guage wire jumpers
For the wiring, I'm going to:
- jumper pin 1 of SV3 to pin 6 of SV1
- jumper pin 4 of SV3 to pint 1 of SV1
- tie one resistor to pin 6 of SV2
- tie the other resistor to pin 5 of SV2
- jumper the resistor tied to pin 6 of SV2 to pin 5 of SV1
- jumper the resistor tied to pin 5 of SV2 to pin 4 of SV1
This way I can replace both the breakout board the the Photon or simply reuse them on other projects. I've also added a 6th header on the other side of my board so I can setup a second app with some analog sensors on the right side:
The bottom of the board looks like:
As you can probably tell, I've reused this board for a few other projects, but that has mostly had to do with resoldering the the jumpers for the I2C pins.
The this point, you should be able to setup your WiFi connection using the Particle phone app, or you can use the particle setup wifi
CLI command to configure your board. Once your board is connected to your WiFi, you can use the compile and upload code using the cloud
button to flash your device with the app.
Configuring your workflow
Over at Shipiot.net, you can sign up for a free bip.io account. Bip.io is a data service that provides integrations into a number of web applications. It allows you to create automated workflows that are attached to your device's data.
For this tutorial, we will connect our data to a web based graph. We will use this graph to visualize the data. Later we could attach actions based on patterns we discover in the data. For example, if we attached the Photon and accelerometer to an object, each time the object moved, we could have Twilio send a text message to our phone, and we could record each movement to a Google Spreadsheet for later analysis.
Once you click the Create A Bip
button, you will be taken to a blank workflow canvas:
If you click on the center circle, you will be able to Select Event Source
:
For integrating with the Particle.io's Cloud API, we will select Incoming Web Hook
which will allow us to process each event that is sent by their webhook to our workflow. After selecting Incoming Web Hook
, your canvas should look like this:
Above the canvas, there is a URL bar with a path component set to Untitled
. Change this to accel
so that we can have a path that looks like:
http://<your_username>.api.shipiot.net/bip/http/accel
We will need this URL to setup the webhook on the the Particle.io Cloud API. Before we do that, however, we should finish configuring the remainder of the workflow so that the Cloud API doesn't error out while attempting to connect to an endpoint that doesn't exist!
Next we'll add a chart to visualize the data coming in off of the X and Y components of the accelerometer. First thing to do is click Add An Action
, and it will bring you to an action selection panel:
Here we will select Data Visualization
, which will enable us to plot the values sent by the device. Click it will bring us to a subpanel:
To view the data in chart form we'll obviously pick View Chart
, but we could as easily generated a visualization that would have allowed us to view the data as JSON or simply see the raw data as it enters the system. This is very handy for debugging communications between elements in our workflow.
Once we've selected the View Chart
option, we will be presented with a canvas with two nodes on it:
Now by dragging and dropping from the Incoming Web Hook
icon to the Data Visualization
icon, we can create a data flow from one to the other:
Now all of the messages that come in at our URL will be sent to the chart. But in order for us to plot the data, we need to describe the contents of the message. Clicking on the Parser
tab will bring you to a two panel interface that looks like this:
Into the left panel, we will enter some JSON that looks like the JSON that our application sent to the API:
We then click the Parse
button to generate the associated JSON schema:
We can now use these values as inputs to our chart. If we double click on the icon for the data visualizer, it will bring up a control panel for setting a number of values. Scroll down to the bottom of the panel and you'll see entries for setting the value of X, Y1, and Y2. For the X value we'll use the time of the incoming request:
We can then set the Y1 and Y2 values to the accelerometer's x and y values respectively:
Once you click OK
it will save the configuration. Double clicking the icon again will present you additional tabs including one for the Chart
:
Here we can copy the URL and open it up in a new browser window to see the data as it comes in.
The last thing we need to do before saving our workflow is setup some credentials for the webhook. By selecting the Auth
tab under the webhook panel, we can change the authentication to Basic Auth
, and in my case I'm going to use test:test for submitting data to my webhook:
We will also need the Authorization
header later to configure the webhook on the Cloud API side of things. Clicking Save
or Save and Close
will start your workflow running!
Configuring the Cloud API
For the remainder of the setup, we will use the particle CLI tool to interact with the device and the Particle Cloud API. The particle
CLI tool allows us to do basically everything we need including flashing the chip.
To compile our source code we can use the particle compile command
:
This will save our firmware image to a .bin file in the local directory. We can flash this via USB or over WiFi. To flash over WiFi, we need the device ID from the listing which we can get with particle list
Here I'll flash my device darkstar02
using the particle flash
command:
Being able to flash your device remotely is really handy when you've installed the device somewhere. You can also provide the source files to the particle flash
command, and the cloud will attempt to compile it and flash it too, but I like having a copy of the firmware for flashing again at a later date.
Once the device is done flashing and LED is breathing teal, we can attach to the serial monitor using the particle serial monitor
command:
As you can see I shook the device a couple times to make sure it was working. If you don't see any serial output, that probably means your sketch isn't working. Unfortunately, debugging via the serial monitor doesn't have a full debugger support.
Assuming you are seeing data in the serial monitor, you can then setup the Particle Cloud API webhook. Edit the accel.json
file to contain your device details:
Once you've setup your device
and url
settings, you can create the webhook using the particle webhook create
command:
This webhook forwards all of the events published to the accel
events to the url specified in our accel.json
file. We can sample these events using the particle subscribe
command to view the messages as they arrive from the device:
Because the webhook has the json
line in it, the data sent to our URL will have the x, y, and z values extracted from the data
field and placed in the top level of the event. The json sent to the webhook also contains device details, ttl, etc. as well.
Viewing the Data
If you remember the URL of the chart URL, you can after a few seconds pop over to the chart and see the new data as it comes in. You will need to be logged into shipiot.net to view the data. Here's a sample with me shaking the device:
At this point, you can go back and add new actions to your workflow, and have them trigger based on changes in the state of your device. Send a tweet. SMS your friends. Record your shaking to a spreadsheet.