Post

ENG | Raspberry Pi Pico W Indoor Weather Station

Project page for personal indoor weather station using MicroPython, with design considerations and practical insights.

ENG | Raspberry Pi Pico W Indoor Weather Station

This article describes building a weather station based on Raspberry Pi Pico W. The project starts with a simple indoor setup measuring temperature, humidity and atmospheric pressure, displaying values on a screen and uploading them to a server. Later versions may add features like local data storage, pressure trend analysis and a configuration menu.

Project is work in progress for winter 2024/25

Why (Yet Another Useless) Weather Station?

It’s just a perfect learning project as it touches many fundamental tasks, transferable to other projects:

  • Platform and development toolset familiarity (beyond “hello world”)
  • Sensor and display interfacing (I2C, SPI)
  • Data acquisition, storage and/or transmission
  • Power management
  • Client-server communication
  • Getting familiar with a display
  • Making menu system

Analysis of Weather Station Scenarios

When thinking about building a weather station, the design can range from a remote, outdoor, battery-operated device to an indoor, internet-connected setup. Each has its own design considerations and trade-offs, and there’s also the option to combine features from both, creating a more complex hybrid design.

Scenario 1: Remote, battery operated data logger

This data logger must have very low power consumption as it’s powered by batteries. It has to exploit some deep-sleep states of microcontroller, possibly disconnect sensors and i2c bus during sleep and interrupts are needed to wake it up. It has to safe data in longer intervals.

  • RTC must be synchronized, for example via terminal connection.
  • RTC should have backup battery.
  • Data must be synchronized using BLE or serial terminal - or by turning device off and reading storage externally.
  • Exploiting deep-sleep modes and wakes on interupt-driven wake-ups is crucial.
  • Tools for reading data and clock synchronization are needed.
  • Device can operate either in normal or service mode where user interaction via terminal has priority over low power operation.
  • There should be safe shutdown when battery voltage is low.

Suitable microcontrollers can be Arduino Pro Mini with disabled LED or maybe Nordic Semiconductor nRF52 series.

Scenario 2: Indoor Conditions Monitoring

On the other hand, if the weather station is intended for indoor use, the design can be much simpler. Since power is readily available and internet access is assumed, frequent data synchronization is possible. For example, measurements could be uploaded every few minutes without the need for a local RTC. In case of local time, RTC could be synchronized via NTP.

In this case, a weather station becomes more of a live data monitor. A display could be added for immediate readings, and while storing historical data is unnecessary, it can be useful for tracking atmospheric pressure trends.

In the most simple scenario, weather station may have direct access to server (e.g. Raspberry Pi) with fixed IP address.

Some data backup plan on server side should be considered.

Hybrid Scenarios & Added Complexity

Things get more “interesting” when combining features from both scenarios. A hybrid design might include:

  • Local backup storage for unreliable / unavailable wifi
  • Display and buttons
  • Service menu for configuration such as
    • Setting clock manually
    • Reconditioning SHT40 sensor
    • Setting altitude for sea level pressure calculation
    • Recent errors (log entries)
    • WiFi connection setup
  • Options to display history locally (graphs)
  • Decimation and aggregation of old data (to conserve memory, or for graphs)
  • Multiple power options combining USB, solar, and battery
  • More, perhaps optional sensors such as rainfall, wind speed & direction, CO2, …
  • Because this option has buttons, it has to be responsive

While these features add a lot of functionality, they also significantly increase the complexity of the design and the logic required in the microcontroller.

Design considerations

Bluetooth Low Energy (BLE)

After playing with BLE briefly just for curiosity, I came to the conclusion that it’s not worth using for a simple weather station.

How I understand it, it’s good for devices such as smart watch or sensors that operate from battery, but to synchronize files, they need a client that can periodically download data from a server (device that collects data). A suitable client is a more complex device such as a mobile phone with dedicated application which downloads data from a server and uploads them to other server (let’s call it cloud) which stores them permanently.

This adds layer of complexity - learning how to program mobile app, another programming language and toolset.

Raspberry Pi Pico W has a WiFi module, it can establish HTTPS connections directly. Also it’s not a low-power device per se, so I don’t see a point in using BLE.

However, BLE can be fine in a different scenario, where a weather station is a battery-powered device which collects a few hundred kilobytes of data per month and is occasionally synchronized with a laptop brought to the site. Nonetheless, Raspberry Pi Pico is not a suitable microcontroller for that scenario.

Other scenario which came to my mind is using BLE if the server is in the same room as a sensor and server supports BLE - either it is a single board computer with BLE support or via USB adapter.

