How to configure a NodeMCU device with IoT Hub

NodeMCU - Overview

Scaleway’s IoT Hub lets your connected devices share messages. In this tutorial we use a NodeMCU embedded Microcontroller (ESP8266) with WiFi, and a DHT11 temperature sensor, to collect temperature and humidity information. We use the Arduino IDE to configure the microcontroller and transfer the data via WiFi to the IoT Hub. The data is then retrieved from the IoT Hub by Node-RED in order to allow visualization in a dashboard.

Requirements:

Configuring the Arduino IDE

Note: This step requires that you have downloaded and installed the Arduino IDE on your local computer.

1 . Start the Arduino IDE application on your local computer.

2 . Go to Arduino menu and click Preferences:

3 . Add the following link in the Additional Boards Manager URLs: http://arduino.esp8266.com/stable/package_esp8266com_index.json and click OK to validate:

4 . Go to Tools > Board > Board Manager

5 . Type esp in the search bar and install the esp8266 boards package. Then close the window.

6 . Enter the Tools menu, then Board and select NodeMCU 1.0 (ESP-12E Module).

Your Arduino IDE is now ready to communicate with the NodeMCU device.

Creating an IoT Hub

1 . Log into your Scaleway console and click on IoT Hub in the side menu:

2 . Click Create a Hub and create your new IoT Hub.

3 . Enter a name for your hub (here we use iot-hub-esp8266) and choose a plan. For this tutorial we use the Free plan. If your project needs more resources you can choose one of the larger hubs. Click Create a hub to deploy it.

4 . Once your hub is ready, click on it. You will see the following page:

5 . Navigate to the Devices tab and click Add device to add a new device to the hub:

Note: Make sure to enable insecure connections to be able to communicate with the IoT Hub, as we are not using certificates in this tutorial.

6 . Click Add device to your hub to add the device.

7 . Once added, click on the device name to display some statistics about the device.

Your IoT Hub is now ready to accept connections.

Connecting MQTT Explorer to Scaleway IoT Hub

MQTT Explorer is a MQTT client that provides a structured overview of your MQTT topics and allows you to subscribe and push messages to and from your devices/services via the IoT Hub.

1 . Download and install the MQTT Explorer application.

2 . Open MQTT Explorer and fill in the following information:

Host: iot.fr-par.scw.cloud Username: your-device-id

Note: Find your Device ID on the “Device Information” screen in your IoT Hub (see above)

3 . Click Connect to establish the connection to your IoT Hub. The following screen displays:

Your MQTT Explorer is now sucesfully connected to your IoT Hub.

Connecting your ESP8266 to Scaleway IoT Hub

We now connect the ESP8266 device to our IoT Hub. To do so, some additional libraries are required. Download them on your local computer and add them to the Arduino IDE by by clicking on Sketch > Include Library > Add . ZIP library. We use the following libraries:

  • PubSubClient library: The PubSubClient library provides a client for doing simple publish/subscribe messaging with a server that supports MQTT (basically allows your ESP8266 to talk with your MQTT Broker).

  • Adafruit Sensor: A unified sensor driver.

  • DHT sensor library: The DHT sensor library provides an easy way of using any DHT sensor to read temperature and humidity with your ESP8266 or Arduino boards.

1 . Create a new sketch (program) in the Arduino IDE.

2 . Add these lines to the begining of your sketch to include the Wifi and PubSubClient libraries. The PubSubClient library allows us to publish/subscribe messages in topics:

#include <ESP8266WiFi.h>
#include <PubSubClient.h>

3 . Declare some global variables for the WiFi and MQTT connections. Edit the following parameters to match your configuration:

const char* ssid = "WiFi Name"; // Enter your WiFi name
const char* password =  "WiFi Password"; // Enter WiFi password
const char* mqttServer = "iot.fr-par.scw.cloud";
const int mqttPort = 1883;
const char* mqttUser = "your-device-id"; // Enter your Device ID
const char* mqttPassword = "";

WiFiClient espClient;
PubSubClient client(espClient);

4 . We use the setup function to check the connection to our WiFi network and print a message in the Serial Monitor to confirm whether the device is connected or not:

void setup() {
  Serial.begin(115200);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
  	delay(500);
  	Serial.println("Connecting to WiFi..");
  }
  Serial.println("Connected to the WiFi network");
  
  client.setServer(mqttServer, mqttPort);
  client.setCallback(callback);

5 . The following loop function will connect the device to the MQTT server and print the output on the Serial Monitor. This process runs in a loop until the device gets connected:

while (!client.connected()) {
    Serial.println("Connecting to MQTT...");
    if (client.connect("ESP8266Client", mqttUser, mqttPassword )) {
      Serial.println("connected"); 
    } else {

      Serial.print("failed with state ");
      Serial.print(client.state());
      delay(2000);
    }
}

