Adafruit hosts a cloud service, io.adafruit.com, where you can upload data from your devices and also subscribe to data from other devices. The service is currently in beta, but you can sign up for a free account to test it. The data is stored in “feeds” and you can configure your own dashboards for viewing the data. There are two API:s available. One is REST-based and the other follows the publish/subscribe pattern of MQTT. In this post I will try both alternatives.
Background
I want to have control of the temperature and humidity in our garage. When parking a wet/snowy car in the garage, the humidity can be immense (the garage has floor heating). We have a dehumidifier that we can turn on when we think that the climate in the garage is too humid. If I can measure the temperature and humidity in the garage and view the values remotely, I can decide if the dehumidifier needs to be turned on or off. Ultimately, the dehumidifier should be remote controlled – but that will be a discussion in a future post.
Hardware setup
433 MHz signals (as investigated in a previous post) are too weak between our house and the detached garage. The WiFi has acceptable connection in the garage, though. I have an Adafruit Feather Huzzah that is based on an ESP8266 WiFi chip. It will be able to send signals and receive commands via WiFi from around the house. As WiFi activity is power hungry, I will use a power-saving pattern based on putting the ESP8266 to “deep sleep” between measurements.
As a sensor I use an inexpensive DHT11 module. It is not very accurate, but performs sufficiently well for the purpose of my experiment.
The wiring is setup like this:
- Pin 12 (yellow): Input from DHT11
- Pin 16 (white): Attached to the reset pin when the board is running. Note: when uploading the sketch to the board, this wire has to be removed.
- 3.3V pin (red): connected to VCC on the DHT11
- Ground pin (black): connected to GND on DHT11
For details on how to setup the Arduino IDE for Feather Huzzah, see my post:
https://larsbergqvist.wordpress.com/2016/03/27/meet-the-huzzah/
Send data with a REST client
My first test will use the Adafruit Arduino IO Library: https://github.com/adafruit/Adafruit_IO_Arduino
The complete sketch can be found in GiHub.
The setup() and loop() looks like this:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void setup() | |
{ | |
setupWiFi(); | |
aio.begin(); | |
dht.begin(); | |
float h = dht.readHumidity(); | |
float t = dht.readTemperature(); | |
sendDataToAdafruitIO(t,h); | |
// Put the board to deep sleep to save power. Will send a signal on D16 when it is time to wake up. | |
// Thus, connect D16 to the reset pin. After reset, setup will be executed again. | |
Serial.print("Going to deep sleep for "); | |
Serial.print(SLEEP_SECONDS); | |
Serial.println(" seconds"); | |
ESP.deepSleep(SLEEP_SECONDS * 1000000); | |
} | |
void loop() | |
{ | |
// nothing to do here as setup is called when waking up after deep sleep | |
} |
The setup() method is called when the board is started and it performs the WiFi-setup, the Adafruit IO init, the sampling of values from the sensor and finally the sending of data to Adafruit IO. As you can see, the loop() method is empty. This is because at the end of the setup() call, the board goes to sleep for 10 minutes and when it wakes up, the board is reset and the setup() method is called again. Thus, the loop() method will not be used.
I encountered two problems with the Adafruit IO library. The feed objects accepts float values, but when sending a float I get an error back. The workaround was to convert the float value to a string and send this string instead.
Adafruit_IO_Feed.send(20) = OK
Adafruit_IO_Feed(20.0) = ERROR
Adafruit_IO_Feed(“20.0”) = Workaround
The other problem was that Adafruit_IO_Feed.send() is super slow. Sending two small strings normally took 40 seconds! The serial output from a test run looked like this:
Connecting to MYWIFI ........ WiFi connected IP address: 192.168.1.17 Setting up WiFi took 1.50 second(s) Start sending data to Adafruit IO... 22.0 Sent temperature ok 20.0 Sent humidity ok Sending data took 40.47 second(s) Going to deep sleep for 600 seconds
Adafruit IO is in beta so there could be a performance issue that will be fixed later (or I am simply using this library incorrectly).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void sendDataToAdafruitIO(float temperature, float humidity) | |
{ | |
unsigned long startTime = millis(); | |
if (isnan(temperature) || isnan(humidity)) | |
{ | |
Serial.println("Failed to read from DHT sensor!"); | |
return; | |
} | |
Serial.println("Start sending data to Adafruit IO…"); | |
char temperature_str[20]; | |
ftoa(temperature_str,temperature); | |
if (temperatureFeed.send(temperature_str)) | |
{ | |
Serial.println(temperature_str); | |
Serial.println("Sent temperature ok"); | |
} | |
else | |
{ | |
Serial.println("Failed sending temperature"); | |
} | |
char humidity_str[20]; | |
ftoa(humidity_str,humidity); | |
if (humidityFeed.send(humidity_str)) | |
{ | |
Serial.println(humidity_str); | |
Serial.println("Sent humidity ok"); | |
} | |
else | |
{ | |
Serial.println("Failed sending humidity"); | |
} | |
unsigned long endTime = millis(); | |
Serial.print("Sending data took "); | |
Serial.print((endTime-startTime)/1000.0); | |
Serial.println(" second(s)"); | |
} |
Send data with an MQTT client
As the REST calls to Adafruit IO were not very responsive, I decided to try the MQTT API instead.
The complete sketch can be found in GitHub.
The setup() and loop() looks very similar to my previous test, but the publishing of data uses MQTT publish calls instead:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void sendDataToAdafruitIO(float temperature, float humidity) | |
{ | |
unsigned long startTime = millis(); | |
if (isnan(temperature) || isnan(humidity)) | |
{ | |
Serial.println("Failed to read from DHT sensor!"); | |
return; | |
} | |
Serial.println("Start sending data to Adafruit IO…"); | |
MQTT_connect(); | |
if (temperaturePub.publish(temperature)) | |
{ | |
Serial.println(temperature); | |
Serial.println("Sent temperature ok"); | |
} | |
else | |
{ | |
Serial.println("Failed sending temperature"); | |
} | |
if (humidityPub.publish(humidity)) | |
{ | |
Serial.println(humidity); | |
Serial.println("Sent humidity ok"); | |
} | |
else | |
{ | |
Serial.println("Failed sending humidity"); | |
} | |
unsigned long endTime = millis(); | |
Serial.print("Sending data took "); | |
Serial.print((endTime-startTime)/1000.0); | |
Serial.println(" second(s)"); | |
} |
With this approach, the performance was ok. Publishing two floats took around 1 s. The serial output looks like this:
Connecting to MYWIFI ........ WiFi connected IP address: 192.168.1.17 Setting up WiFi took 1.50 second(s) Start sending data to Adafruit IO... Connecting to MQTT... MQTT Connected! 22.00 Sent temperature ok 21.00 Sent humidity ok Sending data took 1.22 second(s) Going to deep sleep for 600 seconds
So, the MQTT API seems to be the best option for Adafruit IO right now. It is quick and it handles publishing of floats without the need of a string conversion.
Dashboard
Adafruit IO lets you create dashboards where you can view your data. The dashboard setup supports adding different widget blocks that are connected to your feeds. My test dashboard looks like this:
Summary
Adafruit IO is a convenient way for storing and viewing data from internet connected devices. The devices could be microcontrollers like Arduinos, but you can send and fetch data from desktop computers as well. I had problems with the REST client API, but the MQTT API performs well. It is easy to setup your own local MQTT network, but by using a cloud service like Adafruit IO, you get the benefit of dashboards for accessing the data from a browser anywhere.
The Adafruit IO beta looks nice and is very easy to use. I’m really looking forward to the future enhancements of this service!
Addendum
After the initial publication of this blog post, I have written a few more articles on MQTT and Adafruit IO. The approach that I have used is to have a local MQTT broker where all IoT-nodes publish their data. On this broker, I have a subscriber that gets all published data and then forwards them to Adafruit IO. This way, I can easily add more cloud services without re-programming the IoT-nodes and also filter and transform the data in one single place.
A self-hosted MQTT environment for Internet of Things – Part 1
A self-hosted MQTT environment for Internet of Things – Part 2
A self-hosted MQTT environment for Internet of Things – Part 3
I have also added local storage of the data and a local visualization application:
A web app for IoT data visualization
After using the setup for a few days I noted that the board sometimes would not wake up from deep sleep. The Huzzah would hang when it was time to wake up with an automatic reset. I could not find a good solution for this erratic behavior, so I switched to using a power supply and skipped deep sleep. I have uploaded an additional version of the MQTT sketch to the Git repository where the board never goes to sleep.
LikeLike
For promoting security, I have modified the MQTT examples on GitHub to use SSL encryption with port 8883 on io.adafruit.com and using the WiFiClientSecure class instead of WiFiClient.
LikeLiked by 1 person