Note from the future: using USB BT adapter and Python+Bleak library is just as viable option as WiFi and it removes HTTP uploads of JSON files, which I used. Experiments are in the article Testing Bluetooth LE from June 2025.

Server-side Database

I’d like to start with keep it simple stupid approach such as uploading data to python/flask server that appends them into CSV (comma seperated values) file or possibly adds them into database. Then there should be some periodic task that aggregates data for week/month/year interval. Maybe using good old RRDtool could be a solution? Or modern Grafana ? In the simple case, front end can be a webpage that creates graphs from CSV files using gnuplot or python seaborn+pandas libraries.

I believe this approach has several advantages:

  • CVS format is human-readable, easy to parse and timeless
  • Low initial complexity, easy to debug
  • Can be extended later
  • Simple data processing, minimal infrastructure required
  • Rather straight-forward backup and recovery plan or data retention policy

And several details to consider:

  • Handling of missing data
  • Data might be stored in UTC, you may want to handle daylight saving and data over day boundaries
  • Optional caching of generated graphs
  • Interactive visualization is harder to implement

Alternative to CSV may be sending single-line JSON files and appending them to a single file, for example (some data are added by server):

1
{"station_id": "sta01", "time": "2025-01-01T08:33:34Z", "temperature": 20.11, "pressure": 98582.4, "humidity": 42.43, "time_of_arrival": "2025-01-01T08:33:35Z", "dew_point": 6.96, "sea_level_pressure": 101557.1, "specific_humidity": 0.00633}

This format is a bit verbose, but self-documenting, easy to extend, and parse. Another alternative could be binary file, possibly containing raw sensor readings.

Configuration file

  • Station ID
  • Altitude for barometric pressure conversion
  • Wi-Fi SSID and password
  • Physical pin configuration
    • Default pins for I2C devices
    • Display pin mappings (SPI, GPIO for D/C, RST, etc.)
    • Optional pins (LED output pins, button input pins)

Block diagram

Note: Numbers after slash denote number of wires. All components except sensors are optional, allowing for flexible configuration from minimal (sensors only) to full-featured setup.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 +-----------+             +---------------+
 |       SPI |..../6-7.....|    Display    |
 |           |             +---------------+
 | RASPBERRY |     
 | PI PICO W |      +---------+ +--------+ +-----+
 |           |      | BMP 280 | | SHT 40 | | RTC |
 |           |      +---------+ +--------+ +-----+
 |           |            .         .         .
 |       I2C |..../4...........................
 |           |
 |           |
 |           |             +-----------------+
 |  3xDout+G |..../4 ......| RGB LED  +  3xR |
 |           |             +-----------------+
 |           |
 |           |             +-----------------+
 |   4xDin+G |..../5.......| 4 Arrow Buttons | 
 |           |             | (or rotary enc) |
 |           |             +-----------------+
 |           |
 |           |             +-----------------+
 |     Vin+G |..../2.......|     Battery     |
 +-----------+             +-----------------+

Front panel

Front panel is inspired by CRT TV and menu system of old phones - four buttons are back, up, down, enter

1
2
3
4
5
6
7
8
9
10
11
+----------------------+
|                      |
| +-------------+  (<) |
| |             |      |
| | LCD         |  (^) |
| |             |      |
| |             |  (v) |
| |             |      |
| +-------------+  (>) |
|                      |
+----------------------+

Breaking into task

Because I already started exploring Raspberry Pi Pico variants, I’ll focus on starting with indoor scenario with and I may progress towards hybrid scenario. This means implementing sensors, relying heavilly on wifi connectivity and creating some simple server for upload. I already have a Linux server at home that can host server part and rely on Cloudflare for connectivity.

Some tasks can be handled by external tools (e.g. SHT40 sensor reconditioning)

Common task (high priority):

Indoor station tasks:

  • Create Python/Flask server
    • Create upload page
    • Create dashboard (current values)
    • Create graph page (plotly dash? grafana?)
    • Additional computations (sea level pressure, dew point)
  • Create function to connect to WiFi
  • Synchronize time
  • Create function for data upload over HTTPS
  • Create function to disconnect from WiFi
    • Verify it works, seems that other connections are established instantly (it does not)
    • 2nd attempt to disconnect wifi
  • Diagnostic RGB LED

Hybrid station tasks:

Advanced tasks:

  • Create main loop with minimal waits
  • Integrate SPI flash (or use local filesystem)
  • Integrate battery backed RTC
  • Handle buttons with debounce - four buttons for menu, two can be replaced by rotation encoder
  • Integrate menu system
    • Manually set RTC
    • Last log messages
    • SHT40 reconditioning (blocks data logging)
    • Manually set altitude
    • WiFi credentials (I guess entering text using four buttons is hard)
    • Upload data on request
    • Upload interval
  • Explore watch dog timer/reset
  • Try to resend data on failed attempt
  • Isolate server as docker image with volume for data
  • Bluetooth low energy

