Build an All-in-One ESP32 Weather Station Shield

In this project I’ll show you how you can build an all-in-one ESP32 weather station shield and display the sensor readings on a web server. The web server displays data from all the sensors and automatically updates the readings every ten seconds, without the need to refresh the web page.

Watch the Video Tutorial and Project Demo

This guide is available in video format (watch below) and in written format (continue reading).

JLCPCB

The previous video was sponsored by JLCPCB. JLCPCB is a well known PCB prototype company in China. It is specialized in quick PCB prototype and small-batch production. You can order a minimum of 10 PCBs for just $2.

If you want to turn your breadboard circuits into real boards and make your projects look more professional, you just have to upload the Gerber files to order high quality PCBs for low prices. We’ll show you how to do this later in this blog post.

Resources

You can find all the resources needed to build this project in the bullets below.

ESP32 Weather Station Shield Features

To build this project, I’ve designed a PCB for the ESP32 DEVKIT V1 DOIT board. The PCB I’ve built only works with the version with 30 GPIOs.

I’ve designed the shield to be a compact weather station. The PCB has a lot of features so that it can suit a lot of different projects for different applications. In fact, I didn’t use all the PCB features in this project.

Additionally, this shield can also be used as a learning shield as it comes with some of the most used components when starting to learn how to program the ESP32.

The shield allows you to control:

  • 2x SMD LEDs
  • 1x Pushbutton
  • 1x Trimpot
  • 1x DHT22 temperature and humidity sensor
  • 1x BMP180 barometric sensor
  • 1x Light dependent resistor
  • 1x MicroSD card module
  • 2x Terminal blocks – that give you access to 3 GPIOs to connect other components

The microSD card module is a very interesting addition to the shield: it can be used to store readings if you want to build a data logger, or it can store an HTML file to serve a web page – as we’ll do in this project. I think this is a better and easier way to build a web server that requires more complex web pages.

ESP32 Shield Pin Assignment

The following table describes the pin assignment for each component on the shield:

Component ESP32 Pin Assignment
Pushbutton GPIO 33
Trimpot GPIO 32
Photoresistor (LDR) GPIO 4
DHT22 data pin GPIO 15
LED1 GPIO 27
LED2 GPIO 26
BMP180 SDA(GPIO 21); SCL(GPIO 22)
SD card module MOSI(GPIO 23); MISO(GPIO 19): CLK(GPIO 18); CS(GPIO 5)
Free GPIOs (terminal blocks) GPIO14, GPIO13, GPIO12

Note: there’s a small problem with our pin assignment. Currently the Arduino WiFi library uses GPIO 4 that is connected to the LDR. So, you’ll probably have trouble taking readings from the LDR when you use the WiFi library. To make it work, you can solder a wire from the LDR to another available GPIO (must support ADC).

Testing the Circuit on a Breadboard

Before designing the shield, I’ve assembled the circuit on a breadboard. If you don’t want to make a PCB, you can still follow this project by assembling the circuit on a breadboard.

Parts Required

To assemble the circuit on a breadboard you need the following parts:

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!

Schematic

After gathering all the needed parts, you can assemble the circuit by following the next schematic diagram:

Important: if you’re using a different board, you need to double-check the pinout.

Here’s the circuit diagram:

Designing the PCB

After making sure the circuit was working properly, I’ve designed the PCB version on KiCad. KiCad is an open-source software used to design PCBs.

I won’t explore how I’ve designed the PCB, but I provide all the files if you want to modify the PCB for yourself. Click here to download the KiCad project files.

Ordering the PCBs

You don’t need to know how to design the PCB to order one. You just have to:

1. To download the Gerber files, click here to download the .zip file.

2. Go to JLCPCB.com, click the “QUOTE NOW” button, and upload the .zip file you’ve just downloaded.

3. You’ll see a success message at the bottom. Then, you can use the “Gerber Viewer” link at the bottom right corner to check if everything went as expected. You can view the top and bottom of the PCB. You can view or hide the solder-mask, silkscreen, copper, etc.

With the default settings, you can order 10 PCBs for just $2. However, if you want to select other settings like a different PCB Color it will cost you a few more dollars.

When, you’re happy with your order. Click the “SAVE TO CART” button to complete the order.

My PCBs took 1 day to be manufactured and they arrived in 5 business days using DHL delivery option.

Unboxing

After a week, I received my PCBs at my office. Everything came well packed, and I also received a pen from JLCPCB.

Taking a closer look at the PCBs, I must say that I’m really impressed with the quality. I don’t think you can get a better PCB service for this price.

Soldering the Components

The next step was soldering the components to the PCB. I used SMD LEDs and SMD resistors. I know it’s a bit difficult to solder SMD components, but they can save a lot of space on the PCB. I’ve solder header pins to attach the ESP32, and the sensors. This way, I can easily replace the sensors, if needed.

Here’s a list of all the components you need to solder on the PCB:

The following figure shows how the PCB looks like after soldering all the components.

Preparing the ESP32 board in Arduino IDE

In order to upload code to your ESP32 using Arduino IDE, you should install an add-on for the Arduino IDE that allows you to program the ESP32 using the Arduino IDE and its programming language. Follow the next tutorial to prepare your Arduino IDE:

You also need to install the following libraries:

Code

The next step is writing the code to read the sensors and build the web server. The code for this project is divided into two parts:

  • The code in Arduino IDE to read the sensors and host a web server
  • An HTML file to build the web page. This HTML file should be saved in the microSD card.

Copy the code provided to the Arduino IDE. The code for this project is a bit long, but it’s fairly easy to understand. I’ve also added various comments along the code. Don’t upload the code yet.

/*
 * Rui Santos 
 * Complete Project Details https://randomnerdtutorials.com
 */

// Load required libraries
#include <WiFi.h>
#include "SD.h"
#include "DHT.h"
#include <Wire.h>
#include <Adafruit_BMP085.h>

// Replace with your network credentials
const char* ssid     = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

// uncomment one of the lines below for whatever DHT sensor type you're using
//#define DHTTYPE DHT11   // DHT 11
//#define DHTTYPE DHT21   // DHT 21 (AM2301)
#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321