6 . We test the publish/subscribe function by publishing a test message and subscribing to the topic:

  Serial.println("Sending payload hello-world...");
  client.publish("esp/test", "hello-world"); //Topic name
  Serial.println("Payload sent!");
  client.subscribe("esp/test");
}  

7 . To print out the message we specify a call-back function and print the topic name and the received message on the Serial Monitor:

void callback(char* topic, byte* payload, unsigned int length) {
 
  Serial.print("Message arrived in topic: ");
  Serial.println(topic);
 
  Serial.print("Message:");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
 
  Serial.println();
  Serial.println("-----------------------");
 
}

8 . Finish by adding the following lines in the loop:

void loop() {
  client.loop();
}

You should now have a sketch that begins with the following lines:

#include <ESP8266WiFi.h>
#include <PubSubClient.h>

and includes all the forementioned code, ending with:

void loop() {
  client.loop();
}

9 . Upload your code to your ESP8266 microcontroller. An output as in the following example displays in the Serial Monitor:

Note: You can access the Serial Monitor from the Arduino IDE by clicking on Tools > Serial Monitor

10 . You can also view the message in the MQTT Explorer tool:

Controlling a LED and measuring temperature and humidity

Next, we will use our NodeMCU device to measure temperature and humidity and publish these values in a topic. Besides the NodeMCU device, you need the following hardware for this step:

  • A Breadboard
  • An LED
  • A DHT11 sensor
  • A 330 ohms resistor (You can use a higher resitor, but it will make the LED less bright)
  • Some connectors to complete the wiring

1 . Perform the following wiring on the breadboard:

This is the pinout table of the NodeMCU device:

Pin Names on NodeMCU Development KitESP8266 Internal GPIO Pin number
D0GPIO16
D1GPIO5
D2GPIO4
D3GPIO0
D4GPIO2
D5GPIO14
D6GPIO12
D7GPIO13
D8GPIO15
D9/RXGPIO3
D10/TXGPIO1
D11/SD2GPIO9
D12/SD3GPIO10

2 . Create a new Arduino Sketch and add the following code:

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include "DHT.h"

#define DHTTYPE DHT11     // DHT 11

// Change the credentials below, so your ESP8266 connects to your router
const char* ssid = "YOUR_WIFI_NAME";
const char* password = "YOUR_WIFI_PASSWORD";

// Change the variable to your MQTT Broker, so it connects to it
const char* mqttServer = "iot.fr-par.scw.cloud";
const int mqttPort = 1883;
const char* mqttUser = "YOUR_DEVICE_ID";
const char* mqttPassword = "";

// Initializes the espClient. You should change the espClient name if you have multiple ESPs running in your home automation system
WiFiClient espClient;
PubSubClient client(espClient);

// DHT Sensor - GPIO 5 = D1 on ESP-12E NodeMCU board
const int DHTPin = 5;

// Lamp - LED - GPIO 2 = D4 on ESP-12E NodeMCU board
const int lamp = 2;

// Initialize DHT sensor.
DHT dht(DHTPin, DHTTYPE);

// Timers auxiliar variables
long now = millis();
long lastMeasure = 0;

// Don't change the function below. This function connects your ESP8266 to your router
void setup_wifi() {
  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("WiFi connected - ESP IP address: ");
  Serial.println(WiFi.localIP());
}

// This function is executed when some device publishes a message to a topic that your ESP8266 is subscribed to
// Change the function below to add logic to your program, so when a device publishes a message to a topic that 
// your ESP8266 is subscribed you can actually do something
void callback(String topic, byte* message, unsigned int length) {
  Serial.print("Message arrived on topic: ");
  Serial.print(topic);
  Serial.print(". Message: ");
  String messageTemp;
  
  for (int i = 0; i < length; i++) {
    Serial.print((char)message[i]);
    messageTemp += (char)message[i];
  }
  Serial.println();

  // Feel free to add more if statements to control more GPIOs with MQTT

  // If a message is received on the topic room/lamp, you check if the message is either on or off. Turns the lamp GPIO according to the message
  if(topic=="room/lamp"){
      Serial.print("Changing Room lamp to ");
      if(messageTemp == "on"){
        digitalWrite(lamp, HIGH);
        Serial.print("On");
      }
      else if(messageTemp == "off"){
        digitalWrite(lamp, LOW);
        Serial.print("Off");
      }
  }
  Serial.println();
}

