How to build IoT based Weather Station Using ESP32 and Node-RED

In recent years, IoT-based weather stations have gained popularity due to their ability to provide real-time weather data. With the advancements in IoT technologies, building a weather station using off-the-shelf components has become easier. In this article, we will build an IoT-based weather station using ESP32 and Node-RED.

ESP32

ESP32 is a low-cost, low-power system-on-chip microcontroller with integrated Wi-Fi and Bluetooth. It has a powerful CPU, plenty of RAM, and built-in peripherals such as sensors and GPIO pins, making it an excellent choice for building IoT devices.

Node-RED

Node-RED is an open-source low-programming platform for project prototyping and a quick programming tool. We can quickly implement and test many event-driven IoT project prototypes in a short time. It's free and available for Linux, Android, and Windows platforms. Node-RED installation on Windows is simple and straightforward. You can also use Node-RED on an Android device by using the Termux app.

Components Requirements for Weather Station

  • ESP32 Development Board
  • DHT11 Temperature and Humidity Sensor
  • BMP180 Barometric Pressure Sensor
  • Breadboard
  • Jumper Wires
  • MQTT Broker (e.g., Mosquito)

Step 1: Setting Up ESP32

The first step is to set up the ESP32 development board. Connect the board to your computer using a micro-USB cable. Then, open the Arduino IDE and select the appropriate board and port from the Tools menu. 

Step 1: ESP32 Code for IoT-based Weather Station

Upload the code below to the ESP32 board:

#include <WiFi.h>
#include <PubSubClient.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BMP280.h>
#include <DHT.h>
#define DHTPIN 14
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
Adafruit_BMP280 bmp;
const char* ssid = "your_SSID";
const char* password = "your_PASSWORD";
const char* mqtt_server = "your_mqtt_server_address";
const char* mqtt_user = "your_mqtt_username";
const char* mqtt_password = "your_mqtt_password";
WiFiClient espClient;
PubSubClient client(espClient);
void setup() {
  Serial.begin(9600);
  delay(1000);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi...");
  }
  Serial.println("Connected to WiFi");
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
  if (!bmp.begin(0x76)) {
    Serial.println("Could not find a valid BMP280 sensor, check wiring!");
    while (1);
  }
  dht.begin();
}
void loop() {
  if (!client.connected()) {
    reconnect();
  }
  client.loop();
  float temperature = dht.readTemperature();
  float humidity = dht.readHumidity();
  float pressure = bmp.readPressure() / 100.0F;
  if (isnan(temperature) || isnan(humidity)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }
  String temperatureString = String(temperature);
  String humidityString = String(humidity);
  String pressureString = String(pressure);
  String payload = "{\"temperature\": " + temperatureString + ", \"humidity\": " + humidityString + ", \"pressure\": " + pressureString + "}";
  client.publish("weather", payload.c_str());
  delay(300000);
}
void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
}
void reconnect() {
  while (!client.connected()) {
    Serial.println("Connecting to MQTT broker...");
    if (client.connect("ESP32Client", mqtt_user, mqtt_password)) {
      Serial.println("Connected to MQTT broker");
      client.subscribe("control");
    } else {
      Serial.print("Failed with state ");
      Serial.print(client.state());
      delay(2000);
    }
  }
}code-box

This code sets up the ESP32 to read data from the DHT and BMP180 sensors. It then connects to a Wi-Fi network and an MQTT broker. The data is published to the "weather" topic every 5 minutes.

ESP32 Code Explanation

 #define DHTPIN 14
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
Adafruit_BMP280 bmp; code-box

These lines define a PIN (DHTPIN) and a DHT sensor type (DHTTYPE) for the DHT11 sensor. Then, a DHT object is instantiated with these parameters. The Adafruit_BMP280 object is also declared without any parameters.

const char* ssid = "your_SSID";
const char* password = "your_PASSWORD";
const char* mqtt_server = "your_mqtt_server_address";
const char* mqtt_user = "your_mqtt_username";
const char* mqtt_password = "your_mqtt_password"; code-box

These lines declare several variables as pointers to constant characters (i.e., string literals) for the Wi-Fi network name (SSID), the Wi-Fi network password (password), the MQTT server address (mqtt_server), the MQTT username (mqtt_user), and the MQTT password (mqtt_password). You should replace the placeholders with your Wi-Fi network and MQTT information.

void setup() {
  Serial.begin(9600);
  delay(1000);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi...");
  }
  Serial.println("Connected to WiFi");
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
  if (!bmp.begin(0x76)) {
    Serial.println("Could not find a valid BMP280 sensor, check wiring!");
    while (1);
  }
  dht.begin();
} code-box

The setup() function is called once when the device is powered on or reset. It sets up the serial communication, connects to the Wi-Fi network, sets up the MQTT client, sets up the callback function for incoming messages, initializes the BMP280 sensor, and initializes the DHT11 sensor.

void loop() {
  if (!client.connected()) {
    reconnect();
  }
  client.loop();
  float temperature = dht.readTemperature();
  float humidity = dht.readHumidity();
  float pressure = bmp.readPressure() / 100.0F;
  if (isnan(temperature) || isnan(humidity)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }
  String temperatureString = String(temperature);
  String humidityString = String(humidity);
  String pressureString = String(pressure);
  String payload = "{\"temperature\": " + temperatureString + ", \"humidity\": " + humidityString + ", \"pressure\": " + pressureString + "}";
  client.publish("weather", payload.c_str());
  delay(300000);
} code-box

