In this project you’ll discover how integrate the ESP8266 Multisensor Shield for the Wemos D1 Mini board with Node-RED. The ESP8266 Multisensor Shield will establish an MQTT connection with a Raspberry Pi running Node-RED and Mosquitto MQTT broker.
Project Overview
The Multisensor shield consists of a temperature sensor, a motion sensor, an LDR, and a 3 pin socket where you can connect any output, like a relay module for example.
We’ll use the Mosquitto broker installed on the same Raspberry Pi running Node-RED. The broker is responsible for receiving all messages, filtering the messages, decide who is interested in them and publishing the messages to all subscribed clients. To learn more about MQTT, you can read: What is MQTT and How It Works.
The following figure shows an overview of what we’re going to do in this tutorial.
- The Node-RED application publishes messages (“on” or “off“) in the topic esp8266/output. The ESP8266 is subscribed to that topic. So, it receives the message with “on” or “off” to turn the output on or off.
- The ESP8266 publishes temperature on the esp8266/temperature topic and the luminosity on the esp8266/ldr topic. The Node-RED application is subscribed to those topics. So, it receives temperature and luminosity readings that are displayed on a chart and gauge.
- Node-RED is subscribed to the topic esp8266/motion. The ESP8266 publishes on that topic when motion is detected. When motion is detected the message “MOTION DETECTED!” is displayed for 10 seconds in the Node-RED Dashboard text widget.
Recommended reading: ESP32 MQTT – Publish and Subscribe with Arduino IDE
Prerequisites
- Design and build the Multisensor Shield for ESP8266
- You should be familiar with the Raspberry Pi – read Getting Started with Raspberry Pi.
- You should have the Raspbian operating system installed in your Raspberry Pi – read Installing Raspbian Lite, Enabling and Connecting with SSH.
- Learn what’s MQTT and how it works.
- You need to have installed in your Raspberry Pi: Node-RED, Node-RED Dashboard, and Mosquitto MQTT broker.
If you like home automation and you want to learn more about Node-RED, Raspberry Pi, ESP8266 and Arduino, we recommend that you download our course: Build a Home Automation System with Node-RED, ESP8266 and Arduino.
Resources
You can find all the resources needed to build this project in the links below (or you can visit the GitHub project):
- ESP8266 with MQTT for Node-RED (for Arduino IDE)
- Schematic diagram
- Gerber files
- KiCad project to edit the PCB
- 3D Printer Enclosure (STL files and SketchUp Project)
- Click here to download all the files
Schematic
You can build the multisensor shield on a PCB, or you can build the multisensor shield circuit on a breadboard.
Here’s a list of parts you need to build the circuit:
- ESP8266 Wemos D1 Mini – read Best ESP8266 Wi-Fi Development Board
- 1x 5mm LED
- 1x 330 Ohm resistor
- 1x DS18B20 temperature sensor
- 1x mini PIR motion sensor
- 1x light dependent resistor
- 2x 10k Ohm resistor
- 1x relay module
- Breadboard
- Jumper wires
You can use the preceding links or go directly to MakerAdvisor.com/tools to find all the parts for your projects at the best price!
After gathering all the needed parts, assemble the circuit by following the next schematic diagram:
Here’s how the circuit looks like on a breadboard:
Alternatively, you can build a PCB for the WeMos D1 Mini (learn how to Build a Multisensor Shield for ESP8266):
Here’s how the circuit looks like using the PCB shield with a 3D printed enclosure:
Preparing the Arduino IDE
We’ll program the ESP8266 using the Arduino IDE. In order to upload code to your ESP8266 using the Arduino IDE, you need to install the ESP8266 add-on (How to Install the ESP8266 Board in Arduino IDE). You’ll also need to install three additional libraries to run the code on the ESP8266.
Installing the 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 Node-RED).
- Click here to download the PubSubClient library. You should have a .zip folder in your Downloads folder
- Unzip the .zip folder and you should get pubsubclient-master folder
- Rename your folder from
pubsubclient-masterto pubsubclient - Move the pubsubclient folder to your Arduino IDE installation libraries folder
OneWire library
- Click here to download the OneWire library. You should have a .zip folder in your Downloads
- Unzip the .zip folder and you should get OneWire-master folder
- Rename your folder from
OneWire-masterto OneWire - Move the OneWire folder to your Arduino IDE installation libraries folder
Dallas Temperature library
- Click here to download the DallasTemperature library. You should have a .zip folder in your Downloads
- Unzip the .zip folder and you should get Arduino-Temperature-Control-Library-master folder
- Rename your folder from
Arduino-Temperature-Control-Library-masterto DallasTemperature - Move the DallasTemperature folder to your Arduino IDE installation libraries folder
- Finally, re-open your Arduino IDE
Uploading Code
Copy the following code to the Arduino IDE. The code is well commented on where you need to make changes. You need to edit the code with your own SSID, password and MQTT Broker IP Address (Raspberry Pi IP Address).
/*********
Rui Santos
Complete project details at https://randomnerdtutorials.com
*********/
// Load libraries
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <OneWire.h>
#include <DallasTemperature.h>
// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
// Change the variable to your Raspberry Pi IP address, so it connects to your MQTT broker
const char* mqtt_server = "REPLACE_WITH_YOUR_MQTT_BROKER";
// MQTT Broker IP example
//const char* mqtt_server = "192.168.1.144";
// 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);
// Variable to hold the temperature reading
String temperatureString = "";
// Set GPIOs for: output variable, status LED, PIR Motion Sensor, and LDR
const int output = 15;
const int statusLed = 12;
const int motionSensor = 5;
const int ldr = A0;
// Store the current output state
String outputState = "off";
// GPIO where the DS18B20 is connected to
const int oneWireBus = 4;
// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(oneWireBus);
// Pass our oneWire reference to Dallas Temperature sensor
DallasTemperature sensors(&oneWire);
// Timers - Auxiliary variables
unsigned long now = millis();
unsigned long lastMeasure = 0;
boolean startTimer = false;
unsigned long currentTime = millis();
unsigned long previousTime = 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 functions 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 esp8266/output, you check if the message is either on or off.
// Turns the output according to the message received
if(topic=="esp8266/output"){
Serial.print("Changing output to ");
if(messageTemp == "on"){
digitalWrite(output, LOW);
Serial.print("on");
}
else if(messageTemp == "off"){
digitalWrite(output, HIGH);
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...");
// Create a random client ID
String clientId = "ESP8266Client-";
clientId += String(random(0xffff), HEX);
// Attempt to connect
if (client.connect(clientId.c_str())) {
Serial.println("connected");
// Subscribe or resubscribe to a topic
// You can subscribe to more topics (to control more outputs)
client.subscribe("esp8266/output");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
// Checks if motion was detected and the sensors are armed. Then, starts a timer.
ICACHE_RAM_ATTR void detectsMovement() {
Serial.println("MOTION DETECTED!");
client.publish("esp8266/motion", "MOTION DETECTED!");
previousTime = millis();
startTimer = true;
}
void setup() {
// Start the DS18B20 sensor
sensors.begin();
// Serial port for debugging purposes
Serial.begin(115200);
// PIR Motion Sensor mode, then set interrupt function and RISING mode
pinMode(motionSensor, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(motionSensor), detectsMovement, RISING);
// Initialize the output variable and the LED as OUTPUTs
pinMode(output, OUTPUT);
pinMode(statusLed, OUTPUT);
digitalWrite(output, HIGH);
digitalWrite(statusLed, LOW);
setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
}
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
// Timer variable with current time
now = millis();
// Publishes new temperature and LDR readings every 30 seconds
if (now - lastMeasure > 30000) {
lastMeasure = now;
sensors.requestTemperatures();
// Temperature in Celsius degrees
temperatureString = String(sensors.getTempCByIndex(0));
// Uncomment the next line for temperature in Fahrenheit degrees
//temperatureString = String(sensors.getTempFByIndex(0));
// Publishes Temperature values
client.publish("esp8266/temperature", temperatureString.c_str());
Serial.println("Temperature published");
// Publishes LDR values
client.publish("esp8266/ldr", String(analogRead(ldr)).c_str());
Serial.println("LDR values published");
}
// After 10 seconds have passed since motion was detected, publishes a "No motion" message
if ((now - previousTime > 10000) && startTimer) {
client.publish("esp8266/motion", "No motion");
Serial.println("Motion stopped");
startTimer = false;
}
}
This code is quite long to explain, so you can simply replace the following three variables with your details and the code will work straight away.
const char* ssid = ""; const char* password = ""; const char* mqtt_server = "";
If you want to learn how this code works, continue reading.
callback()
In the callback() function when a new message is received on the topic esp8266/output, you check if the message is either on or off to turn the output on or off accordingly.
if(topic=="esp8266/output"){ Serial.print("Changing output to "); if(messageTemp == "on"){ digitalWrite(output, LOW); Serial.print("on"); } else if(messageTemp == "off"){ digitalWrite(output, HIGH); Serial.print("off"); } }
Publishing temperature and LDR readings
This section of code publishes new temperature and LDR readings every 30 seconds. The temperatures readings are published on the esp8266/temperature topic. The luminosity readings are published on the esp8266/ldr topic.
if (now - lastMeasure > 30000) { lastMeasure = now; sensors.requestTemperatures(); // Temperature in Celsius degrees temperatureString = String(sensors.getTempCByIndex(0)); // Uncomment the next line for temperature in Fahrenheit degrees //temperatureString = String(sensors.getTempFByIndex(0)); // Publishes Temperature values client.publish("esp8266/temperature", temperatureString.c_str()); Serial.println("Temperature published"); // Publishes LDR values client.publish("esp8266/ldr", String(analogRead(ldr)).c_str()); Serial.println("LDR values published"); }
Note: the temperature is being published in Celsius degrees, but you can uncomment the following line for temperature in Fahrenheit degrees:
temperatureString = String(sensors.getTempFByIndex(0));
Motion detection
When motion is detected it calls the detectsMovement() function, publishes the message “MOTION DETECTED!” on the esp8266/motion topic, and starts a timer:
void detectsMovement() { Serial.println("MOTION DETECTED!"); client.publish("esp8266/motion", "MOTION DETECTED!"); previousTime = millis(); startTimer = true; }
If motion is not detected for more than 10 seconds, a new message is published in the esp8266/motion with the text “No motion”:
// After 10 seconds have passed since motion was detected, publishes a "No motion" message if ((now - previousTime > 10000) && startTimer) { client.publish("esp8266/motion", "No motion"); Serial.println("Motion stopped"); startTimer = false; }
Those are the main sections of code that you need to worry about. You can modify the messages, subscribe to more topics to control more outputs, or publish other sensor readings.
Testing the connection
Upload the code to your board. After uploading it, and with the Raspberry Pi running your Node-RED application and the Mosquitto broker, open the Arduino IDE serial monitor at a baud rate of 115200 and see what’s happening in real time.
This is helpful to check if the ESP8266 has established a successful connection to your router and with the Mosquitto broker.
Creating the Node-RED Flow
Before creating the flow, you need to have installed in your Raspberry Pi:
Importing the Node-RED flow
To import the provided Node-RED flow, go to the GitHub repository or click the figure below to see the raw file, and copy the code provided.
Next, in the Node-RED window, at the top right corner, select the menu, and go to Import > Clipboard.
Then, paste the code provided and click Import.
Here’s the imported flow that controls the ESP8266 and displays the published sensor readings.
Node-RED UI
After making all the necessary changes, click the Deploy button to save all the changes.
Now, your Node-RED application is ready. To access Node-RED UI and see how your application looks, access any browser in your local network and type:
http://Your_RPi_IP_address:1880/ui
Your application should look as in the following figure.
When motion is detected, it prints the message “MOTION DETECTED!” in the PIR Status field:
Wrapping Up
That’s it for this project. We hope you’ve found this project useful and you’re able to integrate the Multisensor Shield with your own home automation system using Node-RED.
If you like this project, you may also like our other projects:
- Home Automation Using ESP8266 Course
- Build a Multisensor Shield for ESP8266
- Build an All-in-One ESP32 Weather Station Shield
- ESP32 Web Server with BME280 – Mini Weather Station
Thanks for reading.
I like you tutorials as I have gotten further ahead with your website as any others.
However, with this project:
a) the ldr readings are backward
b) no matter which pir I use, and I have several including the one in the tutorial, I get erratic motion. It’s constantly sensing motion.
I would appreciate some help here
Tks
Hi Rod.
What do you mean by backward?
Have you used our code without modifications?
Regards,
Sara 🙂
Hi Sara,
I cant find where to enter mqtt_username and mqtt_password. Could you help me with these, please?
Thanks,
Edgar
……….
Attempting MQTT connection…failed, rc=5 try again in 5 seconds
Attempting MQTT connection…failed, rc=5 try again in 5 seconds
Attempting MQTT connection…failed, rc=5 try again in 5 seconds
Attempting MQTT connection…failed, rc=5 try again in 5 seconds
Attempting MQTT connection…failed, rc=5 try again in 5 seconds
………….
Hi Edgar.
If you’re using our example, you just need to enter the MQTT broker IP address on line 17: https://github.com/RuiSantosdotme/ESP8266-Multisensor-Shield/blob/master/Code/NodeRED_ESP8266_Multisensor_Shield/NodeRED_ESP8266_Multisensor_Shield.ino#L17
If you’re having trouble setting up your broker on Raspberry Pi, take a look at the following tutorial: How to Install Mosquitto Broker on Raspberry Pi
Hi, When importing your Node Flow I’m missing the pallettes ui_switch, ui_text, ui_gauge and ui_chart. i.e. the blue ones in your picture. Do you know where i can find them.
(i’m running Node-RED on an WIN10 machine)
Regards Olov
Hi.
I think you’re missing Node-RED dashboard installation.
Go to this tutorial: https://randomnerdtutorials.com/getting-started-with-node-red-dashboard/ and follow the “Installing Node-RED Dashboard” section.
I hope this helps.
Regards,
Sara
Hi Sara,
it is possible use this application without Rasberry, simply by PC?
Thanks,
Renzo
Agree, I was thinking the same.
Hi.
Yes, you can install node-red and mosquito on your computer.
Regards,
Sara
Hello i working on a project the i use this code on a ESP32
I need a code to Node-RED and ESP32 the i can get to now if the ESP 32 is on line with a commanded from Node-Red.
If i send a Commanded from Node-Red (Raspberry Pi) on the WIFI
i want to get a replay (ESP1 on line) (ESP2 on line) (ESP3 on line )
Hello, I’m Paul ,I’m trying your project with node-red on PC, mqtt mosquitto, board Esp8266 nodemcu at the moment without any sensor. On the serial monitor everything is ok, but the message “Message arrived on topic” never appears: ” even if I change the output sato from on to off on the ui dashboard, while on the node-red it is ok.. Can you give me an answer? Thank you…
Hello, Ruy and Sara,
I ordered the printed circuits to carry out the Multisensor shield with Node-Red project and I noticed an error in the diagram and therefore in the printed circuit. Indeed the ldr pin on the left on the diagram is connected to 3.3V, but on the printed circuit it is connected to GND; similarly the resistor connected on one side to the ldr is connected on the diagram to the GND or on the printed circuit it is connected to 3.3V. All this means that the values given by the ldr are inverted.
Just to let you know.
Sincerely.
Bruno