<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://bcmeter.org/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Bcmwiki</id>
	<title>bcmeter.org - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://bcmeter.org/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Bcmwiki"/>
	<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=Special:Contributions/Bcmwiki"/>
	<updated>2026-07-25T23:26:21Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.36.0</generator>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=Introduction&amp;diff=430</id>
		<title>Introduction</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=Introduction&amp;diff=430"/>
		<updated>2026-06-08T19:17:02Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Consistency: &amp;#039;open design/PCB&amp;#039; -&amp;gt; &amp;#039;source-available&amp;#039; per licensing decision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
The &amp;#039;&amp;#039;&amp;#039;bcMeter&amp;#039;&amp;#039;&amp;#039; is a source-available optical absorption photometer designed to measure Black Carbon (BC) aerosols — commonly known as soot — in real-time. The design is freely available for private, educational and research use (CC BY-NC 4.0); assembled instruments are offered on request. Whether you are monitoring ambient air quality in your neighborhood or measuring direct emissions from wood stoves, this device provides scientific-grade data at a fraction of the cost of reference instruments.&lt;br /&gt;
&lt;br /&gt;
The device operates &amp;quot;headless&amp;quot; — it has no built-in screen. Instead, it hosts its own website that you can access from any smartphone or computer connected to the same network.&lt;br /&gt;
&lt;br /&gt;
The software is source-available — freely available for private, educational and research use (CC BY-NC 4.0): [https://github.com/dahljo/bcmeter-pi github.com/dahljo/bcmeter-pi]&lt;br /&gt;
&lt;br /&gt;
=== Device Types ===&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;bcMeter (DIY)&amp;#039;&amp;#039;&amp;#039; — The source-available, self-build version. Runs on a Raspberry Pi using the source-available PCB design, freely available for private, educational and research use (CC BY-NC 4.0). Build your own from the source-available design files and the Wiki (nothing is sold).&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;bcMeter Kit&amp;#039;&amp;#039;&amp;#039; — Assembled-instrument PCB plus components for self-assembly and 3D printing. Available on request.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;bcMeter Complete&amp;#039;&amp;#039;&amp;#039; — Fully assembled, ready-to-use instrument on a compact platform that starts in seconds and updates over the air, with no microSD card or Linux system to maintain. Available on request.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;eBcMeter&amp;#039;&amp;#039;&amp;#039; — Emission measurement instrument for direct source sampling from wood-burning stoves and similar combustion sources. Uses microgram (µg) units instead of nanogram (ng). Available on request.&lt;br /&gt;
&lt;br /&gt;
=== How Does It Work? ===&lt;br /&gt;
&lt;br /&gt;
[[File:Working principle of a bcMeter.png|300px|right]]&lt;br /&gt;
&lt;br /&gt;
# Polluted air is drawn through filter paper by a pump&lt;br /&gt;
# The filter paper absorbs black carbon (BC) particles&lt;br /&gt;
# An LED shining at 880 nm passes through the filter; a sensor measures the attenuation (reduction in light intensity)&lt;br /&gt;
# A separate reference channel monitors the same LED through a clean portion of the filter, compensating for environmental changes&lt;br /&gt;
# The attenuation is converted to BC concentration (ng/m³) using Beer-Lambert law&lt;br /&gt;
# Data is saved as CSV and displayed in real-time on the web interface&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Multi-wavelength (in development):&amp;#039;&amp;#039;&amp;#039; Additional 520 nm and 370 nm channels for source apportionment via the Ångström Exponent (AAE) are in development and &amp;#039;&amp;#039;&amp;#039;not available in shipped hardware&amp;#039;&amp;#039;&amp;#039;. Current devices measure at 880 nm only.&lt;br /&gt;
&lt;br /&gt;
=== Sensors &amp;amp; Capabilities ===&lt;br /&gt;
&lt;br /&gt;
==== Core ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Measurement !! Sensor / Method !! Notes&lt;br /&gt;
|-&lt;br /&gt;
| Black Carbon (BC) || Optical absorption at 880 nm || Primary measurement&lt;br /&gt;
|-&lt;br /&gt;
| Temperature / Humidity || SHT4x ||&lt;br /&gt;
|-&lt;br /&gt;
| Airflow || Omron D6F differential pressure || Pump flow rate&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Optional Hardware ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Measurement !! Sensor / Method !! Notes&lt;br /&gt;
|-&lt;br /&gt;
| Temperature / Humidity / Pressure || BME280 || Barometric altitude&lt;br /&gt;
|-&lt;br /&gt;
| PM2.5 / PM10 || Sensirion SPS30 || Particulate matter&lt;br /&gt;
|-&lt;br /&gt;
| GPS || AT6668 UART || Position, altitude, speed&lt;br /&gt;
|-&lt;br /&gt;
| 4G Connectivity || SIM7080G LTE-M modem || Remote data upload&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=Bill_of_material&amp;diff=429</id>
		<title>Bill of material</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=Bill_of_material&amp;diff=429"/>
		<updated>2026-06-08T19:10:05Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Fix GitHub org: bcmeter/bcmeter -&amp;gt; dahljo/bcmeter (legacy V1 Pi repo)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Note|1=&amp;#039;&amp;#039;&amp;#039;bcMeter (DIY)&amp;#039;&amp;#039;&amp;#039; — This page documents the bill of materials for the source-available bcMeter (DIY) — the Raspberry-Pi-based design, freely available for private, educational and research use (CC BY-NC 4.0). The assembled bcMeter instruments use a different PCB design.}}&lt;br /&gt;
&lt;br /&gt;
== Overview of Parts (bcMeter DIY) ==&lt;br /&gt;
&lt;br /&gt;
[[File:bcMeter_parts.jpg|thumb|none|800px]]&lt;br /&gt;
&lt;br /&gt;
== Mandatory Components ==&lt;br /&gt;
&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;bcMeter Pi Hat&amp;#039;&amp;#039;&amp;#039; — Order prepopulated (~95 EUR) or build your own from PCB + components (~5 EUR per PCB for 10+ on JLCPCB or similar)&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Raspberry Pi 3A or Zero 2 W&amp;#039;&amp;#039;&amp;#039; (~35 EUR)&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;MicroSD Card&amp;#039;&amp;#039;&amp;#039; (~10 EUR)&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Power Supply 5.25V/2A&amp;#039;&amp;#039;&amp;#039; (~15 EUR)&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Air Pump&amp;#039;&amp;#039;&amp;#039; (~10–200 EUR depending on type)&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Prefer not to source parts? bcMeter Kit/Complete available on request — contact jd@bcmeter.org.&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
== 3D Printed Case ==&lt;br /&gt;
&lt;br /&gt;
STL files for 3D Printing (SLA or FDM): [https://github.com/dahljo/bcmeter/tree/main/stl GitHub repository] — printing material ~10 EUR.&lt;br /&gt;
&lt;br /&gt;
Use black filament/resin. FDM is prone to leakage if not properly configured. If possible, mix resin with flex resin.&lt;br /&gt;
&lt;br /&gt;
== Filter Paper ==&lt;br /&gt;
&lt;br /&gt;
AE33 filter paper is standard for bcMeter. Any filter paper with a known scattering factor can be used. See [[Best practices#Supported Filter Papers|Supported Filter Papers]] for correction factors.&lt;br /&gt;
&lt;br /&gt;
Send a sample of your filter paper to jd@bcmeter.org for calibration.&lt;br /&gt;
&lt;br /&gt;
== Additional Material (~75 EUR) ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Description !! Quantity !! Approx. Price&lt;br /&gt;
|-&lt;br /&gt;
| 22 AWG Wire || 1 || $10&lt;br /&gt;
|-&lt;br /&gt;
| Hot Glue || 1 || $7&lt;br /&gt;
|-&lt;br /&gt;
| Rubber Band (SHORE A) for sealing || 1 || $13&lt;br /&gt;
|-&lt;br /&gt;
| Silicone Hose (5mm ID) || 1 || $5&lt;br /&gt;
|-&lt;br /&gt;
| M3 Screws || 1 set || $7&lt;br /&gt;
|-&lt;br /&gt;
| M3 Threaded Inserts || 1 set || $7&lt;br /&gt;
|-&lt;br /&gt;
| MicroSD Card 16GB || 1 || $8&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Key PCB Components ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Component !! Description !! Approx. Price&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;U1&amp;#039;&amp;#039;&amp;#039; MCP3428 || 4-Channel ADC || €6&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;D1/D2&amp;#039;&amp;#039;&amp;#039; IRL81A || IR LEDs (880nm) || €2&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;J1&amp;#039;&amp;#039;&amp;#039; Omron D6F || Airflow Sensor || €50&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;U2&amp;#039;&amp;#039;&amp;#039; LM1117 || Voltage Regulator || €1&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;U3&amp;#039;&amp;#039;&amp;#039; SHT4x || Humidity/Temp Sensor || €4&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;Pump&amp;#039;&amp;#039;&amp;#039; D15S PWM || Membrane Pump || €95&lt;br /&gt;
|-&lt;br /&gt;
| Capacitors, resistors, connectors || Various || ~€20&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Full BOM with exact product numbers available at [https://github.com/dahljo/bcmeter GitHub].&lt;br /&gt;
&lt;br /&gt;
== PCB / Gerber Files ==&lt;br /&gt;
&lt;br /&gt;
Gerber files for PCB fabrication: [https://github.com/dahljo/bcmeter/tree/main/gerbers GitHub]&lt;br /&gt;
&lt;br /&gt;
Two PCB variants exist:&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;SMD PCB&amp;#039;&amp;#039;&amp;#039; — For 5V and smaller pumps. More compact, recommended.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;THT PCB&amp;#039;&amp;#039;&amp;#039; — For 12V and larger pumps. Easier to assemble but less accurate.&lt;br /&gt;
&lt;br /&gt;
== Assembled instruments (Kit/Complete/eBcMeter) ==&lt;br /&gt;
&lt;br /&gt;
The assembled bcMeter instruments use a different hardware design:&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;ADS1220&amp;#039;&amp;#039;&amp;#039; 24-bit ADC (replaces MCP3428)&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Integrated microcontroller&amp;#039;&amp;#039;&amp;#039; (instead of the Raspberry Pi used in the DIY build)&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Internal flash storage&amp;#039;&amp;#039;&amp;#039; (replaces microSD)&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Optional:&amp;#039;&amp;#039;&amp;#039; SIM7080G LTE-M modem, AT6668 GPS, SPS30 PM sensor&lt;br /&gt;
&lt;br /&gt;
For current device information, see [[Introduction]].&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=Maintenance&amp;diff=428</id>
		<title>Maintenance</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=Maintenance&amp;diff=428"/>
		<updated>2026-06-08T18:59:35Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Restructure: platform separation (ESP32 commercial prioritised, Raspberry Pi DIY in own section); verified against firmware/Pi source; complete serial command list&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Maintenance Procedures ==&lt;br /&gt;
&lt;br /&gt;
Open maintenance functions with the &amp;#039;&amp;#039;&amp;#039;Maintenance&amp;#039;&amp;#039;&amp;#039; button in the navigation bar. The modal has cards for device management, system status, time synchronization, and geolocation.&lt;br /&gt;
&lt;br /&gt;
=== Filter Change Procedure ===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;The filter is not identical on both sides.&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
* Identify the side with markings (black line, dot, or circles).&lt;br /&gt;
* The &amp;#039;&amp;#039;&amp;#039;marked side must face UP&amp;#039;&amp;#039;&amp;#039; (towards the LEDs/light source in the upper optical chamber).&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Warning:&amp;#039;&amp;#039;&amp;#039; Incorrect orientation (marked side down) results in ~30% measurement error.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Procedure:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
# Stop any running session.&lt;br /&gt;
# Unscrew the top cap of the optical chamber.&lt;br /&gt;
# Remove the saturated filter.&lt;br /&gt;
# Insert a new filter with &amp;#039;&amp;#039;&amp;#039;markings facing up&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
# Screw the cap back on (hand-tight).&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Check hose&amp;#039;&amp;#039;&amp;#039; (if used): check that the air hose is still connected to the inlet port.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Run [[Maintenance#Calibration|Calibration]] (required).&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
=== Calibration ===&lt;br /&gt;
&lt;br /&gt;
Filters vary slightly in optical density. Calibration balances the sensor signal against the reference signal for the specific filter currently installed.&lt;br /&gt;
&lt;br /&gt;
# Go to &amp;#039;&amp;#039;&amp;#039;Maintenance&amp;#039;&amp;#039;&amp;#039; &amp;gt; &amp;#039;&amp;#039;&amp;#039;Calibrate Device&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
# Check that a &amp;#039;&amp;#039;&amp;#039;new and clean filter&amp;#039;&amp;#039;&amp;#039; is installed.&lt;br /&gt;
# Click &amp;quot;Yes.&amp;quot;&lt;br /&gt;
# A progress bar appears. The device adjusts LED intensity per channel to find stable reference and sensor readings.&lt;br /&gt;
# Wait for &amp;quot;Calibration Successful&amp;quot; before starting a new log.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Technical detail:&amp;#039;&amp;#039;&amp;#039; Calibration determines the per-channel correction factor K = Ref_avg / Sen_avg and stores it with the LED duty cycle values. Calibration typically takes 30–60 seconds.&lt;br /&gt;
&lt;br /&gt;
=== Data Management ===&lt;br /&gt;
&lt;br /&gt;
Click &amp;#039;&amp;#039;&amp;#039;Log Files&amp;#039;&amp;#039;&amp;#039; to open the data manager. The modal lists all stored sessions:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Column !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;Log&amp;#039;&amp;#039;&amp;#039; || Session name or filename (e.g., &amp;lt;code&amp;gt;26-03-12_212600.csv&amp;lt;/code&amp;gt;). &amp;quot;Current Session&amp;quot; shows the active log.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;Size&amp;#039;&amp;#039;&amp;#039; || File size in KB, or number of data points for the current session.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;Download&amp;#039;&amp;#039;&amp;#039; || Download button for each individual log file.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Below the table:&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Clear All Data&amp;#039;&amp;#039;&amp;#039; — Deletes all stored log files. Requires confirmation.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Remove Empty Logs&amp;#039;&amp;#039;&amp;#039; — Cleans up zero-byte or near-empty files from aborted sessions.&lt;br /&gt;
&lt;br /&gt;
Stored log files are downloaded as CSV for analysis. The dashboard&amp;#039;s &amp;#039;&amp;#039;&amp;#039;Download View&amp;#039;&amp;#039;&amp;#039; button can additionally export the currently visible chart view as CSV, PNG, or SVG. CSV files use semicolon separation with dot as decimal divider.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Backup:&amp;#039;&amp;#039;&amp;#039; Internal storage is not archival. Download data to a secure location regularly.&lt;br /&gt;
&lt;br /&gt;
=== Device Management ===&lt;br /&gt;
&lt;br /&gt;
==== Routine Maintenance ====&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Calibrate Device:&amp;#039;&amp;#039;&amp;#039; Adjusts LED duty cycles. Required after each filter change.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;View System Status:&amp;#039;&amp;#039;&amp;#039; Opens a structured status report for diagnosing issues. Entries are grouped by category: hardware, measurement, system, network.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Download Logs:&amp;#039;&amp;#039;&amp;#039; Downloads the structured system status report as a text file for troubleshooting or support.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Identify Device:&amp;#039;&amp;#039;&amp;#039; Blinks the device LED for about two minutes. Use this to find the right unit when more than one bcMeter is nearby.&lt;br /&gt;
&lt;br /&gt;
==== System Operations ====&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Reboot Device:&amp;#039;&amp;#039;&amp;#039; Restarts the device.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Shutdown Device:&amp;#039;&amp;#039;&amp;#039; Powers down before unplugging. Use this before disconnecting power. If the device loses power during an active session, it resumes measurement on the next boot.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Manual Firmware Update:&amp;#039;&amp;#039;&amp;#039; Opens a dialog to upload a firmware file. The device also checks for updates a few times a day.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Factory Reset:&amp;#039;&amp;#039;&amp;#039; Permanently erases all measurement logs, WiFi credentials, calibration data, and device settings. A slide-to-confirm gesture is required. The device reboots into factory state.&lt;br /&gt;
&lt;br /&gt;
==== Firmware Update Notifications ====&lt;br /&gt;
&lt;br /&gt;
When the device detects a newer firmware version, an &amp;#039;&amp;#039;&amp;#039;Update Available&amp;#039;&amp;#039;&amp;#039; modal appears showing:&lt;br /&gt;
* The new version number and current version&lt;br /&gt;
* Release notes (if available)&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Update Now&amp;#039;&amp;#039;&amp;#039; button to apply the update immediately (with progress bar)&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Skip for now&amp;#039;&amp;#039;&amp;#039; to dismiss and update later&lt;br /&gt;
&lt;br /&gt;
Updates download over WiFi and are applied automatically. The device reboots after a successful update.&lt;br /&gt;
&lt;br /&gt;
=== System Status ===&lt;br /&gt;
&lt;br /&gt;
Shows device information:&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Device ID:&amp;#039;&amp;#039;&amp;#039; Unique hardware identifier (MAC address).&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Software Version:&amp;#039;&amp;#039;&amp;#039; Installed firmware version.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Free Memory:&amp;#039;&amp;#039;&amp;#039; Available system memory.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Last Calibration:&amp;#039;&amp;#039;&amp;#039; Timestamp of the most recent calibration.&lt;br /&gt;
&lt;br /&gt;
=== Time Synchronization ===&lt;br /&gt;
&lt;br /&gt;
Accurate timestamps need a correct device clock, especially on devices without internet access.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Browser Time / Device Time:&amp;#039;&amp;#039;&amp;#039; Displayed for comparison.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Sync:&amp;#039;&amp;#039;&amp;#039; If mismatch exceeds 10 seconds, a sync button appears to synchronize the device clock with your browser.&lt;br /&gt;
&lt;br /&gt;
Devices connected to the internet sync automatically via NTP. Modem-based time sync (CLTS) is also supported when a 4G modem is connected.&lt;br /&gt;
&lt;br /&gt;
=== Geolocation ===&lt;br /&gt;
&lt;br /&gt;
When location services are active (Settings &amp;gt; Measurement &amp;gt; Location), the Geolocation card shows:&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Location:&amp;#039;&amp;#039;&amp;#039; Latitude/longitude with source (GPS, cell tower, or IP-based) and accuracy indicator.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Altitude (barometric):&amp;#039;&amp;#039;&amp;#039; Derived from the pressure sensor.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Altitude (GPS) &amp;amp; Speed:&amp;#039;&amp;#039;&amp;#039; Shown when a GPS module is connected and has a fix.&lt;br /&gt;
&lt;br /&gt;
The location input accepts common coordinate formats: &amp;lt;code&amp;gt;48.2082, 16.3738&amp;lt;/code&amp;gt; — &amp;lt;code&amp;gt;48.2082 16.3738&amp;lt;/code&amp;gt; — &amp;lt;code&amp;gt;(48.2082; 16.3738)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== bcMeter (DIY) — Raspberry Pi ===&lt;br /&gt;
&lt;br /&gt;
The following notes apply specifically to the &amp;#039;&amp;#039;&amp;#039;bcMeter (DIY)&amp;#039;&amp;#039;&amp;#039; Raspberry Pi version. For the commercial bcMeter (ESP32), the sections above describe all maintenance procedures.&lt;br /&gt;
&lt;br /&gt;
==== Storage ====&lt;br /&gt;
&lt;br /&gt;
The Raspberry Pi version stores measurement data on the Linux filesystem (typically under &amp;lt;code&amp;gt;/home/bcmeter/logs/&amp;lt;/code&amp;gt;). There is no fixed flash storage limit — available disk space depends on the SD card and system configuration. The web interface data manager works the same way as on the ESP32: log files are listed and can be downloaded or deleted individually.&lt;br /&gt;
&lt;br /&gt;
The Pi does &amp;#039;&amp;#039;&amp;#039;not&amp;#039;&amp;#039;&amp;#039; use LittleFS or NVS. Configuration is stored in &amp;lt;code&amp;gt;~/bcmeter/bcMeter_config.json&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Service Management ====&lt;br /&gt;
&lt;br /&gt;
The bcMeter software runs as a systemd service (&amp;lt;code&amp;gt;bcMeter.service&amp;lt;/code&amp;gt;). &amp;#039;&amp;#039;&amp;#039;Do not use &amp;lt;code&amp;gt;systemctl stop&amp;lt;/code&amp;gt;&amp;#039;&amp;#039;&amp;#039; — stopping the service also disables the WiFi access point, cutting off remote access. Use the web interface Reboot or Shutdown buttons, or &amp;lt;code&amp;gt;systemctl restart&amp;lt;/code&amp;gt; if a restart is needed from the terminal.&lt;br /&gt;
&lt;br /&gt;
The firmware update endpoint (&amp;lt;code&amp;gt;POST /api/update&amp;lt;/code&amp;gt;) accepts a &amp;lt;code&amp;gt;.tar.gz&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;.zip&amp;lt;/code&amp;gt; archive, extracts it over the code directory, and runs &amp;lt;code&amp;gt;sudo systemctl restart bcMeter.service&amp;lt;/code&amp;gt; automatically.&lt;br /&gt;
&lt;br /&gt;
==== Maintenance Log Bundle ====&lt;br /&gt;
&lt;br /&gt;
The Raspberry Pi version provides an additional endpoint, &amp;lt;code&amp;gt;GET /api/maintenance-logs&amp;lt;/code&amp;gt;, which downloads a zip bundle for support purposes. The bundle contains:&lt;br /&gt;
&lt;br /&gt;
* Rotating &amp;lt;code&amp;gt;bcmeter.log&amp;lt;/code&amp;gt; files&lt;br /&gt;
* Syslog and &amp;lt;code&amp;gt;dmesg&amp;lt;/code&amp;gt; output&lt;br /&gt;
* The 10 most recent CSV session files&lt;br /&gt;
* &amp;lt;code&amp;gt;journalctl&amp;lt;/code&amp;gt; output for the bcMeter and pigpiod services&lt;br /&gt;
* The current config JSON (sensitive keys redacted)&lt;br /&gt;
* The incident log&lt;br /&gt;
&lt;br /&gt;
This endpoint does not exist on the ESP32, which uses the structured &amp;lt;code&amp;gt;/api/logs&amp;lt;/code&amp;gt; endpoint and crash report email for equivalent diagnostics.&lt;br /&gt;
&lt;br /&gt;
==== ADC Hardware ====&lt;br /&gt;
&lt;br /&gt;
The Raspberry Pi version uses the ADS8344E (18-bit, SPI) or MCP3428 (I2C, legacy) ADC, rather than the ADS1220 used on the ESP32. Calibration and measurement procedures are identical from the user&amp;#039;s perspective.&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=API_reference&amp;diff=427</id>
		<title>API reference</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=API_reference&amp;diff=427"/>
		<updated>2026-06-08T18:59:35Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Restructure: platform separation (ESP32 commercial prioritised, Raspberry Pi DIY in own section); verified against firmware/Pi source; complete serial command list&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== API Reference ==&lt;br /&gt;
&lt;br /&gt;
The bcMeter exposes a REST API on port 80. All endpoints are accessible without authentication when connected to the device network. CORS is enabled for all responses (&amp;lt;code&amp;gt;Access-Control-Allow-Origin: *&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
The device identifies its platform via the &amp;lt;code&amp;gt;&amp;quot;env&amp;quot;&amp;lt;/code&amp;gt; field in &amp;lt;code&amp;gt;/api/status&amp;lt;/code&amp;gt;: &amp;lt;code&amp;gt;&amp;quot;env&amp;quot;: &amp;quot;esp32&amp;quot;&amp;lt;/code&amp;gt; for bcMeter (commercial) and &amp;lt;code&amp;gt;&amp;quot;env&amp;quot;: &amp;quot;pi&amp;quot;&amp;lt;/code&amp;gt; for bcMeter (DIY / Raspberry Pi).&lt;br /&gt;
&lt;br /&gt;
The software is source-available — freely available for private, educational and research use (CC BY-NC 4.0): [https://github.com/dahljo/bcmeter-pi github.com/dahljo/bcmeter-pi] (Pi / DIY version).&lt;br /&gt;
&lt;br /&gt;
=== Status &amp;amp; Diagnostics ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Method !! Endpoint !! Description !! Platforms&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/status&amp;lt;/code&amp;gt; || Current measurement state, last sensor readings (BC, ATN, sensor/reference voltages, flow, filter loading), error codes, sample count, session active, WiFi mode/SSID/RSSI, internet flag, firmware version, OTA result flag, time-sync state. || Both&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/system&amp;lt;/code&amp;gt; || Hardware info: IP, MAC address, heap and PSRAM usage, flash usage, modem status and signal, GPS detail, barometric altitude, geolocation source, current time, cycle timing statistics. || Both&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/logs&amp;lt;/code&amp;gt; || Structured health report as JSON with sections: &amp;lt;code&amp;gt;hardware&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;measurement&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;system&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;network&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;incidents&amp;lt;/code&amp;gt;. Each entry has &amp;lt;code&amp;gt;{k, v, s}&amp;lt;/code&amp;gt; (key, value, status: ok/warn/error/info). || Both&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/debug_mobile/status&amp;lt;/code&amp;gt; || Returns modem debug email send progress (from email handler). || Both&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Measurement Control ===&lt;br /&gt;
&lt;br /&gt;
All control is dispatched through a single endpoint with an &amp;lt;code&amp;gt;action&amp;lt;/code&amp;gt; query parameter:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Method !! Endpoint !! Description !! Platforms&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/control?action=start&amp;lt;/code&amp;gt; || Begin measurement session. Returns 409 if time not synced, 423 if never calibrated, 424 if calibration stale (&amp;gt;28 days). Add &amp;lt;code&amp;gt;&amp;amp;force=1&amp;lt;/code&amp;gt; to override preflight checks. Optional &amp;lt;code&amp;gt;&amp;amp;indoor=0|1&amp;lt;/code&amp;gt; for one-shot indoor/outdoor override. || Both&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/control?action=stop&amp;lt;/code&amp;gt; || Stop measurement and finalise session file. || Both&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/control?action=calibrate&amp;lt;/code&amp;gt; || Start optical calibration routine (returns 202 immediately — poll &amp;lt;code&amp;gt;/api/calibration&amp;lt;/code&amp;gt; for progress). Requires sampling to be stopped. || Both&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/calibration&amp;lt;/code&amp;gt; || Calibration status: &amp;lt;code&amp;gt;{running, done, ok, elapsed_ms, log}&amp;lt;/code&amp;gt;. || Both&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/control?action=clear_error&amp;lt;/code&amp;gt; || Reset error state to ERR_NONE. || Both&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/control?action=identify&amp;lt;/code&amp;gt; || Triggers LED identify blink pattern (Morse code &amp;quot;bcmeter&amp;quot;, ~30 seconds). Useful for locating a specific device when multiple units are deployed. || Both&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/control?action=debug_mobile&amp;lt;/code&amp;gt; || Triggers modem debug email via Lambda. Requires modem present. Returns 409 if modem unavailable or already running. || Both&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/control?action=synctime&amp;amp;ts=EPOCH&amp;amp;tz=IANA&amp;lt;/code&amp;gt; || Sync device clock. &amp;lt;code&amp;gt;ts&amp;lt;/code&amp;gt; = Unix timestamp, &amp;lt;code&amp;gt;tz&amp;lt;/code&amp;gt; = IANA timezone string (e.g. &amp;lt;code&amp;gt;Europe/Berlin&amp;lt;/code&amp;gt;). || Both&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/control?action=cleardata&amp;lt;/code&amp;gt; || Delete all stored log files. || Both&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/control?action=reboot&amp;lt;/code&amp;gt; || End session and reboot the device. || Both&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/control?action=shutdown&amp;lt;/code&amp;gt; || Safely shut down the device. || Both&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/control?action=factory_reset&amp;lt;/code&amp;gt; || Permanently erase all logs, WiFi credentials, calibration data, and settings. Reboots into factory state. || Both&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Method !! Endpoint !! Description !! Platforms&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/config&amp;lt;/code&amp;gt; || All settings as JSON. Each parameter includes type, value, label, tab, and description. || Both&lt;br /&gt;
|-&lt;br /&gt;
| POST || &amp;lt;code&amp;gt;/api/config&amp;lt;/code&amp;gt; || Update settings. JSON body with key-value pairs. Accepts &amp;lt;code&amp;gt;{key: value}&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;{key: {value: ...}}&amp;lt;/code&amp;gt; format. Only changed values need to be sent. || Both&lt;br /&gt;
|-&lt;br /&gt;
| POST || &amp;lt;code&amp;gt;/api/device/rename&amp;lt;/code&amp;gt; || Set device name. Body: &amp;lt;code&amp;gt;{&amp;quot;name&amp;quot;: &amp;quot;bcmeter-A3AB&amp;quot;}&amp;lt;/code&amp;gt; (1–32 chars). Updates mDNS/hostname accordingly. || Both&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/ap-security&amp;lt;/code&amp;gt; || Hotspot security settings: &amp;lt;code&amp;gt;{secured: bool, password: str}&amp;lt;/code&amp;gt;. || Both&lt;br /&gt;
|-&lt;br /&gt;
| POST || &amp;lt;code&amp;gt;/api/ap-security&amp;lt;/code&amp;gt; || Update hotspot password. Body: &amp;lt;code&amp;gt;{&amp;quot;secured&amp;quot;: true, &amp;quot;password&amp;quot;: &amp;quot;...&amp;quot;}&amp;lt;/code&amp;gt; (min 8 chars). || Both&lt;br /&gt;
|-&lt;br /&gt;
| POST || &amp;lt;code&amp;gt;/api/email/validate&amp;lt;/code&amp;gt; || Validate email API key against the Lambda endpoint. Body: &amp;lt;code&amp;gt;{&amp;quot;api_key&amp;quot;: &amp;quot;...&amp;quot;}&amp;lt;/code&amp;gt;. Returns &amp;lt;code&amp;gt;{valid: bool, error: str}&amp;lt;/code&amp;gt;. || Both&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== WiFi Management ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Method !! Endpoint !! Description !! Platforms&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/wifi/scan&amp;lt;/code&amp;gt; || List nearby networks: &amp;lt;code&amp;gt;{scanning: bool, networks: [{ssid, rssi, secure}]}&amp;lt;/code&amp;gt;. Add &amp;lt;code&amp;gt;?refresh=1&amp;lt;/code&amp;gt; to trigger a new background scan. || Both&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/wifi/status&amp;lt;/code&amp;gt; || Current connection: &amp;lt;code&amp;gt;{mode, status, ssid, ip, rssi, quality (0-4), internet, timeSynced}&amp;lt;/code&amp;gt;. || Both&lt;br /&gt;
|-&lt;br /&gt;
| POST || &amp;lt;code&amp;gt;/api/wifi&amp;lt;/code&amp;gt; || Save WiFi credentials. Body: &amp;lt;code&amp;gt;{&amp;quot;ssid&amp;quot;: &amp;quot;...&amp;quot;, &amp;quot;pass&amp;quot;: &amp;quot;...&amp;quot;}&amp;lt;/code&amp;gt; (password min 8 chars). Initiates reconnect. || Both&lt;br /&gt;
|-&lt;br /&gt;
| POST || &amp;lt;code&amp;gt;/api/wifi/connect&amp;lt;/code&amp;gt; || Save credentials and initiate background connection attempt (returns 202). Password must be 8–63 chars. Body: &amp;lt;code&amp;gt;{&amp;quot;ssid&amp;quot;: &amp;quot;...&amp;quot;, &amp;quot;pass&amp;quot;: &amp;quot;...&amp;quot;}&amp;lt;/code&amp;gt;. || Both&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/wifi/connect/status&amp;lt;/code&amp;gt; || Connection progress: &amp;lt;code&amp;gt;{state: 0-3, elapsed, log, mode, ip, ssid, device_name, hostname}&amp;lt;/code&amp;gt;. States: 0=idle, 1=connecting, 2=success, 3=failed. Poll after POST to &amp;lt;code&amp;gt;/api/wifi/connect&amp;lt;/code&amp;gt;. || Both&lt;br /&gt;
|-&lt;br /&gt;
| POST || &amp;lt;code&amp;gt;/api/wifi/delete&amp;lt;/code&amp;gt; || Delete credentials and switch to AP mode (deferred 2s background switch). || Both&lt;br /&gt;
|-&lt;br /&gt;
| POST || &amp;lt;code&amp;gt;/api/wifi/scan/refresh&amp;lt;/code&amp;gt; || Explicitly trigger a new WiFi scan (returns 202, or 409 if already scanning). || Both&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Data Management ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Method !! Endpoint !! Description !! Platforms&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/csv&amp;lt;/code&amp;gt; || Current session CSV data. Returns header-only if no active session. Add &amp;lt;code&amp;gt;?file=FILENAME&amp;lt;/code&amp;gt; for archived files. || Both&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/files&amp;lt;/code&amp;gt; || List stored CSV logs: &amp;lt;code&amp;gt;[{name, size, lines, date}]&amp;lt;/code&amp;gt; sorted newest first. Add &amp;lt;code&amp;gt;?name=FILENAME&amp;lt;/code&amp;gt; to download a specific file. || Both&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Firmware Updates ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Method !! Endpoint !! Description !! Platforms&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/ota/status&amp;lt;/code&amp;gt; || Check if update available: &amp;lt;code&amp;gt;{available, version, notes, apply_state, apply_progress, apply_error}&amp;lt;/code&amp;gt;. || Both&lt;br /&gt;
|-&lt;br /&gt;
| POST || &amp;lt;code&amp;gt;/api/ota/check&amp;lt;/code&amp;gt; || Force check for new firmware. || Both&lt;br /&gt;
|-&lt;br /&gt;
| POST || &amp;lt;code&amp;gt;/api/ota/skip&amp;lt;/code&amp;gt; || Skip current available update. || Both&lt;br /&gt;
|-&lt;br /&gt;
| POST || &amp;lt;code&amp;gt;/api/ota/apply&amp;lt;/code&amp;gt; || Download and apply firmware update. Returns 409 if none pending. || Both&lt;br /&gt;
|-&lt;br /&gt;
| POST || &amp;lt;code&amp;gt;/api/update&amp;lt;/code&amp;gt; || Direct firmware upload. ESP32: accepts a raw &amp;lt;code&amp;gt;.bin&amp;lt;/code&amp;gt; file, flashes to the OTA partition, reboots. Pi: accepts a &amp;lt;code&amp;gt;.tar.gz&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;.zip&amp;lt;/code&amp;gt; archive, extracts over the code directory, restarts the &amp;lt;code&amp;gt;bcMeter.service&amp;lt;/code&amp;gt;. || Both&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Captive Portal ===&lt;br /&gt;
&lt;br /&gt;
These endpoints handle captive portal detection on mobile devices and redirect to the main interface in AP mode:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Endpoint !! Purpose&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/generate_204&amp;lt;/code&amp;gt; || Android captive portal check&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/hotspot-detect.html&amp;lt;/code&amp;gt; || Apple captive portal check&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/canonical.html&amp;lt;/code&amp;gt; || Firefox captive portal check&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/ncsi.txt&amp;lt;/code&amp;gt; || Windows captive portal check&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/success.txt&amp;lt;/code&amp;gt; || Generic connectivity probe (returns &amp;lt;code&amp;gt;&amp;quot;success&amp;quot;&amp;lt;/code&amp;gt;)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Static Routes ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Path !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt; || Serves the SPA frontend&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/discover&amp;lt;/code&amp;gt; || Standalone device discovery page&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/current_log.csv&amp;lt;/code&amp;gt; || Legacy redirect to &amp;lt;code&amp;gt;/api/csv&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== bcMeter (DIY) — Raspberry Pi OS-level extras ===&lt;br /&gt;
&lt;br /&gt;
The following endpoints exist &amp;#039;&amp;#039;&amp;#039;only on the Raspberry Pi&amp;#039;&amp;#039;&amp;#039; version. They use Linux system commands and are not applicable to the ESP32.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Method !! Endpoint !! Description&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/maintenance-logs&amp;lt;/code&amp;gt; || Downloads a zip bundle containing: rotating bcmeter.log files, syslog, 10 newest CSV sessions, dmesg, journalctl output for bcmeter and pigpiod services, config JSON, incident log. Uses &amp;lt;code&amp;gt;journalctl&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;dmesg&amp;lt;/code&amp;gt; — Linux only.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Additionally, on the Pi:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;/api/control?action=reboot&amp;lt;/code&amp;gt; runs &amp;lt;code&amp;gt;sudo reboot&amp;lt;/code&amp;gt; (Pi: &amp;lt;code&amp;gt;routes_control.py:151&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &amp;lt;code&amp;gt;/api/control?action=shutdown&amp;lt;/code&amp;gt; runs &amp;lt;code&amp;gt;sudo shutdown -h now&amp;lt;/code&amp;gt; (Pi: &amp;lt;code&amp;gt;routes_control.py:161&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &amp;lt;code&amp;gt;/api/control?action=synctime&amp;lt;/code&amp;gt; sets the timezone via &amp;lt;code&amp;gt;sudo timedatectl set-timezone&amp;lt;/code&amp;gt; (Pi: &amp;lt;code&amp;gt;routes_control.py:276&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &amp;lt;code&amp;gt;/api/device/rename&amp;lt;/code&amp;gt; calls &amp;lt;code&amp;gt;sudo hostnamectl set-hostname&amp;lt;/code&amp;gt; and restarts avahi (Pi: &amp;lt;code&amp;gt;bcmeter/identity.py:41&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &amp;lt;code&amp;gt;/api/update&amp;lt;/code&amp;gt; runs &amp;lt;code&amp;gt;sudo systemctl restart bcMeter.service&amp;lt;/code&amp;gt; after extracting the archive (Pi: &amp;lt;code&amp;gt;routes_update.py:134&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
The following endpoints exist only on the Pi and have no ESP32 equivalent:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Method !! Endpoint !! Description&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/qc/pi/report&amp;lt;/code&amp;gt; || Pi QC test report as JSON.&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/qc/pi/report.html&amp;lt;/code&amp;gt; || Pi QC test report as HTML.&lt;br /&gt;
|-&lt;br /&gt;
| POST || &amp;lt;code&amp;gt;/api/qc/pi/start&amp;lt;/code&amp;gt; || Start the Pi QC test sequence.&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/qc/pi/status&amp;lt;/code&amp;gt; || Pi QC test status.&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/lab/run&amp;lt;/code&amp;gt; || Lab/engineering raw ADC capture (Pi equivalent of ESP32 serial LAB mode).&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/lab/info&amp;lt;/code&amp;gt; || Lab session status.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The following endpoints exist only on the &amp;#039;&amp;#039;&amp;#039;ESP32&amp;#039;&amp;#039;&amp;#039; and have no Pi equivalent:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Method !! Endpoint !! Description&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/sdfiles&amp;lt;/code&amp;gt; || List CSV files on the SD card.&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/crash&amp;lt;/code&amp;gt; || Last crash/reset report from CrashReport module.&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/coredump&amp;lt;/code&amp;gt; || Stream the raw ELF coredump from the coredump flash partition. Add &amp;lt;code&amp;gt;?erase=1&amp;lt;/code&amp;gt; to erase after download.&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/modem/test&amp;lt;/code&amp;gt; || Run modem AT diagnostic and return results as JSON.&lt;br /&gt;
|-&lt;br /&gt;
| POST || &amp;lt;code&amp;gt;/api/lab/start&amp;lt;/code&amp;gt; || Start a lab ADC capture session (params: &amp;lt;code&amp;gt;led_ch&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;led_duty&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;pump_duty&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;pump_hz&amp;lt;/code&amp;gt;).&lt;br /&gt;
|-&lt;br /&gt;
| POST || &amp;lt;code&amp;gt;/api/lab/stop&amp;lt;/code&amp;gt; || Stop the lab capture session.&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/lab/status&amp;lt;/code&amp;gt; || Lab session status: active, pairs captured, LED/pump settings.&lt;br /&gt;
|-&lt;br /&gt;
| POST || &amp;lt;code&amp;gt;/api/raw_capture/enable&amp;lt;/code&amp;gt; || Toggle raw ADC sample capture ring buffer (param: &amp;lt;code&amp;gt;on=0|1&amp;lt;/code&amp;gt;).&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/raw_capture/read&amp;lt;/code&amp;gt; || Drain the raw capture ring buffer as binary float32 pairs (8 bytes each). &amp;lt;code&amp;gt;X-Dropped&amp;lt;/code&amp;gt; header reports overflow count.&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/qc/sensors&amp;lt;/code&amp;gt; || Live SPS30 + env-sensor read for QC (409 while sampling).&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/qc/diag&amp;lt;/code&amp;gt; || Passive diagnostic snapshot: heap, PSRAM, uptime, reset reason, WiFi, modem state. No AT calls.&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/qc/pump_ramp/status&amp;lt;/code&amp;gt; || QC pump ramp test status.&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/qc/led_880/status&amp;lt;/code&amp;gt; || QC LED stability test status.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Example: Start a Measurement ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Sync time first&lt;br /&gt;
curl &amp;quot;http://bcmeter-XXXX.local/api/control?action=synctime&amp;amp;ts=$(date +%s)&amp;amp;tz=Europe/Berlin&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Start measurement&lt;br /&gt;
curl &amp;quot;http://bcmeter-XXXX.local/api/control?action=start&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Poll status&lt;br /&gt;
curl &amp;quot;http://bcmeter-XXXX.local/api/status&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Download current data&lt;br /&gt;
curl &amp;quot;http://bcmeter-XXXX.local/api/csv&amp;quot; -o measurement.csv&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=Serial_commands&amp;diff=426</id>
		<title>Serial commands</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=Serial_commands&amp;diff=426"/>
		<updated>2026-06-08T18:59:35Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Restructure: platform separation (ESP32 commercial prioritised, Raspberry Pi DIY in own section); verified against firmware/Pi source; complete serial command list&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Serial Commands ==&lt;br /&gt;
&lt;br /&gt;
This page documents the USB serial command interface of the &amp;#039;&amp;#039;&amp;#039;bcMeter&amp;#039;&amp;#039;&amp;#039; (ESP32 commercial device).&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Raspberry Pi (DIY) note:&amp;#039;&amp;#039;&amp;#039; The Raspberry Pi version of bcMeter does &amp;#039;&amp;#039;&amp;#039;not&amp;#039;&amp;#039;&amp;#039; have a serial command protocol. All control and diagnostics on the Pi are handled through the HTTP API (see [[API reference]]). The information on this page applies exclusively to the bcMeter (ESP32).&lt;br /&gt;
&lt;br /&gt;
Connect via USB-C at &amp;#039;&amp;#039;&amp;#039;115200 baud&amp;#039;&amp;#039;&amp;#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# macOS / Linux&lt;br /&gt;
screen /dev/tty.usbmodem* 115200&lt;br /&gt;
&lt;br /&gt;
# Or via minicom&lt;br /&gt;
minicom -D /dev/ttyACM0 -b 115200&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Commands are plain text, terminated with a newline. The serial interface is always available regardless of measurement or WiFi mode.&lt;br /&gt;
&lt;br /&gt;
=== Status &amp;amp; Diagnostics ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Command !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;status&amp;lt;/code&amp;gt; || Compact one-liner: state, init step, error, BC, ATN, sensor/reference voltages, flow, pump duty, filter loading, sample count.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;status json&amp;lt;/code&amp;gt; || Same data as a JSON object — suitable for scripting and QC tooling.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;system&amp;lt;/code&amp;gt; || Firmware version, env, free heap, PSRAM usage, flash usage, WiFi mode/SSID/IP/RSSI, MAC address, time-sync state.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;sensors&amp;lt;/code&amp;gt; || Live read of all peripheral sensors: pump flow + duty + airflow voltage + bias, temperature/humidity/pressure (BME280 or SHT4x), GPS fix (if present), SPS30 PM values (if present).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;pumpinfo&amp;lt;/code&amp;gt; || Detailed pump diagnostics: duty, flow (L/min), airflow voltage, bias, target flow, recovering flag, failed flag.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;logs [N]&amp;lt;/code&amp;gt; || Print the last N incident log entries (default: all). Newest first.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;crash&amp;lt;/code&amp;gt; || Last reset reason and crash report JSON (if a watchdog/panic crash was recorded on previous boot).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ver&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;version&amp;lt;/code&amp;gt; || Firmware version string and environment tag (prod/dev).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;bcm:probe&amp;lt;/code&amp;gt; || Machine-readable JSON identity probe for QC tooling: device name, MAC, firmware version, environment, uptime. Output is a single line prefixed for easy grep/parse.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;cfg&amp;lt;/code&amp;gt; || Quick display of key config values: &amp;lt;code&amp;gt;mail_logs_to&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;onboarding_step_one/two&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;device_name&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;send_log_by_mail&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;STATUS&amp;lt;/code&amp;gt; (caps) || Machine-readable one-liner for QC scripts: &amp;lt;code&amp;gt;OK sampling=... serLab=... adcPresent=... debug=... version=...&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Measurement &amp;amp; Calibration ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Command !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;start&amp;lt;/code&amp;gt; || Start measurement. Fails with an error message if time is not synced. Use &amp;lt;code&amp;gt;start force&amp;lt;/code&amp;gt; to override the time-sync check.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;start force&amp;lt;/code&amp;gt; || Start measurement unconditionally (bypasses time-sync guard).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;stop&amp;lt;/code&amp;gt; || Stop measurement.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;calibrate&amp;lt;/code&amp;gt; || Start optical calibration (same routine as the web UI). Requires sampling to be stopped.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;clear_error&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;clearerr&amp;lt;/code&amp;gt; || Reset the error state to ERR_NONE.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;identify&amp;lt;/code&amp;gt; || Start LED identify blink pattern (Morse &amp;quot;bcmeter&amp;quot;, ~30 s). Used to locate a specific device.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;identify_stop&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;identifystop&amp;lt;/code&amp;gt; || Stop the identify blink.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;tempcal&amp;lt;/code&amp;gt; || Toggle temperature calibration routine. If already running, stops it. Requires sampling stopped.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;factory_reset&amp;lt;/code&amp;gt; || Mirror of &amp;lt;code&amp;gt;/api/control?action=factory_reset&amp;lt;/code&amp;gt;: stops sampling, erases all logs and config, reboots into factory state. Used by QC provisioning workflow.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Configuration — Read &amp;amp; Write ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Command !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;get &amp;amp;lt;key&amp;amp;gt;&amp;lt;/code&amp;gt; || Print a single config key with its type and current value.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;set &amp;amp;lt;key&amp;amp;gt; &amp;amp;lt;value&amp;amp;gt;&amp;lt;/code&amp;gt; || Write a string config key to NVS. Special handling for &amp;lt;code&amp;gt;onboarding_step_one&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;onboarding_step_two&amp;lt;/code&amp;gt; (stored as bool).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;setint &amp;amp;lt;key&amp;amp;gt; &amp;amp;lt;value&amp;amp;gt;&amp;lt;/code&amp;gt; || Write an integer config key.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;setfloat &amp;amp;lt;key&amp;amp;gt; &amp;amp;lt;value&amp;amp;gt;&amp;lt;/code&amp;gt; || Write a float config key.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;setbool &amp;amp;lt;key&amp;amp;gt; &amp;amp;lt;true|false&amp;amp;gt;&amp;lt;/code&amp;gt; || Write a bool config key. Accepts &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;on&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;yes&amp;lt;/code&amp;gt; as true.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;cfgall [prefix]&amp;lt;/code&amp;gt; || Dump all config entries, optionally filtered by key prefix.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;cfgjson&amp;lt;/code&amp;gt; || Dump entire config as a JSON object (same structure as &amp;lt;code&amp;gt;/api/config&amp;lt;/code&amp;gt;).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Time Configuration ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Command !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;settime &amp;amp;lt;epoch&amp;amp;gt;&amp;lt;/code&amp;gt; || Inject wall time (POSIX epoch seconds). Refuses values before 2023-11-14. Used when NTP is not available.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;settz &amp;amp;lt;POSIX TZ&amp;amp;gt;&amp;lt;/code&amp;gt; || Set the POSIX timezone string, e.g. &amp;lt;code&amp;gt;CET-1CEST,M3.5.0/2,M10.5.0/3&amp;lt;/code&amp;gt;. Persists to NVS and applies immediately.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Hardware Diagnostics ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Command !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;led &amp;amp;lt;ch&amp;amp;gt; &amp;amp;lt;duty&amp;amp;gt;&amp;lt;/code&amp;gt; || Set LED brightness. Channel 0–2 (880 / 520 / 370 nm), duty 0–255. Turns the channel on immediately.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;pump &amp;amp;lt;duty&amp;amp;gt;&amp;lt;/code&amp;gt; || Set pump PWM duty cycle (0–255). Use &amp;lt;code&amp;gt;pumplock on&amp;lt;/code&amp;gt; first to prevent the control task from overriding this.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;pumplock on&amp;lt;/code&amp;gt; || Hand pump control to the serial operator — the automatic pump control task yields while locked.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;pumplock off&amp;lt;/code&amp;gt; || Restore automatic pump control.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;adc&amp;lt;/code&amp;gt; || Detect ADS1220 ADC and print current raw channel values. Reports &amp;quot;ADC OK&amp;quot; or &amp;quot;ADC not detected&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;sps30&amp;lt;/code&amp;gt; || One-shot read from SPS30 particulate matter sensor. Returns PM2.5 and PM10 in µg/m³.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;gps&amp;lt;/code&amp;gt; || GPS status: fix validity, satellite count, HDOP, latitude/longitude, altitude, speed, date/time.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== WiFi ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Command !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;wifi&amp;lt;/code&amp;gt; || Current WiFi state: mode (AP/STA), SSID, IP address, RSSI, internet reachability, time-sync status.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;scan&amp;lt;/code&amp;gt; || Scan for nearby WiFi networks, print SSID, RSSI, and open/secured flag.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;connect &amp;amp;lt;ssid&amp;amp;gt; &amp;amp;lt;password&amp;amp;gt;&amp;lt;/code&amp;gt; || Save WiFi credentials to NVS and initiate connection.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ap&amp;lt;/code&amp;gt; || Switch to access-point (hotspot) mode.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;wificlear&amp;lt;/code&amp;gt; || Delete stored WiFi credentials and force AP mode. Used in QC to ensure the 4G modem test cannot fall back to WiFi.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Modem / 4G ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Command !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;modem &amp;amp;lt;AT command&amp;amp;gt;&amp;lt;/code&amp;gt; || Send a raw AT command to the SIM7080G modem and print the response. Requires modem to be powered on first.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;modemscan&amp;lt;/code&amp;gt; || Scan UART configurations to detect modem baud rate and port.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;modemon&amp;lt;/code&amp;gt; || Power on and initialise the modem.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;modemoff&amp;lt;/code&amp;gt; || Power off the modem.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;debugmobile&amp;lt;/code&amp;gt; || Trigger the debug-mobile email send (same as &amp;lt;code&amp;gt;/api/control?action=debug_mobile&amp;lt;/code&amp;gt;). Sends a diagnostic email via the 4G modem.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;modemlog&amp;lt;/code&amp;gt; || Synchronously trigger the modem log streaming path (chunked upload to Lambda). Prints OK/FAIL.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;postest &amp;amp;lt;url&amp;amp;gt; &amp;amp;lt;size&amp;amp;gt;&amp;lt;/code&amp;gt; || POST a padded test payload of the given byte size to a URL via the modem. Used to verify HTTP POST framing over 4G. Lambda responds 200 to &amp;lt;code&amp;gt;_coap_test&amp;lt;/code&amp;gt; payloads.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Storage &amp;amp; Session ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Command !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;storage&amp;lt;/code&amp;gt; || Show LittleFS usage (used/total bytes), SD card presence, active session filename, and write-buffer depth.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;export&amp;lt;/code&amp;gt; || Export all log files to SD card.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;startsess&amp;lt;/code&amp;gt; || Manually start a new storage session (creates a new CSV file).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;endsess&amp;lt;/code&amp;gt; || Manually end the current storage session.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;loginfo&amp;lt;/code&amp;gt; || Print current session filename, file size, remote-sent offset, session-active flag, and free heap.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;dellog &amp;amp;lt;filename|current&amp;amp;gt;&amp;lt;/code&amp;gt; || Delete a named log file, or the current session if &amp;lt;code&amp;gt;current&amp;lt;/code&amp;gt; is given.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;gentest &amp;amp;lt;KB&amp;amp;gt;&amp;lt;/code&amp;gt; || Write a synthetic CSV log of the given size (1–1024 KB) for storage stress-testing.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;resetoffset&amp;lt;/code&amp;gt; || Reset the remote-sent byte offset to 0 (forces re-upload of the current session on the next mail cycle).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;reset&amp;lt;/code&amp;gt; || Reboot the device.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Email &amp;amp; QC ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Command !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;testemail [4g]&amp;lt;/code&amp;gt; || Send a test status email. Without &amp;lt;code&amp;gt;4g&amp;lt;/code&amp;gt;, sends via WiFi/Lambda. With &amp;lt;code&amp;gt;4g&amp;lt;/code&amp;gt;, forces 4G modem path. Recipient is &amp;lt;code&amp;gt;mail_logs_to&amp;lt;/code&amp;gt; (falls back to &amp;lt;code&amp;gt;jd@bcmeter.org&amp;lt;/code&amp;gt;).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;qcemail &amp;amp;lt;type&amp;amp;gt; &amp;amp;lt;json&amp;amp;gt;&amp;lt;/code&amp;gt; || Send a QC result email via 4G modem. &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; is the email subject key; &amp;lt;code&amp;gt;json&amp;lt;/code&amp;gt; is the JSON payload. Used by the provisioning QC workflow.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Lab / Engineering Mode ===&lt;br /&gt;
&lt;br /&gt;
These commands are used during hardware characterisation and manufacturing tests. They require no special mode to be active — they are always available.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Command !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;PING&amp;lt;/code&amp;gt; || Responds &amp;lt;code&amp;gt;PONG\n&amp;lt;/code&amp;gt;. Used by QC scripts to verify serial connectivity.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;LAB &amp;amp;lt;ch&amp;amp;gt; &amp;amp;lt;led_duty&amp;amp;gt; &amp;amp;lt;pump_duty&amp;amp;gt; &amp;amp;lt;pump_hz&amp;amp;gt; &amp;amp;lt;n_pairs&amp;amp;gt;&amp;lt;/code&amp;gt; || Run a lab ADC capture session: set LED channel/duty and pump duty/frequency, capture N raw ADC pairs, return binary data over serial.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;STREAM &amp;amp;lt;ch&amp;amp;gt; &amp;amp;lt;led_duty&amp;amp;gt; &amp;amp;lt;led_hz&amp;amp;gt; &amp;amp;lt;target_ml&amp;amp;gt; &amp;amp;lt;pump_hz&amp;amp;gt; &amp;amp;lt;duration_s&amp;amp;gt;&amp;lt;/code&amp;gt; || Streaming lab mode: continuous ADC pairs with airflow control for the given duration.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;LABFLOW &amp;amp;lt;ch&amp;amp;gt; &amp;amp;lt;led_duty&amp;amp;gt; &amp;amp;lt;led_hz&amp;amp;gt; &amp;amp;lt;target_ml&amp;amp;gt; &amp;amp;lt;pump_hz&amp;amp;gt; &amp;amp;lt;n_pairs&amp;amp;gt;&amp;lt;/code&amp;gt; || Lab mode with airflow target: capture N pairs at controlled flow rate.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;LABEND&amp;lt;/code&amp;gt; || End the current lab session. Responds &amp;lt;code&amp;gt;OK\n&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;STOP&amp;lt;/code&amp;gt; || Acknowledge stop. Used by QC scripts as a generic stop/sync marker.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;SILENCE on&amp;lt;/code&amp;gt; || Suppress serial log output during lab capture (reduces USB-CDC overhead).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;SILENCE off&amp;lt;/code&amp;gt; || Re-enable serial log output.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ADCMODE &amp;amp;lt;0–6&amp;amp;gt;&amp;lt;/code&amp;gt; || Set ADS1220 data rate: 0=20, 1=45, 2=90, 3=175, 4=330, 5=600+turbo (→1200), 6=1000+turbo (→2000) SPS.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Debug Isolation (MUTE) ===&lt;br /&gt;
&lt;br /&gt;
Used to isolate audible or electrical noise sources by progressively silencing PWM and RF emitters.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Command !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MUTE status on&amp;lt;/code&amp;gt; || Pause the status LED task (pin to high-Z). Reversible without reset.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MUTE status off&amp;lt;/code&amp;gt; || Resume the status LED task.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MUTE leds&amp;lt;/code&amp;gt; || Detach all three measurement LED PWM channels (requires &amp;lt;code&amp;gt;reset&amp;lt;/code&amp;gt; to restore).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MUTE pump&amp;lt;/code&amp;gt; || Detach the pump PWM channel (requires &amp;lt;code&amp;gt;reset&amp;lt;/code&amp;gt; to restore).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MUTE wifi&amp;lt;/code&amp;gt; || Disconnect WiFi and turn off the radio (requires &amp;lt;code&amp;gt;reset&amp;lt;/code&amp;gt; to restore).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== General ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Command !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;help&amp;lt;/code&amp;gt; || Print a grouped command summary to the serial console.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Usage Examples ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Check device status&lt;br /&gt;
&amp;gt; status&lt;br /&gt;
[Status] state=idle(0) init=0:... err=0:OK bc=0.0 atn=0.000 ...&lt;br /&gt;
&lt;br /&gt;
# Start measurement (after syncing time via the web UI)&lt;br /&gt;
&amp;gt; start&lt;br /&gt;
OK sampling started&lt;br /&gt;
&lt;br /&gt;
# Read live sensor snapshot&lt;br /&gt;
&amp;gt; sensors&lt;br /&gt;
[Pump]  flow=0.3001 LPM  duty=80  v=1.234  bias=0.002&lt;br /&gt;
[Env]   T=22.50°C  H=48.3%  P=1013.2 hPa&lt;br /&gt;
[GPS]   fix=YES sats=7 hdop=1.2  52.463100,13.306900 alt=48m&lt;br /&gt;
&lt;br /&gt;
# Manually test pump at a fixed duty (lock first to prevent auto-override)&lt;br /&gt;
&amp;gt; pumplock on&lt;br /&gt;
OK pump locked — controlTask yielding&lt;br /&gt;
&amp;gt; pump 120&lt;br /&gt;
Pump set to 120&lt;br /&gt;
&amp;gt; pumpinfo&lt;br /&gt;
[Pump] duty=120 flow=0.4210 ...&lt;br /&gt;
&amp;gt; pumplock off&lt;br /&gt;
OK pump unlocked&lt;br /&gt;
&lt;br /&gt;
# Set device timezone&lt;br /&gt;
&amp;gt; settz CET-1CEST,M3.5.0/2,M10.5.0/3&lt;br /&gt;
OK tz=CET-1CEST,M3.5.0/2,M10.5.0/3&lt;br /&gt;
&lt;br /&gt;
# Probe via QC tooling&lt;br /&gt;
&amp;gt; bcm:probe&lt;br /&gt;
{&amp;quot;_bcm&amp;quot;:1,&amp;quot;schema&amp;quot;:&amp;quot;probe/v1&amp;quot;,&amp;quot;name&amp;quot;:&amp;quot;bcmeter-A1B2&amp;quot;,&amp;quot;mac&amp;quot;:&amp;quot;AA:BB:CC:DD:EE:FF&amp;quot;,&amp;quot;fw&amp;quot;:&amp;quot;1.5.230&amp;quot;,&amp;quot;env&amp;quot;:&amp;quot;prod&amp;quot;,&amp;quot;up&amp;quot;:3721}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=Developer_mode&amp;diff=425</id>
		<title>Developer mode</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=Developer_mode&amp;diff=425"/>
		<updated>2026-06-08T18:47:40Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Consistency pass 2: airflow range via Configuration, multi-wavelength as in-development, ESP32/Pi CSV filename split, legacy sensor wording&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Developer Mode ==&lt;br /&gt;
&lt;br /&gt;
The bcMeter interface has a hidden developer mode for hardware tuning and diagnostics. &amp;#039;&amp;#039;&amp;#039;Changes in developer mode affect hardware directly&amp;#039;&amp;#039;&amp;#039; and can make measurements unusable when set incorrectly. Use it only for support, development, or device-specific provisioning.&lt;br /&gt;
&lt;br /&gt;
=== Activating Developer Mode ===&lt;br /&gt;
&lt;br /&gt;
# Open &amp;#039;&amp;#039;&amp;#039;Settings&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
# Click the &amp;#039;&amp;#039;&amp;#039;device name&amp;#039;&amp;#039;&amp;#039; text next to &amp;quot;Configuration&amp;quot; &amp;#039;&amp;#039;&amp;#039;7 times within 3 seconds&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
# The name changes to include &amp;lt;code&amp;gt;[DEV]&amp;lt;/code&amp;gt;.&lt;br /&gt;
# A new &amp;#039;&amp;#039;&amp;#039;⚠ Dev&amp;#039;&amp;#039;&amp;#039; tab appears in the settings panel.&lt;br /&gt;
&lt;br /&gt;
Developer mode is active for the current page session and is reset when the page is reloaded.&lt;br /&gt;
&lt;br /&gt;
=== Developer Tab Layout ===&lt;br /&gt;
&lt;br /&gt;
The Developer tab opens with a warning banner:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote style=&amp;quot;background:#fff3cd;padding:8px 16px;border-radius:4px;&amp;quot;&amp;gt;Developer mode — changes affect hardware directly. Save only if you know what you are doing.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Settings are grouped by namespace. The values below match the current ESP32 firmware defaults in &amp;lt;code&amp;gt;cfgstore.cpp&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== BC Smoothing Algorithm ====&lt;br /&gt;
&lt;br /&gt;
The first control selects the BC smoothing algorithm. This setting is stored as &amp;lt;code&amp;gt;bc_filter&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Value !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;median3&amp;lt;/code&amp;gt; (default) || 3-sample median filter. Good default for rejecting isolated outliers.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ema&amp;lt;/code&amp;gt; || Exponential moving average. Smoother trend, slower response to abrupt changes.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;kalman&amp;lt;/code&amp;gt; || Adaptive Kalman-style smoothing based on signal dynamics.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Calibration (&amp;lt;code&amp;gt;dev:calibration&amp;lt;/code&amp;gt;) ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parameter !! Description !! Default&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;sample_spot_diameter&amp;lt;/code&amp;gt; || Sample spot diameter in cm. Used in BC mass concentration calculations. || 0.4&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;filter_scattering_factor&amp;lt;/code&amp;gt; || Filter scattering factor used by the optical correction model. || 1.39&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;device_specific_correction_factor&amp;lt;/code&amp;gt; || Per-device correction factor from lab comparison or provisioning. || 1.0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Optical (&amp;lt;code&amp;gt;dev:optical&amp;lt;/code&amp;gt;) ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parameter !! Description !! Default&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;burst_measurement&amp;lt;/code&amp;gt; || LED is only enabled during the final seconds of a sample cycle. Experimental power/thermal mode. || false&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;adc_block_samples&amp;lt;/code&amp;gt; || ADC samples per sensor/reference block. Higher values reduce noise and increase capture time. || 256&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;led_duty_cycle_370nm&amp;lt;/code&amp;gt; || UV LED brightness/PWM duty for 370 nm channel. || 255&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;led_duty_cycle_520nm&amp;lt;/code&amp;gt; || Green LED brightness/PWM duty for 520 nm channel. || 255&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;led_duty_cycle_880nm&amp;lt;/code&amp;gt; || IR LED brightness/PWM duty for 880 nm channel. || 100&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;cal_k_370nm&amp;lt;/code&amp;gt; || Calibration factor for the 370 nm channel. || 1.0&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;cal_k_520nm&amp;lt;/code&amp;gt; || Calibration factor for the 520 nm channel. || 1.0&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;cal_k_880nm&amp;lt;/code&amp;gt; || Calibration factor for the 880 nm channel. || 1.0&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;shadow_factor&amp;lt;/code&amp;gt; || Weingartner shadow factor. Typical examples: 1.1 diesel, 1.2 urban, 1.5 biomass. || 1.2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Pump (&amp;lt;code&amp;gt;dev:pump&amp;lt;/code&amp;gt;) ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parameter !! Description !! Default&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;pump_dutycycle&amp;lt;/code&amp;gt; || Base pump power/PWM duty. || 20&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;max_pump_duty&amp;lt;/code&amp;gt; || Maximum pump duty cycle. || 255&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;min_pump_duty&amp;lt;/code&amp;gt; || Minimum pump duty cycle. || 1&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;min_airflow_ml&amp;lt;/code&amp;gt; || Minimum airflow before stall recovery starts, in ml/min. || 70&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;twelvevolt_duty&amp;lt;/code&amp;gt; || 12V pump output duty cycle. || 20&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;reverse_dutycycle&amp;lt;/code&amp;gt; || Reverse pump duty-cycle handling for hardware variants. || false&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;disable_pump_control&amp;lt;/code&amp;gt; || Disable internal pump control loop. Use only with external control hardware. || false&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;TWELVEVOLT_ENABLE&amp;lt;/code&amp;gt; || Enable 12V power output. || false&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;log_pump_duty&amp;lt;/code&amp;gt; || Write pump duty cycle into the CSV per sample. || false&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Auto Flow Control (&amp;lt;code&amp;gt;dev:afc&amp;lt;/code&amp;gt;) ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parameter !! Description !! Default&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;afc_bc_low&amp;lt;/code&amp;gt; || BC concentration below which AFC moves toward maximum flow. || 300 ng/m³&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;afc_bc_high&amp;lt;/code&amp;gt; || BC concentration above which AFC moves toward minimum flow. || 2000 ng/m³&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;afc_flow_low&amp;lt;/code&amp;gt; || Minimum airflow when AFC is active. || 0.05 L/min&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;afc_flow_high&amp;lt;/code&amp;gt; || Maximum airflow when AFC is active. || 0.7 L/min&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;afc_slope_gain&amp;lt;/code&amp;gt; || Flow boost per 100 ng/min downward BC trend. || 0.05&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Hardware (&amp;lt;code&amp;gt;dev:hardware&amp;lt;/code&amp;gt;) ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parameter !! Description !! Default&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;airflow_sensor&amp;lt;/code&amp;gt; || Airflow sensor is installed and should be used. || true&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;af_sensor_type&amp;lt;/code&amp;gt; || Airflow sensor type: 0 = P0001A1, 1 = P0010A2. || 1&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;enable_wifi&amp;lt;/code&amp;gt; || WiFi connectivity is available. || true&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;iot_enable&amp;lt;/code&amp;gt; || 4G / IoT modem connectivity is available. || true&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;show_undervoltage_warning&amp;lt;/code&amp;gt; || Show warning when the optical 12V rail / ADC is not detected. || false&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== System (&amp;lt;code&amp;gt;dev:system&amp;lt;/code&amp;gt;) ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parameter !! Description !! Default&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;num_channels&amp;lt;/code&amp;gt; || Number of optical wavelength channels. || 1&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;is_ebcMeter&amp;lt;/code&amp;gt; || Direct emission measurement mode. Changes units and emission-oriented behavior. || false&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;device_name&amp;lt;/code&amp;gt; || Device hostname/name used for mDNS and UI display. || bcMeter&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;heating&amp;lt;/code&amp;gt; || Enable heating hardware if installed. || false&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;use_display&amp;lt;/code&amp;gt; || Device has an attached display. || false&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;email_service_password&amp;lt;/code&amp;gt; || Mail service password for DIY/development devices. Provisioned devices normally already have this set. || email_service_password&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;onboarding_step_one&amp;lt;/code&amp;gt; || Phase 1 onboarding complete: contact email and WiFi setup. || false&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;onboarding_step_two&amp;lt;/code&amp;gt; || Phase 2 onboarding complete: calibration and data sharing choice. || false&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;onboarding_email_sent&amp;lt;/code&amp;gt; || Welcome/access email has already been sent. || false&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;team_upload_interval&amp;lt;/code&amp;gt; || Cloud/team upload interval in hours when data sharing is enabled. || 1&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;bcmeter_team_email&amp;lt;/code&amp;gt; || Contact email used for bcMeter team workflows. || empty&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;last_cal_time&amp;lt;/code&amp;gt; || Timestamp of the last successful calibration. || never&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Onboarding State ===&lt;br /&gt;
&lt;br /&gt;
The current firmware stores onboarding progress with separate flags:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;onboarding_step_one&amp;lt;/code&amp;gt;: WiFi/email phase completed.&lt;br /&gt;
* &amp;lt;code&amp;gt;onboarding_step_two&amp;lt;/code&amp;gt;: calibration/data-sharing phase completed.&lt;br /&gt;
* &amp;lt;code&amp;gt;onboarding_email_sent&amp;lt;/code&amp;gt;: welcome email has already been sent.&lt;br /&gt;
&lt;br /&gt;
The browser also uses local storage and cookies for temporary &amp;quot;Skip for now&amp;quot; behavior. &amp;quot;Don&amp;#039;t show again&amp;quot; writes the matching onboarding step flag to the device.&lt;br /&gt;
&lt;br /&gt;
=== Development Build Detection ===&lt;br /&gt;
&lt;br /&gt;
When the device is running a development build, the status API returns &amp;lt;code&amp;gt;&amp;quot;env&amp;quot;:&amp;quot;dev&amp;quot;&amp;lt;/code&amp;gt;. The interface shows a red banner:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote style=&amp;quot;background:#dc3545;color:#fff;padding:8px 16px;border-radius:4px;&amp;quot;&amp;gt;DEVELOPMENT BUILD — connected to dev backend&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 12V Power Warning ===&lt;br /&gt;
&lt;br /&gt;
If the optical ADC is not detected, the interface can show a 12V warning:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote style=&amp;quot;background:#fff3cd;padding:8px 16px;border-radius:4px;&amp;quot;&amp;gt;&amp;#039;&amp;#039;&amp;#039;⚠ 12V Power Missing&amp;#039;&amp;#039;&amp;#039; — The optical ADC is not detected. Optics and light sensors will not function. Pump and airflow control may be limited by hardware state.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Platform Variants (DIY / open line vs assembled instruments) ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;bcmeter-dev&amp;lt;/code&amp;gt; Raspberry Pi codebase powers &amp;#039;&amp;#039;&amp;#039;bcMeter (DIY)&amp;#039;&amp;#039;&amp;#039; builds, but it differs from the ESP32 firmware in the assembled instruments. Device-specific differences should be treated as implementation details of the same function:&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Networking:&amp;#039;&amp;#039;&amp;#039; Raspberry Pi builds use FastAPI/uvicorn and NetworkManager, while ESP32 builds use the embedded web server and ESP-IDF WiFi stack.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Optics/ADC:&amp;#039;&amp;#039;&amp;#039; Pi builds use ADS8344E hardware (legacy units may use MCP342X); ESP32 builds use ADS1220-based optical acquisition.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Firmware updates:&amp;#039;&amp;#039;&amp;#039; bcMeter (DIY) builds may update through OS/GitHub release workflows, while ESP32 devices use OTA firmware images.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Sensors:&amp;#039;&amp;#039;&amp;#039; Some legacy or prototype DIY builds expose additional sensors (e.g. DS18B20 1-Wire temperature) not present on standard units.&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=CSV_data_format&amp;diff=424</id>
		<title>CSV data format</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=CSV_data_format&amp;diff=424"/>
		<updated>2026-06-08T18:47:40Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Consistency pass 2: airflow range via Configuration, multi-wavelength as in-development, ESP32/Pi CSV filename split, legacy sensor wording&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== CSV Data Format ==&lt;br /&gt;
&lt;br /&gt;
bcMeter stores measurement data as CSV files. This page documents the file format and column definitions.&lt;br /&gt;
&lt;br /&gt;
=== File Format ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Property !! Value&lt;br /&gt;
|-&lt;br /&gt;
| Delimiter || Semicolon (&amp;lt;code&amp;gt;;&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| Encoding || UTF-8&lt;br /&gt;
|-&lt;br /&gt;
| Decimal separator || Dot (&amp;lt;code&amp;gt;.&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| Line ending || LF (&amp;lt;code&amp;gt;\n&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| First row || Column headers&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Filename Convention ===&lt;br /&gt;
&lt;br /&gt;
* Active session: &amp;lt;code&amp;gt;YY-MM-DD_HHMMSS.csv&amp;lt;/code&amp;gt; on ESP32 builds, &amp;lt;code&amp;gt;DD-MM-YY_HHMMSS.csv&amp;lt;/code&amp;gt; on Raspberry Pi builds (based on session start time)&lt;br /&gt;
* Fallback (no RTC sync): &amp;lt;code&amp;gt;nosync_HHMMSS.csv&amp;lt;/code&amp;gt; (based on uptime)&lt;br /&gt;
&lt;br /&gt;
=== Column Definitions ===&lt;br /&gt;
&lt;br /&gt;
==== Core Columns (always present) ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Column !! Type !! Unit !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;bcmDate&amp;lt;/code&amp;gt; || string || DD-MM-YY || Measurement date&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;bcmTime&amp;lt;/code&amp;gt; || string || HH:MM:SS || Measurement time&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;bcmRef_880nm&amp;lt;/code&amp;gt; || float || V || Reference channel voltage (880nm LED through clean filter)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;bcmSen_880nm&amp;lt;/code&amp;gt; || float || V || Sensor channel voltage (880nm LED through sample spot)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;bcmATN_880nm&amp;lt;/code&amp;gt; || float || — || Attenuation at 880nm = −100·ln(Sen/Ref), dimensionless. The absorption cross-section σ enters the BC concentration, not ATN.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;BCngm3_unfiltered_880nm&amp;lt;/code&amp;gt; || float || ng/m³ || Real-time BC concentration (unsmoothed)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;BCngm3_880nm&amp;lt;/code&amp;gt; || float || ng/m³ || BC concentration with rolling average applied&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;relativeLoad&amp;lt;/code&amp;gt; || float || % || Filter loading (0 = clean, 100 = saturated)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;AAE&amp;lt;/code&amp;gt; || float || — || Ångström Absorption Exponent (requires multi-wavelength)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Temperature&amp;lt;/code&amp;gt; || float || °C || Internal device temperature&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;airflow&amp;lt;/code&amp;gt; || float || L/min || Measured airflow rate&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Multi-Wavelength Columns (in development, not in shipped hardware) ====&lt;br /&gt;
&lt;br /&gt;
Same structure as 880nm, repeated for each wavelength:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;bcmRef_520nm&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;bcmSen_520nm&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;bcmATN_520nm&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;BCngm3_unfiltered_520nm&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;BCngm3_520nm&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;bcmRef_370nm&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;bcmSen_370nm&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;bcmATN_370nm&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;BCngm3_unfiltered_370nm&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;BCngm3_370nm&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Environmental Columns (optional, sensor-dependent) ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Column !! Type !! Unit !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;humidity&amp;lt;/code&amp;gt; || float || % || Relative humidity (BME280/SHT4x)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;hPa&amp;lt;/code&amp;gt; || float || hPa || Atmospheric pressure (BME280)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;PM2.5&amp;lt;/code&amp;gt; || float || µg/m³ || Particulate matter &amp;lt;2.5µm (SPS30)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;PM10&amp;lt;/code&amp;gt; || float || µg/m³ || Particulate matter &amp;lt;10µm (SPS30)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== GPS Columns (optional, if GPS module connected and has fix) ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Column !! Type !! Unit !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;lat&amp;lt;/code&amp;gt; || float || degrees || Latitude (WGS84)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;lon&amp;lt;/code&amp;gt; || float || degrees || Longitude (WGS84)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;altitude&amp;lt;/code&amp;gt; || float || m || GPS altitude above sea level&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Metadata Columns ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Column !! Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;notice&amp;lt;/code&amp;gt; || string || System notices or warnings per data point&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;sampleDuration&amp;lt;/code&amp;gt; || float || Actual measurement duration for this sample (seconds)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;notes&amp;lt;/code&amp;gt; || string || User-added annotations&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Example Data ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bcmDate;bcmTime;bcmRef_880nm;bcmSen_880nm;bcmATN_880nm;BCngm3_unfiltered_880nm;BCngm3_880nm;relativeLoad;AAE;Temperature;airflow&lt;br /&gt;
04-03-26;19:37:09;0.9679;0.9321;3.76;1686;1686;0;0;0;0.4659&lt;br /&gt;
04-03-26;19:42:09;0.9745;0.9335;4.3;4028.5;1686;0;0;0;0.3088&lt;br /&gt;
04-03-26;19:47:09;0.9752;0.9315;4.59;2371.4;1830.2;0;0;0;0.2832&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Import Notes ===&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Excel:&amp;#039;&amp;#039;&amp;#039; Use &amp;quot;Text Import Wizard&amp;quot; and set delimiter to semicolon. The date format DD-MM-YY may need manual conversion.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Python/Pandas:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;pd.read_csv(&amp;#039;file.csv&amp;#039;, sep=&amp;#039;;&amp;#039;)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;R:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;read.csv2(&amp;#039;file.csv&amp;#039;)&amp;lt;/code&amp;gt; (uses semicolon by default)&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=Interface&amp;diff=423</id>
		<title>Interface</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=Interface&amp;diff=423"/>
		<updated>2026-06-08T18:47:40Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Consistency pass 2: airflow range via Configuration, multi-wavelength as in-development, ESP32/Pi CSV filename split, legacy sensor wording&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Web Interface Overview ==&lt;br /&gt;
&lt;br /&gt;
The bcMeter web interface is a local dashboard for measurement data, device control, and settings. Open it from a browser on the same network as the device.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Try the live demo:&amp;#039;&amp;#039;&amp;#039; [https://bcmeter.org/demo/ bcmeter.org/demo]&lt;br /&gt;
&lt;br /&gt;
=== Dashboard Elements ===&lt;br /&gt;
&lt;br /&gt;
The main screen has five areas:&lt;br /&gt;
&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Control Bar&amp;#039;&amp;#039;&amp;#039; — Buttons to Start/Stop measurement, access Log Files, Settings, and Maintenance. On mobile or narrow screens, the bar collapses into a hamburger menu (☰).&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Status Panel&amp;#039;&amp;#039;&amp;#039; — Device state (with color-coded status dot), filter loading indicator, and time synchronization status.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Statistics&amp;#039;&amp;#039;&amp;#039; — 1h Average, Session Average, and Peak Value. The Peak Value card includes the timestamp of the peak and a &amp;#039;&amp;#039;&amp;#039;Reset&amp;#039;&amp;#039;&amp;#039; button.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Live Plot&amp;#039;&amp;#039;&amp;#039; — Black Carbon concentration over time.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Plot Controls&amp;#039;&amp;#039;&amp;#039; — Download, zoom reset, axis scaling, log selection, Y-axis assignment, resampling, and denoising.&lt;br /&gt;
&lt;br /&gt;
==== Dark Mode ====&lt;br /&gt;
&lt;br /&gt;
A dark mode toggle (moon/sun icon) is in the top-right corner of the navigation bar. The preference is saved in the browser.&lt;br /&gt;
&lt;br /&gt;
=== Status Indicators ===&lt;br /&gt;
&lt;br /&gt;
==== Device Status ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Status !! Meaning&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;Ready&amp;#039;&amp;#039;&amp;#039; || Device is idle. Pump is off.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;Initializing&amp;#039;&amp;#039;&amp;#039; || Pump is priming and the optical chamber is warming up. Data is not yet recorded.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;Running&amp;#039;&amp;#039;&amp;#039; || Active measurement. Data is being saved.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;Error&amp;#039;&amp;#039;&amp;#039; || System error detected. Open System Status or download logs in the Maintenance menu.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Time Sync Status ====&lt;br /&gt;
&lt;br /&gt;
The status bar shows whether the device clock is synced. If it shows &amp;quot;Time: not synced&amp;quot; in red, use &amp;#039;&amp;#039;&amp;#039;Maintenance &amp;gt; Time Synchronization&amp;#039;&amp;#039;&amp;#039; to sync the device clock with your browser.&lt;br /&gt;
&lt;br /&gt;
==== Filter Loading Status ====&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Filter&amp;quot; indicator shows how much of the filter strip is loaded. The color changes with loading level:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Color !! Loading !! Meaning&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#28a745;color:#fff&amp;quot; | &amp;#039;&amp;#039;&amp;#039;Green&amp;#039;&amp;#039;&amp;#039; || 0–30% || Filter is clean. Signal quality is optimal.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#ffc107&amp;quot; | &amp;#039;&amp;#039;&amp;#039;Orange&amp;#039;&amp;#039;&amp;#039; || 30–70% || Loading increasing. Mathematical compensation is active. Prepare a replacement.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#dc3545;color:#fff&amp;quot; | &amp;#039;&amp;#039;&amp;#039;Red&amp;#039;&amp;#039;&amp;#039; || 70–85% || Heavily loaded. Compensation becomes less reliable. Replace soon. Email alert sent every 12h when &amp;gt;70%.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#343a40;color:#fff&amp;quot; | &amp;#039;&amp;#039;&amp;#039;Dark&amp;#039;&amp;#039;&amp;#039; || 85%+ || Near saturation. Replace immediately.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Alert Modals ====&lt;br /&gt;
&lt;br /&gt;
The interface opens alert modals for these measurement conditions:&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Filter Loading High&amp;#039;&amp;#039;&amp;#039; — Filter loading exceeds the configured threshold. Replace the filter paper soon.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;No Airflow Detected&amp;#039;&amp;#039;&amp;#039; — Appears when airflow drops to near zero during measurement. Check pump tubing and connections.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;High Humidity&amp;#039;&amp;#039;&amp;#039; — Warning when humidity inside the device is too high.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Low Disk Space&amp;#039;&amp;#039;&amp;#039; — Warning when internal storage is running low.&lt;br /&gt;
&lt;br /&gt;
These alerts appear once per condition and can be dismissed with &amp;quot;Got it.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== Data Visualization ===&lt;br /&gt;
&lt;br /&gt;
==== Plot Behavior ====&lt;br /&gt;
&lt;br /&gt;
The graph shows measurements as a time series. The optical signal is analog, so the raw line is usually jagged. Smoothed values show the trend more clearly.&lt;br /&gt;
&lt;br /&gt;
After starting a measurement, the graph needs about 3–4 samples before it appears. At the default 300s (5 min) sample interval, first data appears after 15–20 minutes.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Zoom:&amp;#039;&amp;#039;&amp;#039; Click and drag to zoom in. Double-click to reset.&lt;br /&gt;
&lt;br /&gt;
==== Plot Controls ====&lt;br /&gt;
&lt;br /&gt;
Below the live plot:&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Download View:&amp;#039;&amp;#039;&amp;#039; Export current view as CSV, PNG, or SVG.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Reset Zoom:&amp;#039;&amp;#039;&amp;#039; Restore default view after zooming.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Axis Scaling:&amp;#039;&amp;#039;&amp;#039; Manually override automatic Y-axis scaling (min/max per axis) when peaks compress the view.&lt;br /&gt;
&lt;br /&gt;
==== View Log ====&lt;br /&gt;
&lt;br /&gt;
Dropdown for the current session or a previous log file stored on the device.&lt;br /&gt;
&lt;br /&gt;
==== Y-Axis Controls ====&lt;br /&gt;
&lt;br /&gt;
Each axis row (Y1, Y2, and added axes) includes:&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Toggle switch&amp;#039;&amp;#039;&amp;#039; — Show or hide the axis on the chart.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Variable selector&amp;#039;&amp;#039;&amp;#039; — Choose which parameter to display (see [[Interface#Plot Parameters|Plot Parameters]]).&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Resample slider&amp;#039;&amp;#039;&amp;#039; — Averages consecutive samples before plotting. &amp;quot;Off&amp;quot; shows every sample; higher values reduce visual noise and data density.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Denoise mode&amp;#039;&amp;#039;&amp;#039; — Segmented control with four options:&lt;br /&gt;
** &amp;#039;&amp;#039;&amp;#039;Raw&amp;#039;&amp;#039;&amp;#039; — Unfiltered signal, showing every data point as-is.&lt;br /&gt;
** &amp;#039;&amp;#039;&amp;#039;Med&amp;#039;&amp;#039;&amp;#039; — Median filter (default, highlighted in teal). Good default noise reduction.&lt;br /&gt;
** &amp;#039;&amp;#039;&amp;#039;EMA&amp;#039;&amp;#039;&amp;#039; — Exponential Moving Average. Gives more weight to recent values, good for tracking trends.&lt;br /&gt;
** &amp;#039;&amp;#039;&amp;#039;ONA&amp;#039;&amp;#039;&amp;#039; — Optimized Noise Average.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Denoise slider&amp;#039;&amp;#039;&amp;#039; — Adjusts the strength/window size for the selected denoise mode. The number next to the slider shows the current value.&lt;br /&gt;
** &amp;#039;&amp;#039;Direct emission monitoring:&amp;#039;&amp;#039; Keep below 4 for fast response.&lt;br /&gt;
** &amp;#039;&amp;#039;Ambient monitoring:&amp;#039;&amp;#039; Higher values are acceptable when a smoother trend is more important than fast response.&lt;br /&gt;
&lt;br /&gt;
==== Adding Extra Axes ====&lt;br /&gt;
&lt;br /&gt;
Click &amp;#039;&amp;#039;&amp;#039;+ Add axis&amp;#039;&amp;#039;&amp;#039; below Y2 to add more Y-axes. Each extra axis has the same controls. Use extra axes to compare values such as BC concentration, temperature, and airflow in one chart.&lt;br /&gt;
&lt;br /&gt;
=== Plot Parameters ===&lt;br /&gt;
&lt;br /&gt;
These parameters can be assigned to any Y-axis:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parameter !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;Reference (880nm)&amp;#039;&amp;#039;&amp;#039; || Light intensity from the 880nm LED through the clean portion of the filter — baseline for comparison. Optional 520nm / 370nm channels are in development (not available in shipped hardware).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;Sensor (880nm)&amp;#039;&amp;#039;&amp;#039; || Light intensity after passing through the particle-loaded spot.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;Attenuation (880nm)&amp;#039;&amp;#039;&amp;#039; || Calculated reduction in light intensity caused by absorbing particles.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;BC Unfiltered (880nm)&amp;#039;&amp;#039;&amp;#039; || Real-time black carbon concentration without smoothing.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;Black Carbon (880nm)&amp;#039;&amp;#039;&amp;#039; || BC concentration in ng/m³, with rolling average applied.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;Relative Load&amp;#039;&amp;#039;&amp;#039; || Filter spot saturation level (%), indicating when replacement is needed.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;Ångström Exponent&amp;#039;&amp;#039;&amp;#039; || Ratio indicating aerosol source characteristics (requires multi-wavelength hardware — in development, not in shipped devices).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;Temperature (°C)&amp;#039;&amp;#039;&amp;#039; || Internal operating temperature — important for measurement stability.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;Humidity (%)&amp;#039;&amp;#039;&amp;#039; || Relative humidity inside the device (if sensor equipped).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;Air Flow (l/min)&amp;#039;&amp;#039;&amp;#039; || Current airflow rate through the filter (if flow sensor equipped).&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=Best_practices&amp;diff=422</id>
		<title>Best practices</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=Best_practices&amp;diff=422"/>
		<updated>2026-06-08T18:47:40Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Consistency pass 2: airflow range via Configuration, multi-wavelength as in-development, ESP32/Pi CSV filename split, legacy sensor wording&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Best Practices ==&lt;br /&gt;
&lt;br /&gt;
=== Environment ===&lt;br /&gt;
&lt;br /&gt;
* Keep the device &amp;#039;&amp;#039;&amp;#039;away from direct sunlight&amp;#039;&amp;#039;&amp;#039;, radiators, and fireplaces — it is sensitive to temperature and lighting changes.&lt;br /&gt;
* Position the inlet away from localized emission sources unless intentionally measuring them.&lt;br /&gt;
* For indoor use, avoid placement near HVAC vents or drafts.&lt;br /&gt;
&lt;br /&gt;
=== Sampling Configuration ===&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Sample frequency:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
** Ambient immission monitoring: &amp;#039;&amp;#039;&amp;#039;180–600 seconds&amp;#039;&amp;#039;&amp;#039; (3–10 min)&lt;br /&gt;
** Direct emissions from wood stoves (µg vs ng range): &amp;#039;&amp;#039;&amp;#039;10–30 seconds&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
** Note: increasing frequency may increase noise.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Airflow:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
** Default 300 mL/min, adjustable (see [[Configuration]] for the range). Higher flow improves signal but loads the filter faster; the usable range narrows as the filter loads. With Auto Flow Control the device sets the rate automatically from the measured BC concentration.&lt;br /&gt;
** Higher airflow improves signal strength but loads the filter faster.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Pollution Level !! Daily Avg BC !! Recommended Airflow&lt;br /&gt;
|-&lt;br /&gt;
| Heavy pollution || &amp;gt;2000 ng/m³ || 50 mL/min&lt;br /&gt;
|-&lt;br /&gt;
| Typical urban || ~500 ng/m³ || 100–250 mL/min&lt;br /&gt;
|-&lt;br /&gt;
| Low pollution || &amp;lt;500 ng/m³ || 300–400 mL/min&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When &amp;#039;&amp;#039;&amp;#039;Auto Flow Control&amp;#039;&amp;#039;&amp;#039; is enabled, the device adjusts airflow automatically based on measured BC concentration — reducing flow when BC is high (to extend filter life) and increasing flow when BC is low (for better signal).&lt;br /&gt;
&lt;br /&gt;
=== Signal Quality ===&lt;br /&gt;
&lt;br /&gt;
Signal-to-noise ratio improves with:&lt;br /&gt;
* Higher BC loads&lt;br /&gt;
* Higher air volume per sample&lt;br /&gt;
* Smaller sample spot diameter&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Filtering:&amp;#039;&amp;#039;&amp;#039; Apply median/average filtering (denoise slider) to reduce noise. The rolling average is closer to the &amp;quot;real&amp;quot; value than individual data points.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Calibration:&amp;#039;&amp;#039;&amp;#039; Always calibrate after every filter change for reliable filter status indication and accurate measurement.&lt;br /&gt;
&lt;br /&gt;
=== Filter Management ===&lt;br /&gt;
&lt;br /&gt;
* At the default airflow in a typical urban environment (~500 ng/m³), a filter lasts approximately &amp;#039;&amp;#039;&amp;#039;3–5 days&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
* In heavily polluted areas, a filter may saturate in &amp;#039;&amp;#039;&amp;#039;6–12 hours&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
* Filter status is derived from attenuation (ATN): measurements are fully quantitative up to about ATN 75 and degrade at higher loading; the device flags the filter for replacement around ATN 120. (The ATN value is not a simple percentage of light loss.)&lt;br /&gt;
* The [[Configuration#Measurement Tab|Airflow Reference table]] in Settings helps estimate filter lifetime for your conditions.&lt;br /&gt;
&lt;br /&gt;
=== Supported Filter Papers ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Filter Paper !! Scattering Correction Factor&lt;br /&gt;
|-&lt;br /&gt;
| Pall T60A20 || 1.0&lt;br /&gt;
|-&lt;br /&gt;
| AE33 Filter || 0.75&lt;br /&gt;
|-&lt;br /&gt;
| AE51 Filter || 1.0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Other filter papers can be supported by determining their scattering factor. Send a sample to jd@bcmeter.org for calibration.&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=Developer_mode&amp;diff=421</id>
		<title>Developer mode</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=Developer_mode&amp;diff=421"/>
		<updated>2026-06-08T18:43:41Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Consistency pass: multi-wavelength in-development, bcmeter-pi link, anchor/Flask/V2 fixes, airflow &amp;amp; ATN clarifications&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Developer Mode ==&lt;br /&gt;
&lt;br /&gt;
The bcMeter interface has a hidden developer mode for hardware tuning and diagnostics. &amp;#039;&amp;#039;&amp;#039;Changes in developer mode affect hardware directly&amp;#039;&amp;#039;&amp;#039; and can make measurements unusable when set incorrectly. Use it only for support, development, or device-specific provisioning.&lt;br /&gt;
&lt;br /&gt;
=== Activating Developer Mode ===&lt;br /&gt;
&lt;br /&gt;
# Open &amp;#039;&amp;#039;&amp;#039;Settings&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
# Click the &amp;#039;&amp;#039;&amp;#039;device name&amp;#039;&amp;#039;&amp;#039; text next to &amp;quot;Configuration&amp;quot; &amp;#039;&amp;#039;&amp;#039;7 times within 3 seconds&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
# The name changes to include &amp;lt;code&amp;gt;[DEV]&amp;lt;/code&amp;gt;.&lt;br /&gt;
# A new &amp;#039;&amp;#039;&amp;#039;⚠ Dev&amp;#039;&amp;#039;&amp;#039; tab appears in the settings panel.&lt;br /&gt;
&lt;br /&gt;
Developer mode is active for the current page session and is reset when the page is reloaded.&lt;br /&gt;
&lt;br /&gt;
=== Developer Tab Layout ===&lt;br /&gt;
&lt;br /&gt;
The Developer tab opens with a warning banner:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote style=&amp;quot;background:#fff3cd;padding:8px 16px;border-radius:4px;&amp;quot;&amp;gt;Developer mode — changes affect hardware directly. Save only if you know what you are doing.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Settings are grouped by namespace. The values below match the current ESP32 firmware defaults in &amp;lt;code&amp;gt;cfgstore.cpp&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== BC Smoothing Algorithm ====&lt;br /&gt;
&lt;br /&gt;
The first control selects the BC smoothing algorithm. This setting is stored as &amp;lt;code&amp;gt;bc_filter&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Value !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;median3&amp;lt;/code&amp;gt; (default) || 3-sample median filter. Good default for rejecting isolated outliers.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ema&amp;lt;/code&amp;gt; || Exponential moving average. Smoother trend, slower response to abrupt changes.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;kalman&amp;lt;/code&amp;gt; || Adaptive Kalman-style smoothing based on signal dynamics.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Calibration (&amp;lt;code&amp;gt;dev:calibration&amp;lt;/code&amp;gt;) ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parameter !! Description !! Default&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;sample_spot_diameter&amp;lt;/code&amp;gt; || Sample spot diameter in cm. Used in BC mass concentration calculations. || 0.4&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;filter_scattering_factor&amp;lt;/code&amp;gt; || Filter scattering factor used by the optical correction model. || 1.39&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;device_specific_correction_factor&amp;lt;/code&amp;gt; || Per-device correction factor from lab comparison or provisioning. || 1.0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Optical (&amp;lt;code&amp;gt;dev:optical&amp;lt;/code&amp;gt;) ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parameter !! Description !! Default&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;burst_measurement&amp;lt;/code&amp;gt; || LED is only enabled during the final seconds of a sample cycle. Experimental power/thermal mode. || false&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;adc_block_samples&amp;lt;/code&amp;gt; || ADC samples per sensor/reference block. Higher values reduce noise and increase capture time. || 256&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;led_duty_cycle_370nm&amp;lt;/code&amp;gt; || UV LED brightness/PWM duty for 370 nm channel. || 255&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;led_duty_cycle_520nm&amp;lt;/code&amp;gt; || Green LED brightness/PWM duty for 520 nm channel. || 255&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;led_duty_cycle_880nm&amp;lt;/code&amp;gt; || IR LED brightness/PWM duty for 880 nm channel. || 100&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;cal_k_370nm&amp;lt;/code&amp;gt; || Calibration factor for the 370 nm channel. || 1.0&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;cal_k_520nm&amp;lt;/code&amp;gt; || Calibration factor for the 520 nm channel. || 1.0&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;cal_k_880nm&amp;lt;/code&amp;gt; || Calibration factor for the 880 nm channel. || 1.0&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;shadow_factor&amp;lt;/code&amp;gt; || Weingartner shadow factor. Typical examples: 1.1 diesel, 1.2 urban, 1.5 biomass. || 1.2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Pump (&amp;lt;code&amp;gt;dev:pump&amp;lt;/code&amp;gt;) ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parameter !! Description !! Default&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;pump_dutycycle&amp;lt;/code&amp;gt; || Base pump power/PWM duty. || 20&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;max_pump_duty&amp;lt;/code&amp;gt; || Maximum pump duty cycle. || 255&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;min_pump_duty&amp;lt;/code&amp;gt; || Minimum pump duty cycle. || 1&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;min_airflow_ml&amp;lt;/code&amp;gt; || Minimum airflow before stall recovery starts, in ml/min. || 70&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;twelvevolt_duty&amp;lt;/code&amp;gt; || 12V pump output duty cycle. || 20&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;reverse_dutycycle&amp;lt;/code&amp;gt; || Reverse pump duty-cycle handling for hardware variants. || false&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;disable_pump_control&amp;lt;/code&amp;gt; || Disable internal pump control loop. Use only with external control hardware. || false&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;TWELVEVOLT_ENABLE&amp;lt;/code&amp;gt; || Enable 12V power output. || false&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;log_pump_duty&amp;lt;/code&amp;gt; || Write pump duty cycle into the CSV per sample. || false&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Auto Flow Control (&amp;lt;code&amp;gt;dev:afc&amp;lt;/code&amp;gt;) ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parameter !! Description !! Default&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;afc_bc_low&amp;lt;/code&amp;gt; || BC concentration below which AFC moves toward maximum flow. || 300 ng/m³&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;afc_bc_high&amp;lt;/code&amp;gt; || BC concentration above which AFC moves toward minimum flow. || 2000 ng/m³&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;afc_flow_low&amp;lt;/code&amp;gt; || Minimum airflow when AFC is active. || 0.05 L/min&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;afc_flow_high&amp;lt;/code&amp;gt; || Maximum airflow when AFC is active. || 0.7 L/min&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;afc_slope_gain&amp;lt;/code&amp;gt; || Flow boost per 100 ng/min downward BC trend. || 0.05&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Hardware (&amp;lt;code&amp;gt;dev:hardware&amp;lt;/code&amp;gt;) ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parameter !! Description !! Default&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;airflow_sensor&amp;lt;/code&amp;gt; || Airflow sensor is installed and should be used. || true&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;af_sensor_type&amp;lt;/code&amp;gt; || Airflow sensor type: 0 = P0001A1, 1 = P0010A2. || 1&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;enable_wifi&amp;lt;/code&amp;gt; || WiFi connectivity is available. || true&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;iot_enable&amp;lt;/code&amp;gt; || 4G / IoT modem connectivity is available. || true&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;show_undervoltage_warning&amp;lt;/code&amp;gt; || Show warning when the optical 12V rail / ADC is not detected. || false&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== System (&amp;lt;code&amp;gt;dev:system&amp;lt;/code&amp;gt;) ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parameter !! Description !! Default&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;num_channels&amp;lt;/code&amp;gt; || Number of optical wavelength channels. || 1&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;is_ebcMeter&amp;lt;/code&amp;gt; || Direct emission measurement mode. Changes units and emission-oriented behavior. || false&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;device_name&amp;lt;/code&amp;gt; || Device hostname/name used for mDNS and UI display. || bcMeter&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;heating&amp;lt;/code&amp;gt; || Enable heating hardware if installed. || false&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;use_display&amp;lt;/code&amp;gt; || Device has an attached display. || false&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;email_service_password&amp;lt;/code&amp;gt; || Mail service password for DIY/development devices. Provisioned devices normally already have this set. || email_service_password&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;onboarding_step_one&amp;lt;/code&amp;gt; || Phase 1 onboarding complete: contact email and WiFi setup. || false&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;onboarding_step_two&amp;lt;/code&amp;gt; || Phase 2 onboarding complete: calibration and data sharing choice. || false&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;onboarding_email_sent&amp;lt;/code&amp;gt; || Welcome/access email has already been sent. || false&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;team_upload_interval&amp;lt;/code&amp;gt; || Cloud/team upload interval in hours when data sharing is enabled. || 1&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;bcmeter_team_email&amp;lt;/code&amp;gt; || Contact email used for bcMeter team workflows. || empty&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;last_cal_time&amp;lt;/code&amp;gt; || Timestamp of the last successful calibration. || never&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Onboarding State ===&lt;br /&gt;
&lt;br /&gt;
The current firmware stores onboarding progress with separate flags:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;onboarding_step_one&amp;lt;/code&amp;gt;: WiFi/email phase completed.&lt;br /&gt;
* &amp;lt;code&amp;gt;onboarding_step_two&amp;lt;/code&amp;gt;: calibration/data-sharing phase completed.&lt;br /&gt;
* &amp;lt;code&amp;gt;onboarding_email_sent&amp;lt;/code&amp;gt;: welcome email has already been sent.&lt;br /&gt;
&lt;br /&gt;
The browser also uses local storage and cookies for temporary &amp;quot;Skip for now&amp;quot; behavior. &amp;quot;Don&amp;#039;t show again&amp;quot; writes the matching onboarding step flag to the device.&lt;br /&gt;
&lt;br /&gt;
=== Development Build Detection ===&lt;br /&gt;
&lt;br /&gt;
When the device is running a development build, the status API returns &amp;lt;code&amp;gt;&amp;quot;env&amp;quot;:&amp;quot;dev&amp;quot;&amp;lt;/code&amp;gt;. The interface shows a red banner:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote style=&amp;quot;background:#dc3545;color:#fff;padding:8px 16px;border-radius:4px;&amp;quot;&amp;gt;DEVELOPMENT BUILD — connected to dev backend&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 12V Power Warning ===&lt;br /&gt;
&lt;br /&gt;
If the optical ADC is not detected, the interface can show a 12V warning:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote style=&amp;quot;background:#fff3cd;padding:8px 16px;border-radius:4px;&amp;quot;&amp;gt;&amp;#039;&amp;#039;&amp;#039;⚠ 12V Power Missing&amp;#039;&amp;#039;&amp;#039; — The optical ADC is not detected. Optics and light sensors will not function. Pump and airflow control may be limited by hardware state.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Platform Variants (DIY / open line vs assembled instruments) ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;bcmeter-dev&amp;lt;/code&amp;gt; Raspberry Pi codebase powers &amp;#039;&amp;#039;&amp;#039;bcMeter (DIY)&amp;#039;&amp;#039;&amp;#039; builds, but it differs from the ESP32 firmware in the assembled instruments. Device-specific differences should be treated as implementation details of the same function:&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Networking:&amp;#039;&amp;#039;&amp;#039; Raspberry Pi builds use FastAPI/uvicorn and NetworkManager, while ESP32 builds use the embedded web server and ESP-IDF WiFi stack.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Optics/ADC:&amp;#039;&amp;#039;&amp;#039; Pi builds use ADS8344E hardware (legacy units may use MCP342X); ESP32 builds use ADS1220-based optical acquisition.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Firmware updates:&amp;#039;&amp;#039;&amp;#039; bcMeter (DIY) builds may update through OS/GitHub release workflows, while ESP32 devices use OTA firmware images.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Sensors:&amp;#039;&amp;#039;&amp;#039; bcMeter (DIY) builds may expose DS18B20 or other prototype sensors that are not present on every ESP32 unit.&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=Best_practices&amp;diff=420</id>
		<title>Best practices</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=Best_practices&amp;diff=420"/>
		<updated>2026-06-08T18:43:41Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Consistency pass: multi-wavelength in-development, bcmeter-pi link, anchor/Flask/V2 fixes, airflow &amp;amp; ATN clarifications&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Best Practices ==&lt;br /&gt;
&lt;br /&gt;
=== Environment ===&lt;br /&gt;
&lt;br /&gt;
* Keep the device &amp;#039;&amp;#039;&amp;#039;away from direct sunlight&amp;#039;&amp;#039;&amp;#039;, radiators, and fireplaces — it is sensitive to temperature and lighting changes.&lt;br /&gt;
* Position the inlet away from localized emission sources unless intentionally measuring them.&lt;br /&gt;
* For indoor use, avoid placement near HVAC vents or drafts.&lt;br /&gt;
&lt;br /&gt;
=== Sampling Configuration ===&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Sample frequency:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
** Ambient immission monitoring: &amp;#039;&amp;#039;&amp;#039;180–600 seconds&amp;#039;&amp;#039;&amp;#039; (3–10 min)&lt;br /&gt;
** Direct emissions from wood stoves (µg vs ng range): &amp;#039;&amp;#039;&amp;#039;10–30 seconds&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
** Note: increasing frequency may increase noise.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Airflow:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
** Adjustable roughly between 25 and 500 mL/min (default 300 mL/min); the usable range narrows as the filter loads. With Auto Flow Control the device sets the rate automatically from the measured BC concentration.&lt;br /&gt;
** Higher airflow improves signal strength but loads the filter faster.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Pollution Level !! Daily Avg BC !! Recommended Airflow&lt;br /&gt;
|-&lt;br /&gt;
| Heavy pollution || &amp;gt;2000 ng/m³ || 50 mL/min&lt;br /&gt;
|-&lt;br /&gt;
| Typical urban || ~500 ng/m³ || 100–250 mL/min&lt;br /&gt;
|-&lt;br /&gt;
| Low pollution || &amp;lt;500 ng/m³ || 300–400 mL/min&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When &amp;#039;&amp;#039;&amp;#039;Auto Flow Control&amp;#039;&amp;#039;&amp;#039; is enabled, the device adjusts airflow automatically based on measured BC concentration — reducing flow when BC is high (to extend filter life) and increasing flow when BC is low (for better signal).&lt;br /&gt;
&lt;br /&gt;
=== Signal Quality ===&lt;br /&gt;
&lt;br /&gt;
Signal-to-noise ratio improves with:&lt;br /&gt;
* Higher BC loads&lt;br /&gt;
* Higher air volume per sample&lt;br /&gt;
* Smaller sample spot diameter&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Filtering:&amp;#039;&amp;#039;&amp;#039; Apply median/average filtering (denoise slider) to reduce noise. The rolling average is closer to the &amp;quot;real&amp;quot; value than individual data points.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Calibration:&amp;#039;&amp;#039;&amp;#039; Always calibrate after every filter change for reliable filter status indication and accurate measurement.&lt;br /&gt;
&lt;br /&gt;
=== Filter Management ===&lt;br /&gt;
&lt;br /&gt;
* At the default airflow in a typical urban environment (~500 ng/m³), a filter lasts approximately &amp;#039;&amp;#039;&amp;#039;3–5 days&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
* In heavily polluted areas, a filter may saturate in &amp;#039;&amp;#039;&amp;#039;6–12 hours&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
* Filter status is derived from attenuation (ATN): measurements are fully quantitative up to about ATN 75 and degrade at higher loading; the device flags the filter for replacement around ATN 120. (The ATN value is not a simple percentage of light loss.)&lt;br /&gt;
* The [[Configuration#Measurement Tab|Airflow Reference table]] in Settings helps estimate filter lifetime for your conditions.&lt;br /&gt;
&lt;br /&gt;
=== Supported Filter Papers ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Filter Paper !! Scattering Correction Factor&lt;br /&gt;
|-&lt;br /&gt;
| Pall T60A20 || 1.0&lt;br /&gt;
|-&lt;br /&gt;
| AE33 Filter || 0.75&lt;br /&gt;
|-&lt;br /&gt;
| AE51 Filter || 1.0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Other filter papers can be supported by determining their scattering factor. Send a sample to jd@bcmeter.org for calibration.&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=Troubleshooting&amp;diff=419</id>
		<title>Troubleshooting</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=Troubleshooting&amp;diff=419"/>
		<updated>2026-06-08T18:43:41Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Consistency pass: multi-wavelength in-development, bcmeter-pi link, anchor/Flask/V2 fixes, airflow &amp;amp; ATN clarifications&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Troubleshooting ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Issue !! Likely Cause &amp;amp; Solution&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;Negative data over a longer period&amp;#039;&amp;#039;&amp;#039; || &amp;#039;&amp;#039;&amp;#039;Temperature or lighting changes.&amp;#039;&amp;#039;&amp;#039; Ensure the bcMeter is not in direct or reflected sunlight (keep reflections from windows on other side of the road in mind). Do not place near radiators or heat sources. If issue persists, contact support.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;Device keeps restarting&amp;#039;&amp;#039;&amp;#039; || &amp;#039;&amp;#039;&amp;#039;Power supply.&amp;#039;&amp;#039;&amp;#039; Cable too long or thin — see power requirements in [[Setup#Hardware Requirements|Setup]].&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;WiFi unstable or disconnects&amp;#039;&amp;#039;&amp;#039; || Voltage instability (see power supply) or weak signal. The hotspot may temporarily disappear for 2–3 minutes during self-recovery — it returns automatically.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;No WiFi networks listed&amp;#039;&amp;#039;&amp;#039; || Reload the interface to re-initialize the network scan.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;No data on graph&amp;#039;&amp;#039;&amp;#039; || &amp;#039;&amp;#039;&amp;#039;Sampling interval.&amp;#039;&amp;#039;&amp;#039; The chart needs 3–4 samples before it can render. With the default 300s sample time, the first data point appears after ~15–20 minutes. Check that a session is running and wait for the first samples to arrive.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;Pump noise when stopped&amp;#039;&amp;#039;&amp;#039; || Motor controller signal latch. Go to &amp;#039;&amp;#039;&amp;#039;Maintenance &amp;gt; Reboot Device&amp;#039;&amp;#039;&amp;#039; or start a new log and stop right after initialization.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;Pump stall / no airflow&amp;#039;&amp;#039;&amp;#039; || The device has automatic stall protection. If flow drops below threshold for 3 seconds, recovery is attempted (up to 4 times). After 4 failures, measurement stops with pump error. Check for blocked tubing, saturated filter, or hardware issues.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;&amp;quot;Time: not synced&amp;quot; warning&amp;#039;&amp;#039;&amp;#039; || Device clock not synchronized. Internet-connected devices sync automatically; for offline devices, use Maintenance &amp;gt; Time Synchronization.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;Email notifications not working&amp;#039;&amp;#039;&amp;#039; || Verify the email service password (API key) is entered and validated in Email settings. Check that at least one valid recipient address is configured.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;Sensor values very low, don&amp;#039;t change&amp;#039;&amp;#039;&amp;#039; || Check voltages on LED and sensor connections. Verify 12V power is connected (the optical ADC requires it). Run calibration with a clean filter.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;ADC saturation error&amp;#039;&amp;#039;&amp;#039; || LED too bright or sensor oversaturated. The device attempts auto-recovery by reducing LED duty. If persistent, recalibrate with a fresh filter. Check in [[Developer mode]] if advanced LED settings need adjustment.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;Overtemperature warning&amp;#039;&amp;#039;&amp;#039; || Internal temperature exceeded 65°C. Move the device to a cooler location. Measurement pauses automatically and resumes when temperature drops.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Error Codes ===&lt;br /&gt;
&lt;br /&gt;
These numerical error codes are &amp;#039;&amp;#039;&amp;#039;not&amp;#039;&amp;#039;&amp;#039; shown in the frontend interface. They appear in the [[API reference|Status API]] response (&amp;lt;code&amp;gt;/api/status&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;error&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;error_msg&amp;lt;/code&amp;gt; fields) and in the &amp;#039;&amp;#039;&amp;#039;System Logs&amp;#039;&amp;#039;&amp;#039; (accessible from Maintenance). The interface displays a human-readable error message instead.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Code !! Name !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || ERR_NONE || No error&lt;br /&gt;
|-&lt;br /&gt;
| 1 || ERR_ADC_LOW || Sensor reading too low — filter extremely loaded&lt;br /&gt;
|-&lt;br /&gt;
| 2 || ERR_ADC_SATURATED || Sensor reading saturated — LED too bright; at low duty this indicates no filter is present&lt;br /&gt;
|-&lt;br /&gt;
| 3 || ERR_FLOW_ZERO || Pump stall, airflow below minimum&lt;br /&gt;
|-&lt;br /&gt;
| 4 || ERR_OVERTEMP || Temperature &amp;gt;65°C&lt;br /&gt;
|-&lt;br /&gt;
| 5 || ERR_LED_FAILURE || LED not functioning&lt;br /&gt;
|-&lt;br /&gt;
| 6 || ERR_ATN_LIMIT || Attenuation &amp;gt;120 — filter extremely clogged&lt;br /&gt;
|-&lt;br /&gt;
| 7 || ERR_OUTLIER_EXCESS || &amp;gt;80% of readings out-of-bounds&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Getting Help ===&lt;br /&gt;
&lt;br /&gt;
If your issue isn&amp;#039;t listed here, contact jd@bcmeter.org with:&lt;br /&gt;
* Description of the problem&lt;br /&gt;
* Screenshot of the interface&lt;br /&gt;
* System logs (download from &amp;#039;&amp;#039;&amp;#039;Maintenance &amp;gt; Download Logs&amp;#039;&amp;#039;&amp;#039;)&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=Main_Page&amp;diff=418</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=Main_Page&amp;diff=418"/>
		<updated>2026-06-08T18:43:41Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Consistency pass: multi-wavelength in-development, bcmeter-pi link, anchor/Flask/V2 fixes, airflow &amp;amp; ATN clarifications&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Welcome to the [https://bcmeter.org bcmeter.org] Wiki ==&lt;br /&gt;
&lt;br /&gt;
The bcMeter wiki is the technical documentation hub for the bcMeter platform — an optical absorption photometer for measuring Black Carbon (BC) aerosols in real-time. The platform spans the source-available &amp;#039;&amp;#039;&amp;#039;bcMeter (DIY)&amp;#039;&amp;#039;&amp;#039; (build it yourself) and the ready-to-use &amp;#039;&amp;#039;&amp;#039;bcMeter Kit, bcMeter Complete and eBcMeter&amp;#039;&amp;#039;&amp;#039; instruments.&lt;br /&gt;
&lt;br /&gt;
Whether you are setting up a new device, configuring measurements, or building your own unit, this wiki covers everything you need.&lt;br /&gt;
&lt;br /&gt;
== Getting Started ==&lt;br /&gt;
&lt;br /&gt;
* [[Introduction]] — What is bcMeter, how it works, capabilities&lt;br /&gt;
* [[Setup]] — Hardware requirements, first boot, WiFi configuration&lt;br /&gt;
* [[Interface]] — Web dashboard overview, status indicators, chart controls&lt;br /&gt;
&lt;br /&gt;
== Using bcMeter ==&lt;br /&gt;
&lt;br /&gt;
* [[Configuration]] — All settings: network, measurement, device, email&lt;br /&gt;
* [[Maintenance]] — Filter changes, calibration, data management&lt;br /&gt;
* [[Troubleshooting]] — Common issues and solutions&lt;br /&gt;
* [[Best practices]] — Environment, sampling, signal quality&lt;br /&gt;
&lt;br /&gt;
== Technical Reference ==&lt;br /&gt;
&lt;br /&gt;
* [[Developer mode]] — Hidden developer settings, hardware tuning&lt;br /&gt;
* [[API reference]] — REST API endpoints for automation and integration&lt;br /&gt;
* [[CSV data format]] — Column definitions and data structure&lt;br /&gt;
* [[Serial commands]] — USB debug interface&lt;br /&gt;
&lt;br /&gt;
== bcMeter (DIY) — build it yourself ==&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;These pages document the source-available bcMeter (DIY) — the Raspberry-Pi-based design, freely available for private, educational and research use (CC BY-NC 4.0), built from open design files (nothing is sold). The assembled bcMeter Kit, Complete and eBcMeter use a different hardware design.&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
* [[Working principle]] — Optical measurement principle&lt;br /&gt;
* [[Bill of material]] — Component list and costs (bcMeter DIY)&lt;br /&gt;
* [[Device assembly]] — Hardware build instructions (bcMeter DIY)&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
&lt;br /&gt;
The bcMeter software is source-available — freely available for private, educational and research use (CC BY-NC 4.0): &amp;#039;&amp;#039;&amp;#039;[https://github.com/dahljo/bcmeter-pi github.com/dahljo/bcmeter-pi]&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The codebase includes the web [[Interface|interface]], [[API reference|REST API]], measurement engine, and all device management functionality.&lt;br /&gt;
&lt;br /&gt;
== Contact ==&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Technical inquiries &amp;amp; devices:&amp;#039;&amp;#039;&amp;#039; Jonas Dahl — jd@bcmeter.org&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Black carbon science &amp;amp; air quality:&amp;#039;&amp;#039;&amp;#039; Axel Friedrich — af@bcmeter.org&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Project website:&amp;#039;&amp;#039;&amp;#039; [https://bcmeter.org bcmeter.org]&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=Introduction&amp;diff=417</id>
		<title>Introduction</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=Introduction&amp;diff=417"/>
		<updated>2026-06-08T18:43:41Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Consistency pass: multi-wavelength in-development, bcmeter-pi link, anchor/Flask/V2 fixes, airflow &amp;amp; ATN clarifications&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
The &amp;#039;&amp;#039;&amp;#039;bcMeter&amp;#039;&amp;#039;&amp;#039; is a source-available optical absorption photometer designed to measure Black Carbon (BC) aerosols — commonly known as soot — in real-time. The design is freely available for private, educational and research use (CC BY-NC 4.0); assembled instruments are offered on request. Whether you are monitoring ambient air quality in your neighborhood or measuring direct emissions from wood stoves, this device provides scientific-grade data at a fraction of the cost of reference instruments.&lt;br /&gt;
&lt;br /&gt;
The device operates &amp;quot;headless&amp;quot; — it has no built-in screen. Instead, it hosts its own website that you can access from any smartphone or computer connected to the same network.&lt;br /&gt;
&lt;br /&gt;
The software is source-available — freely available for private, educational and research use (CC BY-NC 4.0): [https://github.com/dahljo/bcmeter-pi github.com/dahljo/bcmeter-pi]&lt;br /&gt;
&lt;br /&gt;
=== Device Types ===&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;bcMeter (DIY)&amp;#039;&amp;#039;&amp;#039; — The source-available, self-build version. Runs on a Raspberry Pi using the open PCB design, freely available for private, educational and research use (CC BY-NC 4.0). Build your own from the open design files and the Wiki (nothing is sold).&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;bcMeter Kit&amp;#039;&amp;#039;&amp;#039; — Assembled-instrument PCB plus components for self-assembly and 3D printing. Available on request.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;bcMeter Complete&amp;#039;&amp;#039;&amp;#039; — Fully assembled, ready-to-use instrument on a compact platform that starts in seconds and updates over the air, with no microSD card or Linux system to maintain. Available on request.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;eBcMeter&amp;#039;&amp;#039;&amp;#039; — Emission measurement instrument for direct source sampling from wood-burning stoves and similar combustion sources. Uses microgram (µg) units instead of nanogram (ng). Available on request.&lt;br /&gt;
&lt;br /&gt;
=== How Does It Work? ===&lt;br /&gt;
&lt;br /&gt;
[[File:Working principle of a bcMeter.png|300px|right]]&lt;br /&gt;
&lt;br /&gt;
# Polluted air is drawn through filter paper by a pump&lt;br /&gt;
# The filter paper absorbs black carbon (BC) particles&lt;br /&gt;
# An LED shining at 880 nm passes through the filter; a sensor measures the attenuation (reduction in light intensity)&lt;br /&gt;
# A separate reference channel monitors the same LED through a clean portion of the filter, compensating for environmental changes&lt;br /&gt;
# The attenuation is converted to BC concentration (ng/m³) using Beer-Lambert law&lt;br /&gt;
# Data is saved as CSV and displayed in real-time on the web interface&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Multi-wavelength (in development):&amp;#039;&amp;#039;&amp;#039; Additional 520 nm and 370 nm channels for source apportionment via the Ångström Exponent (AAE) are in development and &amp;#039;&amp;#039;&amp;#039;not available in shipped hardware&amp;#039;&amp;#039;&amp;#039;. Current devices measure at 880 nm only.&lt;br /&gt;
&lt;br /&gt;
=== Sensors &amp;amp; Capabilities ===&lt;br /&gt;
&lt;br /&gt;
==== Core ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Measurement !! Sensor / Method !! Notes&lt;br /&gt;
|-&lt;br /&gt;
| Black Carbon (BC) || Optical absorption at 880 nm || Primary measurement&lt;br /&gt;
|-&lt;br /&gt;
| Temperature / Humidity || SHT4x ||&lt;br /&gt;
|-&lt;br /&gt;
| Airflow || Omron D6F differential pressure || Pump flow rate&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Optional Hardware ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Measurement !! Sensor / Method !! Notes&lt;br /&gt;
|-&lt;br /&gt;
| Temperature / Humidity / Pressure || BME280 || Barometric altitude&lt;br /&gt;
|-&lt;br /&gt;
| PM2.5 / PM10 || Sensirion SPS30 || Particulate matter&lt;br /&gt;
|-&lt;br /&gt;
| GPS || AT6668 UART || Position, altitude, speed&lt;br /&gt;
|-&lt;br /&gt;
| 4G Connectivity || SIM7080G LTE-M modem || Remote data upload&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=CSV_data_format&amp;diff=416</id>
		<title>CSV data format</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=CSV_data_format&amp;diff=416"/>
		<updated>2026-06-08T16:20:51Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Fix ATN formula: ATN = -100*ln(Sen/Ref), dimensionless; sigma enters BC not ATN (verified vs firmware measure.cpp)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== CSV Data Format ==&lt;br /&gt;
&lt;br /&gt;
bcMeter stores measurement data as CSV files. This page documents the file format and column definitions.&lt;br /&gt;
&lt;br /&gt;
=== File Format ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Property !! Value&lt;br /&gt;
|-&lt;br /&gt;
| Delimiter || Semicolon (&amp;lt;code&amp;gt;;&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| Encoding || UTF-8&lt;br /&gt;
|-&lt;br /&gt;
| Decimal separator || Dot (&amp;lt;code&amp;gt;.&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| Line ending || LF (&amp;lt;code&amp;gt;\n&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| First row || Column headers&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Filename Convention ===&lt;br /&gt;
&lt;br /&gt;
* Active session: &amp;lt;code&amp;gt;YY-MM-DD_HHMMSS.csv&amp;lt;/code&amp;gt; (based on session start time)&lt;br /&gt;
* Fallback (no RTC sync): &amp;lt;code&amp;gt;nosync_HHMMSS.csv&amp;lt;/code&amp;gt; (based on uptime)&lt;br /&gt;
&lt;br /&gt;
=== Column Definitions ===&lt;br /&gt;
&lt;br /&gt;
==== Core Columns (always present) ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Column !! Type !! Unit !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;bcmDate&amp;lt;/code&amp;gt; || string || DD-MM-YY || Measurement date&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;bcmTime&amp;lt;/code&amp;gt; || string || HH:MM:SS || Measurement time&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;bcmRef_880nm&amp;lt;/code&amp;gt; || float || V || Reference channel voltage (880nm LED through clean filter)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;bcmSen_880nm&amp;lt;/code&amp;gt; || float || V || Sensor channel voltage (880nm LED through sample spot)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;bcmATN_880nm&amp;lt;/code&amp;gt; || float || — || Attenuation at 880nm = −100·ln(Sen/Ref), dimensionless. The absorption cross-section σ enters the BC concentration, not ATN.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;BCngm3_unfiltered_880nm&amp;lt;/code&amp;gt; || float || ng/m³ || Real-time BC concentration (unsmoothed)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;BCngm3_880nm&amp;lt;/code&amp;gt; || float || ng/m³ || BC concentration with rolling average applied&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;relativeLoad&amp;lt;/code&amp;gt; || float || % || Filter loading (0 = clean, 100 = saturated)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;AAE&amp;lt;/code&amp;gt; || float || — || Ångström Absorption Exponent (requires multi-wavelength)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Temperature&amp;lt;/code&amp;gt; || float || °C || Internal device temperature&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;airflow&amp;lt;/code&amp;gt; || float || L/min || Measured airflow rate&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Multi-Wavelength Columns (optional, if hardware installed) ====&lt;br /&gt;
&lt;br /&gt;
Same structure as 880nm, repeated for each wavelength:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;bcmRef_520nm&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;bcmSen_520nm&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;bcmATN_520nm&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;BCngm3_unfiltered_520nm&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;BCngm3_520nm&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;bcmRef_370nm&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;bcmSen_370nm&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;bcmATN_370nm&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;BCngm3_unfiltered_370nm&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;BCngm3_370nm&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Environmental Columns (optional, sensor-dependent) ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Column !! Type !! Unit !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;humidity&amp;lt;/code&amp;gt; || float || % || Relative humidity (BME280/SHT4x)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;hPa&amp;lt;/code&amp;gt; || float || hPa || Atmospheric pressure (BME280)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;PM2.5&amp;lt;/code&amp;gt; || float || µg/m³ || Particulate matter &amp;lt;2.5µm (SPS30)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;PM10&amp;lt;/code&amp;gt; || float || µg/m³ || Particulate matter &amp;lt;10µm (SPS30)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== GPS Columns (optional, if GPS module connected and has fix) ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Column !! Type !! Unit !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;lat&amp;lt;/code&amp;gt; || float || degrees || Latitude (WGS84)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;lon&amp;lt;/code&amp;gt; || float || degrees || Longitude (WGS84)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;altitude&amp;lt;/code&amp;gt; || float || m || GPS altitude above sea level&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Metadata Columns ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Column !! Type !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;notice&amp;lt;/code&amp;gt; || string || System notices or warnings per data point&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;sampleDuration&amp;lt;/code&amp;gt; || float || Actual measurement duration for this sample (seconds)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;notes&amp;lt;/code&amp;gt; || string || User-added annotations&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Example Data ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
bcmDate;bcmTime;bcmRef_880nm;bcmSen_880nm;bcmATN_880nm;BCngm3_unfiltered_880nm;BCngm3_880nm;relativeLoad;AAE;Temperature;airflow&lt;br /&gt;
04-03-26;19:37:09;0.9679;0.9321;3.76;1686;1686;0;0;0;0.4659&lt;br /&gt;
04-03-26;19:42:09;0.9745;0.9335;4.3;4028.5;1686;0;0;0;0.3088&lt;br /&gt;
04-03-26;19:47:09;0.9752;0.9315;4.59;2371.4;1830.2;0;0;0;0.2832&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Import Notes ===&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Excel:&amp;#039;&amp;#039;&amp;#039; Use &amp;quot;Text Import Wizard&amp;quot; and set delimiter to semicolon. The date format DD-MM-YY may need manual conversion.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Python/Pandas:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;pd.read_csv(&amp;#039;file.csv&amp;#039;, sep=&amp;#039;;&amp;#039;)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;R:&amp;#039;&amp;#039;&amp;#039; &amp;lt;code&amp;gt;read.csv2(&amp;#039;file.csv&amp;#039;)&amp;lt;/code&amp;gt; (uses semicolon by default)&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=Setup&amp;diff=415</id>
		<title>Setup</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=Setup&amp;diff=415"/>
		<updated>2026-06-08T10:35:07Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Reframe: bcMeter (DIY) / source-available&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Setup &amp;amp; Initialization ==&lt;br /&gt;
&lt;br /&gt;
=== Hardware Requirements ===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Use a stable power supply:&amp;#039;&amp;#039;&amp;#039; Weak adapters and voltage drops are the most common causes of WiFi dropouts and random reboots.&lt;br /&gt;
&lt;br /&gt;
* bcMeter Kit/Complete: use a suitable &amp;#039;&amp;#039;&amp;#039;12V / 2A&amp;#039;&amp;#039;&amp;#039; power adapter.&lt;br /&gt;
* bcMeter (DIY): use a suitable &amp;#039;&amp;#039;&amp;#039;5V / 2.5A&amp;#039;&amp;#039;&amp;#039; power adapter.&lt;br /&gt;
* Use a &amp;#039;&amp;#039;&amp;#039;short, low-resistance cable&amp;#039;&amp;#039;&amp;#039; (ideally under 40 cm). Long or thin cables can drop enough voltage to reboot the device when the pump starts.&lt;br /&gt;
&lt;br /&gt;
=== Initial Device Setup ===&lt;br /&gt;
&lt;br /&gt;
Before starting measurements:&lt;br /&gt;
&lt;br /&gt;
# Place the device &amp;#039;&amp;#039;&amp;#039;away from direct heat sources and sunlight&amp;#039;&amp;#039;&amp;#039; (thermal drift affects optical measurements).&lt;br /&gt;
# Insert a fresh filter paper (&amp;#039;&amp;#039;&amp;#039;marked side facing up&amp;#039;&amp;#039;&amp;#039; — see [[Maintenance#Filter Change Procedure|Filter Change Procedure]]).&lt;br /&gt;
# If using a rugged case: check that the hose from bcMeter to the outside air is firmly inserted and not blocked.&lt;br /&gt;
&lt;br /&gt;
=== Connecting via Hotspot ===&lt;br /&gt;
&lt;br /&gt;
The device creates its own WiFi network automatically on first boot, or when no known network is available. It can also be forced via Settings (Hotspot Mode).&lt;br /&gt;
&lt;br /&gt;
# Plug in the device.&lt;br /&gt;
# Wait &amp;#039;&amp;#039;&amp;#039;1-2 minutes&amp;#039;&amp;#039;&amp;#039; for the system to boot.&lt;br /&gt;
# On your phone or computer, search for a WiFi network whose name starts with &amp;#039;&amp;#039;&amp;#039;bcMeter&amp;#039;&amp;#039;&amp;#039; or &amp;#039;&amp;#039;&amp;#039;eBcMeter&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
# If asked, connect using the password &amp;lt;code&amp;gt;bcMeterbcMeter&amp;lt;/code&amp;gt; (case sensitive). Current assembled bcMeter instruments may create an open setup hotspot and will not ask for a password.&lt;br /&gt;
# Your phone may warn &amp;quot;No Internet Connection.&amp;quot; &amp;#039;&amp;#039;&amp;#039;This is normal.&amp;#039;&amp;#039;&amp;#039; Select &amp;quot;Keep Connected&amp;quot; if prompted. Do not choose &amp;quot;use mobile data.&amp;quot;&lt;br /&gt;
# Open a browser and type &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;http://bcmeter-XXXX.local&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; (where XXXX are the last 4 hex characters of the MAC address, e.g. &amp;lt;code&amp;gt;bcmeter-A3AB&amp;lt;/code&amp;gt;) or &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;http://192.168.18.8&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The &amp;#039;&amp;#039;&amp;#039;[[Setup#Welcome Screen|Welcome Screen]]&amp;#039;&amp;#039;&amp;#039; will appear on first use.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Apple users:&amp;#039;&amp;#039;&amp;#039; If already connected to another WiFi, the bcMeter hotspot will appear under &amp;quot;Other Networks&amp;quot; submenu. macOS may take up to a minute to scan for new networks.&lt;br /&gt;
&lt;br /&gt;
=== Welcome Screen ===&lt;br /&gt;
&lt;br /&gt;
On first use, bcMeter shows a two-phase welcome screen for network setup, calibration, and data sharing.&lt;br /&gt;
&lt;br /&gt;
==== Phase 1: Connect ====&lt;br /&gt;
&lt;br /&gt;
The first screen (&amp;quot;Connect this bcMeter&amp;quot;) covers connectivity:&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Notification email&amp;#039;&amp;#039;&amp;#039; — Enter the address where bcMeter should send status messages and alerts. After WiFi setup, the device can send its URL and connection details to this address.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Enable email notifications&amp;#039;&amp;#039;&amp;#039; — Toggle to receive status updates and measurement reports.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Connect to network&amp;#039;&amp;#039;&amp;#039; — Select your network from the dropdown, click &amp;#039;&amp;#039;&amp;#039;Scan&amp;#039;&amp;#039;&amp;#039; to refresh, or choose &amp;#039;&amp;#039;&amp;#039;Enter manually&amp;#039;&amp;#039;&amp;#039; for hidden networks. Enter the WiFi password and click &amp;#039;&amp;#039;&amp;#039;Connect&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
The email step offers &amp;quot;Skip for now&amp;quot; and &amp;quot;Don&amp;#039;t show again&amp;quot;. The WiFi step offers &amp;quot;Back&amp;quot; and &amp;quot;Skip&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==== Phase 2: Calibrate &amp;amp; Share ====&lt;br /&gt;
&lt;br /&gt;
After connecting to WiFi (or if WiFi was already configured), the second screen (&amp;quot;Almost there&amp;quot;) appears:&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Install a clean filter&amp;#039;&amp;#039;&amp;#039; — Place a fresh quartz filter in the holder.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Calibrate&amp;#039;&amp;#039;&amp;#039; — Perform a baseline reading. Click &amp;quot;Start calibration →&amp;quot; to open the calibration dialog directly.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Data sharing&amp;#039;&amp;#039;&amp;#039; — Shared measurements help build the bcMeter black carbon map. You can choose:&lt;br /&gt;
** &amp;#039;&amp;#039;&amp;#039;Get Started &amp;amp; Share Data&amp;#039;&amp;#039;&amp;#039; — Enables anonymous data sharing for the project.&lt;br /&gt;
** &amp;#039;&amp;#039;&amp;#039;Get Started without Sharing&amp;#039;&amp;#039;&amp;#039; — Proceeds without sharing. You can change this later in Settings.&lt;br /&gt;
&lt;br /&gt;
The calibration/sharing phase has &amp;quot;Skip for now&amp;quot; and &amp;quot;Don&amp;#039;t show again&amp;quot; options at the bottom.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Tip:&amp;#039;&amp;#039;&amp;#039; The welcome screen will reappear on each visit until setup is complete or you choose &amp;quot;Don&amp;#039;t show again.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Important:&amp;#039;&amp;#039;&amp;#039; Run [[Maintenance#Calibration|calibration]] after setup.&lt;br /&gt;
&lt;br /&gt;
=== Connecting to Wireless Network ===&lt;br /&gt;
&lt;br /&gt;
If you skipped WiFi setup on the welcome screen, or need to change your network later:&lt;br /&gt;
&lt;br /&gt;
# Navigate to &amp;#039;&amp;#039;&amp;#039;Settings&amp;#039;&amp;#039;&amp;#039; &amp;gt; &amp;#039;&amp;#039;&amp;#039;Network&amp;#039;&amp;#039;&amp;#039; tab.&lt;br /&gt;
# Select your network from the list. For hidden networks, choose &amp;quot;Enter manually&amp;quot; and type the SSID yourself.&lt;br /&gt;
# Enter your WiFi key and click &amp;#039;&amp;#039;&amp;#039;Connect&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
# The setup hotspot disconnects while the device joins the selected network. Reconnect your computer to your normal WiFi.&lt;br /&gt;
# Wait 1–2 minutes for the device to join your network.&lt;br /&gt;
&lt;br /&gt;
Click &amp;quot;Forget Network&amp;quot; in the Network tab to disconnect from the stored network and force the device to create its hotspot again.&lt;br /&gt;
&lt;br /&gt;
=== Accessing the Interface ===&lt;br /&gt;
&lt;br /&gt;
When the device is on your network, open it by hostname. The default hostname follows the pattern &amp;lt;code&amp;gt;bcmeter-XXXX&amp;lt;/code&amp;gt; (or &amp;lt;code&amp;gt;ebcmeter-XXXX&amp;lt;/code&amp;gt; for emission devices), where XXXX are the last 4 hex characters of the device&amp;#039;s MAC address. For example:&lt;br /&gt;
&lt;br /&gt;
* Standard device: &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;http://bcmeter-A3AB.local&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
* Emission control version: &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;http://ebcmeter-A3AB.local&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The exact hostname is shown on the device label and in the Welcome screen email. You can rename the device in Settings &amp;gt; Device &amp;gt; Device Name.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Tip:&amp;#039;&amp;#039;&amp;#039; If &amp;lt;code&amp;gt;.local&amp;lt;/code&amp;gt; addresses do not work (common on some Windows networks or older routers), find the device&amp;#039;s IP address in your router&amp;#039;s administration interface.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Browser Security Warnings:&amp;#039;&amp;#039;&amp;#039; The bcMeter web server uses HTTP (not HTTPS), which triggers browser warnings. This is expected — the device runs locally on your network with no public internet connection. You must explicitly allow access to the device&amp;#039;s &amp;lt;code&amp;gt;.local&amp;lt;/code&amp;gt; address. On macOS, you may also need to grant permission for your browser to access LAN devices.&lt;br /&gt;
&lt;br /&gt;
=== Connection Lost ===&lt;br /&gt;
&lt;br /&gt;
If the browser loses contact with the device (for example during a reboot or network drop), a &amp;quot;Connection Lost&amp;quot; overlay appears. The interface keeps trying to reconnect until the device is reachable again.&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=Installation&amp;diff=414</id>
		<title>Installation</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=Installation&amp;diff=414"/>
		<updated>2026-06-08T10:35:06Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Reframe: bcMeter (DIY) / source-available&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Note|1=&amp;#039;&amp;#039;&amp;#039;bcMeter (DIY)&amp;#039;&amp;#039;&amp;#039; — This page documents software setup for the source-available bcMeter (DIY) — the Raspberry-Pi-based design, freely available for private, educational and research use (CC BY-NC 4.0). The assembled bcMeter instruments come pre-configured and are set up via the [[Setup#Welcome Screen|Welcome Screen]].}}&lt;br /&gt;
&lt;br /&gt;
== Recommended: Pre-configured microSD Card Image (bcMeter DIY) ==&lt;br /&gt;
&lt;br /&gt;
=== Step 1: Download and Flash the Image ===&lt;br /&gt;
&lt;br /&gt;
# Download the bcMeter image file [https://bcmeter.org/wp-content/uploads/simple-file-list/bcMeter_latest_img.zip here]&lt;br /&gt;
# Unzip the downloaded file&lt;br /&gt;
# Use [https://www.balena.io/etcher/ Etcher] to flash the image to your microSD card:&lt;br /&gt;
#* Insert your microSD card&lt;br /&gt;
#* Open Etcher and select the image&lt;br /&gt;
#* Select your microSD card as target&lt;br /&gt;
#* Click &amp;quot;Flash!&amp;quot; and wait for completion&lt;br /&gt;
&lt;br /&gt;
=== Step 2: Boot and Connect ===&lt;br /&gt;
&lt;br /&gt;
# Insert the flashed microSD card into the Raspberry Pi&lt;br /&gt;
# Power on the device&lt;br /&gt;
# Wait approximately 2 minutes for boot&lt;br /&gt;
# Connect to the WiFi network &amp;quot;&amp;#039;&amp;#039;&amp;#039;bcMeter&amp;#039;&amp;#039;&amp;#039;&amp;quot; with password: &amp;lt;code&amp;gt;bcMeterbcMeter&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Step 3: Configure ===&lt;br /&gt;
&lt;br /&gt;
# Open a browser and navigate to &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;http://bcmeter-XXXX.local&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; (where XXXX are the last 4 hex characters of the MAC address, shown on the device label)&lt;br /&gt;
# The bcMeter interface will appear&lt;br /&gt;
# Follow on-screen instructions&lt;br /&gt;
&lt;br /&gt;
== Advanced: Manual Setup via SSH (bcMeter DIY) ==&lt;br /&gt;
&lt;br /&gt;
Use the [https://www.raspberrypi.com/software/ Raspberry Pi Imager] to write &amp;#039;&amp;#039;&amp;#039;Raspberry OS 64-bit LITE&amp;#039;&amp;#039;&amp;#039; to the microSD card. Do &amp;#039;&amp;#039;&amp;#039;not&amp;#039;&amp;#039;&amp;#039; install the Desktop variant.&lt;br /&gt;
&lt;br /&gt;
Configure with username &amp;lt;code&amp;gt;bcmeter&amp;lt;/code&amp;gt; and password &amp;lt;code&amp;gt;bcmeter.org&amp;lt;/code&amp;gt;. Enable SSH and WiFi.&lt;br /&gt;
&lt;br /&gt;
=== SSH Installation ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ssh bcmeter@bcMeter&lt;br /&gt;
# or: ssh bcmeter@bcMeter.local&lt;br /&gt;
&lt;br /&gt;
# Download and run installer&lt;br /&gt;
wget -N https://raw.githubusercontent.com/bcmeter/bcmeter/main/install.sh &amp;amp;&amp;amp; sudo bash install.sh&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This runs an unattended installation taking a few minutes.&lt;br /&gt;
&lt;br /&gt;
== Assembled instruments (Kit/Complete/eBcMeter) ==&lt;br /&gt;
&lt;br /&gt;
The assembled bcMeter instruments come with firmware pre-installed. Setup only requires:&lt;br /&gt;
&lt;br /&gt;
# Plug in power&lt;br /&gt;
# Connect to the &amp;quot;bcMeter&amp;quot; WiFi hotspot&lt;br /&gt;
# Open &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;http://bcmeter-XXXX.local&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; (XXXX = last 4 hex chars of MAC address)&lt;br /&gt;
# Follow the [[Setup#Welcome Screen|Welcome Screen]]&lt;br /&gt;
&lt;br /&gt;
See [[Setup]] for detailed instructions.&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=Device_assembly&amp;diff=413</id>
		<title>Device assembly</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=Device_assembly&amp;diff=413"/>
		<updated>2026-06-08T10:35:05Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Reframe: bcMeter (DIY) / source-available&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Note|1=&amp;#039;&amp;#039;&amp;#039;bcMeter (DIY)&amp;#039;&amp;#039;&amp;#039; — This page documents assembly of the source-available bcMeter (DIY) — the Raspberry-Pi-based design, freely available for private, educational and research use (CC BY-NC 4.0). The assembled bcMeter instruments use a different hardware design.}}&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;bcMeter (DIY) Assembly Documentation&amp;#039;&amp;#039;&amp;#039; (v02, January 2025)&lt;br /&gt;
&lt;br /&gt;
== LED and Sensor Brackets ==&lt;br /&gt;
&lt;br /&gt;
The orientation of both the 3D printed infrared LED and sensor assemblies has been simplified to reduce orientation mismatches.&lt;br /&gt;
&lt;br /&gt;
The infrared LEDs are housed in clear-looking parts while the infrared sensors are in dark parts. Each must be correctly oriented – note that the spherical lens on each part should point toward the shorter end of the bracket, ensuring both point toward the filter paper.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Glueing:&amp;#039;&amp;#039;&amp;#039; Use plastics glue (avoid &amp;quot;super glue&amp;quot; as it can leave residue that affects LED and phototransistor sensitivity for days or weeks). Place a droplet of glue on each leg to close the hole.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Assembly:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
** Insert the LED and sensor bracket assembly into the case.&lt;br /&gt;
** Pre-treat both counterparts with plastics glue before insertion to create airtight channels.&lt;br /&gt;
** Ensure the middle section between the sample and sensor areas is completely covered with glue to prevent air leakage.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Fixing:&amp;#039;&amp;#039;&amp;#039; Prior to insertion, secure the LEDs and sensors with plastic or hot glue (avoid tilting; check orientation).&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Mounting:&amp;#039;&amp;#039;&amp;#039; Once inserted, mount the brackets to the case and verify that the LED and sensor lenses are centered.&lt;br /&gt;
&lt;br /&gt;
== Reference &amp;amp; Sample Parts ==&lt;br /&gt;
&lt;br /&gt;
On the circuit board, the LEDs must be connected in series. The negative pin of the first LED serves as the positive pin for the second LED. Use a standard 4-pin 2.54 mm JST connector and cable, soldering the connections in the order:&lt;br /&gt;
&lt;br /&gt;
: &amp;#039;&amp;#039;&amp;#039;red – black – yellow – white&amp;#039;&amp;#039;&amp;#039; - connect one by one. If your cable has different coloring, maintain the same electrical order.&lt;br /&gt;
&lt;br /&gt;
The infrared sensors (for measuring attenuation) are connected &amp;#039;&amp;#039;&amp;#039;in parallel&amp;#039;&amp;#039;&amp;#039;. Their connections follow a different order:&lt;br /&gt;
&lt;br /&gt;
: &amp;#039;&amp;#039;&amp;#039;black – red – white – yellow&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
This completes the most crucial part of the bcMeter assembly. LED-to-sensor orientation and air leakage directly affect accuracy. Minor misalignments can be compensated by the [[Maintenance#Calibration|Calibration function]].&lt;br /&gt;
&lt;br /&gt;
== Sealing ==&lt;br /&gt;
&lt;br /&gt;
Continue case assembly by adding a rubber seal to the bottom part:&lt;br /&gt;
&lt;br /&gt;
* Ensure the seal&amp;#039;s diameter is precisely known — critical for accuracy.&lt;br /&gt;
* Check for air leakage; if needed, apply a second seal to the top part and ensure holes overlap.&lt;br /&gt;
* To verify diameter, let the paper run black and examine the sample spot.&lt;br /&gt;
* Add M3 screw threads to the poles and use superglue to secure them.&lt;br /&gt;
&lt;br /&gt;
== Pump Control Circuit ==&lt;br /&gt;
&lt;br /&gt;
The bcMeter is versatile with pump selection. Any pump running at 5V will work. Two low-cost types:&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Membrane pumps&amp;#039;&amp;#039;&amp;#039; — Recommended.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Propeller pumps&amp;#039;&amp;#039;&amp;#039; — Not recommended for this use case.&lt;br /&gt;
&lt;br /&gt;
Membrane pumps can use a PWM controller (Type A) or operate without one (Type B). For PWM-controlled pumps, remove Q4 from the PCB.&lt;br /&gt;
&lt;br /&gt;
== Airflow Meter Setup ==&lt;br /&gt;
&lt;br /&gt;
If an airflow meter is used:&lt;br /&gt;
&lt;br /&gt;
* Connect the pump&amp;#039;s input to the airflow sensor&amp;#039;s output.&lt;br /&gt;
* Connect the airflow sensor&amp;#039;s input to the air sampling connector.&lt;br /&gt;
* Connect the pump&amp;#039;s output to the bcMeter&amp;#039;s air output.&lt;br /&gt;
&lt;br /&gt;
== Finalizing the Build ==&lt;br /&gt;
&lt;br /&gt;
* Insert filter paper and screw the top part of the case by hand.&lt;br /&gt;
* Connect a stronger 12V pump and cover the air inlet.&lt;br /&gt;
* If noise is heard (indicating leakage), use glue to seal the gap.&lt;br /&gt;
&lt;br /&gt;
== Description of the Components (bcMeter DIY) ==&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;U1:&amp;#039;&amp;#039;&amp;#039; MCP3428 4-Channel Analogue/Digital Converter&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;D1 / D2:&amp;#039;&amp;#039;&amp;#039; IR LED connector for sensor and reference&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Q1 / Q2:&amp;#039;&amp;#039;&amp;#039; IR Phototransistor for sensor and reference (ADC Channels 1 and 2)&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;J1:&amp;#039;&amp;#039;&amp;#039; Omron D6F Airflow Sensor (ADC Channel 4)&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;J2:&amp;#039;&amp;#039;&amp;#039; SSD1306 Display (optional)&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;J7:&amp;#039;&amp;#039;&amp;#039; Heater or Fan (optional)&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;J12:&amp;#039;&amp;#039;&amp;#039; SPI Header (optional)&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;J5:&amp;#039;&amp;#039;&amp;#039; Air Pump&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;J4 / J9:&amp;#039;&amp;#039;&amp;#039; PWM + Power for Air Pump (remove Q4 for PWM pump)&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Additional:&amp;#039;&amp;#039;&amp;#039; Several headers (I2C, ADC, Power) for expandability&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=Bill_of_material&amp;diff=412</id>
		<title>Bill of material</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=Bill_of_material&amp;diff=412"/>
		<updated>2026-06-08T10:35:04Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Reframe: bcMeter (DIY) / source-available&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Note|1=&amp;#039;&amp;#039;&amp;#039;bcMeter (DIY)&amp;#039;&amp;#039;&amp;#039; — This page documents the bill of materials for the source-available bcMeter (DIY) — the Raspberry-Pi-based design, freely available for private, educational and research use (CC BY-NC 4.0). The assembled bcMeter instruments use a different PCB design.}}&lt;br /&gt;
&lt;br /&gt;
== Overview of Parts (bcMeter DIY) ==&lt;br /&gt;
&lt;br /&gt;
[[File:bcMeter_parts.jpg|thumb|none|800px]]&lt;br /&gt;
&lt;br /&gt;
== Mandatory Components ==&lt;br /&gt;
&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;bcMeter Pi Hat&amp;#039;&amp;#039;&amp;#039; — Order prepopulated (~95 EUR) or build your own from PCB + components (~5 EUR per PCB for 10+ on JLCPCB or similar)&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Raspberry Pi 3A or Zero 2 W&amp;#039;&amp;#039;&amp;#039; (~35 EUR)&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;MicroSD Card&amp;#039;&amp;#039;&amp;#039; (~10 EUR)&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Power Supply 5.25V/2A&amp;#039;&amp;#039;&amp;#039; (~15 EUR)&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Air Pump&amp;#039;&amp;#039;&amp;#039; (~10–200 EUR depending on type)&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Prefer not to source parts? bcMeter Kit/Complete available on request — contact jd@bcmeter.org.&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
== 3D Printed Case ==&lt;br /&gt;
&lt;br /&gt;
STL files for 3D Printing (SLA or FDM): [https://github.com/bcmeter/bcmeter/tree/main/stl GitHub repository] — printing material ~10 EUR.&lt;br /&gt;
&lt;br /&gt;
Use black filament/resin. FDM is prone to leakage if not properly configured. If possible, mix resin with flex resin.&lt;br /&gt;
&lt;br /&gt;
== Filter Paper ==&lt;br /&gt;
&lt;br /&gt;
AE33 filter paper is standard for bcMeter. Any filter paper with a known scattering factor can be used. See [[Best practices#Supported Filter Papers|Supported Filter Papers]] for correction factors.&lt;br /&gt;
&lt;br /&gt;
Send a sample of your filter paper to jd@bcmeter.org for calibration.&lt;br /&gt;
&lt;br /&gt;
== Additional Material (~75 EUR) ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Description !! Quantity !! Approx. Price&lt;br /&gt;
|-&lt;br /&gt;
| 22 AWG Wire || 1 || $10&lt;br /&gt;
|-&lt;br /&gt;
| Hot Glue || 1 || $7&lt;br /&gt;
|-&lt;br /&gt;
| Rubber Band (SHORE A) for sealing || 1 || $13&lt;br /&gt;
|-&lt;br /&gt;
| Silicone Hose (5mm ID) || 1 || $5&lt;br /&gt;
|-&lt;br /&gt;
| M3 Screws || 1 set || $7&lt;br /&gt;
|-&lt;br /&gt;
| M3 Threaded Inserts || 1 set || $7&lt;br /&gt;
|-&lt;br /&gt;
| MicroSD Card 16GB || 1 || $8&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Key PCB Components ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Component !! Description !! Approx. Price&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;U1&amp;#039;&amp;#039;&amp;#039; MCP3428 || 4-Channel ADC || €6&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;D1/D2&amp;#039;&amp;#039;&amp;#039; IRL81A || IR LEDs (880nm) || €2&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;J1&amp;#039;&amp;#039;&amp;#039; Omron D6F || Airflow Sensor || €50&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;U2&amp;#039;&amp;#039;&amp;#039; LM1117 || Voltage Regulator || €1&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;U3&amp;#039;&amp;#039;&amp;#039; SHT4x || Humidity/Temp Sensor || €4&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;Pump&amp;#039;&amp;#039;&amp;#039; D15S PWM || Membrane Pump || €95&lt;br /&gt;
|-&lt;br /&gt;
| Capacitors, resistors, connectors || Various || ~€20&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Full BOM with exact product numbers available at [https://github.com/bcmeter/bcmeter GitHub].&lt;br /&gt;
&lt;br /&gt;
== PCB / Gerber Files ==&lt;br /&gt;
&lt;br /&gt;
Gerber files for PCB fabrication: [https://github.com/bcmeter/bcmeter/tree/main/gerbers GitHub]&lt;br /&gt;
&lt;br /&gt;
Two PCB variants exist:&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;SMD PCB&amp;#039;&amp;#039;&amp;#039; — For 5V and smaller pumps. More compact, recommended.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;THT PCB&amp;#039;&amp;#039;&amp;#039; — For 12V and larger pumps. Easier to assemble but less accurate.&lt;br /&gt;
&lt;br /&gt;
== Assembled instruments (Kit/Complete/eBcMeter) ==&lt;br /&gt;
&lt;br /&gt;
The assembled bcMeter instruments use a different hardware design:&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;ADS1220&amp;#039;&amp;#039;&amp;#039; 24-bit ADC (replaces MCP3428)&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Integrated microcontroller&amp;#039;&amp;#039;&amp;#039; (instead of the Raspberry Pi used in the DIY build)&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Internal flash storage&amp;#039;&amp;#039;&amp;#039; (replaces microSD)&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Optional:&amp;#039;&amp;#039;&amp;#039; SIM7080G LTE-M modem, AT6668 GPS, SPS30 PM sensor&lt;br /&gt;
&lt;br /&gt;
For current device information, see [[Introduction]].&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=Developer_mode&amp;diff=411</id>
		<title>Developer mode</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=Developer_mode&amp;diff=411"/>
		<updated>2026-06-08T10:35:03Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Reframe: bcMeter (DIY) / source-available&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Developer Mode ==&lt;br /&gt;
&lt;br /&gt;
The bcMeter interface has a hidden developer mode for hardware tuning and diagnostics. &amp;#039;&amp;#039;&amp;#039;Changes in developer mode affect hardware directly&amp;#039;&amp;#039;&amp;#039; and can make measurements unusable when set incorrectly. Use it only for support, development, or device-specific provisioning.&lt;br /&gt;
&lt;br /&gt;
=== Activating Developer Mode ===&lt;br /&gt;
&lt;br /&gt;
# Open &amp;#039;&amp;#039;&amp;#039;Settings&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
# Click the &amp;#039;&amp;#039;&amp;#039;device name&amp;#039;&amp;#039;&amp;#039; text next to &amp;quot;Configuration&amp;quot; &amp;#039;&amp;#039;&amp;#039;7 times within 3 seconds&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
# The name changes to include &amp;lt;code&amp;gt;[DEV]&amp;lt;/code&amp;gt;.&lt;br /&gt;
# A new &amp;#039;&amp;#039;&amp;#039;⚠ Dev&amp;#039;&amp;#039;&amp;#039; tab appears in the settings panel.&lt;br /&gt;
&lt;br /&gt;
Developer mode is active for the current page session and is reset when the page is reloaded.&lt;br /&gt;
&lt;br /&gt;
=== Developer Tab Layout ===&lt;br /&gt;
&lt;br /&gt;
The Developer tab opens with a warning banner:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote style=&amp;quot;background:#fff3cd;padding:8px 16px;border-radius:4px;&amp;quot;&amp;gt;Developer mode — changes affect hardware directly. Save only if you know what you are doing.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Settings are grouped by namespace. The values below match the current ESP32 firmware defaults in &amp;lt;code&amp;gt;cfgstore.cpp&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== BC Smoothing Algorithm ====&lt;br /&gt;
&lt;br /&gt;
The first control selects the BC smoothing algorithm. This setting is stored as &amp;lt;code&amp;gt;bc_filter&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Value !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;median3&amp;lt;/code&amp;gt; (default) || 3-sample median filter. Good default for rejecting isolated outliers.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ema&amp;lt;/code&amp;gt; || Exponential moving average. Smoother trend, slower response to abrupt changes.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;kalman&amp;lt;/code&amp;gt; || Adaptive Kalman-style smoothing based on signal dynamics.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Calibration (&amp;lt;code&amp;gt;dev:calibration&amp;lt;/code&amp;gt;) ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parameter !! Description !! Default&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;sample_spot_diameter&amp;lt;/code&amp;gt; || Sample spot diameter in cm. Used in BC mass concentration calculations. || 0.4&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;filter_scattering_factor&amp;lt;/code&amp;gt; || Filter scattering factor used by the optical correction model. || 1.39&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;device_specific_correction_factor&amp;lt;/code&amp;gt; || Per-device correction factor from lab comparison or provisioning. || 1.0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Optical (&amp;lt;code&amp;gt;dev:optical&amp;lt;/code&amp;gt;) ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parameter !! Description !! Default&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;burst_measurement&amp;lt;/code&amp;gt; || LED is only enabled during the final seconds of a sample cycle. Experimental power/thermal mode. || false&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;adc_block_samples&amp;lt;/code&amp;gt; || ADC samples per sensor/reference block. Higher values reduce noise and increase capture time. || 256&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;led_duty_cycle_370nm&amp;lt;/code&amp;gt; || UV LED brightness/PWM duty for 370 nm channel. || 255&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;led_duty_cycle_520nm&amp;lt;/code&amp;gt; || Green LED brightness/PWM duty for 520 nm channel. || 255&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;led_duty_cycle_880nm&amp;lt;/code&amp;gt; || IR LED brightness/PWM duty for 880 nm channel. || 100&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;cal_k_370nm&amp;lt;/code&amp;gt; || Calibration factor for the 370 nm channel. || 1.0&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;cal_k_520nm&amp;lt;/code&amp;gt; || Calibration factor for the 520 nm channel. || 1.0&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;cal_k_880nm&amp;lt;/code&amp;gt; || Calibration factor for the 880 nm channel. || 1.0&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;shadow_factor&amp;lt;/code&amp;gt; || Weingartner shadow factor. Typical examples: 1.1 diesel, 1.2 urban, 1.5 biomass. || 1.2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Pump (&amp;lt;code&amp;gt;dev:pump&amp;lt;/code&amp;gt;) ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parameter !! Description !! Default&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;pump_dutycycle&amp;lt;/code&amp;gt; || Base pump power/PWM duty. || 20&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;max_pump_duty&amp;lt;/code&amp;gt; || Maximum pump duty cycle. || 255&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;min_pump_duty&amp;lt;/code&amp;gt; || Minimum pump duty cycle. || 1&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;min_airflow_ml&amp;lt;/code&amp;gt; || Minimum airflow before stall recovery starts, in ml/min. || 70&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;twelvevolt_duty&amp;lt;/code&amp;gt; || 12V pump output duty cycle. || 20&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;reverse_dutycycle&amp;lt;/code&amp;gt; || Reverse pump duty-cycle handling for hardware variants. || false&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;disable_pump_control&amp;lt;/code&amp;gt; || Disable internal pump control loop. Use only with external control hardware. || false&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;TWELVEVOLT_ENABLE&amp;lt;/code&amp;gt; || Enable 12V power output. || false&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;log_pump_duty&amp;lt;/code&amp;gt; || Write pump duty cycle into the CSV per sample. || false&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Auto Flow Control (&amp;lt;code&amp;gt;dev:afc&amp;lt;/code&amp;gt;) ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parameter !! Description !! Default&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;afc_bc_low&amp;lt;/code&amp;gt; || BC concentration below which AFC moves toward maximum flow. || 300 ng/m³&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;afc_bc_high&amp;lt;/code&amp;gt; || BC concentration above which AFC moves toward minimum flow. || 2000 ng/m³&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;afc_flow_low&amp;lt;/code&amp;gt; || Minimum airflow when AFC is active. || 0.05 L/min&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;afc_flow_high&amp;lt;/code&amp;gt; || Maximum airflow when AFC is active. || 0.7 L/min&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;afc_slope_gain&amp;lt;/code&amp;gt; || Flow boost per 100 ng/min downward BC trend. || 0.05&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Hardware (&amp;lt;code&amp;gt;dev:hardware&amp;lt;/code&amp;gt;) ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parameter !! Description !! Default&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;airflow_sensor&amp;lt;/code&amp;gt; || Airflow sensor is installed and should be used. || true&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;af_sensor_type&amp;lt;/code&amp;gt; || Airflow sensor type: 0 = P0001A1, 1 = P0010A2. || 1&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;enable_wifi&amp;lt;/code&amp;gt; || WiFi connectivity is available. || true&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;iot_enable&amp;lt;/code&amp;gt; || 4G / IoT modem connectivity is available. || true&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;show_undervoltage_warning&amp;lt;/code&amp;gt; || Show warning when the optical 12V rail / ADC is not detected. || false&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== System (&amp;lt;code&amp;gt;dev:system&amp;lt;/code&amp;gt;) ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parameter !! Description !! Default&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;num_channels&amp;lt;/code&amp;gt; || Number of optical wavelength channels. || 1&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;is_ebcMeter&amp;lt;/code&amp;gt; || Direct emission measurement mode. Changes units and emission-oriented behavior. || false&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;device_name&amp;lt;/code&amp;gt; || Device hostname/name used for mDNS and UI display. || bcMeter&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;heating&amp;lt;/code&amp;gt; || Enable heating hardware if installed. || false&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;use_display&amp;lt;/code&amp;gt; || Device has an attached display. || false&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;email_service_password&amp;lt;/code&amp;gt; || Mail service password for DIY/development devices. Provisioned devices normally already have this set. || email_service_password&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;onboarding_step_one&amp;lt;/code&amp;gt; || Phase 1 onboarding complete: contact email and WiFi setup. || false&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;onboarding_step_two&amp;lt;/code&amp;gt; || Phase 2 onboarding complete: calibration and data sharing choice. || false&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;onboarding_email_sent&amp;lt;/code&amp;gt; || Welcome/access email has already been sent. || false&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;team_upload_interval&amp;lt;/code&amp;gt; || Cloud/team upload interval in hours when data sharing is enabled. || 1&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;bcmeter_team_email&amp;lt;/code&amp;gt; || Contact email used for bcMeter team workflows. || empty&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;last_cal_time&amp;lt;/code&amp;gt; || Timestamp of the last successful calibration. || never&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Onboarding State ===&lt;br /&gt;
&lt;br /&gt;
The current firmware stores onboarding progress with separate flags:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;onboarding_step_one&amp;lt;/code&amp;gt;: WiFi/email phase completed.&lt;br /&gt;
* &amp;lt;code&amp;gt;onboarding_step_two&amp;lt;/code&amp;gt;: calibration/data-sharing phase completed.&lt;br /&gt;
* &amp;lt;code&amp;gt;onboarding_email_sent&amp;lt;/code&amp;gt;: welcome email has already been sent.&lt;br /&gt;
&lt;br /&gt;
The browser also uses local storage and cookies for temporary &amp;quot;Skip for now&amp;quot; behavior. &amp;quot;Don&amp;#039;t show again&amp;quot; writes the matching onboarding step flag to the device.&lt;br /&gt;
&lt;br /&gt;
=== Development Build Detection ===&lt;br /&gt;
&lt;br /&gt;
When the device is running a development build, the status API returns &amp;lt;code&amp;gt;&amp;quot;env&amp;quot;:&amp;quot;dev&amp;quot;&amp;lt;/code&amp;gt;. The interface shows a red banner:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote style=&amp;quot;background:#dc3545;color:#fff;padding:8px 16px;border-radius:4px;&amp;quot;&amp;gt;DEVELOPMENT BUILD — connected to dev backend&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 12V Power Warning ===&lt;br /&gt;
&lt;br /&gt;
If the optical ADC is not detected, the interface can show a 12V warning:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote style=&amp;quot;background:#fff3cd;padding:8px 16px;border-radius:4px;&amp;quot;&amp;gt;&amp;#039;&amp;#039;&amp;#039;⚠ 12V Power Missing&amp;#039;&amp;#039;&amp;#039; — The optical ADC is not detected. Optics and light sensors will not function. Pump and airflow control may be limited by hardware state.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Platform Variants (DIY / open line vs assembled instruments) ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;bcmeter-dev&amp;lt;/code&amp;gt; Raspberry Pi codebase powers &amp;#039;&amp;#039;&amp;#039;bcMeter (DIY)&amp;#039;&amp;#039;&amp;#039; builds, but it differs from the ESP32 firmware in the assembled instruments. Device-specific differences should be treated as implementation details of the same function:&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Networking:&amp;#039;&amp;#039;&amp;#039; Raspberry Pi builds may use Flask and NetworkManager, while ESP32 builds use the embedded web server and ESP-IDF WiFi stack.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Optics/ADC:&amp;#039;&amp;#039;&amp;#039; Pi builds may reference ADS8344E or MCP342X hardware; current ESP32 V2 builds use ADS1220-based optical acquisition.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Firmware updates:&amp;#039;&amp;#039;&amp;#039; bcMeter (DIY) builds may update through OS/GitHub release workflows, while ESP32 devices use OTA firmware images.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Sensors:&amp;#039;&amp;#039;&amp;#039; bcMeter (DIY) builds may expose DS18B20 or other prototype sensors that are not present on every ESP32 unit.&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=API_reference&amp;diff=410</id>
		<title>API reference</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=API_reference&amp;diff=410"/>
		<updated>2026-06-08T10:35:02Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Reframe: bcMeter (DIY) / source-available&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== API Reference ==&lt;br /&gt;
&lt;br /&gt;
The bcMeter exposes a REST API on port 80. All endpoints are accessible without authentication when connected to the device network. CORS is enabled for all GET requests (&amp;lt;code&amp;gt;allow_origins=[&amp;quot;*&amp;quot;]&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
The software is source-available — freely available for private, educational and research use (CC BY-NC 4.0): [https://github.com/dahljo/bcmeter github.com/dahljo/bcmeter]&lt;br /&gt;
&lt;br /&gt;
=== Status &amp;amp; Diagnostics ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Method !! Endpoint !! Description&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/status&amp;lt;/code&amp;gt; || Current measurement state, last sensor readings, error codes, sample count, WiFi mode, firmware version, OTA info. Returns &amp;lt;code&amp;gt;&amp;quot;env&amp;quot;: &amp;quot;pi&amp;quot;&amp;lt;/code&amp;gt; to distinguish from ESP32 (&amp;lt;code&amp;gt;&amp;quot;env&amp;quot;: &amp;quot;esp32&amp;quot;&amp;lt;/code&amp;gt;).&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/system&amp;lt;/code&amp;gt; || Hardware info: IP, MAC address, disk usage, memory, modem status, GPS detail, barometric altitude, geolocation, current time&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/logs&amp;lt;/code&amp;gt; || Structured health report as JSON with sections: &amp;lt;code&amp;gt;hardware&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;measurement&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;system&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;network&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;incidents&amp;lt;/code&amp;gt;. Each entry has &amp;lt;code&amp;gt;{k, v, s}&amp;lt;/code&amp;gt; (key, value, status: ok/warn/error/info).&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/maintenance-logs&amp;lt;/code&amp;gt; || Downloads a zip bundle containing: rotating bcmeter.log files, syslog, 10 newest CSV sessions, dmesg, journalctl for bcmeter and pigpiod services, config JSON, incident log.&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/debug_mobile/status&amp;lt;/code&amp;gt; || Returns modem debug send progress (from email handler).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Measurement Control ===&lt;br /&gt;
&lt;br /&gt;
All control is dispatched through a single endpoint with an &amp;lt;code&amp;gt;action&amp;lt;/code&amp;gt; query parameter:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Method !! Endpoint !! Description&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/control?action=start&amp;lt;/code&amp;gt; || Begin measurement session. Returns 409 if time not synced, 423 if never calibrated, 424 if calibration stale (&amp;gt;28 days). Add &amp;lt;code&amp;gt;&amp;amp;force=1&amp;lt;/code&amp;gt; to override preflight checks.&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/control?action=stop&amp;lt;/code&amp;gt; || Stop measurement and save session file.&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/control?action=calibrate&amp;lt;/code&amp;gt; || Start calibration routine (returns 202 immediately — poll &amp;lt;code&amp;gt;/api/calibration&amp;lt;/code&amp;gt; for progress). Requires sampling to be stopped.&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/calibration&amp;lt;/code&amp;gt; || Calibration status: &amp;lt;code&amp;gt;{running, done, ok, elapsed_ms, log}&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/control?action=clear_error&amp;lt;/code&amp;gt; || Reset error state to ERR_NONE.&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/control?action=identify&amp;lt;/code&amp;gt; || Triggers LED identify blink pattern (Morse code spelling &amp;quot;bcmeter&amp;quot; for 30 seconds). Useful for locating a specific device when multiple units are deployed.&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/control?action=debug_mobile&amp;lt;/code&amp;gt; || Triggers modem debug email via Lambda. Requires modem present.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Configuration ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Method !! Endpoint !! Description&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/config&amp;lt;/code&amp;gt; || All settings as JSON. Each parameter includes type, value, label, tab, and description.&lt;br /&gt;
|-&lt;br /&gt;
| POST || &amp;lt;code&amp;gt;/api/config&amp;lt;/code&amp;gt; || Update settings. JSON body with key-value pairs. Accepts &amp;lt;code&amp;gt;{key: value}&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;{key: {value: ...}}&amp;lt;/code&amp;gt; format. Only changed values need to be sent. Triggers deferred modem onboarding if &amp;lt;code&amp;gt;mail_logs_to&amp;lt;/code&amp;gt; is set.&lt;br /&gt;
|-&lt;br /&gt;
| POST || &amp;lt;code&amp;gt;/api/device/rename&amp;lt;/code&amp;gt; || Set device name and hostname. Body: &amp;lt;code&amp;gt;{&amp;quot;name&amp;quot;: &amp;quot;bcmeter01&amp;quot;}&amp;lt;/code&amp;gt; (1–32 chars). Runs &amp;lt;code&amp;gt;hostnamectl set-hostname&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/control?action=synctime&amp;amp;ts=EPOCH&amp;amp;tz=IANA&amp;lt;/code&amp;gt; || Sync device clock. &amp;lt;code&amp;gt;ts&amp;lt;/code&amp;gt; = Unix timestamp, &amp;lt;code&amp;gt;tz&amp;lt;/code&amp;gt; = IANA timezone string (e.g. &amp;lt;code&amp;gt;Europe/Berlin&amp;lt;/code&amp;gt;). Applies timezone via &amp;lt;code&amp;gt;timedatectl&amp;lt;/code&amp;gt;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== WiFi Management ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Method !! Endpoint !! Description&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/wifi/scan&amp;lt;/code&amp;gt; || List nearby networks: &amp;lt;code&amp;gt;{scanning: bool, networks: [{ssid, rssi, secure}]}&amp;lt;/code&amp;gt;. Add &amp;lt;code&amp;gt;?refresh=1&amp;lt;/code&amp;gt; to trigger a new background scan.&lt;br /&gt;
|-&lt;br /&gt;
| POST || &amp;lt;code&amp;gt;/api/wifi/scan/refresh&amp;lt;/code&amp;gt; || Explicitly trigger a new WiFi scan (returns 202, or 409 if already scanning).&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/wifi/status&amp;lt;/code&amp;gt; || Current connection: &amp;lt;code&amp;gt;{mode, status, ssid, ip, rssi, quality (0-4), internet, timeSynced}&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| POST || &amp;lt;code&amp;gt;/api/wifi&amp;lt;/code&amp;gt; || Save WiFi credentials. Body: &amp;lt;code&amp;gt;{&amp;quot;ssid&amp;quot;: &amp;quot;...&amp;quot;, &amp;quot;pass&amp;quot;: &amp;quot;...&amp;quot;}&amp;lt;/code&amp;gt; (password min 8 chars).&lt;br /&gt;
|-&lt;br /&gt;
| POST || &amp;lt;code&amp;gt;/api/wifi/connect&amp;lt;/code&amp;gt; || Save credentials and initiate background connection attempt (returns 202). Password must be 8–63 chars. Body: &amp;lt;code&amp;gt;{&amp;quot;ssid&amp;quot;: &amp;quot;...&amp;quot;, &amp;quot;pass&amp;quot;: &amp;quot;...&amp;quot;}&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/wifi/connect/status&amp;lt;/code&amp;gt; || Connection progress: &amp;lt;code&amp;gt;{state: 0-3, elapsed, log, mode, ip, ssid, device_name, hostname}&amp;lt;/code&amp;gt;. States: 0=idle, 1=connecting, 2=success, 3=failed. Poll after POST to &amp;lt;code&amp;gt;/api/wifi/connect&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| POST || &amp;lt;code&amp;gt;/api/wifi/delete&amp;lt;/code&amp;gt; || Delete credentials and switch to AP mode (deferred 2s background switch).&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/ap-security&amp;lt;/code&amp;gt; || Hotspot security settings: &amp;lt;code&amp;gt;{secured: bool, password: str}&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| POST || &amp;lt;code&amp;gt;/api/ap-security&amp;lt;/code&amp;gt; || Update hotspot password. Body: &amp;lt;code&amp;gt;{&amp;quot;secured&amp;quot;: true, &amp;quot;password&amp;quot;: &amp;quot;...&amp;quot;}&amp;lt;/code&amp;gt; (min 8 chars).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Data Management ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Method !! Endpoint !! Description&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/csv&amp;lt;/code&amp;gt; || Current session CSV data. Returns header-only if no active session. Add &amp;lt;code&amp;gt;?file=FILENAME&amp;lt;/code&amp;gt; for archived files.&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/files&amp;lt;/code&amp;gt; || List stored CSV logs: &amp;lt;code&amp;gt;[{name, size, lines, date}]&amp;lt;/code&amp;gt; sorted newest first.&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/control?action=cleardata&amp;lt;/code&amp;gt; || Delete all stored log files.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Firmware Updates ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Method !! Endpoint !! Description&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/ota/status&amp;lt;/code&amp;gt; || Check if update available: &amp;lt;code&amp;gt;{available, version, url, sha256, notes, skipped}&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| POST || &amp;lt;code&amp;gt;/api/ota/check&amp;lt;/code&amp;gt; || Force check for new firmware against GitHub Releases.&lt;br /&gt;
|-&lt;br /&gt;
| POST || &amp;lt;code&amp;gt;/api/ota/skip&amp;lt;/code&amp;gt; || Skip current available update for this boot.&lt;br /&gt;
|-&lt;br /&gt;
| POST || &amp;lt;code&amp;gt;/api/ota/apply&amp;lt;/code&amp;gt; || Download and apply firmware update. Returns 409 if none pending.&lt;br /&gt;
|-&lt;br /&gt;
| POST || &amp;lt;code&amp;gt;/api/update&amp;lt;/code&amp;gt; || Direct firmware upload (.tar.gz or .zip archive). Extracts over the code directory and restarts &amp;lt;code&amp;gt;bcMeter.service&amp;lt;/code&amp;gt; via &amp;lt;code&amp;gt;systemctl&amp;lt;/code&amp;gt;. Stops active session first.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== System Operations ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Method !! Endpoint !! Description&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/control?action=reboot&amp;lt;/code&amp;gt; || End session and reboot the device (fire-and-forget thread via &amp;lt;code&amp;gt;sudo reboot&amp;lt;/code&amp;gt;).&lt;br /&gt;
|-&lt;br /&gt;
| GET || &amp;lt;code&amp;gt;/api/control?action=shutdown&amp;lt;/code&amp;gt; || Safely shut down via &amp;lt;code&amp;gt;sudo shutdown -h now&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| POST || &amp;lt;code&amp;gt;/api/email/validate&amp;lt;/code&amp;gt; || Validate email API key against the Lambda endpoint. Body: &amp;lt;code&amp;gt;{&amp;quot;api_key&amp;quot;: &amp;quot;...&amp;quot;}&amp;lt;/code&amp;gt;. Returns &amp;lt;code&amp;gt;{valid: bool, error: str}&amp;lt;/code&amp;gt;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Captive Portal ===&lt;br /&gt;
&lt;br /&gt;
These endpoints handle captive portal detection on mobile devices and redirect to the main interface in AP mode:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Endpoint !! Purpose&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/generate_204&amp;lt;/code&amp;gt; || Android captive portal check&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/hotspot-detect.html&amp;lt;/code&amp;gt; || Apple captive portal check&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/canonical.html&amp;lt;/code&amp;gt; || Firefox captive portal check&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/ncsi.txt&amp;lt;/code&amp;gt; || Windows captive portal check&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/success.txt&amp;lt;/code&amp;gt; || Generic connectivity probe (returns &amp;lt;code&amp;gt;&amp;quot;success&amp;quot;&amp;lt;/code&amp;gt;)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Static Routes ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Path !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt; || Serves the SPA frontend (&amp;lt;code&amp;gt;interface/index.html&amp;lt;/code&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/discover&amp;lt;/code&amp;gt; || Standalone device discovery page (also hostable on bcmeter.org)&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/manual/*&amp;lt;/code&amp;gt; || Static files from &amp;lt;code&amp;gt;interface/manual/&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;/current_log.csv&amp;lt;/code&amp;gt; || Legacy redirect to &amp;lt;code&amp;gt;/api/csv&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Example: Start a Measurement ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Sync time first&lt;br /&gt;
curl &amp;quot;http://bcmeter-XXXX.local/api/control?action=synctime&amp;amp;ts=$(date +%s)&amp;amp;tz=Europe/Berlin&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Start measurement&lt;br /&gt;
curl &amp;quot;http://bcmeter-XXXX.local/api/control?action=start&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Poll status&lt;br /&gt;
curl &amp;quot;http://bcmeter-XXXX.local/api/status&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Download current data&lt;br /&gt;
curl &amp;quot;http://bcmeter-XXXX.local/api/csv&amp;quot; -o measurement.csv&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=Introduction&amp;diff=409</id>
		<title>Introduction</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=Introduction&amp;diff=409"/>
		<updated>2026-06-08T10:35:01Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Reframe: bcMeter (DIY) / source-available&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Introduction ==&lt;br /&gt;
&lt;br /&gt;
The &amp;#039;&amp;#039;&amp;#039;bcMeter&amp;#039;&amp;#039;&amp;#039; is a source-available optical absorption photometer designed to measure Black Carbon (BC) aerosols — commonly known as soot — in real-time. The design is freely available for private, educational and research use (CC BY-NC 4.0); assembled instruments are offered on request. Whether you are monitoring ambient air quality in your neighborhood or measuring direct emissions from wood stoves, this device provides scientific-grade data at a fraction of the cost of reference instruments.&lt;br /&gt;
&lt;br /&gt;
The device operates &amp;quot;headless&amp;quot; — it has no built-in screen. Instead, it hosts its own website that you can access from any smartphone or computer connected to the same network.&lt;br /&gt;
&lt;br /&gt;
The software is source-available — freely available for private, educational and research use (CC BY-NC 4.0): [https://github.com/dahljo/bcmeter github.com/dahljo/bcmeter]&lt;br /&gt;
&lt;br /&gt;
=== Device Types ===&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;bcMeter (DIY)&amp;#039;&amp;#039;&amp;#039; — The source-available, self-build version. Runs on a Raspberry Pi using the open PCB design, freely available for private, educational and research use (CC BY-NC 4.0). Build your own from the open design files and the Wiki (nothing is sold).&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;bcMeter Kit&amp;#039;&amp;#039;&amp;#039; — Assembled-instrument PCB plus components for self-assembly and 3D printing. Available on request.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;bcMeter Complete&amp;#039;&amp;#039;&amp;#039; — Fully assembled, ready-to-use instrument on a compact platform that starts in seconds and updates over the air, with no microSD card or Linux system to maintain. Available on request.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;eBcMeter&amp;#039;&amp;#039;&amp;#039; — Emission measurement instrument for direct source sampling from wood-burning stoves and similar combustion sources. Uses microgram (µg) units instead of nanogram (ng). Available on request.&lt;br /&gt;
&lt;br /&gt;
=== How Does It Work? ===&lt;br /&gt;
&lt;br /&gt;
[[File:Working principle of a bcMeter.png|300px|right]]&lt;br /&gt;
&lt;br /&gt;
# Polluted air is drawn through filter paper by a pump&lt;br /&gt;
# The filter paper absorbs black carbon (BC) particles&lt;br /&gt;
# An LED shining at 880 nm passes through the filter; a sensor measures the attenuation (reduction in light intensity)&lt;br /&gt;
# A separate reference channel monitors the same LED through a clean portion of the filter, compensating for environmental changes&lt;br /&gt;
# The attenuation is converted to BC concentration (ng/m³) using Beer-Lambert law&lt;br /&gt;
# Data is saved as CSV and displayed in real-time on the web interface&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Multi-wavelength:&amp;#039;&amp;#039;&amp;#039; Optional 520 nm and 370 nm channels enable source apportionment via the Ångström Exponent (AAE) — distinguishing between fossil fuel and biomass burning sources.&lt;br /&gt;
&lt;br /&gt;
=== Sensors &amp;amp; Capabilities ===&lt;br /&gt;
&lt;br /&gt;
==== Core ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Measurement !! Sensor / Method !! Notes&lt;br /&gt;
|-&lt;br /&gt;
| Black Carbon (BC) || Optical absorption at 880 nm || Primary measurement&lt;br /&gt;
|-&lt;br /&gt;
| Source apportionment || 520 nm, 370 nm || Ångström Exponent&lt;br /&gt;
|-&lt;br /&gt;
| Temperature / Humidity || SHT4x ||&lt;br /&gt;
|-&lt;br /&gt;
| Airflow || Omron D6F differential pressure || Pump flow rate&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Optional Hardware ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Measurement !! Sensor / Method !! Notes&lt;br /&gt;
|-&lt;br /&gt;
| Temperature / Humidity / Pressure || BME280 || Barometric altitude&lt;br /&gt;
|-&lt;br /&gt;
| PM2.5 / PM10 || Sensirion SPS30 || Particulate matter&lt;br /&gt;
|-&lt;br /&gt;
| GPS || AT6668 UART || Position, altitude, speed&lt;br /&gt;
|-&lt;br /&gt;
| 4G Connectivity || SIM7080G LTE-M modem || Remote data upload&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=Main_Page&amp;diff=408</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=Main_Page&amp;diff=408"/>
		<updated>2026-06-08T10:34:59Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Reframe: bcMeter (DIY) / source-available&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Welcome to the [https://bcmeter.org bcmeter.org] Wiki ==&lt;br /&gt;
&lt;br /&gt;
The bcMeter wiki is the technical documentation hub for the bcMeter platform — an optical absorption photometer for measuring Black Carbon (BC) aerosols in real-time. The platform spans the source-available &amp;#039;&amp;#039;&amp;#039;bcMeter (DIY)&amp;#039;&amp;#039;&amp;#039; (build it yourself) and the ready-to-use &amp;#039;&amp;#039;&amp;#039;bcMeter Kit, bcMeter Complete and eBcMeter&amp;#039;&amp;#039;&amp;#039; instruments.&lt;br /&gt;
&lt;br /&gt;
Whether you are setting up a new device, configuring measurements, or building your own unit, this wiki covers everything you need.&lt;br /&gt;
&lt;br /&gt;
== Getting Started ==&lt;br /&gt;
&lt;br /&gt;
* [[Introduction]] — What is bcMeter, how it works, capabilities&lt;br /&gt;
* [[Setup]] — Hardware requirements, first boot, WiFi configuration&lt;br /&gt;
* [[Interface]] — Web dashboard overview, status indicators, chart controls&lt;br /&gt;
&lt;br /&gt;
== Using bcMeter ==&lt;br /&gt;
&lt;br /&gt;
* [[Configuration]] — All settings: network, measurement, device, email&lt;br /&gt;
* [[Maintenance]] — Filter changes, calibration, data management&lt;br /&gt;
* [[Troubleshooting]] — Common issues and solutions&lt;br /&gt;
* [[Best practices]] — Environment, sampling, signal quality&lt;br /&gt;
&lt;br /&gt;
== Technical Reference ==&lt;br /&gt;
&lt;br /&gt;
* [[Developer mode]] — Hidden developer settings, hardware tuning&lt;br /&gt;
* [[API reference]] — REST API endpoints for automation and integration&lt;br /&gt;
* [[CSV data format]] — Column definitions and data structure&lt;br /&gt;
* [[Serial commands]] — USB debug interface&lt;br /&gt;
&lt;br /&gt;
== bcMeter (DIY) — build it yourself ==&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;These pages document the source-available bcMeter (DIY) — the Raspberry-Pi-based design, freely available for private, educational and research use (CC BY-NC 4.0), built from open design files (nothing is sold). The assembled bcMeter Kit, Complete and eBcMeter use a different hardware design.&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
* [[Working principle]] — Optical measurement principle&lt;br /&gt;
* [[Bill of material]] — Component list and costs (bcMeter DIY)&lt;br /&gt;
* [[Device assembly]] — Hardware build instructions (bcMeter DIY)&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
&lt;br /&gt;
The bcMeter software is source-available — freely available for private, educational and research use (CC BY-NC 4.0): &amp;#039;&amp;#039;&amp;#039;[https://github.com/dahljo/bcmeter github.com/dahljo/bcmeter]&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The codebase includes the web [[Interface|interface]], [[API reference|REST API]], measurement engine, and all device management functionality.&lt;br /&gt;
&lt;br /&gt;
== Contact ==&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Technical inquiries &amp;amp; devices:&amp;#039;&amp;#039;&amp;#039; Jonas Dahl — jd@bcmeter.org&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Black carbon science &amp;amp; air quality:&amp;#039;&amp;#039;&amp;#039; Axel Friedrich — af@bcmeter.org&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Project website:&amp;#039;&amp;#039;&amp;#039; [https://bcmeter.org bcmeter.org]&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=File:Bcmeter_interface14.jpg&amp;diff=407</id>
		<title>File:Bcmeter interface14.jpg</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=File:Bcmeter_interface14.jpg&amp;diff=407"/>
		<updated>2026-05-02T20:30:59Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Bcmwiki uploaded a new version of File:Bcmeter interface14.jpg&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Update bcMeter ESP32 light-mode screenshot (May 2026)&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=File:Bcmeter_interface7.jpg&amp;diff=406</id>
		<title>File:Bcmeter interface7.jpg</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=File:Bcmeter_interface7.jpg&amp;diff=406"/>
		<updated>2026-05-02T20:30:59Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Bcmwiki uploaded a new version of File:Bcmeter interface7.jpg&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Update bcMeter ESP32 light-mode screenshot (May 2026)&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=File:Bcmeter_interface_factoryreset.jpg&amp;diff=405</id>
		<title>File:Bcmeter interface factoryreset.jpg</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=File:Bcmeter_interface_factoryreset.jpg&amp;diff=405"/>
		<updated>2026-05-02T20:30:59Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Bcmwiki uploaded a new version of File:Bcmeter interface factoryreset.jpg&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Update bcMeter ESP32 light-mode screenshot (May 2026)&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=File:Bcmeter_interface9.jpg&amp;diff=404</id>
		<title>File:Bcmeter interface9.jpg</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=File:Bcmeter_interface9.jpg&amp;diff=404"/>
		<updated>2026-05-02T20:30:58Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Bcmwiki uploaded a new version of File:Bcmeter interface9.jpg&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Update bcMeter ESP32 light-mode screenshot (May 2026)&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=File:Bcmeter_interface_email.jpg&amp;diff=403</id>
		<title>File:Bcmeter interface email.jpg</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=File:Bcmeter_interface_email.jpg&amp;diff=403"/>
		<updated>2026-05-02T20:30:58Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Bcmwiki uploaded a new version of File:Bcmeter interface email.jpg&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Update bcMeter ESP32 light-mode screenshot (May 2026)&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=File:Bcmeter_interface_device.jpg&amp;diff=402</id>
		<title>File:Bcmeter interface device.jpg</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=File:Bcmeter_interface_device.jpg&amp;diff=402"/>
		<updated>2026-05-02T20:30:58Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Bcmwiki uploaded a new version of File:Bcmeter interface device.jpg&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Update bcMeter ESP32 light-mode screenshot (May 2026)&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=File:Bcmeter_interface_measurement.jpg&amp;diff=401</id>
		<title>File:Bcmeter interface measurement.jpg</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=File:Bcmeter_interface_measurement.jpg&amp;diff=401"/>
		<updated>2026-05-02T20:30:57Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Bcmwiki uploaded a new version of File:Bcmeter interface measurement.jpg&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Update bcMeter ESP32 light-mode screenshot (May 2026)&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=File:Bcmeter_interface17.jpg&amp;diff=400</id>
		<title>File:Bcmeter interface17.jpg</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=File:Bcmeter_interface17.jpg&amp;diff=400"/>
		<updated>2026-05-02T20:30:57Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Bcmwiki uploaded a new version of File:Bcmeter interface17.jpg&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Update bcMeter ESP32 light-mode screenshot (May 2026)&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=File:Bcmeter_interface_network.jpg&amp;diff=399</id>
		<title>File:Bcmeter interface network.jpg</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=File:Bcmeter_interface_network.jpg&amp;diff=399"/>
		<updated>2026-05-02T20:30:29Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Bcmwiki uploaded a new version of File:Bcmeter interface network.jpg&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Update bcMeter ESP32 light-mode screenshot (May 2026)&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=File:Bcmeter_interface_onboarding2.jpg&amp;diff=398</id>
		<title>File:Bcmeter interface onboarding2.jpg</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=File:Bcmeter_interface_onboarding2.jpg&amp;diff=398"/>
		<updated>2026-05-02T20:30:28Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Bcmwiki uploaded a new version of File:Bcmeter interface onboarding2.jpg&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Update bcMeter ESP32 light-mode screenshot (May 2026)&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=File:Bcmeter_interface_onboarding1.jpg&amp;diff=397</id>
		<title>File:Bcmeter interface onboarding1.jpg</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=File:Bcmeter_interface_onboarding1.jpg&amp;diff=397"/>
		<updated>2026-05-02T20:30:28Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Bcmwiki uploaded a new version of File:Bcmeter interface onboarding1.jpg&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Update bcMeter ESP32 light-mode screenshot (May 2026)&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=File:Bcmeter_interface14.jpg&amp;diff=396</id>
		<title>File:Bcmeter interface14.jpg</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=File:Bcmeter_interface14.jpg&amp;diff=396"/>
		<updated>2026-05-02T20:28:24Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Bcmwiki uploaded a new version of File:Bcmeter interface14.jpg&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Update bcMeter ESP32 light-mode screenshot (May 2026)&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=File:Bcmeter_interface7.jpg&amp;diff=395</id>
		<title>File:Bcmeter interface7.jpg</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=File:Bcmeter_interface7.jpg&amp;diff=395"/>
		<updated>2026-05-02T20:28:23Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Bcmwiki uploaded a new version of File:Bcmeter interface7.jpg&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Update bcMeter ESP32 light-mode screenshot (May 2026)&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=File:Bcmeter_interface_factoryreset.jpg&amp;diff=394</id>
		<title>File:Bcmeter interface factoryreset.jpg</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=File:Bcmeter_interface_factoryreset.jpg&amp;diff=394"/>
		<updated>2026-05-02T20:28:23Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Bcmwiki uploaded a new version of File:Bcmeter interface factoryreset.jpg&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Update bcMeter ESP32 light-mode screenshot (May 2026)&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=File:Bcmeter_interface9.jpg&amp;diff=393</id>
		<title>File:Bcmeter interface9.jpg</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=File:Bcmeter_interface9.jpg&amp;diff=393"/>
		<updated>2026-05-02T20:28:23Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Bcmwiki uploaded a new version of File:Bcmeter interface9.jpg&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Update bcMeter ESP32 light-mode screenshot (May 2026)&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=File:Bcmeter_interface_email.jpg&amp;diff=392</id>
		<title>File:Bcmeter interface email.jpg</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=File:Bcmeter_interface_email.jpg&amp;diff=392"/>
		<updated>2026-05-02T20:28:22Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Bcmwiki uploaded a new version of File:Bcmeter interface email.jpg&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Update bcMeter ESP32 light-mode screenshot (May 2026)&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=File:Bcmeter_interface_device.jpg&amp;diff=391</id>
		<title>File:Bcmeter interface device.jpg</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=File:Bcmeter_interface_device.jpg&amp;diff=391"/>
		<updated>2026-05-02T20:28:22Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Bcmwiki uploaded a new version of File:Bcmeter interface device.jpg&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Update bcMeter ESP32 light-mode screenshot (May 2026)&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=File:Bcmeter_interface_measurement.jpg&amp;diff=390</id>
		<title>File:Bcmeter interface measurement.jpg</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=File:Bcmeter_interface_measurement.jpg&amp;diff=390"/>
		<updated>2026-05-02T20:28:22Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Bcmwiki uploaded a new version of File:Bcmeter interface measurement.jpg&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Update bcMeter ESP32 light-mode screenshot (May 2026)&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=File:Bcmeter_interface17.jpg&amp;diff=389</id>
		<title>File:Bcmeter interface17.jpg</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=File:Bcmeter_interface17.jpg&amp;diff=389"/>
		<updated>2026-05-02T20:28:22Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Bcmwiki uploaded a new version of File:Bcmeter interface17.jpg&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Update bcMeter ESP32 light-mode screenshot (May 2026)&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=File:Bcmeter_interface18.jpg&amp;diff=388</id>
		<title>File:Bcmeter interface18.jpg</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=File:Bcmeter_interface18.jpg&amp;diff=388"/>
		<updated>2026-05-02T20:28:21Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Bcmwiki uploaded a new version of File:Bcmeter interface18.jpg&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Update bcMeter ESP32 light-mode screenshot (May 2026)&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=File:Bcmeter_interface1.jpg&amp;diff=387</id>
		<title>File:Bcmeter interface1.jpg</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=File:Bcmeter_interface1.jpg&amp;diff=387"/>
		<updated>2026-05-02T20:28:21Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Bcmwiki uploaded a new version of File:Bcmeter interface1.jpg&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Update bcMeter ESP32 light-mode screenshot (May 2026)&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=File:Bcmeter_interface_network.jpg&amp;diff=386</id>
		<title>File:Bcmeter interface network.jpg</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=File:Bcmeter_interface_network.jpg&amp;diff=386"/>
		<updated>2026-05-02T20:28:21Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Bcmwiki uploaded a new version of File:Bcmeter interface network.jpg&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Update bcMeter ESP32 light-mode screenshot (May 2026)&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=File:Bcmeter_interface_onboarding2.jpg&amp;diff=385</id>
		<title>File:Bcmeter interface onboarding2.jpg</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=File:Bcmeter_interface_onboarding2.jpg&amp;diff=385"/>
		<updated>2026-05-02T20:28:21Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Bcmwiki uploaded a new version of File:Bcmeter interface onboarding2.jpg&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Update bcMeter ESP32 light-mode screenshot (May 2026)&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=File:Bcmeter_interface_onboarding1.jpg&amp;diff=384</id>
		<title>File:Bcmeter interface onboarding1.jpg</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=File:Bcmeter_interface_onboarding1.jpg&amp;diff=384"/>
		<updated>2026-05-02T20:28:20Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Bcmwiki uploaded a new version of File:Bcmeter interface onboarding1.jpg&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Update bcMeter ESP32 light-mode screenshot (May 2026)&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=Developer_mode&amp;diff=383</id>
		<title>Developer mode</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=Developer_mode&amp;diff=383"/>
		<updated>2026-05-02T20:15:57Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Polish English manual/wiki wording&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Developer Mode ==&lt;br /&gt;
&lt;br /&gt;
The bcMeter interface has a hidden developer mode for hardware tuning and diagnostics. &amp;#039;&amp;#039;&amp;#039;Changes in developer mode affect hardware directly&amp;#039;&amp;#039;&amp;#039; and can make measurements unusable when set incorrectly. Use it only for support, development, or device-specific provisioning.&lt;br /&gt;
&lt;br /&gt;
=== Activating Developer Mode ===&lt;br /&gt;
&lt;br /&gt;
# Open &amp;#039;&amp;#039;&amp;#039;Settings&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
# Click the &amp;#039;&amp;#039;&amp;#039;device name&amp;#039;&amp;#039;&amp;#039; text next to &amp;quot;Configuration&amp;quot; &amp;#039;&amp;#039;&amp;#039;7 times within 3 seconds&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
# The name changes to include &amp;lt;code&amp;gt;[DEV]&amp;lt;/code&amp;gt;.&lt;br /&gt;
# A new &amp;#039;&amp;#039;&amp;#039;⚠ Dev&amp;#039;&amp;#039;&amp;#039; tab appears in the settings panel.&lt;br /&gt;
&lt;br /&gt;
Developer mode is active for the current page session and is reset when the page is reloaded.&lt;br /&gt;
&lt;br /&gt;
=== Developer Tab Layout ===&lt;br /&gt;
&lt;br /&gt;
The Developer tab opens with a warning banner:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote style=&amp;quot;background:#fff3cd;padding:8px 16px;border-radius:4px;&amp;quot;&amp;gt;Developer mode — changes affect hardware directly. Save only if you know what you are doing.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Settings are grouped by namespace. The values below match the current ESP32 firmware defaults in &amp;lt;code&amp;gt;cfgstore.cpp&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== BC Smoothing Algorithm ====&lt;br /&gt;
&lt;br /&gt;
The first control selects the BC smoothing algorithm. This setting is stored as &amp;lt;code&amp;gt;bc_filter&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Value !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;median3&amp;lt;/code&amp;gt; (default) || 3-sample median filter. Good default for rejecting isolated outliers.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ema&amp;lt;/code&amp;gt; || Exponential moving average. Smoother trend, slower response to abrupt changes.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;kalman&amp;lt;/code&amp;gt; || Adaptive Kalman-style smoothing based on signal dynamics.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Calibration (&amp;lt;code&amp;gt;dev:calibration&amp;lt;/code&amp;gt;) ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parameter !! Description !! Default&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;sample_spot_diameter&amp;lt;/code&amp;gt; || Sample spot diameter in cm. Used in BC mass concentration calculations. || 0.4&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;filter_scattering_factor&amp;lt;/code&amp;gt; || Filter scattering factor used by the optical correction model. || 1.39&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;device_specific_correction_factor&amp;lt;/code&amp;gt; || Per-device correction factor from lab comparison or provisioning. || 1.0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Optical (&amp;lt;code&amp;gt;dev:optical&amp;lt;/code&amp;gt;) ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parameter !! Description !! Default&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;burst_measurement&amp;lt;/code&amp;gt; || LED is only enabled during the final seconds of a sample cycle. Experimental power/thermal mode. || false&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;adc_block_samples&amp;lt;/code&amp;gt; || ADC samples per sensor/reference block. Higher values reduce noise and increase capture time. || 256&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;led_duty_cycle_370nm&amp;lt;/code&amp;gt; || UV LED brightness/PWM duty for 370 nm channel. || 255&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;led_duty_cycle_520nm&amp;lt;/code&amp;gt; || Green LED brightness/PWM duty for 520 nm channel. || 255&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;led_duty_cycle_880nm&amp;lt;/code&amp;gt; || IR LED brightness/PWM duty for 880 nm channel. || 100&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;cal_k_370nm&amp;lt;/code&amp;gt; || Calibration factor for the 370 nm channel. || 1.0&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;cal_k_520nm&amp;lt;/code&amp;gt; || Calibration factor for the 520 nm channel. || 1.0&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;cal_k_880nm&amp;lt;/code&amp;gt; || Calibration factor for the 880 nm channel. || 1.0&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;shadow_factor&amp;lt;/code&amp;gt; || Weingartner shadow factor. Typical examples: 1.1 diesel, 1.2 urban, 1.5 biomass. || 1.2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Pump (&amp;lt;code&amp;gt;dev:pump&amp;lt;/code&amp;gt;) ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parameter !! Description !! Default&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;pump_dutycycle&amp;lt;/code&amp;gt; || Base pump power/PWM duty. || 20&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;max_pump_duty&amp;lt;/code&amp;gt; || Maximum pump duty cycle. || 255&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;min_pump_duty&amp;lt;/code&amp;gt; || Minimum pump duty cycle. || 1&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;min_airflow_ml&amp;lt;/code&amp;gt; || Minimum airflow before stall recovery starts, in ml/min. || 70&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;twelvevolt_duty&amp;lt;/code&amp;gt; || 12V pump output duty cycle. || 20&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;reverse_dutycycle&amp;lt;/code&amp;gt; || Reverse pump duty-cycle handling for hardware variants. || false&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;disable_pump_control&amp;lt;/code&amp;gt; || Disable internal pump control loop. Use only with external control hardware. || false&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;TWELVEVOLT_ENABLE&amp;lt;/code&amp;gt; || Enable 12V power output. || false&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;log_pump_duty&amp;lt;/code&amp;gt; || Write pump duty cycle into the CSV per sample. || false&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Auto Flow Control (&amp;lt;code&amp;gt;dev:afc&amp;lt;/code&amp;gt;) ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parameter !! Description !! Default&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;afc_bc_low&amp;lt;/code&amp;gt; || BC concentration below which AFC moves toward maximum flow. || 300 ng/m³&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;afc_bc_high&amp;lt;/code&amp;gt; || BC concentration above which AFC moves toward minimum flow. || 2000 ng/m³&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;afc_flow_low&amp;lt;/code&amp;gt; || Minimum airflow when AFC is active. || 0.05 L/min&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;afc_flow_high&amp;lt;/code&amp;gt; || Maximum airflow when AFC is active. || 0.7 L/min&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;afc_slope_gain&amp;lt;/code&amp;gt; || Flow boost per 100 ng/min downward BC trend. || 0.05&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Hardware (&amp;lt;code&amp;gt;dev:hardware&amp;lt;/code&amp;gt;) ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parameter !! Description !! Default&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;airflow_sensor&amp;lt;/code&amp;gt; || Airflow sensor is installed and should be used. || true&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;af_sensor_type&amp;lt;/code&amp;gt; || Airflow sensor type: 0 = P0001A1, 1 = P0010A2. || 1&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;enable_wifi&amp;lt;/code&amp;gt; || WiFi connectivity is available. || true&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;iot_enable&amp;lt;/code&amp;gt; || 4G / IoT modem connectivity is available. || true&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;show_undervoltage_warning&amp;lt;/code&amp;gt; || Show warning when the optical 12V rail / ADC is not detected. || false&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== System (&amp;lt;code&amp;gt;dev:system&amp;lt;/code&amp;gt;) ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parameter !! Description !! Default&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;num_channels&amp;lt;/code&amp;gt; || Number of optical wavelength channels. || 1&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;is_ebcMeter&amp;lt;/code&amp;gt; || Direct emission measurement mode. Changes units and emission-oriented behavior. || false&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;device_name&amp;lt;/code&amp;gt; || Device hostname/name used for mDNS and UI display. || bcMeter&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;heating&amp;lt;/code&amp;gt; || Enable heating hardware if installed. || false&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;use_display&amp;lt;/code&amp;gt; || Device has an attached display. || false&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;email_service_password&amp;lt;/code&amp;gt; || Mail service password for DIY/development devices. Provisioned devices normally already have this set. || email_service_password&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;onboarding_step_one&amp;lt;/code&amp;gt; || Phase 1 onboarding complete: contact email and WiFi setup. || false&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;onboarding_step_two&amp;lt;/code&amp;gt; || Phase 2 onboarding complete: calibration and data sharing choice. || false&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;onboarding_email_sent&amp;lt;/code&amp;gt; || Welcome/access email has already been sent. || false&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;team_upload_interval&amp;lt;/code&amp;gt; || Cloud/team upload interval in hours when data sharing is enabled. || 1&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;bcmeter_team_email&amp;lt;/code&amp;gt; || Contact email used for bcMeter team workflows. || empty&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;last_cal_time&amp;lt;/code&amp;gt; || Timestamp of the last successful calibration. || never&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Onboarding State ===&lt;br /&gt;
&lt;br /&gt;
The current firmware stores onboarding progress with separate flags:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;onboarding_step_one&amp;lt;/code&amp;gt;: WiFi/email phase completed.&lt;br /&gt;
* &amp;lt;code&amp;gt;onboarding_step_two&amp;lt;/code&amp;gt;: calibration/data-sharing phase completed.&lt;br /&gt;
* &amp;lt;code&amp;gt;onboarding_email_sent&amp;lt;/code&amp;gt;: welcome email has already been sent.&lt;br /&gt;
&lt;br /&gt;
The browser also uses local storage and cookies for temporary &amp;quot;Skip for now&amp;quot; behavior. &amp;quot;Don&amp;#039;t show again&amp;quot; writes the matching onboarding step flag to the device.&lt;br /&gt;
&lt;br /&gt;
=== Development Build Detection ===&lt;br /&gt;
&lt;br /&gt;
When the device is running a development build, the status API returns &amp;lt;code&amp;gt;&amp;quot;env&amp;quot;:&amp;quot;dev&amp;quot;&amp;lt;/code&amp;gt;. The interface shows a red banner:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote style=&amp;quot;background:#dc3545;color:#fff;padding:8px 16px;border-radius:4px;&amp;quot;&amp;gt;DEVELOPMENT BUILD — connected to dev backend&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 12V Power Warning ===&lt;br /&gt;
&lt;br /&gt;
If the optical ADC is not detected, the interface can show a 12V warning:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote style=&amp;quot;background:#fff3cd;padding:8px 16px;border-radius:4px;&amp;quot;&amp;gt;&amp;#039;&amp;#039;&amp;#039;⚠ 12V Power Missing&amp;#039;&amp;#039;&amp;#039; — The optical ADC is not detected. Optics and light sensors will not function. Pump and airflow control may be limited by hardware state.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Development Device Variants ===&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;bcmeter-dev&amp;lt;/code&amp;gt; Raspberry Pi codebase is useful for development and older prototypes, but it differs from the ESP32 production firmware. Device-specific differences should be treated as implementation details of the same function:&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Networking:&amp;#039;&amp;#039;&amp;#039; Raspberry Pi builds may use Flask and NetworkManager, while ESP32 builds use the embedded web server and ESP-IDF WiFi stack.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Optics/ADC:&amp;#039;&amp;#039;&amp;#039; Pi builds may reference ADS8344E or MCP342X hardware; current ESP32 V2 builds use ADS1220-based optical acquisition.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Firmware updates:&amp;#039;&amp;#039;&amp;#039; Pi development devices may update through OS/GitHub release workflows, while ESP32 devices use OTA firmware images.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Sensors:&amp;#039;&amp;#039;&amp;#039; Development devices may expose DS18B20 or other prototype sensors that are not present on every ESP32 unit.&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=Maintenance&amp;diff=382</id>
		<title>Maintenance</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=Maintenance&amp;diff=382"/>
		<updated>2026-05-02T20:15:57Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Polish English manual/wiki wording&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Maintenance Procedures ==&lt;br /&gt;
&lt;br /&gt;
Open maintenance functions with the &amp;#039;&amp;#039;&amp;#039;Maintenance&amp;#039;&amp;#039;&amp;#039; button in the navigation bar. The modal has cards for device management, system status, time synchronization, and geolocation.&lt;br /&gt;
&lt;br /&gt;
=== Filter Change Procedure ===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;The filter is not identical on both sides.&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
* Identify the side with markings (black line, dot, or circles).&lt;br /&gt;
* The &amp;#039;&amp;#039;&amp;#039;marked side must face UP&amp;#039;&amp;#039;&amp;#039; (towards the LEDs/light source in the upper optical chamber).&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Warning:&amp;#039;&amp;#039;&amp;#039; Incorrect orientation (marked side down) results in ~30% measurement error.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Procedure:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
# Stop any running session.&lt;br /&gt;
# Unscrew the top cap of the optical chamber.&lt;br /&gt;
# Remove the saturated filter.&lt;br /&gt;
# Insert a new filter with &amp;#039;&amp;#039;&amp;#039;markings facing up&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
# Screw the cap back on (hand-tight).&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Check hose&amp;#039;&amp;#039;&amp;#039; (if used): check that the air hose is still connected to the inlet port.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Run [[Maintenance#Calibration|Calibration]] (required).&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
=== Calibration ===&lt;br /&gt;
&lt;br /&gt;
Filters vary slightly in optical density. Calibration balances the sensor signal against the reference signal for the specific filter currently installed.&lt;br /&gt;
&lt;br /&gt;
# Go to &amp;#039;&amp;#039;&amp;#039;Maintenance&amp;#039;&amp;#039;&amp;#039; &amp;gt; &amp;#039;&amp;#039;&amp;#039;Calibrate Device&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
# Check that a &amp;#039;&amp;#039;&amp;#039;new and clean filter&amp;#039;&amp;#039;&amp;#039; is installed.&lt;br /&gt;
# Click &amp;quot;Yes.&amp;quot;&lt;br /&gt;
# A progress bar appears. The device adjusts LED intensity per channel to find stable reference and sensor readings.&lt;br /&gt;
# Wait for &amp;quot;Calibration Successful&amp;quot; before starting a new log.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Technical detail:&amp;#039;&amp;#039;&amp;#039; Calibration determines the per-channel correction factor K = Ref_avg / Sen_avg and stores it with the LED duty cycle values. Current ESP32 builds use ADS1220 block averaging for the optical readings. Calibration typically takes 30–60 seconds.&lt;br /&gt;
&lt;br /&gt;
=== Data Management ===&lt;br /&gt;
&lt;br /&gt;
Data is stored on the device&amp;#039;s internal flash storage (LittleFS) and persists across reboots.&lt;br /&gt;
&lt;br /&gt;
Click &amp;#039;&amp;#039;&amp;#039;Log Files&amp;#039;&amp;#039;&amp;#039; to open the data manager. The modal lists all stored sessions:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Column !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;Log&amp;#039;&amp;#039;&amp;#039; || Session name or filename (e.g., &amp;lt;code&amp;gt;bcmeter_20260312_2126.csv&amp;lt;/code&amp;gt;). &amp;quot;Current Session&amp;quot; shows the active log.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;Size&amp;#039;&amp;#039;&amp;#039; || File size in KB, or number of data points for the current session.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;Download&amp;#039;&amp;#039;&amp;#039; || Download button for each individual log file.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Below the table:&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Clear All Data&amp;#039;&amp;#039;&amp;#039; — Deletes all stored log files. Requires confirmation.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Remove Empty Logs&amp;#039;&amp;#039;&amp;#039; — Cleans up zero-byte or near-empty files from aborted sessions.&lt;br /&gt;
&lt;br /&gt;
Stored log files are downloaded as CSV for analysis. The dashboard&amp;#039;s &amp;#039;&amp;#039;&amp;#039;Download View&amp;#039;&amp;#039;&amp;#039; button can additionally export the currently visible chart view as CSV, PNG, or SVG. CSV files use semicolon separation with dot as decimal divider.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Backup:&amp;#039;&amp;#039;&amp;#039; Internal storage is not archival. Download data to a secure location regularly.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Storage management:&amp;#039;&amp;#039;&amp;#039; The device has ~2 MB internal flash for logs. Warning at 512 KB free, critical at 32 KB. Old logs are auto-deleted when critical threshold is reached. Empty files are cleaned on startup.&lt;br /&gt;
&lt;br /&gt;
=== Device Management ===&lt;br /&gt;
&lt;br /&gt;
==== Routine Maintenance ====&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Calibrate Device:&amp;#039;&amp;#039;&amp;#039; Adjusts LED duty cycles. Required after each filter change.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;View System Status:&amp;#039;&amp;#039;&amp;#039; Opens a structured status report for diagnosing issues. Entries are grouped by category: hardware, measurement, system, network.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Download Logs:&amp;#039;&amp;#039;&amp;#039; Downloads the structured system status report as a text file for troubleshooting or support.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Identify Device:&amp;#039;&amp;#039;&amp;#039; Blinks the device LED for about two minutes. Use this to find the right unit when more than one bcMeter is nearby.&lt;br /&gt;
&lt;br /&gt;
==== System Operations ====&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Reboot Device:&amp;#039;&amp;#039;&amp;#039; Restarts the device.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Shutdown Device:&amp;#039;&amp;#039;&amp;#039; Powers down before unplugging. Use this before disconnecting power. If the device loses power during an active session, it resumes measurement on the next boot.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Manual Firmware Update:&amp;#039;&amp;#039;&amp;#039; Opens a dialog to upload a firmware file (.bin). The device also checks for updates a few times a day.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Factory Reset:&amp;#039;&amp;#039;&amp;#039; Permanently erases all measurement logs, WiFi credentials, calibration data, and device settings. A slide-to-confirm gesture is required. The device reboots into factory state.&lt;br /&gt;
&lt;br /&gt;
==== Firmware Update Notifications ====&lt;br /&gt;
&lt;br /&gt;
When the device detects a newer firmware version, an &amp;#039;&amp;#039;&amp;#039;Update Available&amp;#039;&amp;#039;&amp;#039; modal appears showing:&lt;br /&gt;
* The new version number and current version&lt;br /&gt;
* Release notes (if available)&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Update Now&amp;#039;&amp;#039;&amp;#039; button to apply the update immediately (with progress bar)&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Skip for now&amp;#039;&amp;#039;&amp;#039; to dismiss and update later&lt;br /&gt;
&lt;br /&gt;
Updates download over WiFi and are applied automatically. The device reboots after a successful update.&lt;br /&gt;
&lt;br /&gt;
=== System Status ===&lt;br /&gt;
&lt;br /&gt;
Shows device information:&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Device ID:&amp;#039;&amp;#039;&amp;#039; Unique hardware identifier (MAC address).&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Software Version:&amp;#039;&amp;#039;&amp;#039; Installed firmware version.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Free Memory:&amp;#039;&amp;#039;&amp;#039; Available system memory.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Last Calibration:&amp;#039;&amp;#039;&amp;#039; Timestamp of the most recent calibration.&lt;br /&gt;
&lt;br /&gt;
=== Time Synchronization ===&lt;br /&gt;
&lt;br /&gt;
Accurate timestamps need a correct device clock, especially on devices without internet access.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Browser Time / Device Time:&amp;#039;&amp;#039;&amp;#039; Displayed for comparison.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Sync:&amp;#039;&amp;#039;&amp;#039; If mismatch exceeds 10 seconds, a sync button appears to synchronize the device clock with your browser.&lt;br /&gt;
&lt;br /&gt;
Devices connected to the internet sync automatically via NTP. Modem-based time sync (CLTS) is also supported when a 4G modem is connected.&lt;br /&gt;
&lt;br /&gt;
=== Geolocation ===&lt;br /&gt;
&lt;br /&gt;
When location services are active (Settings &amp;gt; Measurement &amp;gt; Location), the Geolocation card shows:&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Location:&amp;#039;&amp;#039;&amp;#039; Latitude/longitude with source (GPS, cell tower, or IP-based) and accuracy indicator.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Altitude (barometric):&amp;#039;&amp;#039;&amp;#039; Derived from the pressure sensor.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Altitude (GPS) &amp;amp; Speed:&amp;#039;&amp;#039;&amp;#039; Shown when a GPS module is connected and has a fix.&lt;br /&gt;
&lt;br /&gt;
The location input accepts common coordinate formats: &amp;lt;code&amp;gt;48.2082, 16.3738&amp;lt;/code&amp;gt; — &amp;lt;code&amp;gt;48.2082 16.3738&amp;lt;/code&amp;gt; — &amp;lt;code&amp;gt;(48.2082; 16.3738)&amp;lt;/code&amp;gt;.&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
	<entry>
		<id>https://bcmeter.org/wiki/index.php?title=Interface&amp;diff=381</id>
		<title>Interface</title>
		<link rel="alternate" type="text/html" href="https://bcmeter.org/wiki/index.php?title=Interface&amp;diff=381"/>
		<updated>2026-05-02T20:15:57Z</updated>

		<summary type="html">&lt;p&gt;Bcmwiki: Polish English manual/wiki wording&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Web Interface Overview ==&lt;br /&gt;
&lt;br /&gt;
The bcMeter web interface is a local dashboard for measurement data, device control, and settings. Open it from a browser on the same network as the device.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Try the live demo:&amp;#039;&amp;#039;&amp;#039; [https://bcmeter.org/demo/ bcmeter.org/demo]&lt;br /&gt;
&lt;br /&gt;
=== Dashboard Elements ===&lt;br /&gt;
&lt;br /&gt;
The main screen has five areas:&lt;br /&gt;
&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Control Bar&amp;#039;&amp;#039;&amp;#039; — Buttons to Start/Stop measurement, access Log Files, Settings, and Maintenance. On mobile or narrow screens, the bar collapses into a hamburger menu (☰).&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Status Panel&amp;#039;&amp;#039;&amp;#039; — Device state (with color-coded status dot), filter loading indicator, and time synchronization status.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Statistics&amp;#039;&amp;#039;&amp;#039; — 1h Average, Session Average, and Peak Value. The Peak Value card includes the timestamp of the peak and a &amp;#039;&amp;#039;&amp;#039;Reset&amp;#039;&amp;#039;&amp;#039; button.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Live Plot&amp;#039;&amp;#039;&amp;#039; — Black Carbon concentration over time.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Plot Controls&amp;#039;&amp;#039;&amp;#039; — Download, zoom reset, axis scaling, log selection, Y-axis assignment, resampling, and denoising.&lt;br /&gt;
&lt;br /&gt;
==== Dark Mode ====&lt;br /&gt;
&lt;br /&gt;
A dark mode toggle (moon/sun icon) is in the top-right corner of the navigation bar. The preference is saved in the browser.&lt;br /&gt;
&lt;br /&gt;
=== Status Indicators ===&lt;br /&gt;
&lt;br /&gt;
==== Device Status ====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Status !! Meaning&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;Ready&amp;#039;&amp;#039;&amp;#039; || Device is idle. Pump is off.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;Initializing&amp;#039;&amp;#039;&amp;#039; || Pump is priming and the optical chamber is warming up. Data is not yet recorded.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;Running&amp;#039;&amp;#039;&amp;#039; || Active measurement. Data is being saved.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;Error&amp;#039;&amp;#039;&amp;#039; || System error detected. Open System Status or download logs in the Maintenance menu.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Time Sync Status ====&lt;br /&gt;
&lt;br /&gt;
The status bar shows whether the device clock is synced. If it shows &amp;quot;Time: not synced&amp;quot; in red, use &amp;#039;&amp;#039;&amp;#039;Maintenance &amp;gt; Time Synchronization&amp;#039;&amp;#039;&amp;#039; to sync the device clock with your browser.&lt;br /&gt;
&lt;br /&gt;
==== Filter Loading Status ====&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Filter&amp;quot; indicator shows how much of the filter strip is loaded. The color changes with loading level:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Color !! Loading !! Meaning&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#28a745;color:#fff&amp;quot; | &amp;#039;&amp;#039;&amp;#039;Green&amp;#039;&amp;#039;&amp;#039; || 0–30% || Filter is clean. Signal quality is optimal.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#ffc107&amp;quot; | &amp;#039;&amp;#039;&amp;#039;Orange&amp;#039;&amp;#039;&amp;#039; || 30–70% || Loading increasing. Mathematical compensation is active. Prepare a replacement.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#dc3545;color:#fff&amp;quot; | &amp;#039;&amp;#039;&amp;#039;Red&amp;#039;&amp;#039;&amp;#039; || 70–85% || Heavily loaded. Compensation becomes less reliable. Replace soon. Email alert sent every 12h when &amp;gt;70%.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;background:#343a40;color:#fff&amp;quot; | &amp;#039;&amp;#039;&amp;#039;Dark&amp;#039;&amp;#039;&amp;#039; || 85%+ || Near saturation. Replace immediately.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Alert Modals ====&lt;br /&gt;
&lt;br /&gt;
The interface opens alert modals for these measurement conditions:&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Filter Loading High&amp;#039;&amp;#039;&amp;#039; — Filter loading exceeds the configured threshold. Replace the filter paper soon.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;No Airflow Detected&amp;#039;&amp;#039;&amp;#039; — Appears when airflow drops to near zero during measurement. Check pump tubing and connections.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;High Humidity&amp;#039;&amp;#039;&amp;#039; — Warning when humidity inside the device is too high.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Low Disk Space&amp;#039;&amp;#039;&amp;#039; — Warning when internal storage is running low.&lt;br /&gt;
&lt;br /&gt;
These alerts appear once per condition and can be dismissed with &amp;quot;Got it.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== Data Visualization ===&lt;br /&gt;
&lt;br /&gt;
==== Plot Behavior ====&lt;br /&gt;
&lt;br /&gt;
The graph shows measurements as a time series. The optical signal is analog, so the raw line is usually jagged. Smoothed values show the trend more clearly.&lt;br /&gt;
&lt;br /&gt;
After starting a measurement, the graph needs about 3–4 samples before it appears. At the default 300s (5 min) sample interval, first data appears after 15–20 minutes.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Zoom:&amp;#039;&amp;#039;&amp;#039; Click and drag to zoom in. Double-click to reset.&lt;br /&gt;
&lt;br /&gt;
==== Plot Controls ====&lt;br /&gt;
&lt;br /&gt;
Below the live plot:&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Download View:&amp;#039;&amp;#039;&amp;#039; Export current view as CSV, PNG, or SVG.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Reset Zoom:&amp;#039;&amp;#039;&amp;#039; Restore default view after zooming.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Axis Scaling:&amp;#039;&amp;#039;&amp;#039; Manually override automatic Y-axis scaling (min/max per axis) when peaks compress the view.&lt;br /&gt;
&lt;br /&gt;
==== View Log ====&lt;br /&gt;
&lt;br /&gt;
Dropdown for the current session or a previous log file stored on the device.&lt;br /&gt;
&lt;br /&gt;
==== Y-Axis Controls ====&lt;br /&gt;
&lt;br /&gt;
Each axis row (Y1, Y2, and added axes) includes:&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Toggle switch&amp;#039;&amp;#039;&amp;#039; — Show or hide the axis on the chart.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Variable selector&amp;#039;&amp;#039;&amp;#039; — Choose which parameter to display (see [[Interface#Plot Parameters|Plot Parameters]]).&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Resample slider&amp;#039;&amp;#039;&amp;#039; — Averages consecutive samples before plotting. &amp;quot;Off&amp;quot; shows every sample; higher values reduce visual noise and data density.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Denoise mode&amp;#039;&amp;#039;&amp;#039; — Segmented control with four options:&lt;br /&gt;
** &amp;#039;&amp;#039;&amp;#039;Raw&amp;#039;&amp;#039;&amp;#039; — Unfiltered signal, showing every data point as-is.&lt;br /&gt;
** &amp;#039;&amp;#039;&amp;#039;Med&amp;#039;&amp;#039;&amp;#039; — Median filter (default, highlighted in teal). Good default noise reduction.&lt;br /&gt;
** &amp;#039;&amp;#039;&amp;#039;EMA&amp;#039;&amp;#039;&amp;#039; — Exponential Moving Average. Gives more weight to recent values, good for tracking trends.&lt;br /&gt;
** &amp;#039;&amp;#039;&amp;#039;ONA&amp;#039;&amp;#039;&amp;#039; — Optimized Noise Average.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Denoise slider&amp;#039;&amp;#039;&amp;#039; — Adjusts the strength/window size for the selected denoise mode. The number next to the slider shows the current value.&lt;br /&gt;
** &amp;#039;&amp;#039;Direct emission monitoring:&amp;#039;&amp;#039; Keep below 4 for fast response.&lt;br /&gt;
** &amp;#039;&amp;#039;Ambient monitoring:&amp;#039;&amp;#039; Higher values are acceptable when a smoother trend is more important than fast response.&lt;br /&gt;
&lt;br /&gt;
==== Adding Extra Axes ====&lt;br /&gt;
&lt;br /&gt;
Click &amp;#039;&amp;#039;&amp;#039;+ Add axis&amp;#039;&amp;#039;&amp;#039; below Y2 to add more Y-axes. Each extra axis has the same controls. Use extra axes to compare values such as BC concentration, temperature, and airflow in one chart.&lt;br /&gt;
&lt;br /&gt;
=== Plot Parameters ===&lt;br /&gt;
&lt;br /&gt;
These parameters can be assigned to any Y-axis:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parameter !! Description&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;Reference (880nm)&amp;#039;&amp;#039;&amp;#039; || Light intensity from the 880nm LED through the clean portion of the filter — baseline for comparison. Optional: 520nm, 370nm if multi-wavelength hardware installed.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;Sensor (880nm)&amp;#039;&amp;#039;&amp;#039; || Light intensity after passing through the particle-loaded spot.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;Attenuation (880nm)&amp;#039;&amp;#039;&amp;#039; || Calculated reduction in light intensity caused by absorbing particles.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;BC Unfiltered (880nm)&amp;#039;&amp;#039;&amp;#039; || Real-time black carbon concentration without smoothing.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;Black Carbon (880nm)&amp;#039;&amp;#039;&amp;#039; || BC concentration in ng/m³, with rolling average applied.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;Relative Load&amp;#039;&amp;#039;&amp;#039; || Filter spot saturation level (%), indicating when replacement is needed.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;Ångström Exponent&amp;#039;&amp;#039;&amp;#039; || Ratio indicating aerosol source characteristics (requires multi-wavelength hardware).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;Temperature (°C)&amp;#039;&amp;#039;&amp;#039; || Internal operating temperature — important for measurement stability.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;Humidity (%)&amp;#039;&amp;#039;&amp;#039; || Relative humidity inside the device (if sensor equipped).&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;Air Flow (l/min)&amp;#039;&amp;#039;&amp;#039; || Current airflow rate through the filter (if flow sensor equipped).&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Bcmwiki</name></author>
	</entry>
</feed>