diff options
Diffstat (limited to 'content')
-rw-r--r-- | content/articles/temperature-sensors.md | 494 |
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 +) +``` + + +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." |