--- title: "Temperature Sensors" slug: "temperature-sensors" date: "2024-08-26" toc: true pics: pico-ws: css: "image" tip: "Pico Ws with BME280 sensors attached." sources: - "/files/articles/temperature-sensors/pico-ws-1024.webp" - src: "/files/articles/temperature-sensors/pico-ws-1024.jpg" width: 1024 height: 771 old-sensors: css: "image" tip: "Original BME280 sensors." sources: - "/files/articles/temperature-sensors/old-sensors-20180724-1024.webp" - src: "/files/articles/temperature-sensors/old-sensors-20180724-1024.jpg" width: 1024 height: 768 old-pi3: css: "image" tip: "Bedroom Pi 3 HTPC with BME280 sensor attached." sources: - "/files/articles/temperature-sensors/old-pi3-20180724-1024.webp" - src: "/files/articles/temperature-sensors/old-pi3-20180724-1024.jpg" width: 1024 height: 768 old-web-ui-1: css: "image" tip: "Original web interface (2018)." sources: - "/files/articles/temperature-sensors/old-web-ui-1-1024.webp" - src: "/files/articles/temperature-sensors/old-web-ui-1-1024.png" width: 1024 height: 576 old-web-ui-2: css: "image" tip: "Improved web interface (2019)." sources: - "/files/articles/temperature-sensors/old-web-ui-2-20190905-1024.webp" - src: "/files/articles/temperature-sensors/old-web-ui-2-20190905-1024.png" width: 1024 height: 765 web-desktop-0: css: "image" tip: "Current Data, Charts, and Forecast panels in the desktop web interface (2024)." sources: - "/files/articles/temperature-sensors/web-desktop-0-1024.webp" - src: "/files/articles/temperature-sensors/web-desktop-0-1024.png" width: 1024 height: 640 web-desktop-1: css: "image" tip: "Edit Sensor dialog in the desktop web interface (2024)." sources: - "/files/articles/temperature-sensors/web-desktop-1-1024.webp" - src: "/files/articles/temperature-sensors/web-desktop-1-1024.png" width: 1024 height: 640 web-desktop-2: css: "image" tip: "Charts panel in the desktop web interface (2024)." sources: - "/files/articles/temperature-sensors/web-desktop-2-1024.webp" - src: "/files/articles/temperature-sensors/web-desktop-2-1024.png" width: 1024 height: 640 web-desktop-3: css: "image" tip: "Forecast details dialog in the desktop web interface (2024)." sources: - "/files/articles/temperature-sensors/web-desktop-3-1024.webp" - src: "/files/articles/temperature-sensors/web-desktop-3-1024.png" width: 1024 height: 640 carousel: bottom: - link: "/files/articles/temperature-sensors/web-mobile-0.png" tip: "Current Data panel." css: "image" sources: - "/files/articles/temperature-sensors/web-mobile-0-1024.webp" - src: "/files/articles/temperature-sensors/web-mobile-0-1024.png" width: 460 height: 1024 - link: "/files/articles/temperature-sensors/web-mobile-1.png" tip: "Edit Sensor dialog." css: "image" sources: - "/files/articles/temperature-sensors/web-mobile-1-1024.webp" - src: "/files/articles/temperature-sensors/web-mobile-1-1024.png" width: 460 height: 1024 - link: "/files/articles/temperature-sensors/web-mobile-2.png" tip: "Charts panel." css: "image" sources: - "/files/articles/temperature-sensors/web-mobile-2-1024.webp" - src: "/files/articles/temperature-sensors/web-mobile-2-1024.png" width: 460 height: 1024 - link: "/files/articles/temperature-sensors/web-mobile-3.png" tip: "Forecast Details dialog." css: "image" sources: - "/files/articles/temperature-sensors/web-mobile-3-1024.webp" - src: "/files/articles/temperature-sensors/web-mobile-3-1024.png" width: 460 height: 1024 # table data tables: # available table properties pins: name: "Pins" cols: - id: "color" name: "Wire Color" tip: "Wire color." - id: "pico" name: "Pico W" tip: "Pico W pin." - id: "bme280" name: "BME280" tip: "BME280 pin." rows: - color: "Red" pico: "#36, 3V3(OUT)" bme280: "VIN" - color: "Black" pico: "#3, GND" bme280: "GND" - color: "Yellow" pico: "#6, GP4, I2C0 SDA" bme280: "SDA" - color: "Green" pico: "#7, GP5, I2C0 SCL" bme280: "SCL" --- ## Introduction We have several [Raspberry Pi Pico Ws][pico w] throughout the house. The [Pico Ws][pico w] collect temperature and humidity measurements. There is a web interface which shows the current measurements, charts of recent measurements, and the weather forecast for several days. Here is a picture of the web interface: [{{< pe-figure "web-desktop-0" >}}][web-desktop-0] The following sections describe the history of this project, the hardware, the software on the [Pico Ws][pico w], and the software behind the web interface. **Note:** [Home Assistant][] or an [Ecobee][] are both more practical solutions; this started as a tinkering project that accidentally became useful for us. That said, there is some value in controlling all of the hardware and software; none of our our data leaves our home network, we don't have to create an account on a ridiculous online hub with a dubious privacy policy, and we don't have to worry about our [devices being bricked in a couple of years][bricked]. ## History In 2018 I attached [BME280][] sensors to our [Raspberry Pi 3][pi3] [HTPCs][htpc] and created a minimal web interface to view the sensor measurements. Here is a picture of the original [BME280][] sensors: [{{< pe-figure "old-sensors" >}}][old-sensors] Here is the original bedroom [Pi 3][pi3] [HTPC][] with a [BME280][] sensor attached: [{{< pe-figure "old-pi3" >}}][old-pi3] And here is the original web interface (yikes!): [{{< pe-figure "old-web-ui-1" >}}][old-web-ui-1] In 2019 I added a third sensor attached to a [Raspberry Pi Zero W][pi0w] in the basement and outdoor measurements pulled from the [National Weather Service (NWS) API][nws-api]. I also made several improvements to the web interface: - Redesigned in [Bootstrap 4][]. - Added [chart.js][]-based charts. - Added weather forecast from [NWS API][nws-api]. Here is the improved web interface from 2019: [{{< pe-figure "old-web-ui-2" >}}][old-web-ui-2] The setup above worked for several years, but the software was a mishmash of undocumented [Ruby][], [shell scripts][], and [cron][] jobs. This caused several problems: - It was difficult to install and difficult to maintain. - It required a full Raspberry Pi running Linux. This was fine for the dual-use [Pi 3][pi3] [HTPCs][htpc], but it felt like a waste of a [Pi Zero W][pi0w]. - The web interface queried the status of all sensors on page load (pull model). This made the page unnecessarily slow. - The web interface would fail to load when sensors were inactive or unreachable. - The charts in the web interface were not mobile-friendly. - It collected several measurements that we never used, like [load average][loadavg] and network quality. - The collected data was concatenated to a [CSV][] file rather than inserted atomically into a database. This made it slow and difficult to query. - When we moved we needed more sensors, but I didn't want to "waste" any more [Pi Zero Ws][pi0w] or deal with the hassle of setting up the software. In 2022 I [bought a spool of Pico Ws][bought-pico-ws] to replace the existing hardware and decided to rewrite the web interface to address the problems listed above. The [Pico Ws][pico w] sat unused for a couple of years because I didn't have a good work area. In 2023 we lost two of the sensors: - one failed during a [botched Pi Zero W Bookworm upgrade][failed-upgrade]. - one failed for no apparent reason. In 2024 we set up my [home office][] and I started working on the new hardware and software. ## Hardware [Raspberry Pi Pico Ws][pico w] microcontrollers with [BME280s][bme280] connected via [I2C][]. Here are three of them: [{{< pe-figure "pico-ws" >}}][pico-ws] [Fritzing][] is on the fritz for me at the moment so I don't have a pinout diagram. Here is a pinout table instead: {{< table "pins" >}} ## Software The software is available in the [Sensortron Git repository][repo]. The repository contains two directories: - `pico-w/`: [Pico W][] [Micropython][] code which periodically collects and sends [BME280][] sensor measurements to an [API][] endpoint. - `web/`: Web interface which shows sensor measurements and the weather forecast. ### Pico W [Micropython][] script in the `pico-w/` directory of the [Sensortron Git repository][repo] which runs on the [Pico Ws][pico w] and does the following: 1. Read the configuration from `config.py`. 2. Initialize the [BME280][] sensor attached to [I2C][] bus 0. 3. Connect to the [Wi-Fi][] network. 4. Read sensor values every 10 seconds and send them to an [API][] endpoint. The code for the logic above is in [pico-w/main.py][]. Installation is documented and straightforward: 1. Flash latest [Pico W Micropython image][]. 2. Copy `main.py` and `bme280.py` to the [Pico W][]. 3. Edit `config.py` and copy it to the [Pico W][]. Here is an example `config.py`: ```python # diningroom.py: example sensortron configuration file # wifi ssid and password (required) WIFI_SSID = 'YOUR-WIFI-SSID' WIFI_PASSWORD = 'YOUR-WIFI-PASSWORD' # api url (required) URL = 'http://sensors.home.pmdn.org:1979/api/read' # pseudo-mac secret (optional, defaults to '' if unspecified) SECRET = 'SOME-SECRET-STRING' # host name (optional, defaults to pico-$UNIQUE_ID if unspecified) HOSTNAME = 'pico-diningroom' ``` ### Web interface Web interface in the `web/` directory of the [Git repository][repo] which shows current sensor measurements, a filterable chart of recent sensor measurements, and the weather forecast for the next several days. The web interface also exposes an [HTTP][] [API][] endpoint which the [Pico Ws][pico w] use to submit their current sensor readings. The appearance of the current web interface is similar to the older 2019 web interface, but with many improvements. Backend improvements: - Written in [Go][]. - Two dependencies: [go-chi][] and [modernc.org/sqlite][]. - Web assets are [embedded][embed] in the binary. - Periodic tasks are handled in [goroutines][] spawned from the binary rather than a set of [cron][] jobs. - Data is stored in a [SQLite][] database. - Sensors post measurements to an [API][] endpoint (push model). - Built and deployed as single static binary in a a small (<20M) [container][]. The build is [multi-stage][] and the output image is based on [distroless][]. Persistent data is stored in one place (`/data`) so the container is [volume][]-friendly. Frontend improvements: - [Bootstrap 5.3][] and [chart.js 4.4][chart.js]. - Sensor display parameters (name, color, and sort order) are now editable via the web interface. - Charts are now [responsive][] and render correctly on desktop and mobile. - Charts can be downloaded as [PNG][] images. - Removed unused features. Example: air pressure. - Added new useful features. Example: probability of precipitation. - Interface refreshes automatically without a page reload. The home page loads instantly with these improvements. It's also much easier to update, build, and deploy. Here's the one-liner I use to deploy, split into multiple lines for legibility: ```sh # - pull latest code from git repo # - build image # - stop old container (if any) # - start new ephemeral container named "sensortron" which exposes port # 1979, and uses the "sensortron" volume git pull && podman build -t sensortron . && ( podman stop sensortron; podman run -d --rm -p 1979:1979 -v sensortron:/data --name sensortron sensortron ) ```   Here are the current data, charts, and forecast panels on the home page of the 2024 web interface: [{{< pe-figure "web-desktop-0" >}}][web-desktop-0] Edit Sensor dialog: [{{< pe-figure "web-desktop-1" >}}][web-desktop-1] Charts panel: [{{< pe-figure "web-desktop-2" >}}][web-desktop-2] Forecast Details dialog: [{{< pe-figure "web-desktop-3" >}}][web-desktop-3] The web interface is [responsive][] so it works just as well on mobile. Here are screenshots of the same interface components on my phone: [pico w]: https://www.raspberrypi.com/documentation/microcontrollers/pico-series.html#raspberry-pi-pico-w "Raspberry Pi Pico W" [I2C]: https://en.wikipedia.org/wiki/I%C2%B2C "Inter-Integrated Circuit (I2C)" [bme280]: https://www.bosch-sensortec.com/products/environmental-sensors/humidity-sensors-bme280/ "BME280 temperature sensor" [pico-ws]: /files/articles/temperature-sensors/pico-ws.jpg "Pico Ws with BME280 sensors attached." [pi3]: https://www.raspberrypi.com/products/raspberry-pi-3-model-b/ "Raspberry Pi 3 Model B" [htpc]: https://en.wikipedia.org/wiki/Home_theater_PC "Home Theater PC (HTPC)" [old-sensors]: /files/articles/temperature-sensors/old-sensors-20180724.jpg "Original BME280 sensors." [old-pi3]: /files/articles/temperature-sensors/old-pi3-20180724.jpg "Bedroom Pi 3 HTPC with BME280 sensor attached." [old-web-ui-1]: /files/articles/temperature-sensors/old-web-ui-1.png "Original web interface (2018)." [nws-api]: https://www.weather.gov/documentation/services-web-api "National Weather Service (NWS) Application Programming Interface (API)" [pi0w]: https://www.raspberrypi.com/products/raspberry-pi-zero-w/ "Raspberry Pi Zero W" [old-web-ui-2]: /files/articles/temperature-sensors/old-web-ui-2-20190905.png "Improved web interface (2019)." [bootstrap 4]: https://getbootstrap.com/docs/4.6/getting-started/introduction/ "Bootstrap 4 CSS framework." [chart.js]: https://www.chartjs.org/ "JavaScript charting library." [ruby]: https://ruby-lang.org/ "Ruby programming language" [shell scripts]: https://en.wikipedia.org/wiki/Shell_script "Unix shell script." [cron]: https://en.wikipedia.org/wiki/Cron "Command-line Unix job scheduler." [loadavg]: https://en.wikipedia.org/wiki/Load_(computing) "CPU load average." [csv]: https://en.wikipedia.org/wiki/Comma-separated_values "Comma-separated Value (CSV)." [failed-upgrade]: {{< relref "posts//2023-06-02-end-of-may-miscellany.md" >}} "Failed Pi Zero W Bookworm upgrade." [bought-pico-ws]: {{< relref "posts/2022-11-11-pico-ws.md" >}} "Pico Ws" [home office]: {{< relref "articles/home-office.md" >}} "Home Office" [repo]: https://github.com/pablotron/sensortron "Sensortron Git repository." [micropython]: https://micropython.org/ "Micropython programming language" [go]: https://go.dev/ "Go programming language" [container]: https://en.wikipedia.org/wiki/Containerization_(computing) "Operating-system-level virtualization." [sqlite]: https://sqlite.org/ "Small, fast, self-contained SQL database." [restful]: https://en.wikipedia.org/wiki/REST "HTTP-based API which uses HTTP verbs and adheres loosely to REST" [api]: https://en.wikipedia.org/wiki/API "Application Programming Interface (API)" [wi-fi]: https://en.wikipedia.org/wiki/Wi-Fi "Wireless network." [Pico W Micropython image]: https://micropython.org/download/RPI_PICO_W/ "Pico W Micropython image." [go-chi]: https://go-chi.io/ "Small web router for building HTTP services." [modernc.org/sqlite]: https://modernc.org/sqlite "cgo-free port of SQLite." [html]: https://en.wikipedia.org/wiki/HTML "HyperText Markup Language (HTML)." [js]: https://en.wikipedia.org/wiki/JavaScript "Javascript." [css]: https://en.wikipedia.org/wiki/CSS "Cascading Style Sheets (CSS)." [embed]: https://pkg.go.dev/embed "embed package in Go standard library." [goroutines]: https://en.wikipedia.org/wiki/Go_(programming_language)#Concurrency "Concurrency in Go." [bootstrap 5.3]: https://getbootstrap.com/docs/5.3/ "Bootstrap 5.3 CSS framework." [multi-stage]: https://docs.docker.com/build/building/multi-stage/ "Multi-stage build." [responsive]: https://en.wikipedia.org/wiki/Responsive_web_design "Responsive web design." [distroless]: https://en.wikipedia.org/wiki/Responsive_web_design "Minimal container base." [png]: https://en.wikipedia.org/wiki/PNG "Portable Network Graphics (PNG)" [volume]: https://docs.docker.com/engine/storage/volumes/ "Persistent data storage for containers." [web-desktop-0]: /files/articles/temperature-sensors/web-desktop-0.png "Current Data, Charts, and Forecast panels in the desktop web interface (2024)." [web-desktop-1]: /files/articles/temperature-sensors/web-desktop-1.png "Edit Sensor dialog in the desktop web interface (2024)." [web-desktop-2]: /files/articles/temperature-sensors/web-desktop-2.png "Charts panel in the desktop web interface (2024)." [web-desktop-3]: /files/articles/temperature-sensors/web-desktop-3.png "Forecast Details dialog in the desktop web interface (2024)." [http]: https://en.wikipedia.org/wiki/HTTP "HyperText Transfer Protocol (HTTP)" [home assistant]: https://en.wikipedia.org/wiki/Home_Assistant "Open source home automation software." [ecobee]: https://en.wikipedia.org/wiki/Ecobee "Company which makes smart thermostats and temperature sensors" [fritzing]: https://en.wikipedia.org/wiki/Fritzing "Open source electronics CAD hardware." [pico-w/main.py]: https://github.com/pablotron/sensortron/blob/main/pico-w/main.py "pico-w/main.py in Sensortron Git repository." [bricked]: https://arstechnica.com/gadgets/2024/09/ftc-urged-to-make-smart-devices-say-how-long-theyll-be-supported/ "FTC urged to make smart devices say how long they will be supported (arstechnica.com)"