Dorrington
38.3013°N, 120.2771°W · 4,767 ft (1453 m) · America/Los_Angeles
A Raspberry Pi 4 in a sealed enclosure on the cabin roof reads its instruments and publishes over MQTT every 30 seconds. A Raspberry Pi 5 in Berkeley subscribes across a private network and writes each validated reading to SQLite, which is the actual record. A small agent on that Pi 5 signs batches and pushes them out to Cloudflare, where this site reads them. Neither machine accepts an inbound connection from the internet.
The station runs on rural PG&E power, and mountain conditions cause outages more often than we'd like. Stale data usually means a power outage or hardware issue at the site, and we're typically already on it.
Instrument status
7 of 7 instruments reporting. This station is being built in public; channels appear as their hardware is attached.
| Instrument | Device | Location | Status |
|---|---|---|---|
| Air Quality | PMSA003I · 0x12 | Radiation shield | Online |
| Anemometer | SparkFun Weather Meter Kit | Mast above the dormer | Online |
| Rain Gauge | SparkFun Weather Meter Kit | Mast above the dormer | Online |
| Snow Camera | Pi Camera Module 3 | Behind the second door window, aimed at a banded snow stake | Online |
| Temp / Humidity / Pressure | BME688 · 0x77 | Ambient Weather SRS100LX radiation shield | Online |
| UV and Ambient Light | LTR390 · 0x53 | Enclosure, behind the door window | Online |
| Wind Vane ADC | ADS1115 · 0x48 | Enclosure back plate | Online |
Snow camera
A Raspberry Pi camera on a banded stake, read by computer vision on the Pi 5.
The Pi 4 photographs the stake every 20 minutes and sends the frame to the Pi 5, which measures depth and whether snow is falling. A photo is published to the home page only when snow is present and no person or vehicle is in the frame; frames that fail that privacy check are measured for depth and then discarded, never stored and never sent off the Pi.
The barometer changed on 7 August 2026
Why the pressure chart has a kink in it.
Converting this station's pressure to a sea-level equivalent means estimating the weight of an imaginary column of air between 4,767 ft and the sea, and that estimate depends on temperature. The station was using the temperature it happened to be reading at that moment, which meant a 15 °C daily temperature swing manufactured an 8.8 hPa daily pressure swing. The barometer itself only moves about 2.7 hPa a day. Roughly six of those eight were the thermometer, not the weather.
It now uses the WBAN procedure that weather services use: the average of the current temperature and the temperature twelve hours ago, which is half a daily cycle and so cancels most of the swing, plus a correction for the fact that humid air is lighter than dry air. Readings from before the change are still plotted as they were recorded, so the chart has a visible seam rather than a quietly rewritten past.
One piece is knowingly missing. High-altitude stations also carry a station-specific "plateau correction", worth several hPa, which needs a year of local temperature records to calculate. This station has weeks. Until then the absolute value may drift a little with the seasons, though the day-to-day changes, which are what a barometer is actually for, are sound.
The UV channel changed on 12 August 2026
Why the UV history has a staircase in it, and then doesn't.
Until 12 August the UV sensor ran at its library-default gain, where one step of its output is worth 0.042 of an index point. At this station's sheltered mount, an entire day of UV fit inside a handful of those steps, so the chart drew a coarse staircase and the instrument spent weeks under suspicion of being broken.
Two days of field testing settled it. The sensor is healthy: driven across a 96-fold sensitivity range it responded within a few percent of exactly proportionally, on five separate runs. The collector now reads the UV channel at 18 times the gain and 16 times the integration, which resolves one index point into 2,300 steps instead of 24. The visible-light channel keeps the old setting, which suits it fine. Readings from before the change are plotted as they were recorded, so the history shows a visible seam rather than a quietly rewritten past, same policy as the barometer.
One suspicion did not survive testing: the door glass. Measured with and without it, the glass made no detectable difference to UV relative to visible light, because this chip responds mostly to UVA and thin glass passes UVA readily. The index still reads far below the official forecast, and that is the mount: the official number assumes open sky, and this sensor watches the morning through a hole in a box under an eave, among pines. Treat it as a trend.
The two air-quality numbers
Why the dashboard shows a second, smaller AQI.
The large number is what the sensor reports. The smaller one below it applies EPA's US-wide correction for this family of sensors, published after they built the AirNow Fire and Smoke Map out of PurpleAir units running the same Plantower optical engine. It takes the raw reading and the humidity and returns an estimate closer to what a reference monitor would have measured.
In smoke, the corrected number is the better one, and it is usually lower: these sensors read high on wood smoke. The correction disappears whenever the humidity sensor is out, because it needs relative humidity and a guess would be worse than a gap. Neither number is a regulatory measurement. Barkjohn et al., Sensors 2022. AQI bands follow EPA's 2024 revision.
Calibration notes
Known limits of these instruments, stated plainly.
- Air Quality: A laser scattering sensor: it infers mass from how much light passing particles scatter, assuming a size distribution and density. It is not a gravimetric instrument. Wood smoke scatters differently from the aerosol these are calibrated against, and this sensor family is known to read high in wildfire smoke; above roughly 70% humidity, particles absorb water and scatter more, inflating the reading further. Fog and drizzle can produce a spike that is water, not smoke. PM1.0, PM2.5 and PM10 all come from one optical measurement, and PM10 is the weakest of the three because the optics do not size coarse particles well. Below about 5 µg/m³ the counting noise is a large share of the reading. Treat this as a trend instrument and AirNow as authoritative.
- Anemometer: Reed switch on BCM 5. 1.492 mph per Hz.
- Rain Gauge: Tipping bucket on BCM 6. 0.011 in per tip. Totals persisted across restarts.
- Snow Camera: Phase 1 is hourly daylight stills shipped to the Pi 5. Phase 2 adds OpenCV depth detection.
- Temp / Humidity / Pressure: TEMP_OFFSET_C still to be measured against a reference. The shield is passive, so on calm sunny afternoons it can read high by a degree or so; wind fixes it. The gas resistance channel is an uncalibrated VOC proxy and is not an air quality measurement.
- UV and Ambient Light: East-facing under the eave, among pines: a daylight and UV-trend instrument, not a health-grade UV index. A true UV Index assumes an unobstructed view of the whole sky; this sensor sees a slice of it, so the index reads low; that is the mount, not the electronics. The door glass was tested on 12 August 2026 and, on this sensor, costs nothing detectable in the UV band relative to visible light: the chip responds mostly to UVA, which thin glass passes. The reputation glass has for blocking UV was earned by UVB instruments and thicker windows. Lux is the more useful channel.
- Wind Vane ADC: Vane offset of -90° applied in software (bench-verified against 4 cardinals). R_FIXED still to be trimmed; headings read 1-2% low.
Channel availability
Every metric, and what it is waiting on.
| Channel | Unit | Instrument | Status |
|---|---|---|---|
| Dew Point | °C | BME688 | Reporting |
| Gas Resistance | Ω | BME688 | Off by choice |
| Wind Gust | mph | SparkFun Weather Meter Kit | Reporting |
| Relative Humidity | % | BME688 | Reporting |
| Illuminance | lux | LTR390 | Reporting |
| PM10 | µg/m³ | PMSA003I | Reporting |
| PM1.0 | µg/m³ | PMSA003I | Reporting |
| PM2.5 | µg/m³ | PMSA003I | Reporting |
| Sea-level Pressure (reduced) | hPa | BME688 | Reporting |
| Sea-level Pressure | hPa | BME688 | Reporting |
| Station Pressure | hPa | BME688 | Reporting |
| Rainfall (interval) | in | SparkFun Weather Meter Kit | Reporting |
| Rainfall Today | in | SparkFun Weather Meter Kit | Reporting |
| Rainfall Total | in | SparkFun Weather Meter Kit | Reporting |
| Rain Rate | in/h | SparkFun Weather Meter Kit | Reporting |
| Snow brightness | Pi Camera Module 3 | Reporting | |
| Snow confidence | Pi Camera Module 3 | Reporting | |
| Snow Depth | in | Pi Camera Module 3 | Reporting |
| Snow pixel ratio | Pi Camera Module 3 | Reporting | |
| Snow present | Pi Camera Module 3 | Reporting | |
| Snowfall rate | in/hr | Pi Camera Module 3 | Reporting |
| Temperature | °C | BME688 | Reporting |
| UV Index | index | LTR390 | Reporting |
| Wind Direction | ° | ADS1115 | Reporting |
| Wind Speed | mph | SparkFun Weather Meter Kit | Reporting |
Data pipeline health
Because a silent failure is worse than a visible one.
Receiving data Newest reading Oct 2, 12:49 PM (4 min ago)
| Time | Accepted | Rejected | Agent | Error |
|---|---|---|---|---|
| Oct 2, 12:49 PM | 175 | 0 | -- | |
| Oct 2, 12:44 PM | 159 | 0 | -- | |
| Oct 2, 12:39 PM | 157 | 0 | -- | |
| Oct 2, 12:34 PM | 165 | 0 | -- | |
| Oct 2, 12:29 PM | 175 | 0 | -- | |
| Oct 2, 12:24 PM | 157 | 0 | -- | |
| Oct 2, 12:19 PM | 159 | 0 | -- | |
| Oct 2, 12:14 PM | 181 | 0 | -- | |
| Oct 2, 12:09 PM | 158 | 0 | -- | |
| Oct 2, 12:04 PM | 158 | 0 | -- | |
| Oct 2, 11:59 AM | 158 | 0 | -- | |
| Oct 2, 11:54 AM | 181 | 0 | -- | |
| Oct 2, 11:49 AM | 158 | 0 | -- | |
| Oct 2, 11:44 AM | 159 | 0 | -- | |
| Oct 2, 11:39 AM | 157 | 0 | -- | |
| Oct 2, 11:34 AM | 183 | 0 | -- | |
| Oct 2, 11:29 AM | 158 | 0 | -- | |
| Oct 2, 11:24 AM | 159 | 0 | -- | |
| Oct 2, 11:19 AM | 158 | 0 | -- | |
| Oct 2, 11:14 AM | 182 | 0 | -- |
Open data
It is a public good or it is nothing.
- /api/current.json — latest reading from every sensor
- /api/series.json — downsampled time series
- /api/readings.csv — raw export
- /api/forecast.json — our forecasts plus NWS, with scoring
- /api/snow-photo.json — snow camera status and depth