// This functions reconnects your ESP8266 to your MQTT broker
// Change the function below if you want to subscribe to more topics with your ESP8266 
void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect("ESP8266Client", mqttUser, mqttPassword )) {
      Serial.println("connected");  
      // Subscribe or resubscribe to a topic
      // You can subscribe to more topics (to control more LEDs in this example)
      client.subscribe("room/lamp");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

// The setup function sets your ESP GPIOs to Outputs, starts the serial communication at a baud rate of 115200
// Sets your mqtt broker and sets the callback function
// The callback function is what receives messages and actually controls the LEDs
void setup() {
  pinMode(lamp, OUTPUT);
  
  dht.begin();
  
  Serial.begin(115200);
  setup_wifi();
  client.setServer(mqttServer, mqttPort);
  client.setCallback(callback);

}

// For this project, you don't need to change anything in the loop function. Basically it ensures that you ESP is connected to your broker
void loop() {

  if (!client.connected()) {
    reconnect();
  }
  if(!client.loop())
    client.connect("ESP8266Client", mqttUser, mqttPassword );

  now = millis();
  // Publishes new temperature and humidity every 30 seconds
  if (now - lastMeasure > 30000) {
    lastMeasure = now;
    // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
    float h = dht.readHumidity();
    // Read temperature as Celsius (the default)
    float t = dht.readTemperature();
    // Read temperature as Fahrenheit (isFahrenheit = true)
    float f = dht.readTemperature(true);

    // Check if any reads failed and exit early (to try again).
    if (isnan(h) || isnan(t) || isnan(f)) {
      Serial.println("Failed to read from DHT sensor!");
      return;
    }

    // Computes temperature values in Celsius
    float hic = dht.computeHeatIndex(t, h, false);
    static char temperatureTemp[7];
    dtostrf(hic, 6, 2, temperatureTemp);
    
    // Uncomment to compute temperature values in Fahrenheit 
    // float hif = dht.computeHeatIndex(f, h);
    // static char temperatureTemp[7];
    // dtostrf(hic, 6, 2, temperatureTemp);
    
    static char humidityTemp[7];
    dtostrf(h, 6, 2, humidityTemp);

    // Publishes Temperature and Humidity values
    client.publish("room/temperature", temperatureTemp);
    client.publish("room/humidity", humidityTemp);
    
    Serial.print("Humidity: ");
    Serial.print(h);
    Serial.print(" %\t Temperature: ");
    Serial.print(t);
    Serial.print(" *C ");
    Serial.print(f);
    Serial.print(" *F\t Heat index: ");
    Serial.print(hic);
    Serial.println(" *C ");
    // Serial.print(hif);
    // Serial.println(" *F");
  }
} 

3 . Transfer the Arduino Sketch to the NodeMCU device and open the Serial Monitor.

4 . The following output displays, confirming the successful capture and transmission of temperature and humidity data:

Flow Programming with Node-RED

In the following steps we deploy a Node-RED application using the IoT-Hub Kickstart feature and use it for flow programming.

1 . Go back to your IoT Hub in the Scaleway Console and click on the Kickstart tab. Click Create a Kickstart:

2 . Select the Flow Programming Kickstart and choose your Hub and Device from the drop-down lists. Then select a region for your Kickstart to deploy. Click Create to deploy the Node-RED application on a Virtual Instance

3 . Your IoT Kickstart application is deployed. The deployment may take some seconds, once it is ready, a green dot appears next to it. Click Dashboard to access the Node-RED dashboard:

4 . Log into Node Red using the credentials you have set during the deployment:

  • Username: admin
  • Password: your-password

5 . Open the menu and click on Manage Palette:

6 . Find the node-red-dashboard and install it:

7 . Create a layout as follows:

8 . Then add the following nodes to a new flow:

The following elements are used:

  • switch – this will control the ESP8266 output
  • mqtt output node – this will publish a message to the ESP8266 according to the switch state
  • 2x mqtt input nodes – these nodes subscribe to the temperature and humidity topics to receive sensor data from the ESP
  • chart – will display the temperature sensor readings
  • gauge – will display the humidity sensor readings

9 . The MQTT Out in Node-RED and the MQTT broker need to be connected. To connect the MQTT broker to Node-RED, double-click the MQTT output node. A new window pops up – as shown in figure below. It is already pre-configured by the IoT Kickstart, just add the Topic and the Name:

10 . Now edit the switch node as follows:

11 . Configure the MQTT input nodes for temperature and humidity:

12 . Edit the chart node as follows:

13 . Edit the gauge node as follows:

14 . Link the nodes as follows:

15 . Click Deploy to deploy the configuration.

16 . Open a new browser tab and go to: http://your-ip:1880/ui/. A Dashboard showing temperature and humidity displays. You can use the toggle switch for Light. If toggled, a notification displays in the Serial Monitor of the NodeMCU device:

Conclusion

You now have connected a NodeMCU device with IoT Hub, created a publish/subscribe message broker and successfully sent data from the IoT device over a WiFi network to the IoT Hub. With the help of the Node-RED IoT Kickstart, you subscribed to the data published by the device and created a dashboard to monitor both temperature and humidity in your room. For more information about creating flows with Node-RED, refer to the official documentation.

Discover the Cloud That Makes Sense