Maria Cristina Capurro
Published

Temperature, Humidity and Weather Forecast with an ESP32

Check the temperature and humidity of your house, the outside conditions and the weather forecast for today from your phone!

IntermediateFull instructions provided2,705
Temperature, Humidity and Weather Forecast with an ESP32

Things used in this project

Hardware components

ESP 32 - LOLIN D32
×1
DHT 21
×1
OLED
×1

Software apps and online services

Blynk
Blynk
Dark Sky

Story

Read more

Custom parts and enclosures

OLED 3D printing file #1

Using PETG.

OLED 3D printing file #2

Enclosure box

*holes are a bit smaller on purpose, to adjust it manually using a drill.

Enclosure box

holes are a bit smaller on purpose, to adjust them manually using a drill.

Schematics

img_9349_7kpIpbsf2M.JPG

Code

Code for the project

C/C++
// code for an ESP32 with DHT21 sensor on port D2 using blynk app and an OLED.
//The code takes temp and hum averages every 5 minutes. It also measures battery voltage and calculates wifi signal every 5 minutes.
//For the SSD1306 OLED:used library Adafruit_SSD1306, version 1.2.9, using this example: https://gist.github.com/RuiSantosdotme/020c23f3b45132f755f39f37a536b780 . Read for more details here: https://rntlab.com/question/esp32-oled-ssd1306-issue/

#define BLYNK_PRINT Serial  //
#include <BlynkSimpleEsp32.h>
#include <DHT.h>
#include <NTPClient.h>  
#include <WiFi.h>
#include <WiFiUdp.h> 
#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_GFX.h>

#include <JSON_Decoder.h>
#include <DarkSkyWeather.h>
// Just using this library for unix time conversion
#include <Time.h>


#define DHTPIN 2                                           // port where DTH21 is connected
#define DHTTYPE DHT21                                       // I use DHT21, change to other DHT sensor if you use other one
DHT dht(DHTPIN, DHTTYPE);   // enabled DHT sensor

//oled:
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET     -1 // Reset pin #4 (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
//SCL (22) and SDA (21) pins

#define TIME_OFFSET -3UL * 3600UL // UTC + -7 hour (-7 for MST time zone)
#define uS_TO_S_FACTOR 1000000

char auth[] = "XXXXX";         // Your Blynk authentication string
char ssid[] = "XXXXX";         // SSID (name) of your wifi
char pass[] = "XXXXX";         // your wifi password

// Dark Sky API Details, replace x's with your API key
String api_key = "XXXXX"; // Obtain this from your Dark Sky account

// Set both longitude and latitude to at least 4 decimal places
String latitude =  "XXXXX"; // 90.0000 to -90.0000 negative for Southern hemisphere 
String longitude = "XXXXX"; // 180.000 to -180.000 negative for West
String units = "si";  // See notes tab
String language = ""; // See notes tab

WiFiUDP ntpUDP;

NTPClient timeClient(ntpUDP, "ntp.colostate.edu",-3600*7, 60000);   // Google for the NTP server for your location and copy-paste it here

const int update_interval = 5;     // desired update/sample interval in minutes
int oldminutes = 99;

DS_Weather dsw; // Weather forecast library instance

// Attach virtual serial terminal to Virtual Pin V1
WidgetTerminal terminal(V2);


 float h ;
 float t ;

 float wifi_rssi;
 float battery;



// get WiFi Signal Strength https://www.mathworks.com/help/thingspeak/measure-arduino-wifi-signal-strength-with-esp32.html
int getStrength(int points){
    long rssi = 0;
    long averageRSSI = 0;
    for (int i=0;i < points;i++){
        rssi += WiFi.RSSI();
        delay(10);
    }
   averageRSSI = rssi/points;
   return averageRSSI;
}


//function to correct ADC, https://github.com/G6EJD/ESP32-ADC-Accuracy-Improvement-function
 double ReadVoltage(byte pin){
 double reading = analogRead(pin); // Reference voltage is 3v3 so maximum reading is 3v3 = 4095 in range 0 to 4095
 if(reading < 1 || reading > 4095) return 0;
 return -0.000000000009824 * pow(reading,3) + 0.000000016557283 * pow(reading,2) + 0.000854596860691 * reading + 0.065440348345433;
 return -0.000000000000016 * pow(reading,4) + 0.000000000118171 * pow(reading,3)- 0.000000301211691 * pow(reading,2)+ 0.001109019271794 * reading + 0.034143524634089;
  } 


//function for writing in the terminal widget from blynk  
// You can send commands from Terminal to your hardware. Just use
// the same Virtual Pin as your Terminal Widget
BLYNK_WRITE(V2)
{

  // from example from Blynk: if you type "Marco" into Terminal Widget - it will respond: "Polo:"
  if (String("password") == param.asStr()) {
    terminal.println("Want the wifi password?") ;
    terminal.println("Here it is: 'arduinolab'") ;
  } else {

    // Send it back
    terminal.print("You said:");
    terminal.write(param.getBuffer(), param.getLength());
    terminal.println();
  }

  // Ensure everything is sent
  terminal.flush();
}


