Update documentation: Add README and revise CLAUDE.md
- Created comprehensive README.md with: - Project overview and features - Hardware requirements and wiring diagram - Installation and usage instructions - Detailed troubleshooting guide - Learning objectives for students - NextPM protocol reference - Updated CLAUDE.md to reflect: - Simplified educational implementation - Removal of particle counts - Current function structure - Educational focus and objectives 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
71
CLAUDE.md
71
CLAUDE.md
@@ -4,7 +4,13 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
|||||||
|
|
||||||
## Project Overview
|
## 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
|
## Build and Development Commands
|
||||||
|
|
||||||
@@ -46,46 +52,55 @@ pio run --target clean
|
|||||||
|
|
||||||
### Serial Communication Protocol
|
### 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:**
|
**Message Structure (16 bytes total):**
|
||||||
- Header (2 bytes): Command identifier (e.g., `0x81 0x16`)
|
- Header (2 bytes): `0x81 0x12` (concentration response identifier)
|
||||||
- State (1 byte): Device state bits
|
- 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
|
- 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
|
### Key Functions
|
||||||
|
|
||||||
**Initialization (`powerOnTestNPM`):**
|
**`checksum_valid()`**
|
||||||
- Waits 15 seconds for sensor startup
|
- Validates 16-byte messages using checksum algorithm
|
||||||
- Queries sensor state
|
- Returns true if sum of all bytes modulo 256 equals 0
|
||||||
- Starts sensor if stopped
|
|
||||||
- Reads firmware version and temperature/humidity
|
|
||||||
|
|
||||||
**Measurement (`fetchSensorNPM_1min`):**
|
**`send_concentration_command()`**
|
||||||
- Sends concentration command (1-minute averaged readings)
|
- Sends 3-byte command sequence: `{0x81, 0x12, 0x6D}`
|
||||||
- Parses 16-byte response containing 6 values:
|
- Requests 1-minute averaged concentration readings
|
||||||
- N1, N2.5, N10 (particle counts as pcs/L)
|
|
||||||
- PM1, PM2.5, PM10 (mass concentrations as µg/m³ × 10)
|
|
||||||
- Validates checksum before accepting data
|
|
||||||
|
|
||||||
**Loop Behavior:**
|
**`read_concentration()`**
|
||||||
- Reads sensor every 60 seconds (configurable via `interval` constant)
|
- Main sensor reading function with 11 documented steps
|
||||||
- Non-blocking timing using `millis()`
|
- 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
|
### File Organization
|
||||||
|
|
||||||
- `src/main.cpp`: Main application logic, NPM protocol implementation, sensor state machine
|
- `src/main.cpp`: Complete application in single file with extensive educational comments
|
||||||
- `src/utils.h`: Protocol constants, enums, checksum validation prototypes
|
|
||||||
- `src/utils.cpp`: Utility functions for checksum validation and NPM command transmission
|
|
||||||
- `platformio.ini`: PlatformIO configuration for ESP32
|
- `platformio.ini`: PlatformIO configuration for ESP32
|
||||||
|
- `CLAUDE.md`: Developer guidance for AI assistance
|
||||||
|
- `README.md`: User documentation and getting started guide
|
||||||
|
|
||||||
## Important Notes
|
## Important Notes
|
||||||
|
|
||||||
- The sensor requires a 3-second timeout for serial responses
|
- 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)
|
- PM values from the sensor are scaled by 10 (e.g., 25.3 µg/m³ sent as 253)
|
||||||
- The `nextpmconnected` flag prevents infinite loops if sensor disconnects
|
- The 15-second startup delay is critical - sensor won't respond if queried too early
|
||||||
- Comments are in French in some sections of the code
|
- All comments are in English for educational purposes
|
||||||
|
- Code emphasizes readability and learning over performance optimization
|
||||||
|
|||||||
369
README.md
Normal file
369
README.md
Normal file
@@ -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.
|
||||||
Reference in New Issue
Block a user