This tutorial refers to a product that has reached its end-of-life status.

MKR GSM 1400, MKR ENV Shield, MQTT and GSM

Record environmental data and send it over the GSM, using the MQTT protocol.

Introduction

In this tutorial, we will create a setup that allows a MKR GSM 1400 board to publish and subscribe to topics, using MQTT (Message Queuing Telemetry Transport). The data we will publish and subscribe to, are environmental data from the MKR ENV shield, using the Arduino_MKRENV library.

Goals

The goals of this project are:

  • Connect to the GSM network.
  • Connect to a broker (shiftr.io).
  • Publish a topic (humidity) using MQTT.
  • Publish a topic (temperature) using MQTT.
  • Subscribe to the same topics.
  • Print the results in the Serial Monitor.

Hardware & Software Needed

Message Queuing Telemetry Transport (MQTT)

The MQTT protocol was first introduced in 1999, as a light-weight publish and subscribe system. It is particularly useful for devices with low-bandwidth, where we can send commands, sensor values or messages over the Internet with little effort.

A basic explanation of how it works is that a node, for example an Arduino MKR GSM 1400, sends a payload to a broker. A broker is a kind of "middle-point" server, that essentially stores payloads sent to it, in something called topics. A topic, is a definition of what type of data it contains, it could for example be "basement humidity" or "living room temperature". Another node can then subscribe to this information, from the broker, and voilà, data has been moved from Node A to Node B over the Internet.

Basics of MQTT.
Basics of MQTT.

There are several different ways this can be practiced, with many different layers of security depending on what type of broker and setup we use. For example, if we are dealing with non-sensitive data, such as temperature of a specific location, we are not too concerned on who might get access to it. But there's cases where data needs to be protected, for example in Social Media messaging services.

One way to protect the data, is to for example use a token, something that is quite common when working with various IoT services. For example, if we are publishing something to a broker, anyone has the URL, e.g. randombroker.org/randomtopic can subscribe to it. But if we added a unique token on both sides, they wouldn't. These tokens could for example be Z6ACuLwr5T, which is not exactly something easy to guess.

Using encryption with MQTT.
Using encryption with MQTT.

MQTT is quite the interesting topic, and if you wish to read more about it, check out the links below:

Circuit

Simple circuit with board, shield and antenna.
Simple circuit with board, shield and antenna.

Creating the Program

We will now get to the programming part of this tutorial.

1. First, let's make sure we have the drivers installed. If we are using the Web Editor, we do not need to install anything. If we are using an offline editor, we need to install it manually. This can be done by navigating to Tools > Board > Board Manager.... Here we need to look for the Arduino SAMD boards (32-bits Arm® Cortex®-M0+) and install it.

2. Now, we need to install the libraries needed. If we are using the Web Editor, there is no need to install anything. If we are using an offline editor, simply go to Tools > Manage libraries.., and search for MKRGSM and Arduino_MKRENV and install them.

3. We will also need to install the MQTT library, by Joel Gaehwiler.

Note: there are several MQTT libraries, make sure you install the right one! The image below highlights the library that needs to be installed.

Installing the MQTT library.
Installing the MQTT library.

4. We can now take a look at some of the core functions of this sketch:

  • pin[]
    - stores the pin number of your card.

  • apn[]
    - stores the APN of your operator.

  • login[]
    - stores the login to your operator (typically a blank field).

  • password[]
    - stores the password to your operator (typically a blank field).

  • GSM gsmAccess
    - base class for all GSM based functions.

  • GSMClient net
    - creates a GSM client.

  • GPRS gprs
    - base class for GPRS functions, e.g. Internet, server behaviors.

  • MQTTClient client
    - creates a client that can connect to a broker, and publish/subscribe to topics and messages.

  • client.begin(broker, net)
    - connects to the broker.

  • client.publish(topic, message)
    - publishes a topic with a message.

  • client.subscribe(topic)
    - subscribes to a topic.

  • ENV.begin()
    - initializes the Arduino_MKRENV library.

  • ENV.readTemperature()
    - retrieves temperature from the MKR ENV shield.

  • ENV.readHumidity()
    - retrieves humidity from the MKR ENV shield.

The sketch can be found in the snippet below. Upload the sketch to the board.

