This is the next post in a series on mobile development for Arduino.

The Internet of Things (IoT) is producing a fusillade of physical objects, such as wearables, beacons, vehicles and even buildings, that are tangibilizing the interconnectedness of the world wide web. This emerging paradigm is primed to have a profound effect on society as devices that were considered “smart” in the past decade are now becoming increasingly more “aware.” This proliferation of IoT devices, with the capacity to not only be sensitive to their environment but also engage with people in the most subtle and nuanced manner, has created a tremendous opportunity for software engineers to actively participate in social engineering. This trend compels developers and non-developers to learn how to program IoT devices to ensure that the current IoT technological revolution fulfills its potential and uplifts society.

In my first three posts, “Mobile Development for Arduino Part 1, Part 2 and Part 3,” I provided an introduction to IoT software development using Arduino as a platform. Arduino is an open-source hardware solution that gives developers an opportunity to cultivate a thorough understanding of electronics and learn how to integrate them using software. In “Mobile Development for Arduino Part 4,” we developed a prototype that automated gardening by acquiring data regarding soil moisture, temperature, humidity, sunlight and rainfall. In Part 5, we enabled our prototype to communicate remotely with an actuator via RF communication. In this post, we will take our initial steps to connect our prototype to the cloud so we can visualize the data readings from our garden.

Related: Read more on mobile development for Arduino in Part 5

To connect our prototype to the cloud, we will leverage a powerful IoT protocol called MQTT to transmit data. To offer developers the opportunity to set up their own server to handle IoT device data transmission there is MQTT, via MQTT brokers such as Mosquitto and Emitter. (My colleague Florian Harr published an in-depth explanation of MQTT that I strongly suggest reading). For the sake of simplicity, however, we will use the MQTT platform by Adafruit instead of creating a MQTT server. Adafruit has a clean user interface that will allow us to quickly bootstrap our prototype to the cloud.

1. Connect Adafruit Account and Feed

The first thing we need to do is to go to Adafruit and create an account. After creating an account, we should be taken to the console screen. Once there, select the Feeds option on the left so we can create a feed for our soil moisture readings. In the Adafruit console, create a feed called soil_moisture.

mobile-development-for-arduino6Source: Bryan Richardson

To understand the rationale behind creating a feed, we must take a step back to grasp exactly how MQTT works. Essentially, with MQTT we can do two things: publish data to an MQTT broker (in this case Adafruit) and subscribe to data from an MQTT broker. Data is published and subscribed via topics (or as Adafruit labels them, “feeds”). A topic can have multiple subscribers and publishers. However, one must be careful when employing multiple publishers to a single feed as it is not possible to determine the publisher source.

Related: Building An IoT Weather Station – Episode 1

2. Import Adafruit MQTT Library

Our next task is to implement the Adafruit MQTT Library in the Transmitter sketch file for our prototype. Navigate to the Library Manager and search for Adafruit MQTT Library to install it or download the zip file from here and manually install. Next, we need to import the following classes into our sketch file and define some constants.


#include <Adafruit_MQTT.h>
#include <Adafruit_MQTT_Client.h>
#include <Bridge.h>
#include <BridgeClient.h>

#define AIO_SERVER      "io.adafruit.com"
#define AIO_SERVERPORT  1883
#define AIO_USERNAME    "Your username_here" //found at accounts.adafruit.com
#define AIO_KEY         "Your_key_here" // Found at io.adafruit.com Settings

BridgeClient client;
Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);
Adafruit_MQTT_Publish soilMoistureFeed = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/soil_moisture");

The Adafruit_MQTT class handles the actual publishing and subscribing functionality, while the Adafruit_MQTT_Client is essentially an HTTP client that properly configures the BridgeClient instance that will be created for MQTT communication. The Adafruit_MQTT_Publish instance consumes the Adafruit_MQTT_Client that we just created as well as the particular feed that should be published to. Note that if we wanted to subscribe to the soilMoistureFeed, we would use Adafruit_MQTT_Subscribe class and pass the same parameters that we passed to Adafruit_MQTT_Publish. The values that need to be defined, such as AIO_USERNAME and AIO_KEY are easily accessible from the Adafruit console.

3. Initialize Bridge

Next, in our setup() method we must call begin() on our Bridge instance to initiate network communication.

void setup() {
  ...

  Bridge.begin(); //Blocking operation takes two seconds
...
}

Related: Building An IoT Weather Station – Episode 2

4. Create MQTT Connection and Publish Methods

Next, we need to create a method that connects to our MQTT broker.

void connectToMqtt() {
  int8_t returnValue;

  if (mqtt.connected()) {
    return;
  }

  Serial.print("Connecting to MQTT... ");

  while ((returnValue = mqtt.connect()) != 0) {
       Serial.println(mqtt.connectErrorString(returnValue));
       Serial.println("Retrying MQTT connection in 5 seconds...");
       mqtt.disconnect();
       delay(5000);  
  }
  Serial.println("MQTT Connected!");
}

This method is very simple. When we call connect() on our Adafruit_MQTT_Client instance, we expect to be returned an int value of 0, which indicates a successful connection. If we are returned anything besides 0, we disconnect() and try again 5 seconds later. Since this method will be called in our loop() method, we must also be sure to check if our client is already connected by calling connected() on our Adafruit_MQTT_Client instance.

Next, we need to create a method that publishes our soil moisture data to our feed.

void publishToMqtt(int soilMoistureValue) {
  uint32_t value = soilMoistureValue;
  if (!soilMoistureFeed.publish(value)) {
    Serial.println(F("Failed"));
  }

  if (!mqtt.ping()) {
    Serial.println(F("MQTT Ping failed."));
  }
}

Once again, nothing elaborate in this method. All we have to do is call publish() on our Adafruit_MQTT_Publish instance and pass the soil moisture value we want to publish. What’s important here is that after we publish our data we call ping() on our MQTT client in order to keep our connection alive. The default time duration for the MQTT client to keep itself alive without having to call ping() is five minutes, so as long as we publish data once every five minutes, our connection to the MQTT broker won’t drop. Calling ping() serves as a health check for our connection. It is important to note if we wanted to retrieve data from a subscription, all we would have to do is call readSubscription() on our MQTT client and pass it a duration interval to listen for subscription packets. Once a packet is received, we would call lastRead() on the Adafruit_MQTT_Subscribe instance to get the value. For example:

Adafruit_MQTT_Subscribe *subscription;
while ((subscription = mqtt.readSubscription(1000)))) {
    if (subscription == &soilMoistureSubscription) {
        Serial.print((Char *) soilMoistureSubscription.lastread);
    }
}

 

5. Implement MQTT methods

Next, we need to implement our connectToMqtt() and publishToMqtt() method in the loop() method.

void loop() {
  connectToMqtt();

  int soilMoistureValue = analogRead(soilMoisturePin);
  String soilMoisturePercentValue = String(convertToPercent(soilMoistureValue)) + "%";
  Serial.println(soilMoisturePercentValue);
  publishToMqtt(soilMoistureValue);
  delay(1000);
  …
}

 

6. Verify that data is being published

Now, we are ready to load our sketch and visualize our soil moisture data on the Adafruit console. Once the sketch is running on our prototype, the data readings will appear on the soil moisture subscription that we created.

mobile-development-for-arduino6

Source: Bryan Richardson

Congratulations. You have successfully connected your prototype with the cloud. In my next blog post on mobile development for Arduino, we will expand our integration with the cloud.

Leave a Reply

Your email address will not be published. Required fields are marked *