Introduction: Yet Another Smart Weather Station, But...

OK, I know there are so many such weather stations available everywhere, but take a few minutes to see the difference...

  • Low power
  • 2 e-paper displays...
  • but 10 different screens !
  • ESP32 based
  • accelerometer and temperature / humidity sensors
  • Wifi update
  • 3D printed case

and lots of other useful tricks...

The main idea is to display various information on both displays depending on the orientation of the box. The case is in the shape of a parallelepipedic box, a paving stone, with a kind of belt that serves as a foot.


As you can see, the system consists of 2 e-paper screens and a 3D printed box. But there's a lot of things in it:

  • An ESP32
  • One MPU6050 accelerometer
  • A DHT22 sensor
  • A LiPo battery
  • A PCB to connect the whole thing
  • Homemade duPont threads

and a Wi-Fi connection. In fact 3 networks are declared, the system tests them one by one until it succeeds in connecting.

Step 1: Why Another Weather Station ?

The idea is to display various kinds of information on both screens depending on the orientation of the box. The case is in the shape of a parallelepipedic box, a paving stone, with a kind of belt that serves as a support to make it stand.

The accelerometer detects movement and orientation and triggers displays.

To save energy, I chose the e-paper screens (see references below) that keep the display even if they are no longer powered. Similarly for the ESP32, I chose the Lolin32 module (renowned for its frugality) and I had to learn how to manage deep sleep, and the wake-up on interrupt generated by the accelerometer.

The screens are connected through SPI, I searched quite a bit before finding the right pins to connect them to the ESP32, knowing that I also need an I2C for the accelerometer, a pin to read the DHT22 and 2 others for the battery voltage measurement. The ESP32 is almost fully charged! Knowing that some pins are read-only (I used those for the DHT sensor), others cannot be used together with Wifi, it was a little complicated to find the right configuration.

The box can be oriented in 4 directions, plus flat. All in all that makes 4*2+2 = 10 possible types of information to display with only 2 screens. So it allows you to display a lot of things:

  • The date, and the saint of the day
  • The current time
  • Today's weather forecast
  • Weather forecasts for the coming hours
  • Weather forecasts for the coming days
  • The battery charge level
  • And as I still had room, a random quote from a specialized website.

Step 2: What Do You Need ?

  • ESP32 : Lolin32 module (very low power, equiped with a battery connector, can charge the battery through USB plus)
  • 2 epaper displays : 4.2 inches and 2.9 inches. I chose the models from Good Display store.
  • DHT22 sensor
  • MCU6050 accelerometer - gyrometer I2C sensor
  • A LiPo battery
  • For battery voltage measurement: 2 10k resistors, 1 100k resistor, 1 100nF capacitor, 1 MOSFET transistor
  • Solder and soldering iron, printed circuit board
  • Access to a 3D printer for the case

The attached image shows the position of all the components on the PCB : I had to save space to fit in the case, which shouldn't be too big.

In order to get the weather data, you also need to register on the weather APIs and put your keys in the correct places in the 'Variables.h' file (see below).

Weather websites:

Step 3: This Project Made Me Think and Learn a Lot...

This system was supposed to be low-power, so that you don't need to charge the battery every night... To save energy, I chose the e-paper screens that keep the display even if they are no longer powered. Similarly for the ESP32, I chose the Lolin32 module (renowned for its frugality) and I had to learn how to manage deep sleep, and the wake-up call on interruption generated by the accelerometer.

The box can be oriented in 4 directions, more flat. All in all that makes 4*2+2 = 10 possible types of information to display. So it allows you to do a lot of things: the date, and the saint of the day, the time, today's weather forecast, weather forecasts for the coming hours or days, the battery charge level and a random quote from a specialized website.

It's a lot to look for on the Internet, and as you know: WiFi is the enemy of energy saving...

So we have to manage the connection, in order to display up-to-date information but without spending too much time connecting. Another rather complex problem: keeping a fairly accurate time. I don't need a RTC since I can find the time on the internet, but the ESP32's internal clock drifts quite a bit, especially during sleep periods. I had to find a way to stay accurate enough, while waiting to reset the clock by internet. I resynchronize it on the internet every hour.

So there is a trade-off between autonomy (the frequency of Internet connections) and the accuracy of the information displayed.

Another problem to be solved is the memory. When the ESP32 is in deep sleep, the memory is lost, except for what is called RTC RAM. This memory is 4MB wide, of which only 2 can be used for the program. In this memory, I must store the various program variables that must be kept from one execution to the next, after a sleep phase: weather forecasts, time and date, icon file names, quotes, etc. I had to learn to deal with it.

Speaking of icons, they are stored in the SPIFFS, the ESP32 file system. Following the closure of the free Wunderground weather API, I had to look for other free weather data providers. I selected two: one for the current day's weather, with 12 hours forecasts , and another for the multi-day forecasts. The icons are not the same, so it caused me two new problems:

  • Choose an icon set
  • Match these icons to the forecast codes of the 2 sites

This correspondence has also been stored in the RTC RAM so that it does not have to be reloaded each time.

Last problem with icons. Impossible to store all of them in the SPIFFS. The space is too small for all my files. It was necessary to do image compression. I wrote a script in Python that reads my icon files and compresses them into RLE, and then store the compressed files in SPIFFS. There it held.