The loop() function is the program's main loop, executed repeatedly by the ESP32 microcontroller. The function first checks whether the MQTT client is connected to the broker using the if (!client.connected()) statement. If the client is not connected, the reconnect() function is called to attempt to reconnect. 

The client.loop() function is then called to process incoming messages from the MQTT broker. 

The temperature, humidity, and pressure values are read from the DHT11 temperature and humidity sensor and BMP280 pressure sensor using the dht.readTemperature(), dht.readHumidity(), and bmp.readPressure() functions, respectively. These values are assigned to float variables: temperature, humidity, and pressure. 

The isnan() function is then used to check whether the temperature and humidity values are valid. If either value is invalid, an error message is printed to the Serial Monitor using the Serial.println() function. If the temperature and humidity values are valid, they are converted to String variables using the String() function. 

The temperature, humidity, and pressure values are then concatenated into a JSON payload using the String payload = "{\"temperature\": " + temperatureString +, "\" humidity\": " + humidityString + ", \"pressure\": " + pressureString + "}" statement. The JSON payload is then published to the MQTT broker using the client.publish() function with the topic "weather". 

Finally, the function waits for 300000 milliseconds (5 minutes) using the delay() function before starting the loop again.

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

The callback() function is called whenever a message is received from the MQTT broker. The function takes three parameters: topic, payload, and length. The topic parameter is a character array that specifies the topic of the message, the payload is a byte array that contains the message payload, and the length is an integer that specifies the length of the payload. The function first prints a message to the Serial Monitor to indicate that a message has been received using the Serial.print() function.

void reconnect() {
  while (!client.connected()) {
    Serial.println("Connecting to MQTT broker...");
    if (client.connect("ESP32Client", mqtt_user, mqtt_password)) {
      Serial.println("Connected to MQTT broker");
      client.subscribe("control");
    } else {
      Serial.print("Failed with state ");
      Serial.print(client.state());
      delay(2000);
    }
  }
} code-box

The reconnect() function attempts to connect to the MQTT broker if the initial connection attempt fails or the connection is lost. It enters a while loop and checks if the client is connected to the broker. If not, it attempts to connect to the broker using the client.connect() function with the client ID, MQTT username, and MQTT password. If the connection attempt is successful, the function subscribes to the "control" topic using the client.subscribe() function. If the connection attempt fails, the function waits two seconds before connecting to the broker again. The purpose of the reconnect() function is to maintain a stable connection with the MQTT broker and handle any connection issues that may occur.

Step 3: Setting Up Node-RED

The next step is to set up Node-RED. Install Node-RED on your computer or a Raspberry Pi, and install the MQTT and dashboard nodes by running the following command in a terminal:

npm install -g node-red-contrib-mqtt node-red-dashboard code-box

Once the installation is complete, open Node-RED in a web browser and create a new flow.

Step 4: Creating the MQTT Input Node

In the workspace, drag the "MQTT" input node from the input section of the palette and configure it to subscribe to the "weather" topic.

Step 5: Creating the Function Node in Node-RED

Drag a "Function" node from the function section of the palette and connect it to the MQTT node. In the function node, add the following code to parse the incoming message:

var msg1 = msg.payload;
var msg2 = JSON.parse(msg1);
var temp = msg2.temperature;
var hum = msg2.humidity;
var pres = msg2.pressure;
msg.payload = {"payload":{"temperature":temp,"humidity":hum,"pressure":pres}};
return msg; code-box

This code converts the JSON data received from the ESP32 into separate variables for temperature, humidity, and pressure.

Step 5: Creating the Dashboard on Node-RED

Next, drag the "Dashboard" node from the dashboard section of the palette and connect it to the function node. Click on the "Dashboard" tab in the dashboard node and create a new group. Then, configure a "Gauge" node to the group to display the temperature. Add another gauge node to display the humidity and a line chart node to display the pressure.

Step 6: Testing the weather station

To test the setup, run the Node-RED flow by clicking the "Deploy" button in the top right corner of the workspace. Now go to localhost:1880/ui to brows the nodered dashboard.

Conclusion

In this article, we have built an IoT-based weather station using ESP32, MQTT, and Node-RED. Following the steps outlined in this article, you can easily create your weather station and customize it to suit your needs. With the help of Node-RED, you can easily add additional sensors, display the data in different formats, and even create alerts based on specific conditions.


11/Post a Comment/Comments

  1. Great article the detailed explanation of the ESP32 and Node-RED integration extremely helpful. The screenshots and code snippets provided in the article were a great addition, allowing me to understand the process thoroughly.

    ReplyDelete
  2. Amazing and so useful👏🏻👏🏻😍

    ReplyDelete
  3. I really like the way this article uses Node-RED to create a visual interface for the weather station data. It makes it really easy to see the data and understand what it means

    ReplyDelete
  4. Great article and explained aboutESP32 and Node-RED. This article is very helpful and easy to understand in easier way.

    ReplyDelete
  5. really like the way this article uses Node-RED to create a visual interface for the weather station data

    ReplyDelete
  6. Very interesting article, thanks information

    ReplyDelete
  7. I like it to be easier This article uses Node-RED to create a visual interface for weather station data. It makes the data easier to access and understand

    ReplyDelete
  8. Thsnk you for sir you give me a great knowledge about this program

    ReplyDelete
  9. This article is very helpfully, It makes the data easier to access, all step really easy to understand.

    ReplyDelete
  10. Woe amazing a lovely project for the future ❤️😍

    ReplyDelete

Post a Comment