// GPIO the DHT is connected to
const int DHTPin = 15;
//intialize DHT sensor
DHT dht(DHTPin, DHTTYPE);

// create a bmp object
Adafruit_BMP085 bmp;

// Web page file stored on the SD card
File webFile; 

// Set potentiometer GPIO
const int potPin = 32;

// IMPORTANT: At the moment, GPIO 4 doesn't work as an ADC when using the Wi-Fi library
// This is a limitation of this shield, but you can use another GPIO to get the LDR readings
const int LDRPin = 4;

// variables to store temperature and humidity
float tempC;
float tempF;
float humi;

// Variable to store the HTTP request
String header;

// Set web server port number to 80
WiFiServer server(80);

void setup(){    
  // initialize serial port
  Serial.begin(115200); 

  // initialize DHT sensor
  dht.begin();

  // initialize BMP180 sensor
  if (!bmp.begin()){
    Serial.println("Could not find BMP180 or BMP085 sensor");
    while (1) {}
  }

  // initialize SD card
  if(!SD.begin()){
      Serial.println("Card Mount Failed");
      return;
  }
  uint8_t cardType = SD.cardType();
  if(cardType == CARD_NONE){
      Serial.println("No SD card attached");
      return;
  }
  // initialize SD card
  Serial.println("Initializing SD card...");
  if (!SD.begin()) {
      Serial.println("ERROR - SD card initialization failed!");
      return;    // init failed
  }

  // Connect to Wi-Fi network with SSID and password
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  // Print local IP address and start web server
  Serial.println("");
  Serial.println("WiFi connected.");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  server.begin();
}

void loop(){
  WiFiClient client = server.available();   // Listen for incoming clients

  if (client) {  // if new client connects
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {   // client data available to read
        char c = client.read(); // read 1 byte (character) from client
        header += c;
        // if the current line is blank, you got two newline characters in a row.
        // that's the end of the client HTTP request, so send a response:
        if (c == '\n' && currentLineIsBlank) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          // Send XML file or Web page
          // If client already on the web page, browser requests with AJAX the latest
          // sensor readings (ESP32 sends the XML file)
          if (header.indexOf("update_readings") >= 0) {
            // send rest of HTTP header
            client.println("Content-Type: text/xml");
            client.println("Connection: keep-alive");
            client.println();
            // Send XML file with sensor readings
            sendXMLFile(client);
          }
          // When the client connects for the first time, send it the index.html file
          // stored in the microSD card
          else {  
            // send rest of HTTP header
            client.println("Content-Type: text/html");
            client.println("Connection: keep-alive");
            client.println();
            // send web page stored in microSD card
            webFile = SD.open("/index.html");
            if (webFile) {
              while(webFile.available()) {
                // send web page to client
                client.write(webFile.read()); 
              }
              webFile.close();
            }
          }
          break;
        }
        // every line of text received from the client ends with \r\n
        if (c == '\n') {
          // last character on line of received text
          // starting new line with next character read
          currentLineIsBlank = true;
        } 
        else if (c != '\r') {
          // a text character was received from client
          currentLineIsBlank = false;
        }
        } // end if (client.available())
    } // end while (client.connected())
    // Clear the header variable
    header = "";
    // Close the connection
    client.stop();
    Serial.println("Client disconnected.");
  } // end if (client)
}

// Send XML file with the latest sensor readings
void sendXMLFile(WiFiClient cl){
  // Read DHT sensor and update variables
  readDHT();

  // Prepare XML file
  cl.print("<?xml version = \"1.0\" ?>");
  cl.print("<inputs>");

  cl.print("<reading>");
  cl.print(tempC);
  cl.println("</reading>");
  
  cl.print("<reading>");
  cl.print(tempF);
  cl.println("</reading>");
  
  cl.print("<reading>");
  cl.print(humi);
  cl.println("</reading>");
  
  float currentTemperatureC = bmp.readTemperature();
  cl.print("<reading>");
  cl.print(currentTemperatureC);
  cl.println("</reading>");
  float currentTemperatureF = (9.0/5.0)*currentTemperatureC+32.0;
  cl.print("<reading>");
  cl.print(currentTemperatureF);
  cl.println("</reading>");
  
  cl.print("<reading>");
  cl.print(bmp.readPressure());
  cl.println("</reading>");
  
  cl.print("<reading>");
  cl.print(analogRead(potPin));
  cl.println("</reading>");

  // IMPORTANT: Read the note about GPIO 4 at the pin assignment 
  cl.print("<reading>");
  cl.print(analogRead(LDRPin));
  cl.println("</reading>");
  
  cl.print("</inputs>");
}

void readDHT(){
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  humi = dht.readHumidity();
  // Read temperature as Celsius (the default)
  tempC = dht.readTemperature();
  // Read temperature as Fahrenheit (isFahrenheit = true)
  tempF = dht.readTemperature(true);

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

  /*Serial.print("Humidity: ");
  Serial.print(humi);
  Serial.print(" %\t Temperature: ");
  Serial.print(tempC);
  Serial.print(" *C ");
  Serial.print(tempF);
  Serial.println(" *F");*/
}

View raw code

Before uploading the code, you need to modify the following lines to add your SSID and password.

// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

Then, press the upload button to upload the sketch to your ESP32. Make sure you have the right board and COM port selected.

Create a new file using a text editor, and copy the following code. Alternatively, you can click here to download the index.html file.

