diff --git a/CLAUDE.md b/CLAUDE.md index ba053a5..722162b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,7 +4,13 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## Project Overview -This is a PlatformIO-based ESP32 Arduino project for communicating with a NextPM (NPM) particulate matter sensor over serial connection. The project reads PM1, PM2.5, and PM10 measurements in both µg/m³ and particles per liter (pcs/L). +This is a **simplified, educational** PlatformIO-based ESP32 Arduino project for communicating with a NextPM (NPM) particulate matter sensor over serial connection. The project reads PM1, PM2.5, and PM10 mass concentration measurements in µg/m³. + +**Educational Focus:** +- Extensively commented code to help students understand serial communication protocols +- Simplified implementation focusing only on PM concentration readings (particle counts removed) +- Clear step-by-step documentation of the sensor communication process +- Non-blocking timing pattern demonstration ## Build and Development Commands @@ -46,46 +52,55 @@ pio run --target clean ### Serial Communication Protocol -The NextPM sensor uses a binary protocol with checksums. Communication follows a request-response pattern with specific message formats: +The NextPM sensor uses a binary protocol with checksums. Communication follows a request-response pattern: -**Message Structure:** -- Header (2 bytes): Command identifier (e.g., `0x81 0x16`) +**Message Structure (16 bytes total):** +- Header (2 bytes): `0x81 0x12` (concentration response identifier) - State (1 byte): Device state bits -- Data (variable): Response payload +- Data (12 bytes): 6 values × 2 bytes each + - Bytes 0-5: N1, N2.5, N10 particle counts (not used in this simplified version) + - Bytes 6-11: PM1, PM2.5, PM10 mass concentrations - Checksum (1 byte): Sum of all bytes mod 0x100 must equal 0 -**State Machine Enums:** -The code uses multiple enums (`NPM_waiting_for_4`, `NPM_waiting_for_8`, `NPM_waiting_for_16`) to track parsing state for different response types (4, 8, or 16 bytes total). - ### Key Functions -**Initialization (`powerOnTestNPM`):** -- Waits 15 seconds for sensor startup -- Queries sensor state -- Starts sensor if stopped -- Reads firmware version and temperature/humidity +**`checksum_valid()`** +- Validates 16-byte messages using checksum algorithm +- Returns true if sum of all bytes modulo 256 equals 0 -**Measurement (`fetchSensorNPM_1min`):** -- Sends concentration command (1-minute averaged readings) -- Parses 16-byte response containing 6 values: - - N1, N2.5, N10 (particle counts as pcs/L) - - PM1, PM2.5, PM10 (mass concentrations as µg/m³ × 10) -- Validates checksum before accepting data +**`send_concentration_command()`** +- Sends 3-byte command sequence: `{0x81, 0x12, 0x6D}` +- Requests 1-minute averaged concentration readings -**Loop Behavior:** -- Reads sensor every 60 seconds (configurable via `interval` constant) -- Non-blocking timing using `millis()` +**`read_concentration()`** +- Main sensor reading function with 11 documented steps +- Sends command, waits for response (3-second timeout) +- Validates header and checksum +- Extracts PM1, PM2.5, PM10 values from data bytes +- Converts scaled values (÷10) to actual µg/m³ +- Displays results on serial monitor + +**`setup()`** +- Initializes USB serial (115200 baud) for debugging +- Initializes sensor serial (115200 baud, 8E1 parity) +- Waits 15 seconds for sensor power-up + +**`loop()`** +- Non-blocking timing implementation using `millis()` +- Reads sensor every 10 seconds (configurable via `interval`) +- Demonstrates proper Arduino timing patterns ### File Organization -- `src/main.cpp`: Main application logic, NPM protocol implementation, sensor state machine -- `src/utils.h`: Protocol constants, enums, checksum validation prototypes -- `src/utils.cpp`: Utility functions for checksum validation and NPM command transmission +- `src/main.cpp`: Complete application in single file with extensive educational comments - `platformio.ini`: PlatformIO configuration for ESP32 +- `CLAUDE.md`: Developer guidance for AI assistance +- `README.md`: User documentation and getting started guide ## Important Notes - The sensor requires a 3-second timeout for serial responses -- All particle concentration values from the sensor are scaled (PM values by 10, temperature/humidity by 100) -- The `nextpmconnected` flag prevents infinite loops if sensor disconnects -- Comments are in French in some sections of the code +- PM values from the sensor are scaled by 10 (e.g., 25.3 µg/m³ sent as 253) +- The 15-second startup delay is critical - sensor won't respond if queried too early +- All comments are in English for educational purposes +- Code emphasizes readability and learning over performance optimization diff --git a/README.md b/README.md new file mode 100644 index 0000000..79be6a1 --- /dev/null +++ b/README.md @@ -0,0 +1,369 @@ +# ESP32 NextPM Sensor Reader + +An educational ESP32 project for reading particulate matter (PM) concentrations from a NextPM sensor via UART serial communication. This simplified implementation is designed to help students understand serial communication protocols, binary data parsing, and sensor integration. + +## 📋 Table of Contents + +- [About Particulate Matter](#about-particulate-matter) +- [Features](#features) +- [Hardware Requirements](#hardware-requirements) +- [Wiring Connections](#wiring-connections) +- [Software Requirements](#software-requirements) +- [Installation](#installation) +- [Usage](#usage) +- [Understanding the Code](#understanding-the-code) +- [Expected Output](#expected-output) +- [Troubleshooting](#troubleshooting) +- [Learning Objectives](#learning-objectives) +- [License](#license) + +## About Particulate Matter + +Particulate Matter (PM) refers to tiny particles suspended in the air that can be harmful to human health. This project measures three types: + +- **PM1.0**: Particles with diameter < 1.0 micrometers +- **PM2.5**: Particles with diameter < 2.5 micrometers (common air quality metric) +- **PM10**: Particles with diameter < 10 micrometers + +Values are reported in **µg/m³** (micrograms per cubic meter). + +## Features + +- ✅ Reads PM1.0, PM2.5, and PM10 concentrations from NextPM sensor +- ✅ Uses UART serial communication with 8E1 parity +- ✅ Binary protocol with checksum validation +- ✅ Non-blocking timing pattern with `millis()` +- ✅ Extensively commented code for educational purposes +- ✅ Real-time data output to Serial Monitor +- ✅ Error handling and debugging support + +## Hardware Requirements + +| Component | Specification | +|-----------|--------------| +| **Microcontroller** | ESP32 development board | +| **Sensor** | NextPM (NPM) particulate matter sensor | +| **Connections** | UART (Serial) communication | +| **Power Supply** | USB (for ESP32) + sensor power supply | + +## Wiring Connections + +Connect the NextPM sensor to your ESP32 as follows: + +| NextPM Sensor | ESP32 Board | +|---------------|-------------| +| TX (Transmit) | GPIO 39 (RX) | +| RX (Receive) | GPIO 32 (TX) | +| GND | GND | +| VCC | External power supply (check sensor voltage requirements) | + +**Important Notes:** +- The NextPM sensor typically requires an external power supply (check your sensor's datasheet) +- ESP32 GPIO 39 is input-only (perfect for RX) +- Do not connect sensor VCC to ESP32 3.3V unless your sensor specifically supports it + +### Connection Diagram + +``` +┌──────────────┐ ┌──────────────┐ +│ │ │ │ +│ NextPM │ │ ESP32 │ +│ Sensor │ │ │ +│ │ │ │ +│ TX ──┼──────────────┼─→ GPIO 39 │ +│ │ │ (RX) │ +│ RX ←─┼──────────────┼── GPIO 32 │ +│ │ │ (TX) │ +│ │ │ │ +│ GND ──┼──────────────┼── GND │ +│ │ │ │ +│ VCC ──┼─→ External │ │ +│ │ Power │ │ +└──────────────┘ └──────────────┘ +``` + +## Software Requirements + +- **PlatformIO** - Modern embedded development platform + - Recommended: Use PlatformIO IDE extension for VS Code + - Alternative: PlatformIO Core CLI + +- **VS Code** (optional but recommended) + - Download from: https://code.visualstudio.com/ + +## Installation + +### Step 1: Install PlatformIO + +**Option A: VS Code Extension (Recommended)** +1. Open VS Code +2. Go to Extensions (Ctrl+Shift+X) +3. Search for "PlatformIO IDE" +4. Click Install + +**Option B: Command Line** +```bash +pip install platformio +``` + +### Step 2: Clone the Repository + +```bash +git clone http://gitea.aircarto.fr/PaulVua/esp32_NPM_only.git +cd esp32_NPM_only +``` + +### Step 3: Open in PlatformIO + +**Using VS Code:** +1. Open the project folder in VS Code +2. PlatformIO will automatically detect the project + +**Using CLI:** +```bash +pio project init +``` + +## Usage + +### Building the Project + +```bash +pio run +``` + +### Uploading to ESP32 + +1. Connect your ESP32 to your computer via USB +2. Upload the code: + +```bash +pio run --target upload +``` + +### Monitoring Serial Output + +View real-time sensor readings: + +```bash +pio device monitor +``` + +Or combine upload and monitor: + +```bash +pio run --target upload && pio device monitor +``` + +**Exit the monitor:** Press `Ctrl+C` + +### Cleaning Build Files + +```bash +pio run --target clean +``` + +## Understanding the Code + +The code is organized into clear sections with extensive comments: + +### Main Components + +1. **Hardware Configuration** (`main.cpp:18-30`) + - Serial port definitions + - GPIO pin assignments + +2. **Helper Functions** (`main.cpp:50-107`) + - `checksum_valid()`: Validates sensor messages + - `send_concentration_command()`: Sends read request to sensor + - `print_data()`: Debug output for troubleshooting + +3. **Sensor Reading Function** (`main.cpp:109-242`) + - `read_concentration()`: 11-step process documented in detail + - Protocol parsing and data extraction + - Error handling with timeout protection + +4. **Arduino Functions** + - `setup()`: One-time initialization (`main.cpp:244-286`) + - `loop()`: Non-blocking repeated execution (`main.cpp:288-318`) + +### Key Concepts Demonstrated + +- **Binary Serial Protocol**: Reading structured binary data +- **Checksum Validation**: Ensuring data integrity +- **Non-blocking Timing**: Using `millis()` instead of `delay()` +- **UART Communication**: 8E1 parity configuration +- **Error Handling**: Timeout protection and validation checks +- **Data Scaling**: Converting sensor's fixed-point integers to floats + +## Expected Output + +After uploading and opening the Serial Monitor, you should see: + +``` +=== NextPM Sensor Reader === +Simplified version - Concentration readings only +Averaging: 60 seconds, Update: every 10 seconds + +Waiting 15 seconds for sensor initialization... +Sensor ready. Starting measurements... + +--- Reading NextPM Concentrations --- + +=== Particulate Matter Concentrations === +PM1.0: 12.3 µg/m³ +PM2.5: 18.7 µg/m³ +PM10: 24.5 µg/m³ +====================================== +``` + +Readings update every 10 seconds. + +## Troubleshooting + +### No sensor response + +**Symptom:** `ERROR: No response from sensor` + +**Solutions:** +1. Check wiring connections (TX/RX crossed correctly?) +2. Verify sensor has power +3. Wait for full 15-second initialization period +4. Check sensor is compatible with 115200 baud, 8E1 parity + +### Invalid checksum errors + +**Symptom:** `ERROR: Invalid checksum` + +**Solutions:** +1. Check for electrical noise on signal wires +2. Verify correct parity setting (8E1) +3. Ensure ground connection between ESP32 and sensor +4. Try shorter wire lengths + +### Header not found + +**Symptom:** `ERROR: Header not found` + +**Solutions:** +1. Sensor may not be responding correctly +2. Check baud rate matches (115200) +3. Verify sensor is in measurement mode +4. Power cycle the sensor + +### Can't upload to ESP32 + +**Symptom:** Upload fails or port not found + +**Solutions:** +1. Press and hold BOOT button on ESP32 during upload +2. Check USB cable (must support data, not just power) +3. Install USB drivers for your ESP32 board +4. Try a different USB port + +## Learning Objectives + +This project helps students learn: + +### Communication Protocols +- Understanding binary serial communication +- Request-response patterns +- Header/state/data/checksum message structure +- Big-endian vs little-endian byte ordering + +### Embedded Systems Concepts +- UART configuration (baud rate, parity, stop bits) +- GPIO pin assignment and usage +- Non-blocking vs blocking code patterns +- Timeout handling in real-time systems + +### Data Processing +- Binary data parsing and extraction +- Checksum validation algorithms +- Fixed-point to floating-point conversion +- Byte manipulation with `word()` function + +### Arduino/ESP32 Patterns +- Proper use of `setup()` and `loop()` +- Non-blocking timing with `millis()` +- Multiple serial ports (Serial vs Serial1) +- Error handling and debugging techniques + +## Configuration + +### Adjusting Read Interval + +To change how often the sensor is read, modify the `interval` constant: + +```cpp +const long interval = 10000; // Read every 10 seconds (in milliseconds) +``` + +### Changing GPIO Pins + +To use different pins, modify these definitions: + +```cpp +#define PM_SERIAL_RX 39 // Change RX pin +#define PM_SERIAL_TX 32 // Change TX pin +``` + +**Note:** GPIO 39 is input-only on ESP32, so it's ideal for RX. + +## Project Structure + +``` +esp32_NPM_only/ +├── src/ +│ └── main.cpp # Main application with extensive comments +├── include/ # Header files (currently empty) +├── lib/ # Custom libraries (currently empty) +├── test/ # Unit tests (currently empty) +├── platformio.ini # PlatformIO configuration +├── CLAUDE.md # AI assistant guidance +└── README.md # This file +``` + +## NextPM Protocol Reference + +### Concentration Request Command + +| Byte | Value | Description | +|------|-------|-------------| +| 0 | 0x81 | Command prefix | +| 1 | 0x12 | Concentration request | +| 2 | 0x6D | Checksum | + +### Concentration Response (16 bytes) + +| Bytes | Description | Used? | +|-------|-------------|-------| +| 0-1 | Header (0x81 0x12) | ✅ For validation | +| 2 | State byte | ✅ Read but not parsed | +| 3-4 | N1.0 particle count | ❌ Not used | +| 5-6 | N2.5 particle count | ❌ Not used | +| 7-8 | N10 particle count | ❌ Not used | +| 9-10 | PM1.0 × 10 | ✅ Extracted | +| 11-12 | PM2.5 × 10 | ✅ Extracted | +| 13-14 | PM10 × 10 | ✅ Extracted | +| 15 | Checksum | ✅ Validated | + +## Contributing + +This is an educational project. Suggestions for improving code clarity and educational value are welcome! + +## License + +This project is provided for educational purposes. + +## Acknowledgments + +- NextPM sensor documentation +- ESP32 Arduino core community +- Students and educators using this project + +--- + +**Questions or Issues?** + +If you encounter problems or have questions about the code, please open an issue on the repository.