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.

This is our complete guide to program the ESP32 with Arduino IDE, including projects, tips, and tricks!  SIGN UP NOW »

This is our complete guide to program the ESP32 with Arduino IDE, including projects, tips, and tricks! SIGN UP NOW »

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.

Download our Free eBooks and Resources

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!

141 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

  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;

  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

    • 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

  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!

  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.

  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!

  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

    • 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

    • 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

  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.

  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.

  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.

    • 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

  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.

    • 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

  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.

    • 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.

  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!

  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.

  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.

  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.

  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.

  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

    • 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

  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!

  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?

    • 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

  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

    • 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

  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

    • 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

  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.

    • 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

  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!

    • 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

  25. Nice one Rui! Just needs a wind speed sensor on top of all the other sensors you could add! Publish to mqtt and you are all set!

    • 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

  26. 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.

  27. 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 🙂

  28. 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

    • 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

      • 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.

  29. 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.

  30. 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

  31. 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 .

  32. 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.

  33. 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

  34. 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

  35. 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.

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

  36. 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.

    • 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).

      • 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 🙂

  37. 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“);

  38. 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?

    • 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 🙂

  39. 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!

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

  40. 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???

  41. 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

    • 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

  42. 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?

  43. 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

    • 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

  44. 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

    • 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 🙂

      • 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

  45. 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

    • 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

      • 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

  46. 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

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.