void setup()
{
  Serial.begin(115200);                                       // Enabled serial debugging output
  Blynk.begin(auth, ssid, pass);                            // Connects to wifi and Blynk services

  Serial.println("awake");  


 if(WiFi.status() != WL_CONNECTED){                        // connect to WiFi
      int i = 0;
      Serial.println("");
      Serial.print("Attempting to connect to SSID: ");
      Serial.println(ssid);
      while(WiFi.status() != WL_CONNECTED){
      WiFi.begin(ssid, pass);   // Connect to WPA/WPA2 network. Change this line if using open or WEP network
      Serial.print(++i); Serial.print(' ');
      if (i>=9) {                                       // sleep after 9 attempts
      Serial.println("WiFi failed to connect - going to sleep");
      //esp_sleep_enable_timer_wakeup((wakeBoundary-60) * uS_TO_S_FACTOR);   // configure time to sleep, wakeup 60s early
      //esp_deep_sleep_start();
      }
      delay(5000);     
      } 
  }


//OLED
  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x32
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }
  

 // Clear the terminal content
  terminal.clear();

  // This will print Blynk Software version to the Terminal Widget when
  // your hardware gets connected to Blynk Server
   terminal.println(F("Blynk v" BLYNK_VERSION ": Device started"));
   terminal.println(F("Type 'password' and get a reply"));
   terminal.println(F("-------------"));
   terminal.flush();


  timeClient.begin();              // ntp client
  dht.begin();        //initialize sensor

}



void loop()
{

  Blynk.run();   // run blynk

 while(!timeClient.update()) {           // update NTP if needed
    timeClient.forceUpdate();
  }
   
  int hours=timeClient.getHours();        // update time variables
  int minutes=timeClient.getMinutes();
  int seconds=timeClient.getSeconds();
  int epoch=timeClient.getEpochTime();
  
//  if (hours==12 && minutes==0 && seconds==0) { // force update timeClient at noon, only use if always on, no sleep
//    timeClient.update(); 
//  }


  if ((minutes%update_interval==0) && (minutes != oldminutes)) {      // update loop
       oldminutes=minutes;

printCurrentWeather();//  // We can make 1000 requests a day
//  delay(5 * 60 * 1000); // Every 5 minutes = 288 requests per day

h = dht.readHumidity(); 
t = dht.readTemperature(); // read sensor  

wifi_rssi = getStrength(7);     // get wifi strength 
battery = ReadVoltage(35)*2.0;   // read battery volt, A13 for huzzah32, 35 for D32, , must mult by 2 for volt divider
   

  
  
Serial.print("Humidity: ");
Serial.println(h,2);
Serial.print("Temperature: ");  // prints a label
Serial.println(t,2);  
  
  
Serial.print("wifi strength: ");
Serial.println(wifi_rssi);
Serial.print("battery voltage: ");
Serial.println(battery);

Serial.println();        // carriage return after the last label


terminal.print("battery voltage: ");
terminal.println(battery);
terminal.print("wifi strength: ");
terminal.println(wifi_rssi);
terminal.flush();


                      
 
  }
}