1#include <Arduino_MKRENV.h>
2#include <MKRGSM.h>
3#include <MQTT.h>
4
5const char pin[] = "0000";
6const char apn[] = "4g.tele2.se";
7const char login[] = "";
8const char password[] = "";
9
10GSMClient net;
11GPRS gprs;
12GSM gsmAccess;
13MQTTClient client;
14
15int temperature = 0;
16int humidity = 0;
17
18unsigned long lastMillis = 0;
19
20void connect() {
21 // connection state
22 bool connected = false;
23
24 Serial.print("connecting to cellular network ...");
25
26 // After starting the modem with gsmAccess.begin()
27 // attach to the GPRS network with the APN, login and password
28 while (!connected) {
29 if ((gsmAccess.begin(pin) == GSM_READY) &&
30 (gprs.attachGPRS(apn, login, password) == GPRS_READY)) {
31 connected = true;
32 } else {
33 Serial.print(".");
34 delay(1000);
35 }
36 }
37
38 Serial.print("\nconnecting...");
39 while (!client.connect("arduino", "try", "try")) {
40 Serial.print(".");
41 delay(1000);
42 }
43
44 Serial.println("\nconnected!");
45
46 client.subscribe("/gsm_humidity");
47 client.subscribe("/gsm_temperature");
48 // client.unsubscribe("/hello");
49}
50
51void messageReceived(String &topic, String &payload) {
52 Serial.println("Incoming data: " + topic + " : " + payload);
53
54 // Note: Do not use the client in the callback to publish, subscribe or
55 // unsubscribe as it may cause deadlocks when other things arrive while
56 // sending and receiving acknowledgments. Instead, change a global variable,
57 // or push to a queue and handle it in the loop after calling `client.loop()`.
58}
59
60void setup() {
61 Serial.begin(115200);
62
63 if (!ENV.begin()) {
64 Serial.println("Failed to initialize MKR ENV shield!");
65 while (1);
66 }
67
68 // Note: Local domain names (e.g. "Computer.local" on OSX) are not supported
69 // by Arduino. You need to set the IP address directly.
70 client.begin("broker.shiftr.io", net);
71 client.onMessage(messageReceived);
72
73 connect();
74}
75
76void loop() {
77 client.loop();
78 if (!client.connected()) {
79 connect();
80 }
81
82 temperature = ENV.readTemperature();
83 humidity = ENV.readHumidity();
84
85 char tempStr[16];
86 itoa(temperature, tempStr, 10);
87
88 char humiStr[16];
89 itoa(humidity, humiStr, 10);
90
91
92
93 // publish a message roughly every 8 seconds.
94
95 if (millis() - lastMillis > 8000) {
96 lastMillis = millis();
97 client.publish("/gsm_humidity", humiStr);
98 client.publish("/gsm_temperature", tempStr);
99 }
100}

Testing It Out

After you have uploaded the code to the board, open the Serial Monitor to initialize the program. If it is successful, after 10 seconds or so, it will print

connected
followed by the MKR ENV shield values.

Subscribing to environmental data in the serial monitor.
Subscribing to environmental data in the serial monitor.

This means that we have successfully published, and subscribed to a topic containing our MKR ENV shield values, using the shiftr.io broker.

Now, we can actually go and see a live visualization of the data that goes through the broker. To see this visualization, go to shiftr.io/try, and start looking for your message!

To make things easy in this tutorial, we only recorded the temperature and humidity from the MKR ENV shield, but we can also record UVA, UVB, UVindex, LUX & atmospheric pressure. All we have to do is to read the values, create a topic to publish, and subscribe to the same topic.

Note: In this tutorial, we are only using one single board and sketch. If we have two boards with Internet access, we can simply subscribe to the same topic. You can for example setup one publish device and one subscribe device, and transfer data between them using MQTT.

Troubleshoot

If the code is not working, there are some common issues we can troubleshoot:

  • We have not installed the MKRGSM library.
  • We have not installed the MQTT library.
  • We have not installed the Arduino_MKRENV library.
  • We have entered the wrong pin number.
  • We have entered the wrong APN (access point name, check the operator of the SIM card).
  • We are out of coverage (no signal).
  • SIM card may not be activated.

Conclusion

In this tutorial, we have combined the use of the GSM technology, the MQTT communication protocol and environmental sensors. Practically speaking, we have created a tiny weather station that can provide accurate weather conditions which can be deployed anywhere with GSM coverage.

Tip: As the hardware (MKR GSM 1400 + MKR ENV shield) are both designed to consume little power, we can get creative with the ArduinoLowPower library to deploy a complete standalone weather station. The MKR GSM 1400 can be directly powered with a 3.7V LiPo battery with a JST PH connector.

Feel free to explore the MKRGSM library further, and try out some of the many cool functions in this library. You can also check out the MQTT repository on GitHub.

Special thanks to Joel Gaehwiler for developing the MQTT library and to everyone who contributed to this library.

Suggest changes

The content on docs.arduino.cc is facilitated through a public GitHub repository. If you see anything wrong, you can edit this page here.

License

The Arduino documentation is licensed under the Creative Commons Attribution-Share Alike 4.0 license.