<!DOCTYPE html>
<html>
  <head>
    <title>ESP32 Weather Station</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="icon" href="data:,">
    <script>
      function DisplayCurrentTime() {
          var date = new Date();
          var hours = date.getHours() < 10 ? "0" + date.getHours() : date.getHours();
          var minutes = date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes();
          var seconds = date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds();
          time = hours + ":" + minutes + ":" + seconds;
          var currentTime = document.getElementById("currentTime");
          currentTime.innerHTML = time;
      };
      function GetReadings() {
      	nocache = "&nocache";
      	var request = new XMLHttpRequest();
      	request.onreadystatechange = function() {
    			if (this.status == 200) {
    				if (this.responseXML != null) {
    					// XML file received - contains sensor readings
    					var count;
    					var num_an = this.responseXML.getElementsByTagName('reading').length;
    					for (count = 0; count < num_an; count++) {
    						document.getElementsByClassName("reading")[count].innerHTML =
    					  this.responseXML.getElementsByTagName('reading')[count].childNodes[0].nodeValue;
    					}
    				}
    			}
      	}
      	// Send HTTP GET request to get the latest sensor readings
      	request.open("GET", "?update_readings" + nocache, true);
      	request.send(null);
        DisplayCurrentTime();
        setTimeout('GetReadings()', 10000);
      }
      document.addEventListener('DOMContentLoaded', function() {
        DisplayCurrentTime();
        GetReadings();
      }, false);
    </script>
    <style>
      body {
        text-align: center;
        font-family: "Trebuchet MS", Arial;
      }
      table {
        border-collapse: collapse;
        width:60%;
        margin-left:auto;
        margin-right:auto;
      }
      th {
        padding: 16px;
        background-color: #0043af;
        color: white;
      }
      tr {
        border: 1px solid #ddd;
        padding: 16px;
      }
      tr:hover {
        background-color: #bcbcbc;
      }
      td {
        border: none;
        padding: 16px;
      }
      .sensor {
        color:white;
        font-weight: bold;
        background-color: #bcbcbc;
        padding: 8px;
      }
    </style>
  </head>
  <body>
    <h1>ESP32 Weather Station</h1>
    <h3>Last update: <span id="currentTime"></span></h3>
    <table>
      <tr>
        <th>SENSOR</th>
        <th>MEASUREMENT</th>
        <th>VALUE</th>
      </tr>
      <tr>
        <td><span class="sensor">DHT</span></td>
        <td>Temp. Celsius</td>
        <td><span class="reading">...</span> *C</td>
      </tr>
      <tr>
        <td><span class="sensor">DHT</span></td>
        <td>Temp. Fahrenheit</td>
        <td><span class="reading">...</span> *F</td>
      </tr>
      <tr>
        <td><span class="sensor">DHT</span></td>
        <td>Humidity</td>
        <td><span class="reading">...</span> %</td>
      </tr>
      <tr>
        <td><span class="sensor">BMP180</span></td>
        <td>Temp. Celsius</td>
        <td><span class="reading">...</span> *C</td>
      </tr>
      <tr>
        <td><span class="sensor">BMP180</span></td>
        <td>Temp. Fahrenheit</td>
        <td><span class="reading">...</span> *F</td>
      </tr>
      <tr>
        <td><span class="sensor">BMP180</span></td>
        <td>Pressure</td>
        <td><span class="reading">...</span> Pa</td>
      </tr>
      <tr>
        <td><span class="sensor">POT</span></td>
        <td>Position</td>
        <td><span class="reading">...</span>/4095</td>
      </tr>
      <tr>
        <td><span class="sensor">LDR</span></td>
        <td>Luminosity</td>
        <td><span class="reading">...</span>/4095</td>
      </tr>
    </table>
  </body>
</html>

View raw code

This is HTML, and it will build your web page. In this file you can change how your web page looks, the headings, the table, etc… The ESP32 will send this HTML text to your browser when you make an HTTP request on the ESP32 IP address.

Save the file as index.html. Copy the HTML file to your microSD card, and insert the microSD card into the SD card module.

Now, everything should be ready.

Testing the ESP32 Weather Station Shield Web Server

Open the serial monitor at a baud rate of 115200, and check the ESP32 IP address.

By the end of the project, you have your own ESP32 weather station web server, and all the hardware is well compacted on a PCB.

Open your browser, type the IP address and you should see a table with the latest sensor readings. The web server displays the DHT22, BMP180, potentiometer and LDR readings. The readings are updated every 10 seconds without the need to refresh the web page.

To update the readings without refreshing the web page, we use AJAX. As you can read here, AJAX is a developer’s dream, because it can update the web page without reloading the page, request and receive data from a server, after the page has loaded, and send data to a server in the background.

Taking it Further

There’s still room to improve this project, you can use the extra terminals to connect other sensors or a relay. You can also program the ESP32 to trigger an event when a reading is below or above a certain threshold. The idea is that you modify the code provided to use the shield in a way that meets your own specific needs.

If you want to get your own all-in-one ESP32 weather station shield, you just need to upload the .zip file with the Gerber files to the JLCPCB website. You’ll get high quality PCBs for a very reasonable price.

Wrapping Up

I’m giving away 3 bare PCBs to someone that posts a comment below! [Update] the giveaway ended and the winners are: Horváth Balázs, Sayandeep Nayak, and Achim Kern.

We hope you’ve found this project useful. If you liked this project you may also like other related projects:

Thanks for reading.


Learn how to program and build projects with the ESP32 and ESP8266 using MicroPython firmware DOWNLOAD »

Learn how to program and build projects with the ESP32 and ESP8266 using MicroPython firmware DOWNLOAD »


Enjoyed this project? Stay updated by subscribing our weekly newsletter!