/***************************************************************************************
**                          Send weather info to serial port
***************************************************************************************/
void printCurrentWeather()
{
  // Create the structures that hold the retrieved weather
  DSW_current *current = new DSW_current;
  DSW_hourly *hourly = new DSW_hourly;
  DSW_daily  *daily = new DSW_daily;

  time_t time;

  Serial.print("\nRequesting weather information from DarkSky.net... ");

  dsw.getForecast(current, hourly, daily, api_key, latitude, longitude, units, language);
  
  Serial.println("############### Current weather ###############\n");
  Serial.print("Current time             : "); Serial.print(strTime(current->time));
  Serial.print("Current temperature      : "); Serial.println(current->temperature);
  Serial.print("Current humidity         : "); Serial.println(current->humidity);
  Serial.print("Current pressure         : "); Serial.println(current->pressure);
  Serial.print("Current wind speed       : "); Serial.println(current->windSpeed);
 // Serial.print("Current wind gust        : "); Serial.println(current->windGust);
  //Serial.print("Current wind dirn        : "); Serial.println(current->windBearing);
 
 Serial.print("Current summary          : "); Serial.println(current->summary);
 // Serial.print("Current icon             : "); Serial.println(getMeteoconIcon(current->icon));
  Serial.print("Current precipInten      : "); Serial.println(current->precipIntensity);
//  Serial.print("Current precipType       : "); Serial.println(getMeteoconIcon(current->precipType));
  Serial.print("Current precipProbability: "); Serial.println(current->precipProbability);
  Serial.println();

Blynk.virtualWrite(4, String(current->temperature, 1));             // send to Blynk virtual pin 1 temperature value
Blynk.virtualWrite(5, current->humidity);                           // send to Blynk virtual pin 3 humidity value
Blynk.virtualWrite(1, String(t,1));                                 // send to Blynk virtual pin 1 temperature value
Blynk.virtualWrite(3, String(h,1));                                 // send to Blynk virtual pin 3 humidity value

//OLED display:
  display.clearDisplay();
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(0,0);  
  display.print("in T: ");
  display.println(t, 1);
  display.print("in H: ");
  display.println(h, 1);
  display.setCursor(0,21);
  display.setCursor(0,32);  
  display.print("out T:");
  display.println(current->temperature,1);
  display.print("out H:");
  display.println(current->humidity,1);
  display.setCursor(0,53);
  display.display();

terminal.println(F("-------------"));
terminal.print("Current precip Inten: ");
terminal.println(current->precipIntensity);
terminal.print("Current wind speed: ");
terminal.println(current->windSpeed);
terminal.println("");

Serial.println("############### Hourly weather  ###############\n");
 Serial.print("Overall hourly summary : "); Serial.println(hourly->overallSummary);
  for (int i = 0; i<MAX_HOURS; i++)
  {
Serial.print("Hourly summary  "); if (i<10) Serial.print(" ");
Serial.print(i);  Serial.print(" : "); Serial.println(hourly->summary[i]);
Serial.print("precipProbability  : "); Serial.println(hourly->precipProbability[i]);
//Serial.print("precipType         : "); Serial.println(hourly->precipType[i]);
// Serial.print("precipAccumulation : "); Serial.println(hourly->precipAccumulation[i]);
Serial.print("cloudCover         : "); Serial.println(hourly->cloudCover[i]);
Serial.println();
}

Serial.print("NextHour_precipProbability  : "); Serial.println(hourly->precipProbability[1]);
Serial.print("NextHour_cloudCover         : "); Serial.println(hourly->cloudCover[1]);
Serial.println();

  terminal.print("Next hour precip Probability: ");
  terminal.println(hourly->precipProbability[1]);
  terminal.print("Next hour cloud cover: ");
  terminal.println(hourly->cloudCover[1]);
  terminal.println("");


  Serial.println("###############  Daily weather  ###############\n");
  Serial.print("Daily summary     : "); Serial.println(daily->overallSummary);
  Serial.println();

  for (int i = 0; i<MAX_DAYS; i++)
  {
    Serial.print("Daily summary   ");
    Serial.print(i); Serial.print(" : "); Serial.println(daily->summary[i]);
    //Serial.print("time              : "); Serial.print(strTime(daily->time[i]));
    //Serial.print("sunriseTime       : "); Serial.print(strTime(daily->sunriseTime[i]));
    //Serial.print("sunsetTime        : "); Serial.print(strTime(daily->sunsetTime[i]));
    //Serial.print("Moon phase        : "); Serial.println(daily->moonPhase[i]);
    Serial.print("precipProbability : "); Serial.println(daily->precipProbability[i]);
    //Serial.print("precipType        : "); Serial.println(daily->precipType[i]);
    Serial.print("precipAccumulation: "); Serial.println(daily->precipAccumulation[i]);
        Serial.println();
  }

    Serial.print("today_precipAccumulation: "); Serial.println(daily->precipAccumulation[0]);
    Serial.print("today_precipProbability : "); Serial.println(daily->precipProbability[0]);
    Serial.print("Daily summary   ");Serial.println(daily->summary[0]);

 //terminal.print("today_precip Accumulation: ");
 //terminal.println(daily->precipAccumulation[0]);
 //terminal.print("today precip Probability: ");
 //terminal.println(daily->precipProbability[0]);
 //terminal.println("");

 terminal.print("today precip Accumulation: ");
 terminal.println(daily->precipAccumulation[0]);
 terminal.print("today precip Probability: ");
 terminal.println(daily->precipProbability[0]);
 terminal.print("today temperatureHigh: ");
 terminal.println(daily->temperatureHigh[0]);
 terminal.print("today temperatureLow: ");
 terminal.println(daily->temperatureLow[0]);
 terminal.print("Daily summary:  ");
 terminal.println(daily->summary[0]);
 terminal.println("");

  // Delete to free up space and prevent fragmentation as strings change in length
  delete current;
  delete hourly;
  delete daily;
}

/***************************************************************************************
**                          Convert unix time to a time string
***************************************************************************************/
String strTime(time_t unixTime)
{
  unixTime += TIME_OFFSET;
  return ctime(&unixTime);
}

Credits

Maria Cristina Capurro

Maria Cristina Capurro

1 project • 0 followers

Comments