But the e-paper display library only takes BMP-type files, not compressed images. So I had to write an additional function to be able to display my icons from these compressed files.

The data read on the internet is often in json format: weather data, Saint of the day. I use the (great) arduinoJson library for this. But quotes are not like that. I take them from a dedicated site, so I have to read them by looking directly into the content of the web page. I had to write a specific code for that. Every day, around midnight, the program goes to this site and reads about ten random quotes, and stores them in the RTC RAM. One is displayed at random among them when the housing is oriented large screen upwards.

I pass you the problem of the display of accented characters (sorry, but quotes are in French)....

When the small screen is up, the battery voltage is displayed, with a drawing to better see the remaining level. It was necessary to make an electronic assembly to read the battery voltage. As the measurement should not discharge the battery, I used a diagram found on the internet, which uses a MOSFET transistor as a switch in order to consume current only when the measurement is made.

In order to be able to make this circuit and fit everything into the box, that I wanted the smallest possible, I had to make a PCB to connect all the components of the system. This is my first PCB. I was lucky because everything worked well the first time on this side...

See implantation map : the "forbidden zone" is an area reserved for connecting the USB cable. The Lolin32 module allows you to recharge the battery via USB: the battery is charged if the USB cable is connected, and the module works at the same time.

Last point: the fonts. Of different sizes, bold or not, they had to be created and stored. The Adafruit GFX library takes care of that very well, once you have installed the font files in the right directory. To create the files, I used the Font Converter site, very convenient!

Make sure you select:

  • Preview display : TFT 2.4"
  • Library version: Adafruit GFX Font

So to summarize: a big project, which allowed me to learn a lot of things.

Step 4: Using E-paper Displays

The main disadvantage of these screens is clearly visible on the video: the update of the display takes one or two seconds and is done by flashing (alternative display of the normal and inverted versions of the two screens). This is acceptable for weather information because I don't update it very often (every hour except for a change of orientation of the box). But not for the time. That's why (and to limit consumption) I still use the HH:MM display (not the seconds).

So I had to look for another way to update the display. These screens (some of them) support a partial update (applied either to an area of the screen, or to the entire screen...) but it was not good for me because my large screen (which displays the time) keeps ghosts of the pixels that are replaced. For example, when passing from 10:12 to 10:13, the '2' is a little visible inside the '3', and it becomes even more visible after the '4', the '5', etc. I would like to point out that this is the case for my screen: I discussed it with the author of the e-paper display library GxEPD2 who told me that he did not observe this phenomenon with his own screens. We tried to change the parameters without succeeding in hunting ghosts.

So we had to find another solution: I proposed to do a partial double refreshment, which solved the problem (at least it's satisfactory for me). The hours are passed without the screen flashing and there are no ghosts. However, the changeover is not immediate: it takes a little more than one second to change the time.

Step 5: Making It

To ensure that nothing moves inside when the orientation changes, the different components (displays, electronic modules, PCBs, batteries) are glued with a glue gun. To route the wires under the PCB, I installed it on legs made with spacers, the same goes for the battery.

Soon I will install an external USB microphone connector so I won't have to open the case to recharge the battery.

Maybe I'll also be interested in updating by OTA to perfect it all....

Step 6: The Code and the Files

Three archive files are provided:

  • Weather : the Arduino code, to upload using the Arduino IDE
  • Boite : the CAD and 3D printer files for the case
  • : the files to be uploaded in the SPIFFS of the ESP32.

If you don't know how to upload files into the ESP32's SPIFFS, just read this tutorial, which presents a very useful plugin and how to use it in the Arduino IDE.

The deep sleep programming is quite different from the standard programming of an Arduino. For the ESP32, it means that the ESP32 wakes up and executes the setup, then goes to sleep. So, the loop function is empty, and is never executed.

Some initialization phase must be run only once at the first execution (such as getting the time, the weather data, quotes, etc), so the ESP32 needs to know if the current wake up is the first one or not: for that, the solution is to store a variable in the RTC RAM (which remains active even during deep sleep phases) which is increased at each wake-up. If it is equal to 1 then it's the first execution and the ESP32 runs the initialization phase, otherwise this phase is skipped.

To wake the ESP32 up, there are several possibilities:

  • Timer wake-up: the code computes the duration of the deep sleep before going to sleep. This is used to update the time (every 1, 2, 3, or 5 minutes) or the weather data (every 3 or 4 hours) of the quotes and saint of the day (every 24 hours)
  • Interrupt wake-up: the accelerometer sends a signal that is used to wake the ESP32 up. This is used to detect an orientation change and update the displays
  • Touch sensor wake-up: the ESP32 is equiped with several pins acting as touch sensors, but they cannot be used with timer wakeup, so I didn't use this.

There are other programming tricks elsewhere in the code, to keep the time accurate while saving energy (i.e not connect the the NTP server each minute), to remove the accents that are not supported by the Adafruit GFX library, to avoid update a display if it is not necessary, to set the accelerometer parameters especially for interrupt wake-up, accurately compute the time to sleep in case of timer wake-up, avoid using the Serial console if not connected to the IDE (to save energy again), disconnect the wifi when not needed, etc... and the code is full of comments that help understand the functions.

Thanks for reading this Instructable (my very first one). I hope you'll like it and enjoy making this weather station.

Sensors Contest

Runner Up in the
Sensors Contest