Other tasks:

  • Design 3d printed enclosure with front panel for display, four buttons and diagnostic LED.

Rough Plan for indoor station

Version 0.9:

  • Raspberry Pi Pico W + SHT40 sensor + BMP280 sensor
  • WiFi time synchronization
    • integration
  • Data upload client
    • integration
  • Data upload server (note: python+flask)
  • Diagnotistics via USB (printf)

Version 1.0:

  • Upload server: Add time of arrival and derived data
  • Error handling, polishing (unclear goal)
  • Server displays current data (dashboard)

Version 1.1

  • Optimized main loop latencies
  • Display

Version 1.2

  • Graphs

Project repository

See my github

Changelog

  • 2024-12-29:
    • Most code is in a form of snippets, weather station runs on Pico, whereas network stuff is prototyped on Pico W without sensors. Code snippets are being collected and uploaded to GitHub.
  • 2024-12-31:
    • Station shows BMP280 and SHT40 data on display (merged loop code, font rendering, bmp280 snippets)
    • Station upgraded to Pico W.
    • Reached v1.1 goals but not some previous ones
  • 2025-01-01:
    • Implemented upload code
    • Implemented time sync, although sometimes upload with zero time may happen in the first batch
    • Server adds calculated data
    • Reached v0.9 goals
  • 2025-01-02
    • Server now saves last measurement to separate json file
    • Dashboard that reads last measurement, calculated fields
    • Reached v1.0 goals, but error handling (there is some, but is it sufficient?)
  • 2025-01-04
    • Attempt to reduce power consumption by using sleep (fail) and turning off wifi (success)
  • 2024-01-15
    • Plotting scripts
  • 2024-01-17
    • Server: Merged servers for upload and dashboard (index)
  • 2024-01-20
    • Server: Added options to add data into database instead of JSONL file
    • Server: systemd timer used for peridic tasks
  • 2025-06-06
    • Experiments with Bluetooth LE
  • TODO:
    • add bmp280 temperature to uploaded data
    • add systemd scripts to github repo
    • possibly make docker image with python and postgresql
    • pythonic approach to server (jinja2, matplotlib)

Project Summary and Conclusion

To be honest, despite this weather station is somewhat successful, annoying fact is that it needs to be placed into proximity of power outlet. As shown in related article, sea level pressure calculation is affected by temperature extremes, maybe it’s better to exclude them.

The display, while functional with a retro aesthetic, has an issue with unreliable PCB contacts.

TODO: screenshot, photo

Lessons learned

This project provided valuable insights and experience, including:

  • Rendering font into framebuffer for display
  • Time synchronization (MicroPython’s code implementation seems trivial and easily portable)
  • Calculating meteorological parameters like dew point, sea-level pressure, and specific humidity.
  • Python’s lightsleep and deepsleep (lightsleep+reset) are not worth using as they are causing troubles (RTC is stopped, USB is off and Pico unreacheable), but power consumption remains high - this can further explored on RPI Pico without display or sensors.
  • Developing a simple Python+Flask server and data upload and collection.
  • Data upload over HTTPS
  • Limitations such as reliance on the USB power, reliability of used display
  • Basics of time series in PostgreSQL database
  • Very basics of using Flask and SqlAlchemy modules for Python
  • This page with project breakout was actually very useful to break project into small part and prototype them in advance

Areas for Improvement

Future iterations could address the following:

  • Because station is constantly powered by USB charger, OLED display could be used - or no display.
  • If server has BLE capability and it’s located in proximity of server, it can be easier to read broadcasted data rather than using JSON over HTTPS over WiFi. On the other hand current solution works at every place with access to WiFi.

Addendum (2025-01-26)

It went into a bit different direction, than I had in mind. For last two or three weeks, station is on a shelf in my bedroom, collecting data, but I haven’t touched it or looked at display for that time. Instead, I created a web dashboard and later added graphs which are periodically updated. This simplifies code on Raspberry Pi Pico as all what is needed is reading sensor data, time synchronization and upload.

I completely omited using menu system, buttons, 3d printed enclosure, or local data logging.

Addendum (2025-06-07)

And to be fair, BLE solution can further simplify the design:

  • no need for time synchronization (unless if it is on the display)
  • no need for HTTP/JSON although JSON adds some flexibility
  • drawbacks are less reliable data transfers and no option to send data via any access point connected to internet - fine for home, not great for cottage with WiFi, but no server
This post is licensed under CC BY 4.0 by the author.