Tech Facts

A Simple Guide to Building ESP32 Weather Station

A Simple Guide to Building ESP32 Weather Station

In this blog, we will be putting together a compact ‘Weather Station’ using a variety of sensors. The platform being used is an ESP32 development board with built-in Wi-Fi. This will provide communication to the sensors along with a power source. As we work through the project, we will interface various sensors to ESP32. In this process, we create the software sketch to run the weather station.

On completion of the project, the following data will be available:

  • Temperature (BME680)
  • Humidity (BME680)
  • Barometric Pressure (BME280)
  • Rain Gauge (Davis Rain Gauge)
  • Wind Speed (Davis Anemometer)
  • Wind Direction (Davis Anemometer)


The project is broken up into many parts. We will work through connecting each sensor and developing the software as we connect each sensor to the ESP32. The software we use is based on the hookup guides for each sensor and the software library for that sensor. 

BME 680 

This compact sensor contains temperaturehumiditybarometric pressure, and VOC gas sensing capabilities over SPI or I2C. The BME680 takes those sensors to the next step, containing a small MOX sensor. The heated metal oxide changes resistance based on the volatile organic compounds (VOC) in the air, so it can be used to detect gasses & alcohols such as Ethanol, Alcohol, and Carbon Monoxide and perform air quality measurements.


Wire ColorESP32 Connection


#include <Wire.h>

#include <SPI.h>

#include <Adafruit_Sensor.h>

#include “Adafruit_BME680.h”

#define BME_SCK 13

#define BME_MISO 12

#define BME_MOSI 11

#define BME_CS 10

#define SEALEVELPRESSURE_HPA (1013.25)

Adafruit_BME680 bme; // I2C

//Adafruit_BME680 bme(BME_CS); // hardware SPI

//Adafruit_BME680 bme(BME_CS, BME_MOSI, BME_MISO,  BME_SCK);

