ESP8266 Weather Station: Measuring Inside and Outside Temperature – Part 1

The code you get with the WeatherStation (https://github.com/squix78/esp8266-weather-station) is meant as a starting point for beginners and enthusiasts to display information. So far there are modules to get correct time from the internet as well as current and future weather conditions. Now let’s get a bit more local.
What if you wanted to measure and display information from various places in your house or apartment? This blog post shows you how to attach a DHT22 temperature/humidity sensor either directly to the WeatherStation (in case you want to measure it where the WeatherStation is) or how to collect and display data from another room over WiFi.

Requirements & Preparation

For this tutorial I assume that you already have a working WeatherStation and a DHT22 breakout board ready.

ProductWhere to buy?
The ESP8266 WeatherStationAmazon (US)
Squix Shop (World wide)
DHT22 Humidity/ Temperature SensorBanggood
NodeMCU V1.0Banggood

 

Attaching the DHT22 to the ESP8266 directly to the WeatherStation

To measure temperature and humidity in the room where you are running the WeatherStation you can attach the DHT22 breakout board as shown in the schema bellow
ESP8266 WeatherStation with locally attached
DHT22 sensor to measure temperature and humidity

Next you need to import the DHT22 library. This is easiest by using the library Manager:
Sketch > Include Library… > Manage Libraries…

And now search for the DHT library:

Now that you have the library you can start extending the demo. In order for this to work I assume that you have already done everything to get a working WeatherStation. Save your existing sketch under a new name. Here are the necessary changes:

 

Let’s discuss the changes:

  • Line 37: I have added the DHT library
  • Lines 77-83: configuration options for the DHT library. If you are using a DHT11 or DHT21 here you can change it. Also adapt the used pin. If you are not using the NodeMCU board D6 will give you a compile error
  • Lines 104/105: two new variables for humidity and temperature. If this was a new WeatherStation module you would keep the variable in the new classes and not here, in a “global” scope…
  • Lines 110-119: The prototypes help the compiler/linker to use functions which will only be used afterwards
  • Lines 119/124: I added a new drawIndoor method and increased the number of frames to 6. Now the framework knows which method to call in order to draw the indoor information
  • Lines 231-233: In this tutorial we update the temperature und humidity only once every 10 minutes. Updating the values only costs about 250ms but it might still be too much to do it in the hot (main) loop. But you could do it there every once in a while
  • Lines 271-277: This draws the indoor frame. You might see a strong similarity to the drawThingspeak method. This is not coincidental since they draw similar data. In a perfect world we could extract this to an extra method to share the code
[the_ad_placement id=”inpostplacement”]
That’s it! Apply these changes to your code, compile it and flash your ESP8266 with the changes after you set up the wiring.
The result of successfully following this tutorial
Part two of this tutorial will show you how to read the information from another ESP8266 through the cloud…
Posted by Daniel Eichhorn

Daniel Eichhorn is a software engineer and an enthusiastic maker. He loves working on projects related to the Internet of Things, electronics, and embedded software. He owns two 3D printers: a Creality Ender 3 V2 and an Elegoo Mars 3. In 2018, he co-founded ThingPulse along with Marcel Stör. Together, they develop IoT hardware and distribute it to various locations around the world.

76 comments

  1. Nice development! I just did the same last night but I put the dht read in the drawframe6. I know it's not really the right place for it but it seems to work fine and updates each time frame6 is displayed (and sometimes again before moving back to display frame1). I have another node logging to thingspeak, the data being displayed by your weatherstation code on frame5.

    • Hi Sam. You can certainly do that in the drawFrame6 method. Just be aware that the smoothness of the transitions might suffer. You could improve on that by adding a condition to only read the DHT when the frames are not moving:
      if (ui.getUiState().frameState == FIXED) {
      // read the dht values
      }

    • Nice job Dani, as soon my ESP arrives, I have everything else, I'm gonna make one. Later I would like to use my old smart phone as display module!
      Thanks for your help here!
      Tony

  2. You don't need to query the UI Object for the state. You can just use the `state` parameter that is passed into each drawing function.

  3. I get errors like "fatal error: SSD1306.h: No such file or directory" or "fatal error: JsonListener.h: No such file or directory". Where do I get these files?

    • Hi Taki. Please follow the instruction at the github link ar at the beginning of this post. You might have followed the old instructions in the tutorial which I still have to update…

  4. Hi Dani,
    nice project! What about uploading outdoor sensor data to wunderground directly instead of tingspeak?
    Then you could read and display your own data from wunderground (const String WUNDERGROUND_CITY = "pws:YOUR_WEATHERSTATION_ID";)
    Would this work?

  5. Thanks. I had to download the Json Lib, Display Driver and Weather Stations as zip from your Git and add them as library in the library manager. You may describe this steps more detailed in your readme, to avoid confusing others in the future 🙂

  6. Hi Dani,
    Your project looked like a nice startpoint to get some programming experience with the esp8266. It olooked lik ei had all necessary parts… until i discovered i had the SPI version of the oled display. So before i try to get it working with SPI, i'd like to know if you ore somebody else allready had a go at that.

    • I have currently no experience with the SSD1306 and the SPI interface. I would assume that if you take the oled library and modify the methods that are currently about I2C it should be possible to adapt it for SPI..

  7. Hi Dani,

    my internet connection crashed tonight for a short time and the weather station stopped at "updating conditions" until now. Is it possible to implement a timeout while updating? Otherwise i have to do a manual reset.

  8. Hi,
    @Wolfgang : could try something like this:
    // This will send the request to the server
    client.print(String("GET ") + url + " HTTP/1.1rn" +
    "Host: api.wunderground.comrn" +
    "Connection: closernrn");
    int cntr=0;
    while(!client.available()&& cntr < 3) {
    cntr++;// Make 3 tries before quiting
    delay(1000);
    }
    I've used something similar in other code for making sure the wifi is connected.

  9. Hi Dani,

    I'm currently building a new weather station and use the code from this post as my starting point. For the DHT readings I got NaN (not a number). Then I tried the sensor with the DHT lib testsketch and it works. I noticed dht.begin(); is not in the code.

    Isn't this required? I will be testing this afternoon. But it seems weird to me that no one in the posts here mentions the DHT not working.

    Or maybe nobody used that feature yet…

    • Hello,

      I think you are using a different version of the DHT.h library.

      Where as I don't know your version, try adding in the setup instead of dht.begin(); :

      dht.setup(x); //x is the number of the pin connected to DHT22

      NaN values could be found also when Vcc and GND are badly connected to the sensor or the Node/ESP is not supplying enough current to the DHT.

      Hope it helps.

  10. Dan…. just cant work out how….
    All working, but I want to update the DHT22 Read more frequently than I go to wundergroud for an update….

    How do I split up "if (readyForWeatherUpdate && ui.getUiState().frameState == FIXED) {
    updateData(&display);
    }

    so I read the DHT22 say every minute and leave the other for 10 mins?

    Thanks!

    • Checkout Line and 49: just change 60*10 to 60 and you will get an update every minute! Explanation: the number is in seconds. Every 60 seconds the ticker on line 168 fires and will set the variable readyForWeatherUpdate to true. You shouldn't do too much work in a ticker function or the internal watch dog will "bark"

    • Thanks, I had worked that piece out… I want to leave the wunderground update to 10 mins, but have the read of the DHT22 more frequent…..

  11. Hello Daniel,

    I'm using your stuff concerning the Weather Station found on GitHub. I'm improving the project by means of adding a MQTT communication to an EasyIoT server in order to remotely control a Thermostat.
    The MQTT part works fine, but sometimes (expecially during night) I'm having troubles with the OLED, which freezes and stops working (during the update with wunderground) until a RST. I can't understand where's the problem. I've done some checks on WiFi connection before requesting to wunderground, i've even added a timeout of 3 GET attempts.

    May you had this problem? Asap I'll post what i've done to thank you and to share the project to everybody interested.

    Thank you so much for all your stuff

  12. I've had this issue too…. Seems to hang in the wunderground update section.

    Will be keen to see if you've found a way to fix this.

    I have the sensors working with the wunderground sections commented out and been running for a week.

  13. When I set const boolean IS_METRIC = false; the temperature value is displayed in Fahrenheit but it displays C and not F on the screen.

  14. Hi! Should be line 93-99 in the explanation of the added code not just 98-99 🙂 thank you for another great tutorial!

  15. Hello Dani – very nice job ! is there any chance to work with sht11 or shtc1 instead dth22 ? plleeaseee 😉 ? i'm only good in programming in bascom 🙁

  16. Very Nice , but THE Pin Out is noit Korrekt.
    Ichhab das mal so genmacht:
    // Display Settings
    const int I2C_DISPLAY_ADDRESS = 0x3c;
    const int SDA_PIN = D5;
    const int SDC_PIN = D6;

    // DHT Settings
    #define DHTPIN D4

    ud NUN läuft, TOP, DANKE !!! THX

  17. Hi Dani.
    Just one question: is it possible to get weather data on two different thingspeak channels? I have indoor and outdoor data sent in this way, and in your sketch I cannot find an easy way to get and show them. Any hint? Thanks, ciao, –Federico

  18. Hi Dani, Love this project. Thanks much.
    I've spent some time adding new features. I now get the /astronomy/ feed so I can display sunrise, sunset, and moon info.

    Something that may be of interest is that that feed will also provide the time and date – adjusted for the Time Zone and DST if it applies. So this can replace NTP time and I believe that makes the connections much more reliable.
    (I didn't use local time at all, and not calling NTP time really speeded up startup.)

    I also replaced percip with wind direction and speed.

    Thanks again for a great platform. Best beer I ever bought.
    – John

    • How did you do the astronomy feed sunrise, sunset, and moon info. I would love that in my project. That’s brilliant. Is there a instruction on how to do this out there somewhere?

  19. Hi Dani,

    Thanks for the great work. I have been playing around with your weather station program from the start.(lua) I am happy to see it all working now with the Arduino environment. I have the external temps working, but I would like to add the local temps. But I can’t get it to work. I tried to follow the descriptions. My added codes are as follows:

    Line 37: I have added the DHT library
    #include “DHT.h”

    Lines 74-80: configuration options for the DHT library.
    #define DHTTYPE DHT22 // DHT 22 (AM2302)
    #define DHTPIN D6 // what pin we’re connected to
    DHT dht(DHTPIN, DHTTYPE);

    Lines 98/99: I added a new drawFrame6 method and increased the number of frames to 6.
    bool (*frames[])(SSD1306 *display, SSD1306UiState* state, int x, int y) = { drawFrame1, drawFrame2, drawFrame3, drawFrame4, drawFrame5, drawFrame6 };
    int numberOfFrames = 6;

    Lines 106/107: two new variables for humidity and temperature.
    float h;
    float t;

    Lines 203-206: In this tutorial we update the temperature und humidity only once every 10 minutes.
    //orignal code
    void updateData(SSD1306 *display) {
    drawProgress(display, 10, “Updating time…”);
    timeClient.updateTime();
    //new code:
    drawProgress(display, 20, “Updating local temps…”);
    float h = dht.readHumidity();
    float t = dht.readTemperature();

    Lines 279-286: This draws the indoor frame.
    bool drawFrame6(SSD1306 *display, SSD1306UiState* state, int x, int y) {
    display->setTextAlignment(TEXT_ALIGN_CENTER);
    display->setFont(ArialMT_Plain_10);
    display->drawString(64 + x, 0 + y, “Local readings”);
    display->setFont(ArialMT_Plain_24);
    display->drawString(64 + x, 10 + y, h + “°C”);
    display->drawString(64 + x, 30 + y, t + “%”);

    While compiling i get the following error:
    Build options changed, rebuilding all
    WeatherStation_TS_local.ino: In function ‘bool drawFrame6(SSD1306*, SSD1306UiState*, int, int)’:
    WeatherStation_TS_local:281: error: invalid operands of types ‘float’ and ‘const char [4]’ to binary ‘operator+’
    WeatherStation_TS_local:282: error: invalid operands of types ‘float’ and ‘const char [2]’ to binary ‘operator+’
    invalid operands of types ‘float’ and ‘const char [4]’ to binary ‘operator+’

    Even google doesnt help me with this error. I understand from the error means that its not possible to write a float in combination with the const char. But i tried to convert the float(h and t) to char with sprintf() but cant get it to work. Any help is appreciated.

    • Hi Maarten, I got the same problem, I want to connect a dht11 and show the reading of the temperature in the right buttum corner (in the headerOverlay).

      When i put the following lines in the headerOverlay, the temp is visible in the bottum right corner.
      float t = dht.readTemperature();
      display->drawString(128, 54, String(t,0)+ “°C”);

      The only thing is that the node reads the temperature now every 2 seconds or so and the shifting of the frames is not smooth.

      Daniel, can you please share the full code of this tutorial? I would love to know how to update my dht11 reading every 10 minutes.

      Kind regards,
      Vincent

    • Can you please share the full code.
      I stoppde on line 106/107 and i cant finish it.
      this is my first project.
      Can you please help me.

      Thank you.

  20. Try this:

    #include
    #include
    #include
    #include “SSD1306Wire.h”
    #include “OLEDDisplayUi.h”
    #include “Wire.h”
    #include “WundergroundClient.h”
    #include “WeatherStationFonts.h”
    #include “WeatherStationImages.h”
    #include “TimeClient.h”
    #include “ThingspeakClient.h”
    #include
    #include
    #define DS3231_I2C_ADDRESS 0x68

    // WIFI
    const char* WIFI_SSID = “XXXX”;
    const char* WIFI_PWD = “XXXX”;

    // Setup
    const int UPDATE_INTERVAL_SECS = 10 * 60; // Update every 10 minutes
    const int UPDATE_INTERVAL_SECS_SENSOR = 1 * 10; // Update every 10 seconds
    // Display Settings
    const int I2C_DISPLAY_ADDRESS = 0x3c;
    const int SDA_PIN = D2;
    const int SDC_PIN = D1;

    // TimeClient settings
    const float UTC_OFFSET = 2;

    // Wunderground Settings
    const boolean IS_METRIC = true;
    const String WUNDERGRROUND_API_KEY = “e5172b0651d58317”;
    const String WUNDERGRROUND_LANGUAGE = “XX”;
    const String WUNDERGROUND_COUNTRY = “XX”;
    const String WUNDERGROUND_CITY = “XX”;

    //Thingspeak Settings
    const String THINGSPEAK_CHANNEL_ID = “67284”;
    const String THINGSPEAK_API_READ_KEY = “L2VIW20QVNZJBLAK”;

    // Initialize the oled display for address 0x3c
    // sda-pin=14 and sdc-pin=12
    SSD1306Wire display(I2C_DISPLAY_ADDRESS, SDA_PIN, SDC_PIN);
    OLEDDisplayUi ui( &display );

    #define DHTPIN 14

    #define DHTTYPE DHT11

    DHT dht(DHTPIN, DHTTYPE);

    TimeClient timeClient(UTC_OFFSET);

    // Set to false, if you prefere imperial/inches, Fahrenheit
    WundergroundClient wunderground(IS_METRIC);

    ThingspeakClient thingspeak;

    // flag changed in the ticker function every 10 minutes
    bool readyForWeatherUpdate = false;
    bool readyForSensorUpdate = false;
    String lastUpdate = “–“;

    Ticker ticker;
    Ticker ticker2;
    //declaring prototypes
    void drawProgress(OLEDDisplay *display, int percentage, String label);
    void updateData(OLEDDisplay *display);
    void updateIndoorData(OLEDDisplay *display);
    void drawDateTime(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y);
    void drawCurrentWeather(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y);
    void drawForecast(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y);
    void drawThingspeak(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y);
    void drawInside(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y);
    void drawForecastDetails(OLEDDisplay *display, int x, int y, int dayIndex);
    void drawHeaderOverlay(OLEDDisplay *display, OLEDDisplayUiState* state);
    void setReadyForWeatherUpdate();
    void setReadyForSensorUpdate();

    float h;
    float t;

    // Add frames
    // this array keeps function pointers to all frames
    // frames are the single views that slide from right to left
    FrameCallback frames[] = {drawDateTime, drawCurrentWeather, drawForecast, drawThingspeak, drawInside };
    int numberOfFrames = 5;

    OverlayCallback overlays[] = {drawHeaderOverlay };
    int numberOfOverlays = 1;
    void setup() {
    Serial.begin(115200);
    Serial.println();
    Serial.println();

    // initialize dispaly
    display.init();
    display.clear();
    display.display();

    //display.flipScreenVertically();
    display.setFont(ArialMT_Plain_10);
    display.setTextAlignment(TEXT_ALIGN_CENTER);
    display.setContrast(255);

    WiFi.begin(WIFI_SSID, WIFI_PWD);
    dht.begin();
    int counter = 0;
    while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(“.”);
    display.clear();
    display.drawString(64, 10, “Connecting…”);
    display.drawXbm(46, 30, 8, 8, counter % 3 == 0 ? activeSymbole : inactiveSymbole);
    display.drawXbm(60, 30, 8, 8, counter % 3 == 1 ? activeSymbole : inactiveSymbole);
    display.drawXbm(74, 30, 8, 8, counter % 3 == 2 ? activeSymbole : inactiveSymbole);
    display.display();

    counter++;
    }

    ui.setTargetFPS(60);

    ui.setActiveSymbol(activeSymbole);
    ui.setInactiveSymbol(inactiveSymbole);

    // You can change this to
    // TOP, LEFT, BOTTOM, RIGHT
    ui.setIndicatorPosition(BOTTOM);

    // Defines where the first frame is located in the bar.
    ui.setIndicatorDirection(LEFT_RIGHT);

    // You can change the transition that is used
    // SLIDE_LEFT, SLIDE_RIGHT, SLIDE_TOP, SLIDE_DOWN
    ui.setFrameAnimation(SLIDE_LEFT);

    ui.setFrames(frames, numberOfFrames);

    ui.setOverlays(overlays, numberOfOverlays);

    // Inital UI takes care of initalising the display too.
    ui.init();

    Serial.println(“”);

    updateData(&display);
    updateIndoorData(&display);
    ticker.attach(UPDATE_INTERVAL_SECS, setReadyForWeatherUpdate);
    ticker2.attach(UPDATE_INTERVAL_SECS_SENSOR, setReadyForSensorUpdate);
    }

    void loop() {

    if (readyForWeatherUpdate && ui.getUiState()->frameState == FIXED) {
    updateData(&display);
    }

    if (readyForSensorUpdate && ui.getUiState()->frameState == FIXED) {
    updateIndoorData(&display);
    Serial.println(“Updating DHT11”);
    }
    int remainingTimeBudget = ui.update();

    }

    void drawProgress(OLEDDisplay *display, int percentage, String label) {
    display->clear();
    display->setTextAlignment(TEXT_ALIGN_CENTER);
    display->setFont(ArialMT_Plain_10);
    display->drawString(64, 10, label);
    display->drawProgressBar(2, 28, 124, 10, percentage);
    display->display();
    }

    void updateData(OLEDDisplay *display) {
    drawProgress(display, 10, “Updating local temps…”);
    h = dht.readHumidity();
    t = dht.readTemperature();
    drawProgress(display, 25, “Updating time…”);
    timeClient.updateTime();
    drawProgress(display, 40, “Updating conditions…”);
    wunderground.updateConditions(WUNDERGRROUND_API_KEY, WUNDERGRROUND_LANGUAGE, WUNDERGROUND_COUNTRY, WUNDERGROUND_CITY);
    drawProgress(display, 55, “Updating forecasts…”);
    wunderground.updateForecast(WUNDERGRROUND_API_KEY, WUNDERGRROUND_LANGUAGE, WUNDERGROUND_COUNTRY, WUNDERGROUND_CITY);
    drawProgress(display, 80, “Updating thingspeak…”);
    thingspeak.getLastChannelItem(THINGSPEAK_CHANNEL_ID, THINGSPEAK_API_READ_KEY);
    lastUpdate = timeClient.getFormattedTime();
    readyForWeatherUpdate = false;
    drawProgress(display, 100, “Done…”);
    delay(1000);
    }
    void updateIndoorData(OLEDDisplay *display) {
    h = dht.readHumidity();
    t = dht.readTemperature();
    readyForSensorUpdate = false;
    }

    void drawDateTime(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {
    display->setTextAlignment(TEXT_ALIGN_CENTER);
    display->setFont(ArialMT_Plain_10);
    String date = wunderground.getDate();
    int textWidth = display->getStringWidth(date);
    display->drawString(64 + x, 5 + y, date);
    display->setFont(ArialMT_Plain_24);
    String time = timeClient.getFormattedTime();
    textWidth = display->getStringWidth(time);
    display->drawString(64 + x, 15 + y, time);
    display->setTextAlignment(TEXT_ALIGN_LEFT);
    }

    void drawCurrentWeather(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {
    display->setFont(ArialMT_Plain_10);
    display->setTextAlignment(TEXT_ALIGN_LEFT);
    display->drawString(60 + x, 5 + y, wunderground.getWeatherText());

    display->setFont(ArialMT_Plain_24);
    String temp = wunderground.getCurrentTemp() + “°C”;
    display->drawString(60 + x, 15 + y, temp);
    int tempWidth = display->getStringWidth(temp);

    display->setFont(Meteocons_Plain_42);
    String weatherIcon = wunderground.getTodayIcon();
    int weatherIconWidth = display->getStringWidth(weatherIcon);
    display->drawString(32 + x – weatherIconWidth / 2, 05 + y, weatherIcon);
    }

    void drawForecast(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {
    drawForecastDetails(display, x, y, 0);
    drawForecastDetails(display, x + 44, y, 2);
    drawForecastDetails(display, x + 88, y, 4);
    }

    void drawThingspeak(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {
    display->setTextAlignment(TEXT_ALIGN_CENTER);
    display->setFont(ArialMT_Plain_10);
    display->drawString(64 + x, 0 + y, “Outside”);
    display->setFont(ArialMT_Plain_24);
    String OutsideTemp = thingspeak.getFieldValue(0);
    OutsideTemp.remove(2);
    String OutsideHum = thingspeak.getFieldValue(1);
    OutsideHum.remove(2);
    display->drawString(34 + x, 15 + y, OutsideTemp + “°C”);
    display->drawString(100 + x, 15 + y, OutsideHum + “%”);
    }

    void drawInside(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y) {
    display->setTextAlignment(TEXT_ALIGN_CENTER);
    display->setFont(ArialMT_Plain_10);
    display->drawString(64 + x, 0 + y, “Inside”);
    display->setFont(ArialMT_Plain_24);
    display->drawString(34 + x, 15 + y, String(t,0) + “°C”);
    display->drawString(100 + x, 15 + y, String(h,0) + “%”);
    }

    void drawForecastDetails(OLEDDisplay *display, int x, int y, int dayIndex) {
    display->setTextAlignment(TEXT_ALIGN_CENTER);
    display->setFont(ArialMT_Plain_10);
    String day = wunderground.getForecastTitle(dayIndex).substring(0, 3);
    day.toUpperCase();
    display->drawString(x + 20, y, day);

    display->setFont(Meteocons_Plain_21);
    display->drawString(x + 20, y + 12, wunderground.getForecastIcon(dayIndex));

    display->setFont(ArialMT_Plain_10);
    display->drawString(x + 20, y + 34, wunderground.getForecastLowTemp(dayIndex) + “|” + wunderground.getForecastHighTemp(dayIndex));
    display->setTextAlignment(TEXT_ALIGN_LEFT);
    }

    void drawHeaderOverlay(OLEDDisplay *display, OLEDDisplayUiState* state) {
    display->setColor(WHITE);
    display->setFont(ArialMT_Plain_10);
    String time = timeClient.getFormattedTime().substring(0, 5);
    display->setTextAlignment(TEXT_ALIGN_LEFT);
    display->drawString(0, 54, time);
    display->setTextAlignment(TEXT_ALIGN_RIGHT);
    String temp = wunderground.getCurrentTemp() + “°C”;
    display->drawString(128, 54, temp);
    display->drawHorizontalLine(0, 52, 128);
    }

    void setReadyForWeatherUpdate() {
    Serial.println(“Setting readyForUpdate to true”);
    readyForWeatherUpdate = true;
    }

    void setReadyForSensorUpdate() {
    readyForSensorUpdate = true;
    }

    • hey!!! i want to chek temperature of my room using es8266, DHT11, and OLED display ..can u plzzz give the code for it..i am getting error with it..

  21. Hi

    I’ve got this awesome project up and running but can’t seem to find the changes you are referring to for the DHT22 (ie. Line 37: I have added the DHT library)..??

    My line 37 for example is just “#include “OLEDDisplayUi.h”

  22. Great project. Thanks a bunch. I’ve got the Weather Station project running! For days I’ve been studying the parser to determine how this works. So the needed data (ie wunderground.getCurrentTemp() ) get filtered out of the returned data, right? I see where “currentkey” is compared to “temp_c” in the WU.cpp file that comes from the WU web service. But I can’t find where the String “key” gets built.
    If I learn enough, my aim is to convert your code to obtain and display bus arrival times at my bus stop… PLUS show the weather. Can’t thank you enough for your work.

  23. Thanks a lot for your work. I first created my own internet weatherstation with a Wemos D1 and I first ran into your code when I was looking for a library to parse the json that’s returned by the wunderground api, but I decided to use another library. My weatherstation displayed the weather on a simple 16×2 LCD. But I also had an order running from China for a tiny 1″ OLED that I planned to use for a small fm radio, and when it finally arrived I ran for the second time into your work when I was looking for a library to drive the OLED. Only then I found out that your weatherstation is mutch better 🙂 I especially like the animated screen transformations that are really useful with this tiny display. So now I’ve got a very nice little weatherstation running: I’ve added some more information like probability of rain, windspeed and direction, and added a DHT22 sensor that measures indoor temp and uploads it to thingspeak. I also found out last week that the time doesn’t automatically adjust to daylight savings time, so now I get the time from timeapi.org.
    So many thanks again, you’ve developed a very nice piece of code that easy to extend as well.

  24. thanks for your very good work.
    Just one question: Is the Daylight saving time managed? in which library?
    thank you again

  25. Hi all

    First of all thanks to Dani and all of you sharing their code and know-how about ESP8266 and ssd1306.
    I started playing with the weather station kit a few days ago.
    I wanted to display more than weather information so I started to read about stock market ticker.
    I managed to get the stock market information for some stocks and also managed to get the response parsed to get the information I want.
    Now I’m trying to display those information on the ssd1306 display.
    As it is not really comfortable to add a frame for each stock to display I thought I could just add 1 frame more and each time this new frame is displayed I want to display the information of a different stock.
    Example: I got the stock information for Apple and Netflix. I want to display the last price value of the stock.
    I added a new frame called drawStockInformation.
    The first time the frame drawStockInformation is displayed it should display the data for Apple.
    The second time the frame drawStockInformation is displayed it should display the data for Netflix.
    The third time the frame drawStockInformation is displayed it should display the data for Apple. And so on…

    Does anyone have an idea how to do that?

    Thanks in advance for any help!!!

  26. Having trouble getting the Arduino ide to recognize the 8266. works great on uno but driver doesn’t seem to work on the 8266. downloaded new driver but still get ‘ native serial port ….’ . . Have windows 10. Any help is appreciated

  27. Hello, This has got to be the best tutorial I have ever seen, thank you. Most everything is working perfectly for me. I am new to this stuff, I mean ESP8266’s, 0.96 displays and most everything that goes with it. I am however having a few minor problems and I was hoping you could help. I am using a windows 10 comp. The Arduino ide version I have is 1.6.13.
    My problems are with your tutorial “WeatherStation – IDE Setup” the address is https://blog.squix.org/weatherstation-ide-setup.

    1. in the “weatherStationWithlineDHT22” sketch line 124 FrameCallback frames[] = { drawDateTime, drawCurrentWeather, drawForecast, drawThingspeak, drawIndoor };
    line 125 int numberOfFrames = 5;
    in the tutorial you say there are 6 pages I don’t understand this, I only have 5 pages and there are no cloud graphics.

    2. in that same line 124, page 2 and page 3, (I am guessing) drawCurrentWeather, drawForecast, will not work, all I get is N/A.

    3. also on the fourth page labeled “outdoor” it never updates, it has shown the same temp and humidity for the last 24 hours. On the bright side my DHT22 indoor sensor seems to be working just fine.

    I get this message when it is done uploading,
    Sketch uses 319,697 bytes (30%) of program storage space. Maximum is 1,044,464 bytes.
    Global variables use 37,844 bytes (46%) of dynamic memory, leaving 44,076 bytes for local variables. Maximum is 81,920 bytes.
    Uploading 323840 bytes from C:\Users\Jim\AppData\Local\Temp\arduino_build_420951/WeatherStationWithDHT22.ino.bin to flash at 0x00000000
    …………………………………………………………………….. [ 25% ]
    …………………………………………………………………….. [ 50% ]
    …………………………………………………………………….. [ 75% ]
    ………………………………………………………………….. [ 100% ]
    Invalid library found in C:\Users\Jim\Documents\Arduino\libraries\esp8266-projects-master: C:\Users\Jim\Documents\Arduino\libraries\esp8266-projects-master
    Invalid library found in C:\Users\Jim\Documents\Arduino\libraries\esp8266-projects-master: C:\Users\Jim\Documents\Arduino\libraries\esp8266-projects-master
    I went into your GitHub files and downloaded the esp8266-projects-master file they were dated 09/28/2015.

    Could this be part of my problem?

    3. In the tutorial there is a paragraph that states “•In the Wunderground section you can now use the API key you received in the previous section. Also set the country and city of the place you want to show. To figure out which values work you can modify this URL: http://api.wunderground.com/api/3APIKEY/conditions/q/CA/San_Francisco.json and replace APIKEY with yours and “CA” and “San_Francisco” with your state or country and city.”

    You state that I must replace the APIKEY with my api key, does that mean that the 3 in the address should be left in and my key also has a dash as the third character does that stay or should I get rid of it? I did replace the Ca with OH and added my city.

    Sorry this is so long but this project gets me excited to learn as much as I can.

    Thank you

  28. Forget my last question I believe I have found a newer version of your weather station code called “weather station demo Extended DST” . I think it is dated Jan 2017 but I cannot be sure but it does talk about having 6 pages instead of 5.

    My problem is every time I try to compile the code or even load it I get a whole lot of error messages and since I am new to these things I really don’t know what they mean. Can you help me please. I think this program is so cool I must get it to work, it will make the perfect addition to my desk top displays.

    I am using a windows 10 machine and arduino v1.6.1. 3Below is a copy of the error messages I keep getting.

    Arduino: 1.6.13 (Windows 10), Board: “NodeMCU 1.0 (ESP-12E Module), 80 MHz, 115200, 4M (3M SPIFFS)”

    C:\Users\Jim\AppData\Local\Temp\arduino_modified_sketch_830395\WeatherStationDemoExtendedDST.ino: In function ‘void drawDateTime(OLEDDisplay*, OLEDDisplayUiState*, int16_t, int16_t)’:

    WeatherStationDemoExtendedDST:310: error: ‘localtime’ was not declared in this scope

    struct tm * timeinfo = localtime (&now);

    ^

    WeatherStationDemoExtendedDST:314: error: ‘ctime’ was not declared in this scope

    String date = ctime(&now);

    ^

    WeatherStationDemoExtendedDST:315: error: invalid use of incomplete type ‘struct tm’

    date = date.substring(0,11) + String(1900+timeinfo->tm_year);

    ^

    In file included from C:\Users\Jim\AppData\Local\Temp\arduino_modified_sketch_830395\WeatherStationDemoExtendedDST.ino:1:0:

    C:\Users\Jim\Documents\Arduino\libraries\simpleDSTadjust-master/simpleDSTadjust.h:46:26: error: forward declaration of ‘struct tm’

    time_t my_mktime(struct tm *tmptr);

    ^

    WeatherStationDemoExtendedDST:322: error: invalid use of incomplete type ‘struct tm’

    sprintf(time_str, “%02d:%02d:%02d\n”,timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);

    ^

    In file included from C:\Users\Jim\AppData\Local\Temp\arduino_modified_sketch_830395\WeatherStationDemoExtendedDST.ino:1:0:

    C:\Users\Jim\Documents\Arduino\libraries\simpleDSTadjust-master/simpleDSTadjust.h:46:26: error: forward declaration of ‘struct tm’

    time_t my_mktime(struct tm *tmptr);

    ^

    WeatherStationDemoExtendedDST:322: error: invalid use of incomplete type ‘struct tm’

    sprintf(time_str, “%02d:%02d:%02d\n”,timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);

    ^

    In file included from C:\Users\Jim\AppData\Local\Temp\arduino_modified_sketch_830395\WeatherStationDemoExtendedDST.ino:1:0:

    C:\Users\Jim\Documents\Arduino\libraries\simpleDSTadjust-master/simpleDSTadjust.h:46:26: error: forward declaration of ‘struct tm’

    time_t my_mktime(struct tm *tmptr);

    ^

    WeatherStationDemoExtendedDST:322: error: invalid use of incomplete type ‘struct tm’

    sprintf(time_str, “%02d:%02d:%02d\n”,timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);

    ^

    In file included from C:\Users\Jim\AppData\Local\Temp\arduino_modified_sketch_830395\WeatherStationDemoExtendedDST.ino:1:0:

    C:\Users\Jim\Documents\Arduino\libraries\simpleDSTadjust-master/simpleDSTadjust.h:46:26: error: forward declaration of ‘struct tm’

    time_t my_mktime(struct tm *tmptr);

    ^

    C:\Users\Jim\AppData\Local\Temp\arduino_modified_sketch_830395\WeatherStationDemoExtendedDST.ino: In function ‘void drawHeaderOverlay(OLEDDisplay*, OLEDDisplayUiState*)’:

    WeatherStationDemoExtendedDST:412: error: ‘localtime’ was not declared in this scope

    struct tm * timeinfo = localtime (&now);

    ^

    WeatherStationDemoExtendedDST:417: error: invalid use of incomplete type ‘struct tm’

    sprintf(time_str, “%02d:%02d:%02d\n”,timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);

    ^

    In file included from C:\Users\Jim\AppData\Local\Temp\arduino_modified_sketch_830395\WeatherStationDemoExtendedDST.ino:1:0:

    C:\Users\Jim\Documents\Arduino\libraries\simpleDSTadjust-master/simpleDSTadjust.h:46:26: error: forward declaration of ‘struct tm’

    time_t my_mktime(struct tm *tmptr);

    ^

    WeatherStationDemoExtendedDST:417: error: invalid use of incomplete type ‘struct tm’

    sprintf(time_str, “%02d:%02d:%02d\n”,timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);

    ^

    In file included from C:\Users\Jim\AppData\Local\Temp\arduino_modified_sketch_830395\WeatherStationDemoExtendedDST.ino:1:0:

    C:\Users\Jim\Documents\Arduino\libraries\simpleDSTadjust-master/simpleDSTadjust.h:46:26: error: forward declaration of ‘struct tm’

    time_t my_mktime(struct tm *tmptr);

    ^

    WeatherStationDemoExtendedDST:417: error: invalid use of incomplete type ‘struct tm’

    sprintf(time_str, “%02d:%02d:%02d\n”,timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec);

    ^

    In file included from C:\Users\Jim\AppData\Local\Temp\arduino_modified_sketch_830395\WeatherStationDemoExtendedDST.ino:1:0:

    C:\Users\Jim\Documents\Arduino\libraries\simpleDSTadjust-master/simpleDSTadjust.h:46:26: error: forward declaration of ‘struct tm’

    time_t my_mktime(struct tm *tmptr);

    ^

    Multiple libraries were found for “SSD1306Wire.h”
    Used: C:\Users\Jim\Documents\Arduino\libraries\esp8266-oled-ssd1306
    Not used: C:\Users\Jim\Documents\Arduino\libraries\ESP8266_Oled_Driver_for_SSD1306_display
    Not used: C:\Users\Jim\Documents\Arduino\libraries\ESP8266_Oled_Driver_for_SSD1306_display
    Not used: C:\Users\Jim\Documents\Arduino\libraries\ESP8266_Oled_Driver_for_SSD1306_display
    Not used: C:\Users\Jim\Documents\Arduino\libraries\ESP8266_Oled_Driver_for_SSD1306_display
    exit status 1
    ‘localtime’ was not declared in this scope

    Invalid library found in C:\Users\Jim\Documents\Arduino\libraries\esp8266-projects-master: C:\Users\Jim\Documents\Arduino\libraries\esp8266-projects-master
    Invalid library found in C:\Users\Jim\Documents\Arduino\libraries\esp8266-projects-master: C:\Users\Jim\Documents\Arduino\libraries\esp8266-projects-master

    This report would have more information with
    “Show verbose output during compilation”
    option enabled in File -> Preferences.

    Sorry its so long but I can not figure out all of these.

    Thank you
    Jim

  29. Many thanks for this excellent example!!

    Adafruit have updated their libs: with the latest DHT lib we now need to include the “Adafruit Unified Sensor” library as well, otherwise there is an error that “Adafruit_Sensor.h” cannot be found.

  30. hi great program
    is there a sleep setting the the code
    as min screen goes off after 15 mins and stays off
    have to reboot?
    cheers

  31. Great project! I live in the US, I’ve found the line where I change the METRIC_ true: to false to get the wunderground to display Fahrenheit . And gone and changed all the °C’s to °F’s, but how can I get the DHT22 to display in °F?

  32. I have the sketch for the example code up an running for the most part. However only two of the frames are correctly being updated. The time frame is correct as is the Outdoor temperature and humidity, however the next frames I get “N/A C” and for the three day forecast is also N/A. Is there a debug mode I can turn on in the wunderground library so I can figure out why the parsing is not working?

    • This ususually happens when the Wunderground API key is either wrong or not set or the location. Did you have a look in the serial console? There you should see the url it connects to. Make sure that you use state instead of country in the US and your city doesn’t contain spaces. E.g CA for state and San_Francisco for city

      • I see that in the code is looking for the the following URL:

        http://api.wunderground.com/api/59…………67/conditions/lang:EN/q/US/Huntington%20Beach.json

        which results in the following:

        response
        version “0.1”
        termsofService “http://www.wunderground.com/weather/api/d/terms.html”
        features
        conditions 1
        results
        0
        name “Huntington Beach”
        city “Huntington Beach”
        state “CA”
        country “US”
        country_iso3166 “US”
        country_name “USA”
        zmw “92605.1.99999”
        l “/q/zmw:92605.1.99999”
        1
        name “Huntington Beach”
        city “Huntington Beach”
        state “NY”
        country “US”
        country_iso3166 “US”
        country_name “USA”
        zmw “11721.2.99999”
        l “/q/zmw:11721.2.99999”

        I do not see the current conditions in this data. Also the code that you have for the forecast data is using the URL:

        http://api.wunderground.com/api/59…………67/forcast10day/lang:EN/q/US/Huntington%20Beach.json

        Which is for the 10 day forecast. The free account that you suggest as a start only gives you a 3 day forecast. Regardless here is what the request returns:

        response
        version “0.1”
        termsofService “http://www.wunderground.com/weather/api/d/terms.html”
        features {}
        error
        type “unknownfeature”
        results
        0
        name “Huntington Beach”
        city “Huntington Beach”
        state “CA”
        country “US”
        country_iso3166 “US”
        country_name “USA”
        zmw “92605.1.99999”
        l “/q/zmw:92605.1.99999”
        1
        name “Huntington Beach”
        city “Huntington Beach”
        state “NY”
        country “US”
        country_iso3166 “US”
        country_name “USA”
        zmw “11721.2.99999”
        l “/q/zmw:11721.2.99999”

        Because I cut and pasted the code from your example and did not touch the Thingspeak values, I am probably reading your “Outdoor” temperature and humidity. Here is the output of the serial terminal:

        Done…Setting readyForUpdate to true
        Updating time….
        22:31:13
        22:31:13
        81073
        Updating conditions…Requesting URL: /api/59………….67/conditions/lang:EN/q/US/Huntington Beach.json
        Updating forecasts…Requesting URL: /api/59…………67/forecast10day/lang:EN/q/US/Huntington Beach.json
        Updating thingspeak…Requesting URL: /channels/67284/feeds.json?results=1&api_key=L2VIW20QVNZJBLAK
        .
        field1: 27.10
        field2: 48.20
        Done…

        Thank you for your feedback, it is much appreciated.

        – Richard

  33. Hello, congratulations for the project. I’m mounting it with DHT22, but in the fourth outdoor field only the symbols ºC and% come out, I have no data and in the fifth indoor only leaves 0.0 ºC and nan%. You can help me, thanks

  34. Dear Daniel, Nice piece of work. I have it running as well here in Putnam Valley.
    Please warn readers that the wunderground URL needs to be encoded: so e.g. if you have a space in your city name (like I do), you need to encode it as %20. In particular in my .ino file I have: const String WUNDERGROUND_CITY = “Putnam%20Valley”;
    All the best.

  35. Hi, it looks perfect. I was wondering if it would be possible to add a switch button to slide for the next frame ?

  36. Hi as wunderground doesnt provide free api keys anymore can you substitute other keys say from openweathermap or is a complete change of code.
    Many Thanks

    • Having a few issues myself with this. Currently trying to make the modifications, it works absolutely fine if I put in the normal weather station demo code, but getting the following currently:

      Arduino: 1.8.3 (Windows 7), Board: “NodeMCU 1.0 (ESP-12E Module), 80 MHz, 4M (1M SPIFFS), v2 Lower Memory, Disabled, None, Only Sketch, 115200”

      Build options changed, rebuilding all
      WeatherStationDemo:168: error: redefinition of ‘void (* frames [])(OLEDDisplay*, OLEDDisplayUiState*, int16_t, int16_t)’

      FrameCallback frames[] = { drawDateTime, drawCurrentWeather, drawForecast };

      ^

      WeatherStationDemo:149: error: ‘void (* frames [5])(OLEDDisplay*, OLEDDisplayUiState*, int16_t, int16_t)’ previously defined here

      FrameCallback frames[] = { drawDateTime, drawCurrentWeather, drawForecast, drawThingspeak, drawIndoor };

      ^

      WeatherStationDemo:169: error: redefinition of ‘int numberOfFrames’

      int numberOfFrames = 3;

      ^

      WeatherStationDemo:150: error: ‘int numberOfFrames’ previously defined here

      int numberOfFrames = 5;

      ^

      C:\Users\Alex\AppData\Local\Temp\arduino_modified_sketch_434247\WeatherStationDemo.ino: In function ‘void updateData(OLEDDisplay*)’:

      WeatherStationDemo:282: error: ‘dht’ was not declared in this scope

      humidity = dht.readHumidity();

      ^

      exit status 1
      redefinition of ‘void (* frames [])(OLEDDisplay*, OLEDDisplayUiState*, int16_t, int16_t)’

      This report would have more information with
      “Show verbose output during compilation”
      option enabled in File -> Preferences.

    • Also looking for this myself!

      Even with the new guide, I’m having quite a few problems trying to implement the DHT22 into the code.

  37. salve, sono nuovo di Arduino, volevo fare questo progetto, ma quando carico lo sketch mi da il seguente errore:
    ui. setActiveSymbol (activeSymbole);
    ‘activeSymbole’ was not declared in this scope, mi potete aiutare?
    grazie

  38. Hi,i am new in arduino but have made succesfully run my weather with:oled,dht11,thingspeak reader from external sensor now have seen more user add rgb led for weather condition,anyone can upload or tell me how can i run weather with rgb led module?thanks everyone and very lovely project

Leave a Reply to GrzegorzCancel reply