Files
HIL_setup/I2C_emulation_flow.md
2026-02-09 16:36:29 +01:00

125 lines
4.0 KiB
Markdown

# SCD30 HIL Framework Documentation
## 1. System Architecture
The system consists of three layers. The PC handles the **Logic**, the Emulator handles the **Signal Bridge**, and the Target runs the **Production Code**.
```mermaid
graph TD
subgraph "PC (Python)"
A[Global Test Script] <--> B[HIL Library]
end
subgraph "Emulator ESP32 (Slave)"
C[UART Driver] <--> D[I2C Slave Driver]
end
subgraph "Target ESP32 (Master)"
E[SCD30 Driver Component] <--> F[Application Logic]
end
B <-- "921600 Baud Serial" --> C
D <-- "I2C Bus (Clock Stretching)" --> E
```
---
## 2. The Logic Workflow (Sequence)
This is the most critical part: how we synchronize a slow PC with a fast I2C bus.
```mermaid
sequenceDiagram
participant PC as Python (Global Script)
participant Slave as ESP32 Emulator (Slave)
participant Master as ESP32 Target (Master)
Note over Master: App calls scd30_read_data()
Master->>Slave: I2C Write: [0x03, 0x00] (Read Cmd)
activate Slave
Slave->>PC: UART Send: "CMD:0300\n"
Note right of Slave: Slave STRETCHES Clock (SCL LOW)
Note over PC: Lib parses CMD, calculates<br/>Floats & CRCs
PC->>Slave: UART Send: "DATA:010203...\n"
Slave->>Slave: Parse Hex to Bytes
Slave->>Master: Load I2C Buffer & Release SCL
deactivate Slave
Master->>Slave: I2C Read: 18 Bytes
Note over Master: App parses bytes to Float
Master->>PC: UART Print: "CO2: 450.00..."
Note over PC: Global script captures & logs to CSV
```
---
## 3. Component Breakdown
### A. Target ESP32 (`scd30.c`)
* **Role:** Acts as the I2C Master. It believes it is talking to a real SCD30.
* **Key Logic:** * **Initialization:** Configures `scl_wait_us = 150000`. This is the timeout for how long it will wait while the Slave is stretching the clock.
* **Parsing:** Takes 18 bytes and reconstructs three 32-bit floats. It skips every 3rd byte because that is the CRC.
* **Polling:** It continuously asks "Are you ready?" (0x0202) until the Emulator (PC) replies with "Yes" (0x01).
### B. Emulator ESP32 (`main.c`)
* **Role:** The "Transparent Bridge."
* **Key Logic:**
* **Event-Driven:** Uses a callback (`on_recv_done`) to notify a task that the Master has sent a command.
* **Clock Stretching:** By not loading the TX buffer immediately, the hardware automatically holds the SCL line low. This pauses the Master's CPU.
* **Synchronization:** It bridges the I2C domain (microseconds) to the PC domain (milliseconds).
### C. Python Library (`hil_lib.py`)
* **Role:** The "Sensor Physics Engine."
* **Key Logic:**
* **SCD30 Protocol Emulation:** It knows that if the Master sends `0202`, it must reply with `000103` (Ready).
* **Data Formatting:** Converts human-readable numbers (like `450.0`) into the raw hex bytes and CRCs the ESP32 expects.
### D. Global Script (`run_test.py`)
* **Role:** The "Test Orchestrator."
* **Key Logic:**
* **Iteration:** Loops through a list of test values.
* **Verification:** It acts as a "Man-in-the-Middle." It knows what value it *sent* to the sensor and reads the Target's serial to see what value the Target *received*.
* **Persistence:** Saves the input/output pair into a `.csv` for audit and validation.
---
## 4. Hardware Connectivity
| Connection | Requirement | Why? |
| --- | --- | --- |
| **SDA to SDA** | 4.7kΩ Pull-up to 3.3V | Data signal integrity |
| **SCL to SCL** | 4.7kΩ Pull-up to 3.3V | Clock signal integrity |
| **GND to GND** | Solid Copper Wire | Reference voltage for signals |
| **UART 0** | USB Cable to PC | Command/Data bridge |
---
## 5. Troubleshooting the Workflow
* **Symptom:** Target says `Failed to read data`.
* **Cause:** Python script took longer than 200ms to respond OR `scl_wait_us` is too low.
* **Symptom:** Target reads `0.00`.
* **Cause:** The CRC check failed in the C code, or the Python script sent the bytes in the wrong order.
* **Symptom:** CSV only has Column 1, not Column 2.
* **Cause:** The Target ESP32 is not printing to the correct Serial port, or the baud rate is mismatched.