170 thoughts on “Build an All-in-One ESP32 Weather Station Shield”

  1. This is great, recently just install kicad. This post is a great starting point for me. I would love to use the pcb for my campus to monitor various situation on it and do more research for iot

    Reply
  2. The sketch does not compile … error on void setup() ==> uint8_t cardType = SD.cardType();

    Thanks a lot for an answer how to fix ==> without sd-card th program works fine on compilation

    // initialize SD card
    if(!SD.begin()){
    Serial.println(“Card Mount Failed”);
    return;
    }
    uint8_t cardType = SD.cardType();
    if(cardType == CARD_NONE){
    Serial.println(“No SD card attached”);
    return;

    Reply
  3. Nice project, i might add a MQTT client to it, so I can use it with my home automation system, to show some nice dashboards about the state of my house

    Reply
    • Exactly, that’s a future project that I’ll be doing with this board.
      For this tutorial, I wanted to show how you could store a full HTML web page and load it on an ESP32 web server.

      Thanks for your feedback!
      Rui

      Reply
  4. It’s a really great project! If i got one of these PCBs i would remove the dht and replace the bmp180 with a bme280. I look forward to seeing more of these projects!

    Reply
  5. Great project, nice end to end example, alot of projects only show the source end as in the data collector and not where the data goes and how it is displayed to the receiver. I hope this inspires others to start making smart stuff.

    Reply
  6. Awesome yet super simple project!!! Many weather station I had seen, this is the one make the most simple and yet very functional. the author, Rui, explain in very simple and functional way! I highly recommended anyone who want to be familiar with the programming or want to understand how things work to start with Rui. Rui, you did it again! Well done!

    Reply
  7. Excellent work, but unfortuatly ESP32 Code can not be compiled with the Arduino IDE on older MACs, Problem ist know, missing parameter in the tool chain, but nobody seams to be willing to fix ist. Have some ESP32 boards laying on may table and a lot of projects for tehm, but my hands are boud in case of my 2008 24″ iMAC working still very well with el capitan

    Reply
    • I wasn’t aware of that problem. I’ve tested the ESP32 with Arduino on a 2011 MacBook computer and it worked for me… It’s unfortunate, but it’s also very hard to keep the software compatible with every OS and version.
      Thanks for your feedback!
      Regards,
      Rui

      Reply
    • If you want a full web server that is always available, you need to have a power supply constantly providing power.
      However, if you want to run this project on batteries or solar energy…
      You could probably do it, if you would post the readings a few times per hour.
      I might do a project on that subject in the future.

      Thanks!
      Rui

      Reply
  8. Perfect – i like how you present your work – awesome – the idea with a pcb is absolutely great.
    I will think about that – make my sensor nodes this way hopefully one day also.

    Reply
  9. I’m wondering how hard this would be to convert to read two different humidity/temp locations. i.e. the outside and then inside of a beehive. The small size looks like it could easily fit into the top of a Warre hive. Adding that, would there still be an input left over to maybe read a weight from an electronic scale placed on the bottom of the hive? Thank you so much for sharing this project.

    Reply
  10. Hi Rui,
    It’s crazy when PCB manufacturer’s charge so much for postage.
    Your $2 board would cost $24 to ship to the UK!!!
    I don’t see why, when one can buy parts from China on say Ali Express for zero delivery cost.
    Nice project by the way, keep up the good work.

    Reply
    • Hi David,
      With JLCPCB, you can order your first 10 PCBs for $2 (they offer free shipping in your first order). At least, that’s what happened for me.
      Afterwards, it costs around $10 for delivery with normal postage (at least to Portugal).

      To save on shipping costs, if you have multiple PCBs that you want to order, you can do it at once.
      It’s really cheap (10 PCBs = $2) + (10 PCBs = $2) + (Normal Shipping = $10) Total of $14. You end up paying like $7 for 10 PCBs…

      Thanks for your feedback!
      Rui

      Reply
  11. Thank you for sharing this project and for the extensive detailing.

    Yes I aim for the (free) PCB as I would like to integrate my Bird breeding cage into my Domoticz project.

    It will be fun to alarm the parents when the nest turns too cold.

    Reply
    • Yes, with JLCPCB, you can order your first 10 PCBs for $2 (they offer free shipping in your first order).
      I’ll try to explore how to make PCBs in more detail in future tutorials.

      Thanks for your feedback!
      Rui

      Reply
  12. Great project and write up. The only thing that I would do differently if I had the board would be to use a pin compatible BME280 sensor, which combines the temperature, humidity, and pressure sensors onto one I2C module. The code could be modified fairly easily. Thanks for the informative post, and please enter me in you contest.

    Reply
    • Thanks Max! I definitely plan to add the BME280 in a future shield that I have planed for the WeMos D1 Mini.
      Thanks for entering the giveaway! I’ll select randomly 3 readers until the end of the week.

      Reply
    • Hi there @maxwaynet , I did used the BME280 and managed to change the code to work with it. The only thing is the temperature is not correct. I think I’m having Faranheit instead of Celsius.

      Reply
  13. Hi would repurpose your board and ajax hmi for remote logging in a security system i have. Particular sub system has 12 x digital inputs and 12 x relay switched outputs. External rtc, temperature, humidity and barometer (all i2c) devices are also available in sub system.

    Good project (yours) and keep up good work!

    Reply
  14. This looks to be a great project. Many of your projects are very good, the biggest problem I have is I never complete as I find something very interesting and wind up following a different path that leads to more exploration.

    Reply
  15. Nice project. It provides the sensors I would implement into a stand alone weather station. It only needs a solar powersupply and battery power to be stand alone.

    Reply
  16. Cool project. I am working towards building a weather station that displays 3 days of weather forecast on a 7in display. Got one working on a .9in oled and its cool. This would be a great way to start the project off. Good job on the design.

    Reply
  17. Hi Rui
    Another great project from you. I wish I could design my own boards. I second or third the use of bme280s. There is even an even newer module from Bosch, the bme680. Haven’t tried it yet nor do I know about it’s library status. I would also use or include 2 headers for DS18B20 temp sensors. Very accurate and very easy to read. You can even get them encased in metal with 3 to 9 foot leads. That’s what I use for external temp readings on my weather station.

    Reply
  18. As always, a great presentation Rui~!~
    Oh, you might want to mention Chinese New Year, usually, no one works till after Feb. 20th.
    Tnx…
    ~AF7U

    Reply
    • Yup Michael! I forgot to mention that, but they clearly say in their website when you’re trying to check out the expected delivery date.
      Thanks for bringing that up!
      Regards,
      Rui

      Reply
  19. Thanks a lot of for this great learning issue. I am working only with ancient PCB, which are selfmade. It is a new, great way to work easy with new technologie of PCB-s. I heard already about AJAX, but not heard yet about its good performance and suitability for our targets (updatable sensor reading). Thanks!

    Reply
  20. Nice and very clear project. I plan to do something similar: on one outside weather station to add some sensors for wind direction, wind speed and rain value. On few inside weather stations connect just temperature and humidity sensors and monitor all rooms of house and outside weather on one place.
    Do you thing that more weather stations could be connected to web server and share this server by WiFi?

    Reply
    • Hi Dan!

      I’ve been thinking about creating a small shield for the WeMos D1 Mini with BME280 + LDR + PIR + 2 available GPIOs to connect relays.

      In one day or two, I should have the tracking number for the Arduino giveaway that you won! I’ll email you more info when I have it.
      Regards,
      Rui

      Reply
  21. I’m already collecting various sensors to build a similar weather station. This tutorial is great! I’ve been studying your ESP8266 Web Server tutorial, and really enjoy it.

    I’d probably change to a BMP 280 sensor. The baro, temp and humidity readings are a good start. I hadn’t thought about the light level sensor, I like that. Maybe add a UV sensor? might indicate how much sun there is.

    I see the POT for position? I would add a weather vane to that, to give wind direction. A small DC generator (motor) could give wind speed if anemometer cups were added.

    I’ve been playing with outdoor temp/humidity sensors. Keep them out of the rain! I think mine finally dried out. Temp in sun and temp in shade could be useful. I walk several miles each day, and I’m trying to improve my understanding of the weather outside. Humidity is also a factor. More research is needed!

    Great project!

    Alan

    Reply
    • Hi Alan,
      The idea behind using the POT was to calibrate some sort of trigger. For example, if I rotate the potentiometer to 90%, it would need a certain percentage of luminosity to turn on/off a relay.
      There are terminals still available that you could connect other sensors.

      Thanks for your thoughtful feedback!
      Regardsm
      Rui

      Reply
  22. Hi Rui,
    Designing and ordering PC boards is not an option for me, Takes too long for one board which is all i ever need.
    I have been looking for an alternative but as yet have not found one to suit my needs.
    Described below is what i would wish for.
    A printed circuit board the exact shape and design of a popular bread board. It would have copper
    print on the bottom side and ink print of the bread board on the top side with
    the pre-drilled holes matching the bread board so component leads pass through the lay on board
    and into the bread board.( Hope this making sense). When the circuit is operating to your satisfaction lift the components slightly apply a small drop of adhesive. When adhesive cures
    lift layon circuit board, invert, solder and trim excess leads.
    Hope this makes sense.
    Ross

    Reply
    • Hi Rosco,
      For my needs I can usually wait a week or two. And work on another project in the meanwhile.
      But I understand that for quick projects, you might want to etch your own boards for example

      Thanks for your feedback!
      Regards,
      Rui

      Reply
  23. This would be great for my greenhouse project. I would add a relay to activate my pump and also a soil moisture sensor would work brilliantly.

    Reply
    • Yes, you can definitely add a soil moisture to one of the available GPIOs.
      You’ve also entered the giveaway! I’ll select randomly 3 readers until the end of the week.

      Regards,
      Rui

      Reply
  24. Hi Rui,
    First, thank you!
    My kids brought your article to me. I’m relatively new to the Arduino and the Espressif chips, but have worked with microprocessors since the 8080s walked the earth. Your project is exactly what I need to get into this new development. My goal is to make a battery operated version of this, using the ULP to sleep everything until it’s time for a reading. I’d like to hook a local e-paper display to it, and an external sensor or two. I’d also like to configure the WiFi using the BLE radio, and maybe detect when when a phone is nearby & send it a beacon. That should be enough to figure out for the first project. See what you made me do ? Now I’m interested ;-).
    Thanks again. I hope you inspire many others to jump in, just like you inspired me & the kids. I’m sure you have. Great job!

    Reply
    • Thank you Randy! I’m happy to inspire everyone to build projects, that’s why I take time to write them 🙂

      That looks like a fun project. I also plan to post BLE projects with the ESP32 in the upcoming weeks!

      Regards,
      Rui

      Reply
    • Exactly, this was more like a demonstration. In a real application, I’ll make the ESP32 publish the readings to Node-RED.
      There are also pins available that you can use to connect other sensors. Thanks!
      Rui

      Reply
  25. Brilliant. Just what I needed. I spent a long time trying to get a weather logger to work so I could monitor conditions in my holiday cottage. Got it working after a fashion but this is much better. And in addition I can add two extra sensors for outside temp and humidity. Thanks.

    Reply
  26. I love your work! I always get inspiration from your projects! I was thinking for about sometime now on how to build something similar and integrate it with my homeassistant setup to automate the shades at my place. You just made it a lot easier 🙂

    Reply
  27. Rui. It appears that all the micro SD cards available in the UK have a different pin out to the one in your project. The pin outs here are ‘GND,VCC,MISO,MOSI,SCK, CS’.
    I have looked at the KiCAD programme but i am out of my depth.
    Is there a simple way around the problem.
    Thanks Peter

    Reply
    • Hi Peter,
      I’ve used this module from Banggood: banggood.com/Mini-Micro-SD-Card-Module-For-Arduino-AVR-ARM-p-1078570.html?aff_key=21k2_dkf9y&utm_source=ShareASale&utm_medium=aff&cur_warehouse=CN

      Reply
      • Rui. Thanks for the link. Currently out of stock so until they become available again I will mount the the micro SD card on a sub board.

        Reply
  28. Hey. I was highly interested in weather stations especially using the latest esp32 board. A bare board would really be good as I am planning to design the ultimate weather that will utilize the above parameters and also would display them on a oled screen.

    Reply
  29. Dear Rui,
    great idea and very very usefull for my doings. To make the circuit completely, I recommend to extend with a SDS011 Dustsensor. It would be great if You take it into consideration and enlarge the board circuit with that device and the appropriate code.
    I will try it by myself, but haven’t that experice, in any case I will establish Your this actual great project, therefore it would be very lucky for me to get a free PCB to start.
    Looking forward to get new ideas, go ahead please … it’s great
    Yours
    armin thoma

    Reply
  30. It is a super-duper project . This handy weather station is for everyone. It would be really nice add on if there was a mesh network of monitoring system in various locations. Thank you dude for the well explanation of every step. Loved it .

    Reply
  31. I have a Sous Vide Cooker going in the basement and currently I have to go downstairs to check on its progress. I am working on another project to measure cook time, temp(2), Voltage and Power(watts). I’m currently logging on an SD card and displaying on a OLED at the controller in the basement. With your project I am hoping to be able to put my data on a web page and view it upstairs on my smartphone. I was going to put it on ThingSpeak but this seems to be a better solution.

    Reply
  32. Rui. I really want to make this great project but I am having trouble compiling the code using Arduino 1.8.5. Nou sure if this is the right place to ask for help but I keep getting the following errors
    C:\Users\Peter\Documents\Arduino\Weather2\Weather2.ino: In function ‘void setup()’:

    Weather2:71: error: ‘class SdFat’ has no member named ‘cardType’
    uint8_t cardType = SD.cardType();

    ^

    Weather2:72: error: ‘CARD_NONE’ was not declared in this scope
    if(cardType == CARD_NONE){

    ^

    Weather2:86: error: invalid conversion from ‘const char*’ to ‘char*’ [-fpermissive]

    WiFi.begin(ssid, password);

    ^

    In file included from C:\Users\Peter\Documents\Arduino\Weather2\Weather2.ino:7:0:

    C:\Users\Peter\Documents\Arduino\libraries\WiFi\src/WiFi.h:79:9: error: initializing argument 1 of ‘int WiFiClass::begin(char*, const char*)’ [-fpermissive]

    int begin(char* ssid, const char *passphrase.
    Can you help please

    Reply
  33. Hi Rui,

    I have used some DHT11 sensor in the past. Throwing a horse-iron is more precise than these crappy DHT11-Sensors. In your project you are using a DHT22-sensor for measuring hunidity.
    I suspect the DHTs to be not so precise. If you spend mabye 5 dollars more you could use a
    Sensirion SHT31-humidity and temperature-sensor which has more precision.
    SOS-Electronics offers a SHT31 Break-Out-Borad BOB for $7,50
    https://www.soselectronic.de/products/sensirion/sht-31d-bob-218177?gclid=EAIaIQobChMIqfHI0Lqt2QIVlGwbCh2kkQi1EAkYASABEgKc__D_BwE

    best regards

    Stefan

    Reply
  34. Love this article and now waiting for my parts so I can build it as I am trying to get my grandson interested in electronics.
    One thing I would really like to see is when providing KiCad schematics, to put a short track (with hole) on un-used pins so people who who are not familiar with KiCad can use the extra available short track and pin connections for future experimentation.
    I will be attempting to add a wind speed sensor to mine when I build it (nothing fancy, just three wind cups with reed switches operated by a magnet as the spindle rotates.
    It has been 20 years since I last used a soldering iron and this article gave me the incentive to dust it off and get my grand children involved as well.

    Reply
    • Hi John! We’re glad you’ve liked this project and we’re happy that you’re experimenting again with electronics projects! 🙂

      Reply
  35. Tip for the ESP32 dev board: not only there are versions with different pin settings, but there are dev-boards which are 5 mm wider also (21 mm or 26 mm width)
    And when soldering the female headers, I put in the dev board first, which gives a perfect alignment.

    Reply
    • It might also be useful if the min/max value for resistance was given for the LDR. The link through from MakerAdvisor indicates a max of 100k but this seems a bit low and indeed, I’m struggling to find a local supplier (farnell, Maplin, Radio Shack type places).

      Reply
      • Hi George.
        We use a 10KOhm resistor for the LDR.
        The links on maker advisor show options from 10 Ohm to 10M Ohm. So, you should be able to find a suitable resistor in that range.
        Thanks 🙂

        Reply
  36. Thank you for sharing this project and the detailled Instructions.
    I have no SD-Card-Module, so I tried to read the HTML-file from SPIFFS but I my code generated errors.
    My solution: I put the HTML-file on my raspberry-website and the ESP32 sends the XML datafile. The “same origin” problem was solved with an additional line in the HTML-header:
    // send rest of HTTP header
    client.println(“Content-Type: text/xml”);
    //added:
    client.println(“Access-Control-Allow-Origin: http://192.168.1.123“);

    Reply
  37. Hi Rui, I managed to build it but i am having problems with DHT, every few readings i get error:
    Failed to read from DHT sensor!
    When I tried that sensor on arduino, using provided example .ino from DHT library, it worked 2 days sending data to serial port, with no error.
    What could be the the problem?

    Reply
    • Hi.
      Sometimes we came across the same issue. The DHT fails some measurements, and then reads again without additional modifications.
      I’m not sure whether that happens. Sometimes it’s a bad connection between the DHT and ESP pins. Other times, we haven’t find out why that happens.
      Regards,
      Sara 🙂

      Reply
  38. Nice project!
    but I dont wish to wait or to finalize the project on PCB! Of course de ESP32 cannot be fixed on a breadboard… except if you follow this advise:
    Cut a normal breadboard in the middle along the long side (you will not cut any connector), separate de 2 pieces and joint it fixing the ESP32 to leave on each side of the ESP32 a row of holes to insert you pins.
    Very easy to do… very usefull for the future of ESP32!

    Reply
    • Hi Jose.
      Yes, you can make the ESP32 breadboard friendly if you separate the side pieces of two breadboards.
      Thanks for sharing that tip 🙂

      Reply
  39. I was on the right way to finalize the project but at the moment it seems that all the sensors are operating (I checked all separately) …
    BUT when I open 192.168.1.28 (my IP address) with Google Chrome I receive only the index.html as a text without the html conversion and nothing more!
    What can I change?
    From where it can come???

    Reply
  40. Hello Rui, and many thanks for this project.
    But did someone tried it ? Because I did, and I have many BUGS compiling the code, i.e. line 54: “Wi.FiServer” is faulty… Isn’t it “WebServer” instead ?(I’m just trying to understand, I’m a new born baby in Arduino and coding)
    and also line 107, Wi.FiClient doesn’t compile in any way. I have no idea why…
    Plus I had to add “Adafruit.sensor” library and have many problems compiling sd card module. I had to include esp32-micro-sd-card library.
    If I can make a general request to pros, please give us (new born babies) a few more clues about which library was used in your codes, especially when a couple or more of those seems to have the same name (or almost) but different functions. Actually, I’m talking about SD.h.
    Or there might be a point (yet another one) I’ve lost on the road.
    Please excose my dumb interrogations and don’t want to criticise, I love your project but I have compilation problems, so I try to understand with my poor skills and try to ask with my weak english, so sorry also for any wrong formulation.
    Thanks for your clean project, I’ve learn a lot allready, can’t wait to see it run (on breadboard at first)
    pro972

    Reply
    • Yes, I have many readers that sent me photos via email/Facebook with the shield working!
      It looks like it’s something missing in your Arduino IDE installation. It’s usually something about the ESP32 add-on and that can cause some incompatibilities with the Arduino IDE libraries.
      I can guarantee that the code works and it compiles, if you have the right libraries installed. It’s a bit challenging to write instructions with everything needed to work in every scenario and Arduino IDE installation.

      Can you post the exact error that it prints when you compile the code?
      Are you using Arduino IDE version 1.8.5?

      Regards,
      Rui

      Reply
  41. Just built it, thanks for sharing….
    A Couple of things, wondering if anyone has spent any time on the code to,
    1. Log the readings to the SD Card?
    2. Wondering the purpose of the LED’s?

    Reply
  42. Great article. I have received 10 PCBs to your excellent design. I won’t use them all so if you want to distribute some more let me know

    Reply
    • Hi Chris!
      That’s very kind of you.
      We still have some PCBs of that project. At the moment, we don’t need more. But if we’ll need, we’ll let you know.
      However, if someone is interested in getting one, maybe they can reach out to you.
      Regards,
      Sara

      Reply
  43. Hello Rui Santos
    I have worked with the weather station for some time, but I have a problem that has taken some time for me and I have not found a solution at this time.
    I use the downloaded software and I open the browser with the correct IP address.
    The website shows the correct measurements, so it is OK.
    The problem is that the website does not update the measurements – only the time updates.
    If I close the browser and reopen it the website shows updated values.
    I have no more ideas
    Can I get a hint from You?

    Additional information:
    I did not have a BMP180, but I had a BME280 and I changed the code to work with this hw. It works.
    I did some debugging

    Serial.print(“header.index: “);//debug
    Serial.println(header.indexOf(“update_readings”));//debug result -1
    Serial.println(“Jeg venter her”);//debug
    if (header.indexOf(“update_readings”) >= 0)
    I see “update readings” is < =0, and the client is terminated.
    I find your tutorials very helpful, and this is the first time I face a problem which is difficult to solve.
    Kind regards
    Egon

    Reply
    • Hi Egon.
      The web page should update the sensor readings every 10 seconds. We use AJAX to automatically refresh the web page.
      Using the BMP180 instead of the BME280 shouldn’t have any impact on the code.
      Have you changed anything else?
      It’s difficult to understand why it is not working.
      Regards,
      Sara 🙂

      Reply
      • Hi Sara
        No, the only change I have made is changing to BME280 and some serial print statements for debugging.
        One of the print statements show me:
        Serial.println(header.indexOf(“update_readings”));//debug result -1
        After that the client is terminated and the web site do not update readings
        Kind regards
        Egon

        Reply
  44. Hello again
    Yes, I agree with you that it is difficult to understand why it is not working.
    The fact is that it works one time when I open the browser with the correct IP.
    Close the browser and reopen it and you will see updated measurements. The clock update at the website every ten second but the measurements do not. This is the problem in a nutshell.
    I think it had something to do with AJAX which is new to me.
    I have done a lot of debugging but not found a smoking gun.
    Therefore I ask for a hint to what to try next.
    Thank you in advance.
    Kind regards
    Egon

    Reply
    • Hi again.
      As you’ve said, the problem might be the AJAX.
      Because you’re not receiving the update_readings request.
      I don’t know why it is not working – it worked perfectly for us.
      Which browser are you using?
      We’ve tested this with Google Chrome. I don’t know if using other browser might have any impact on the project.
      I really would like to help you, but at the moment I don’t know what else I can do :/
      Regards,
      Sara

      Reply
      • Hi Sara
        I have solved the problem. It was caused by my AVG safety software. It blocked the communication after the first update of the screen without warning.
        Sorry for taken your time with this.
        Thank you for your answer anyway.
        Kind regards
        Egon

        Reply
  45. Hi Sara,

    Nice project, thanks a lot.
    I’ve learned a lot.
    The only I had was the DHT. No output.
    I had to try several libraries to at last find the DHTesp.h library which was able to give an output.
    Now, I’ll get rid of the DHT and use a BMP280.
    Thanks again.

    JLB

    Reply
  46. hi rui
    trying to make it work but “card mount failed” in serial monitor
    wired up correctly and changed sd card reader.. im stuck, any suggestions??
    tom

    Reply
  47. Olá Rui e felicitações pelo projecto. Serve que nem uma luva para apresentar como iniciação ao IoT, assim como à soldadura e electrónica.
    Já construí a primeira estação meteorológica e espero conseguir construir mais. Mas primeiro quero aprender a alterar o código para as minhas intenções e necessidades.
    Para já, não consigo perceber porque não me apresenta os dados do LDR, apesar de ter alterado o GPIO para o 02. Também estou à procura de exemplos de como pôr o botão a funcionar, para poder atribuir-lhe alguma outra função, como também os LED.
    Grande abraço e continuação de bons projectos, simples, explícitos e com baixo custo, para quem quer aprender.
    João Catarino

    Reply
    • Olá João.
      Mais tarde, percebi a razão pela qual não conseguia obter os valores do LDR.
      Basicamente, os ADC2 não funcionam quando se usa Wi-Fi. o GPIO 2 também pertence aos ADC2, é por isso que não funciona.
      Tem de escolher outro pino que seja ADC1, por exemplo, GPIO33.
      Para aprender mais sobre isto, pode consultar o nosso guia para os GPIOs da ESP32: https://randomnerdtutorials.com/esp32-pinout-reference-gpios/
      Obrigada por seguir o nosso trabalho.

      Cumprimentos,
      Sara

      P.S. Da próxima vez, tente colocar as questões em inglês, pois podem ser úteis para os nossos outros leitores.

      Reply
      • Olá Sara,
        obrigado pela resposta. Vou fazer isso mesmo que me diz.
        Efectivamente, ainda ponderei comentar em Inglês, pois não é problema para mim. No entanto, lembrei-me de que, nos grupos e forums que frequento, muitas vezes o pessoal usa o tradutor e conseguem safar-se. Mas sim, entendo e queria só dar uma palavra de apreço a dois compatriotas, os quais, estão a desenvolver um trabalho excepcional na divulgação destas tecnologias.
        Prometo que de futuro irei comentar em Inglês, que, em bem da verdade é mais justo para todos.
        Resta-me acrescentar que, este projecto, do qual já tenho pelo menos dez placas, vai servir para um projecto que tenho em mente e sobre o qual vou fazer uns workshops no nosso makerspace, divulgando ao mesmo tempo o vosso site e excelente trabalho.

        Cumprimentos,
        João Catarino

        Reply
  48. Hi Rui,
    I’d appreciate so much about this project. Is it possible that instead of a using sensors, I will just connect my Arduino mega2560 and this ESP32 will read
    the logic status of 32 I/Os of my Arduino Mega2560, but ESP32 has only limited I/Os that can accommodate the need. Can we utilized the I2C or SPI or Rx/Tx communication, please help me solve this it will be a great help..
    Sincerely Yours,
    Monico

    Reply
  49. HI again.
    I order the board to jlpcb as i saw at your site.
    Now when uploading withoutto ESP32 to prepare while i wait for the board because maybe it arrives tin one or two days (i think i can do it??), i get the error:

    no matching function for call to ‘SDClass::begin()’

    Reply
  50. I have my boards already, waiting for bmp and sc card reader, almost ready, thanks a lot, great project, hope material arrives soon to test it, keep going great projects you have

    Reply
  51. For those guys still about to order the pcbs: Import the files into easy easyeda (easyeda.com/) and change the connection from pin 4 to pin 2 or something else 😉
    That way you won’t have to run an extra wire to remedy the pin 4 issue.

    A really great pcb, looking forward to getting mine (with the changed lanes). I also opted for some SMDs to be soldered onto the pcb before delivery. Had a voucher and will safe me the trouble of ordering the parts myself.
    Might want to include that in the BOM of the PCB as an option for people who are scared of soldering SMD parts.
    I will only be soldering the LEDs, connectors and terminals

    Reply
    • Already arrived without change nothing 3 days ago.
      I soldered myself only wait for card reader to test..
      pety not year that before, but thanks.

      Reply
  52. Hi again.
    Board ready but now when i upload iget the error:

    no matching function for call to ‘SDClass::begin()’
    can you helpplease?
    Thanks.

    Reply
  53. my esp32 is LOLIN
    i see diference in piout layout from yours to mine, and get the error:
    no matching function for call to ‘SDClass::begin()’
    Hope you help me, thanks

    Reply
    • Hi Paulo.
      Make sure you have an ESP32 board selected under Tools > Board. Try selecting ESP32 Wrover module and see what you get.
      That library should exist for the ESP32 board by default.
      Regards,
      Sara

      Reply
  54. Hi Sara.
    sorry for saying thanks so late but i was out, and waiting for thr right board the other wasent. Now yes it uploads with ESP32 Wrover module selected but then nothing, i think that doesnt login into the network.No lectures, allways blank.
    Any idea?
    Thank you for any tip.

    Reply
  55. Sorry …
    Ok it uploads pressing boot buton, then blank and i press buton (EN) on esp32 and i get this:

    18:20:26.488 -> ets Jun 8 2016 00:22:57
    18:20:26.488 ->
    18:20:26.488 -> rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
    18:20:26.488 -> configsip: 0, SPIWP:0xee
    18:20:26.488 -> clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
    18:20:26.488 -> mode:DIO, clock div:1
    18:20:26.522 -> load:0x3fff0018,len:4
    18:20:26.522 -> load:0x3fff001c,len:1044
    18:20:26.522 -> load:0x40078000,len:8896
    18:20:26.522 -> load:0x40080400,len:5816
    18:20:26.522 -> entry 0x400806ac
    18:20:27.823 -> Card Mount Failed
    hope you help me, thanks

    Reply
  56. Hi again.
    soved the problem..
    I found this in net someone post:
    (for anybody else that has the same problem with the micro SD module you should connect the VCC pin of micro SD card module to pin Vin of ESP32 not 3.3 V out. The micro-sd card module needs 5V and can’t work by 3.3 V)
    Mi module works with 5v and as soon as i conect it, starts working right away.
    Now i have to fix the light sensor the thing abought the pin 4 isnt it?
    Thanks for everything, and for the pacience withmy questions.

    Reply
  57. Hi again.
    I dont understand watt is the readings of positio, can you explin me please, i have something like:
    POT Position 1803/4095
    Thanks, again

    Reply
  58. Hi Sara zan you please tell me the meaning of POT POSTION, i have 18080/04095, I dont know what is this reading abought, and also if it is correct.
    Thanks, best regards.

    Reply
  59. Sara tell me please wht means POT position, geografic positio i see in google and its diferent.
    Thanks a lot.
    Sorry to be all the time asking for something, but i dont know programing and have allways a lot of questions, thanks

    Reply
    • Hi.
      POT simply means the position of the potentiometer on the shield.
      It is just an example. You may want to use the potentiometer to set a threshold, for example.
      Regards,
      Sara

      Reply
      • Hi Sara, thanks for the information.
        Keep going with your work, you help a lot of people making stuff that couldnt buy like me, and this way i can have the things cheap and working fine.
        Thank you very much.

        Reply
  60. Hi.
    My weather shield works everything only dont read light, i changed to GPIO33 and nothing.
    Any idea?
    Thanks very much, hope you can help.

    Reply
  61. Hi Sara.
    already fixed light sensor was a bad conection, now works fine on GPIO3, like everything on the board, thanks a lot, best regards.
    Keep doing the great job you are doing.

    Reply
  62. Hi Guys.
    I am new to these modules. I’ve started with Arduino however found to be drawn to the ESP32. I’ve always been interested in automation just never had the time or materials to make it work. I used to do everything using PC’s and basic language. Now I find myself interested in the microPython.
    OK, not knowing the programming language and interested in these micro controllers how can I learn the ESP32 to measure the following. A set of software gauges for vacuum , pressure , voltage and time. This is for a project I would like to make. I have the sensors and have worked with them using Arduino. I just need maybe places to look for more information.
    By the way I have signed up for one of our courses.

    Reply

Leave a Comment

Download our Free eBooks and Resources

Get instant access to our FREE eBooks, Resources, and Exclusive Electronics Projects by entering your email address below.