void setup() {


  while (!Serial);

  Serial.println(F(“BME680 test”));

  if (!bme.begin()) {

    Serial.println(“Could not find a valid BME680 sensor, check wiring!”);

    while (1);


  // Set up oversampling and filter initialization





  bme.setGasHeater(320, 150); // 320*C for 150 ms


void loop() {

  if (! bme.performReading()) {

    Serial.println(“Failed to perform reading :(“);



  Serial.print(“Temperature = “);


  Serial.println(” *C”);

  Serial.print(“Pressure = “);

  Serial.print(bme.pressure / 100.0);

  Serial.println(” hPa”);

  Serial.print(“Humidity = “);


  Serial.println(” %”);

  Serial.print(“Gas = “);

  Serial.print(bme.gas_resistance / 1000.0);

  Serial.println(” KOhms”);

  Serial.print(“Approx. Altitude = “);


  Serial.println(” m”);




Davis Anemometer

This includes both wind speed and wind direction sensors. Rugged components stand up to hurricane‐force winds yet are sensitive to a light breeze. Davis Anemometer includes sealed bearings for long life. Wind Speed is determined by a reed switch interrupt, and Wind direction is determined by the voltage output from the in-build 20K potentiometer.


Wire ColorESP32 Connection
BlackWind speed IO12
GreenWind direction pot IO32


#include “TimerOne.h” // Timer Interrupt set to 2 seconds for read sensors
#include <math.h>

#define WindSensorPin (12) // The pin location of the anemometer sensor
#define WindVanePin (32) // The pin the wind vane sensor is connected to
#define VaneOffset 0; // define the anemometer offset from magnetic north

int VaneValue; // raw analog value from wind vane
int Direction; // translated 0 – 360 direction
int CalDirection; // converted value with offset applied
int LastValue; // last direction value

volatile bool IsSampleRequired; // this is set true every 2.5s. Get wind speed
volatile unsigned int TimerCount; // used to determine 2.5sec timer count
volatile unsigned long Rotations; // cup rotation counter used in interrupt routine
volatile unsigned long ContactBounceTime; // Timer to avoid contact bounce in isr

float WindSpeed; // speed miles per hour

void setup() {

LastValue = 0;

IsSampleRequired = false;

TimerCount = 0;
Rotations = 0; // Set Rotations to 0 ready for calculations


pinMode(WindSensorPin, INPUT);
attachInterrupt(digitalPinToInterrupt(WindSensorPin), isr_rotation, FALLING);

Serial.println(“Davis Anemometer Test”);
Serial.println(“Speed (MPH)\tKnots\tDirection\tStrength”);

// Setup the timer interupt
Timer1.initialize(500000);// Timer interrupt every 2.5 seconds

void loop() {


// Only update the display if change greater than 5 degrees.
if(abs(CalDirection – LastValue) > 5) {
LastValue = CalDirection;

if(IsSampleRequired) {
// convert to mp/h using the formula V=P(2.25/T)
// V = P(2.25/2.5) = P * 0.9
WindSpeed = Rotations * 0.9;
Rotations = 0; // Reset count for next sample

IsSampleRequired = false;

Serial.print(WindSpeed); Serial.print(“\t\t”);
Serial.print(getKnots(WindSpeed)); Serial.print(“\t”);
getHeading(CalDirection); Serial.print(“\t\t”);

// isr handler for timer interrupt
void isr_timer() {


if(TimerCount == 6)
IsSampleRequired = true;
TimerCount = 0;

// This is the function that the interrupt calls to increment the rotation count
void isr_rotation() {

if((millis() – ContactBounceTime) > 15 ) { // debounce the switch contact.
ContactBounceTime = millis();

// Convert MPH to Knots
float getKnots(float speed) {
return speed * 0.868976;

// Get Wind Direction
void getWindDirection() {

VaneValue = analogRead(WindVanePin);
Direction = map(VaneValue, 0, 1023, 0, 359);
CalDirection = Direction + VaneOffset;

if(CalDirection > 360)
CalDirection = CalDirection – 360;

if(CalDirection < 0)
CalDirection = CalDirection + 360;


// Converts compass direction to heading
void getHeading(int direction) {

if(direction < 22)
Serial.print(” N”);
else if (direction < 67)
Serial.print(” NE”);
else if (direction < 112)
Serial.print(” E”);
else if (direction < 157)
Serial.print(” SE”);
else if (direction < 212)
Serial.print(” S”);
else if (direction < 247)
Serial.print(” SW”);
else if (direction < 292)
Serial.print(” W”);
else if (direction < 337)
Serial.print(” NW”);
Serial.print(” N”);

Davis Rain Gauge

The Davis Instruments AeroCone Rain Collector can be used as a stand-alone custom rain station. The AeroCone rain collector reduces wind-induced errors by providing a more aerodynamic path around the collector. Its contours are designed to streamline the airflow and reduce flow distortions. The design improves rain data accuracy in high wind situations where the horizontal wind velocity can cause underreporting.

The inside of the rain collector is equally well designed, keeping intact the carefully engineered interior walls that reduce splash out during high rain conditions. The debris screen locks into place, ensuring that it remains in place during high winds and heavy rainfall events. Features tipping spoon technology that increases accuracy and precision for measuring rainfall. The accuracy is increased from ±4% to ±3%.


Wire ColorConnection


const byte interruptPin = 27;
const int interval = 500;
double rain_m=0 ;
volatile int loop_count;
volatile unsigned long tiptime = millis();
void setup() {
  // Set up our digital pin as an interrupt
  pinMode(interruptPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(interruptPin), count, FALLING);
void loop() {
void count() {
  // Grab the current ms count for common calculations
  unsigned long curtime = millis();
  // Make sure we don’t record bounces
  if ((curtime – tiptime) < interval) {
  rain_mm += 0.2 ;  // How long since the last tip?
  unsigned long tipcount = curtime – tiptime;
  tiptime = curtime;
  // Calculate mm/hr from period between cup tips
  double rainrate = 914400.0 / tipcount;
  Serial.print(“Cup tip: “);
  Serial.print(“Rain rate: “);

Connections to ESP32

Final code for ESP32 weather station

You can find the final code for the ESP32 weather station in the following link:

Ambee’s weather data
Ambee’s weather data is a result of the combination of vigorous research, multiple algorithms, and numerous rounds of scientific validations. Ambee’s data harnesses the power of on-ground sensors, remote satellite imagery, and a global proprietary sensor network to get credible data from multiple sources. Ambee’s accurate weather data gives businesses and individuals the power to take weather considerations into every decision.

Most Popular

To Top
India and Pakistan’s steroid-soaked rhetoric over Kashmir will come back to haunt them both clenbuterol australia bossier man pleads guilty for leadership role in anabolic steriod distribution conspiracy