aboutsummaryrefslogtreecommitdiff
path: root/content
diff options
context:
space:
mode:
Diffstat (limited to 'content')
-rw-r--r--content/articles/temperature-sensors.md494
1 files changed, 469 insertions, 25 deletions
diff --git a/content/articles/temperature-sensors.md b/content/articles/temperature-sensors.md
index 7baac2f..cf3ca4c 100644
--- a/content/articles/temperature-sensors.md
+++ b/content/articles/temperature-sensors.md
@@ -3,32 +3,476 @@ title: "Temperature Sensors"
slug: "temperature-sensors"
date: "2024-08-26"
toc: true
-draft: true
-
-#
-# pics:
-# desk:
-# css: "image"
-# tip: "Project desk."
-# sources:
-# - "/files/articles/home-office/desk-1024.webp"
-# - src: "/files/articles/home-office/desk-1024.jpg"
-# width: 1024
-# height: 771
-# cat-desk:
-# css: "image"
-# tip: "Kitty Says: Good vantage point."
-# sources:
-# - "/files/articles/home-office/cat-desk-1024.webp"
-# - src: "/files/articles/home-office/cat-desk-1024.jpg"
-# width: 1024
-# height: 771
+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
-- pinout (fritzing)
-- pictures of soldered result
-- original raspberry pi setup
-- original sensortron (ruby, bash, and cron)
-- software (github repo)
+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.
+
+## 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, but here is a pinout
+table:
+
+{{< 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
+)
+```
+&nbsp;
+
+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."