Software apps and online services
We have a small stream in our backyard called Lyons Creek; it flows into Lake Washington a quarter mile away. Decades ago, it was full of salmon. Now, maybe one or two fish are spotted each year but unfortunately, they die before spawning. My goal is to reintroduce salmon into the stream and eventually have wild fish returning each year.
But first, we need to know the current state of the stream. I am working with a biology professor at a local university to learn what metrics are required to understand the health of the stream. Initially, I will start with air and water temperature to get the IoT solution up and running but will then add additional sensors to capture the necessary data. Once the data is collected, it's sent to the cloud and displayed in a easy to read dashboard.
For hardware, I wanted something relatively cheap (I want to deploy several sensors) and easy to use (Arduino IDE is still my tool of choice). So, I choose the Microsoft Azure IoT Starter Kit version of the SparkFun Thing. I've been wanting to give the ESP8266 microcontroller a try and now that it can be used with Azure IoT Suite, it was an easy decision. The kit gave me some sensors and LEDs so that I could build some simple projects to get familiar with the Thing. Once I had my bearings, I quickly moved on to this project.
For the cloud side of things, I choose Microsoft Azure and the Remote Monitoring preconfigured IoT solution. Again, with ease of use as the primary criteria, the preconfigured solution gave me a nice dashboard and some advanced features with just a few clicks of a mouse. There is nothing in the preconfigured solution that can't be built on Azure manually but I simply don't have the dev skills (or the time) to code it all up from scratch.
Technically, you don't really need any prior cloud experience as the Azure IoT Suite's Remote Monitoring solution really is "pre-configured" and only requires you to provide a name for the service. However, it's so pre-configured that all the Azure services are hidden underneath. So, if you do want to get a little more information about what's happening behind the scenes, I recommend that you read through my Conference Room Truth Serum and Processing IoT Device Data with Azure and Power BI projects; except for the dashboard, those two projects cover the Azure services utilized in the Remote Monitoring solution.
This project isn't a getting started guide for the ESP8266; there is quite a bit of information available online about these devices and Sparkfun's tutorial for the Thing - Dev Board (the specific ESP8266 board I used for this project) is more than sufficient to get you started. The Sparkfun tutorial also has detailed instructions for adding support for ESP8266 boards to the Arduino IDE so follow those if you need help getting your development environment configured properly; I had no problem getting the SparkFun ESP8266 Thing Dev board working with the Arduino IDE version 1.6.8.
However, once I got my sketch all together - including the integration with the Azure IoT SDK - I did run into issues with the latest version of the ESP8266 core for Arduino. It appears to have memory issues as I repeated got "failed to grow plain buffer" errors and the board kept resetting. A friend of mine mentioned that he saw a check-in to the ESP8266 core for Arduino repository to resolve some memory leak issues in version 2.1.0 (the most recent release). So, I installed the latest bits directly from the repo after first uninstalling version 2.1.0 using Arduino's board manager (see instructions under "Using git version" in the repo's Read Me) and voila, the issues were resolved.
Step 1 - Deploy Remote Monitoring solution in Azure
Time: 5 minutes
No, 5 minutes isn't a typo - that is really all it took to deploy the Azure IoT Suite's Remote Monitoring solution; if you don't already have an Azure subscription and need to first sign up for a free Azure account, allow maybe 10 minutes max. One thing to be aware of is that you need to start from the Azure IoT Suite site rather than the Azure Portal (once you have deployed the solution from the Azure IoT Suite site, you can manage it via the Azure Portal).
Once you have signed in to your Azure account, click on the plus sign to create a new solution, and then click "Select" under Remote Monitoring. Enter the name for your solution (it needs to be unique across all Azure IoT Suite solutions), select the region in which your solution will be deployed, select the subscription against which this solution will be billed (my Free Trial subscription expired a couple of months ago so now I am on a Pay As You Go subscription), and scroll down and click "Create".
It will take a minute or two for Azure to provision the solution. The tile for the solution will display "Provisioning" until it's deployed at which time it will display "Ready". You can click on the image in the tile to see the key info about your solution and you can click on "Launch" to go to the dashboard.
Step 2 - Create a new device identity in Azure
Time - 5 minutes
You'll notice when you first deploy the Remote Monitoring solution and go to the dashboard that there is already data. The solution comes pre-configured with a handful of simulated devices. We'll get rid of those once we deploy some real devices.
Before deploying your device in the field you will need to define the device in Azure and get a device identity for it. Rather than programmatically creating the device identity or using Device Explorer as I did in the Conference Room Truth Serum project, I can use the Remote Monitoring solution's dashboard to define a new device.
From the dashboard, click on the "Add A Device" menu option at the bottom left and then click "Add New" Custom Device. Enter a Device ID or allow Azure to create one for you and then click "Create". Next, the device's credentials will be displayed; copy this information as it will be need to for the connection string in the sketch. After you click "Done", all the devices for this solution will be displayed including the one which was just created.
The newly created device - lyons_creek_1 in my case - will have a status of "Pending" until it makes its first connection to IoT Hub. Then, it will change to "Running" and the device information you added in the sketch will be displayed.
Step 3 - Wire up the device
Time - 5 mins
The Microsoft Azure IoT Starter Kit - SparkFun Thing Dev comes with the headers already soldered onto the board so it's ready to be mounted to the included breadboard right out of the box. But, before you do, go ahead and mount the pull up resistor which connects between the signal and power pins. The width of the Thing leaves only two breadboard columns accessible. And, since I have two temperature sensors, I don't have a column available for the resistor - unless I mount the resistor under the Thing. Trim the wires of the resistor so that it will lie flush against the breadboard when mounted. Then mount the Thing over the resistor - there are a couple of millimeters of clearance between the top of the resistor and the bottom of the Thing. There is quite a bit of discussion online as to what the pull-up resistor is for and whether or not it is really required. I bought into the notion of needing to have a steady 5v so that the voltage doesn't float around when the line is "let go" after being pulled down. Plus, I got good, accurate readings with it so I left it in.
Now, wire in the two temperature sensors. The temperature sensors are DS18B20 and use the 1-Wire interface. Three wires from each of the temperature sensors need to be connected to the Thing - one for power, one for ground, and one for signal. I connected the signal wire to pin 2. The 1-Wire protocol supports multiple sensors on the same line so hook both up identically - i.e. connect the signal pin of both temperature sensors to the Thing's pin 2. And, of course, connect the power wires to the Thing's 5v pin and the ground wires to GND. (To make it easier to connect the temperature sensor's wires into the breadboard, I soldered a male header pin onto the end of each wire.)
Step 4 - Upload the sketch to the ESP8266
Time - 10 mins
Download the code from the GitHub repository and open it in the Arduino IDE. In stream_monitor.ino, specify your wifi network's ssid and password:
char ssid = "<your ssid here>"; // your network SSID (name) char pass = "<your network password here>"; // your network password (use for WPA, or use as key for WEP)
In simplesample_http.c, specify the connection string for your IoT Hub. The connection string information - IoT Hub Hostname, Device Id, and Device Key - were displayed when you created a new device (see step 2). Alternatively, you can get the connection string from Device Explorer - on the Management tab, click List, then left click on the appropriate device in the list and select "Copy connection string for selected device".
static const char* connectionString = "HostName=<your IoT Hub>.azure-devices.net;DeviceId=<your device id>;SharedAccessKey=<your access key>";
You can also update any of the device properties in simplesample_http.c. The device properties are sent to Azure each time the device starts up. The preconfigured solution supports additional device properties beyond what I am using - maybe as I progress this project, I will make use of others. DeviceID is required and if you want to use the map in the dashboard, you have to use the lat/long properties. It's not clear to me whether or not DeviceState is required but I left it in just in case. Everything else is optional.
DECLARE_STRUCT(DeviceProperties, ascii_char_ptr, DeviceID, _Bool, HubEnabledState, ascii_char_ptr, DeviceState, ascii_char_ptr, Manufacturer, ascii_char_ptr, ModelNumber, ascii_char_ptr, FirmwareVersion, int, Latitude, int, Longitude );
You'll also need the Azure IoT Hub library for Arduino. I installed it using the Arduino IDE Library Manager.
Now, compile the sketch and upload it to the Thing. The sketch will start running as soon as the upload is complete. (If it crashes and resets due to memory issues, see the notes under Prerequisites above about upgrading to the most recent bits of the ESP8266 core for Arduino.) There is a lot of log information written to the serial monitor so you can see exactly what's going on. I find it handy to also have Device Explorer open to the Data tab and monitoring the messages.
Now that the device is sending messages to Azure IoT Hub, the Remote Monitoring solution's dashboard will display the data. If you included Lat / Log in the device properties, the map will show the location of the device. The line graph plots the air and water temp.
You'll also notice in the code that there is support for cloud to device messages. In the future, I plan on using this capability to change the sampling rate - currently it's set for 15 minutes. But, for now, I built in the ability to turn off/on air temperature data. Send the following message to the device (I use the "Messages to Device" tab in Device Explorer) to toggle air temperature on or off:
Step 5 - Deploy the device in the stream
Time - 30 minutes
For final deployment, I did make a couple of modifications to the Thing. First, I cut the trace for the PWR-LED jumper to turn off the power LED - reducing power consumption by 7 mA can't hurt. I also swapped the antenna jumper and connected an U.FL WiFi antenna to the board. Both of these modifications can be found in the SparkFun hardware overview for the Thing. In the next iteration, I want to try out the sleep function of the Thing - especially if I set my sampling rate at an hour or more.
SparkFun's Big Red Box is the ideal enclosure for this project - watertight and ample room for the components. I first drilled two holes on the side of the enclosure to run the temperature sensors' wires through. Then I used silicone glue to seal up the holes. I stuck the breadboard to the bottom of the enclosure and velcro'ed the battery to the underside of the lid. To do a battery swap, I just unscrew the lid, unvelcro the battery and unplug the USB cable from it, plug the USB cable in the fresh battery and stick it to the lid with velcro, and reattach the lid - a 30 second job.
I then mounted the entire enclosure to the side of a small wooden bridge across the stream. It's about 4 feet off the stream bed but the 6 foot long wire for the temperature sensor is more than enough to reach the bottom.
I did run into a handful of issues with this project. I was able to work around them but I hope to resolve them in future iterations of the project.
First, as mentioned earlier, I hit what appears to me a memory management issue with the ESP8266 core for Arduino. I was able to deploy the latest bits directly from the repository to get past this. Hopefully, the next release of the ESP8266 firmware will be out soon so that you don't have to manually update it.
Second, the Azure IoT Hub SDK's serializer couldn't serialize floats or doubles. Therefore I was limited to integers - not only for the temperature readings (which is why I used Fahrenheit rather than Celsius) but also for lat/long. For lat/long, as long as you pass some data - 0, 0 in my case - to Azure in the device properties when the device starts up, you can edit the info via the dashboard. So, after the device connects go to the dashboard, click on "DEVICES", then click on your device, then click Edit in the properties pane. You can scroll down, enter the correct lat/long, and save it. Now, the map will display the location of your device properly. I will update the code (and these instructions) once the serializer supports floats.