更新项目文档和传感器模块
主要更改: 1. 新增使用手册: - AI算法更新指南 - HTPA60x40传感器升级指南 - 环境配置教程 2. 传感器模块优化: - HTPA60x40dR1L0.9传感器集成 - HTPAd32x32L1k7传感器更新 - 传感器配置文档完善 3. 项目文档整理: - 删除过期的433MHz使用指南 - 更新README文档结构 - 完善配置教程链接 目标:完善项目文档,优化传感器集成
This commit is contained in:
parent
00c4b9d098
commit
0548c1555f
54
firefly_esp32/main/Sensor/HTPA60x40dR1L0.9/CMakeLists.txt
Normal file
54
firefly_esp32/main/Sensor/HTPA60x40dR1L0.9/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
# CMakeLists.txt for HTPA60x40dR1L0.9/0.8 Thermal Imaging Sensor
|
||||||
|
|
||||||
|
# Add the source files for HTPA60x40 sensor
|
||||||
|
set(HTPA60x40_SOURCES
|
||||||
|
"HTPA_Sensor60x40.cpp"
|
||||||
|
"htpa60x40_lookuptable.cpp"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add the header files
|
||||||
|
set(HTPA60x40_HEADERS
|
||||||
|
"HTPA_Sensor60x40.h"
|
||||||
|
"HTPA60x40dR1L0.9.h"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Include directories
|
||||||
|
set(HTPA60x40_INCLUDE_DIRS
|
||||||
|
"."
|
||||||
|
"../.."
|
||||||
|
"../../Module"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create a component library for HTPA60x40
|
||||||
|
# This allows the sensor to be easily included in the main project
|
||||||
|
add_library(htpa60x40_sensor STATIC ${HTPA60x40_SOURCES})
|
||||||
|
|
||||||
|
# Set include directories for the library
|
||||||
|
target_include_directories(htpa60x40_sensor PUBLIC ${HTPA60x40_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
# Link against required ESP-IDF components
|
||||||
|
target_link_libraries(htpa60x40_sensor
|
||||||
|
idf::freertos
|
||||||
|
idf::esp_common
|
||||||
|
idf::esp_timer
|
||||||
|
idf::driver
|
||||||
|
idf::log
|
||||||
|
)
|
||||||
|
|
||||||
|
# Set compile options
|
||||||
|
target_compile_options(htpa60x40_sensor PRIVATE
|
||||||
|
-Wall
|
||||||
|
-Wextra
|
||||||
|
-Wno-unused-parameter
|
||||||
|
-Wno-missing-field-initializers
|
||||||
|
)
|
||||||
|
|
||||||
|
# Define preprocessor macros for the sensor
|
||||||
|
target_compile_definitions(htpa60x40_sensor PRIVATE
|
||||||
|
HTPA60x40_SENSOR_ENABLED=1
|
||||||
|
HTPA_SENSOR_TYPE="HTPA60x40dR1L0.9"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Export the library for use by parent CMakeLists.txt
|
||||||
|
set(HTPA60x40_LIBRARY htpa60x40_sensor PARENT_SCOPE)
|
||||||
|
set(HTPA60x40_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} PARENT_SCOPE)
|
||||||
125
firefly_esp32/main/Sensor/HTPA60x40dR1L0.9/HTPA60x40dR1L0.9.h
Normal file
125
firefly_esp32/main/Sensor/HTPA60x40dR1L0.9/HTPA60x40dR1L0.9.h
Normal file
|
|
@ -0,0 +1,125 @@
|
||||||
|
#ifndef _HTPA60x40_DEF_H
|
||||||
|
#define _HTPA60x40_DEF_H
|
||||||
|
|
||||||
|
// DEVICE ADDRESS
|
||||||
|
#define SENSOR_ADDRESS_60x40 0x1A
|
||||||
|
#define EEPROM_ADDRESS_60x40 0x50
|
||||||
|
|
||||||
|
// I2C CLOCK
|
||||||
|
#define CLOCK_SENSOR_60x40 1000000
|
||||||
|
#define CLOCK_EEPROM_60x40 400000
|
||||||
|
|
||||||
|
// SETTING
|
||||||
|
#define PTAT_BUFFER_SIZE_60x40 10
|
||||||
|
#define VDD_BUFFER_SIZE_60x40 10
|
||||||
|
#define ELOFFSETS_BUFFER_SIZE_60x40 10
|
||||||
|
#define ELOFFSETS_FILTER_START_DELAY_60x40 100
|
||||||
|
#define START_WITH_BLOCK_60x40 4
|
||||||
|
#define READ_ELOFFSET_EVERYX_60x40 10
|
||||||
|
|
||||||
|
// WIFI SETTING
|
||||||
|
#define UDP_PACKET_LENGTH_60x40 4808 // 60*40*2 + header
|
||||||
|
#define LAST_UDP_PACKET_LENGTH_60x40 4804
|
||||||
|
#define ACCESSPOINTNAME_60x40 "HTPA60x40dR1L0.9"
|
||||||
|
#define ACCESSPOINTKEY_60x40 "heimannsensor"
|
||||||
|
|
||||||
|
// PARAMETER LOOKUPTABLE
|
||||||
|
#define TABLENUMBER_60x40 154 // table number of this sensor type (may need adjustment)
|
||||||
|
#define PCSCALEVAL_60x40 100000000 // scale value for PixC (see formula in datasheet)
|
||||||
|
#define NROFTAELEMENTS_60x40 12 // number of columns (ambient temperature steps)
|
||||||
|
#define NROFADELEMENTS_60x40 1588 // number of rows (digit steps)
|
||||||
|
#define TAEQUIDISTANCE_60x40 100 // distance between two columns
|
||||||
|
#define ADEQUIDISTANCE_60x40 64 // distance between two rows
|
||||||
|
#define ADEXPBITS_60x40 6
|
||||||
|
#define TABLEOFFSET_60x40 4096 // table offset in digits
|
||||||
|
|
||||||
|
// SENSOR INFO - HTPA60x40 specific parameters
|
||||||
|
#define NUMBER_OF_PIXEL_60x40 2400 // number of all pixels (60*40)
|
||||||
|
#define NUMBER_OF_BLOCKS_60x40 10 // number of blocks for each half (increased for 60x40)
|
||||||
|
#define PIXEL_PER_BLOCK_60x40 120 // number of pixels of each block (2400/20 blocks total)
|
||||||
|
#define PIXEL_PER_COLUMN_60x40 60 // number of pixels of each column
|
||||||
|
#define PIXEL_PER_ROW_60x40 40 // number of pixels of each row
|
||||||
|
#define ROW_PER_BLOCK_60x40 4 // number of rows of each block
|
||||||
|
#define ALLOWED_DEADPIX_60x40 12 // max. 0.5% of the pixel number (2400*0.005)
|
||||||
|
#define ATC_ACTIVE_60x40 0 // 1 - sensor has... / 0 - sensor hasn't a cyclops
|
||||||
|
#define ATC_POS_60x40 0 // position of the cyclops in block reading order
|
||||||
|
#define PTAT_POS_60x40 0 // position of PTAT in block reading order
|
||||||
|
#define VDD_POS_60x40 0 // position of VDD in block reading order
|
||||||
|
#define PTAT_VDD_SWITCH_60x40 1 // 1 - PTAT and VDD alternate after each pic / 0 - not
|
||||||
|
#define BLOCK_LENGTH_60x40 242 // number of char in each block (120*2 + 2)
|
||||||
|
#define DATA_POS_60x40 2 // position of first data byte in each block
|
||||||
|
|
||||||
|
// SENSOR REGISTER (same as 32x32)
|
||||||
|
#define TOP_HALF_60x40 0x0A // data of top half
|
||||||
|
#define BOTTOM_HALF_60x40 0x0B // data of bot half
|
||||||
|
#define CONFIGURATION_REGISTER_60x40 0x01 // configuration register (WRITE only)
|
||||||
|
// | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|
||||||
|
// | RFU | Block | Start | VDD_MEAS | BLIND | WAKEUP |
|
||||||
|
#define STATUS_REGISTER_60x40 0x02 // address of status register (read only)
|
||||||
|
// | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|
||||||
|
// | RFU | Block | RFU | VDD_MEAS | BLIND | EOC |
|
||||||
|
#define TRIM_REGISTER1_60x40 0x03 // address for trim register 1 (WRITE only)
|
||||||
|
// | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|
||||||
|
// | RFU | REF_CAL | MBIT |
|
||||||
|
#define TRIM_REGISTER2_60x40 0x04 // address for trim register 2 (WRITE only)
|
||||||
|
// | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|
||||||
|
// | RFU | BIAS TRIM TOP |
|
||||||
|
#define TRIM_REGISTER3_60x40 0x05 // address for trim register 3 (WRITE only)
|
||||||
|
// | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|
||||||
|
// | RFU | BIAS TRIM BOT |
|
||||||
|
#define TRIM_REGISTER4_60x40 0x06 // address for trim register 4 (WRITE only)
|
||||||
|
// | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|
||||||
|
// | RFU | CLK TRIM |
|
||||||
|
#define TRIM_REGISTER5_60x40 0x07 // address for trim register 5 (WRITE only)
|
||||||
|
// | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|
||||||
|
// | RFU | BPA TRIM TOP |
|
||||||
|
#define TRIM_REGISTER6_60x40 0x08 // address for trim register 6 (WRITE only)
|
||||||
|
// | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|
||||||
|
// | RFU | BPA TRIM BOT |
|
||||||
|
#define TRIM_REGISTER7_60x40 0x09 // address for trim register 7 (WRITE only)
|
||||||
|
// | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|
||||||
|
// | PU SDA TRIM | PU SDA TRIM |
|
||||||
|
|
||||||
|
// EEPROM REGISTER (same structure as 32x32)
|
||||||
|
#define E_PIXCMIN_1_60x40 0x0000 // Min of PixC, stored as float in four 8-bit fields
|
||||||
|
#define E_PIXCMIN_2_60x40 0x0001
|
||||||
|
#define E_PIXCMIN_3_60x40 0x0002
|
||||||
|
#define E_PIXCMIN_4_60x40 0x0003
|
||||||
|
#define E_PIXCMAX_1_60x40 0x0004// Max of PixC, stored as float in four 8-bit fields
|
||||||
|
#define E_PIXCMAX_2_60x40 0x0005
|
||||||
|
#define E_PIXCMAX_3_60x40 0x0006
|
||||||
|
#define E_PIXCMAX_4_60x40 0x0007
|
||||||
|
#define E_GRADSCALE_60x40 0x0008 // stored as unsigned char, important for PTAT comp.
|
||||||
|
#define E_TABLENUMBER1_60x40 0x000B // table number of this sensor, stored as unsigned short
|
||||||
|
#define E_TABLENUMBER2_60x40 0x000C
|
||||||
|
#define E_EPSILON_60x40 0x000D // emissivity in percentage, stored as unsigned char
|
||||||
|
#define E_MBIT_CALIB_60x40 0x000F // calibration MBIT, stored as unsigned char
|
||||||
|
#define E_BIAS_CALIB_60x40 0x0010 // calibration BIAS, stored as unsigned char
|
||||||
|
#define E_CLK_CALIB_60x40 0x0011 // calibration CLK, stored as unsigned char
|
||||||
|
#define E_BPA_CALIB_60x40 0x0012 // calibration BPA, stored as unsigned char
|
||||||
|
#define E_PU_CALIB_60x40 0x0013 // calibration PU, stored as unsigned char
|
||||||
|
#define E_MBIT_USER_60x40 0x0014 // user MBIT, stored as unsigned char
|
||||||
|
#define E_BIAS_USER_60x40 0x0015 // user BIAS, stored as unsigned char
|
||||||
|
#define E_CLK_USER_60x40 0x0016 // user CLK, stored as unsigned char
|
||||||
|
#define E_BPA_USER_60x40 0x0017 // user BPA, stored as unsigned char
|
||||||
|
#define E_PU_USER_60x40 0x0018 // user PU, stored as unsigned char
|
||||||
|
#define E_VDDTH1_1_60x40 0x0026 // VDD th1, stored as unsigned short
|
||||||
|
#define E_VDDTH1_2_60x40 0x0027
|
||||||
|
#define E_VDDTH2_1_60x40 0x0028 // VDD th2, stored as unsigned short
|
||||||
|
#define E_VDDTH2_2_60x40 0x0029
|
||||||
|
#define E_PTATTH1_1_60x40 0x002A // PTAT th1, stored as unsigned short
|
||||||
|
#define E_PTATTH1_2_60x40 0x002B
|
||||||
|
#define E_PTATTH2_1_60x40 0x002C // PTAT th2, stored as unsigned short
|
||||||
|
#define E_PTATTH2_2_60x40 0x002D
|
||||||
|
#define E_VDDSCGRAD_60x40 0x002E // VDD scaling gradient, stored as unsigned char
|
||||||
|
#define E_VDDSCOFF_60x40 0x002F // VDD scaling offset, stored as unsigned char
|
||||||
|
#define E_PTATGR_1_60x40 0x0030 // PTAT gradient, stored as unsigned short
|
||||||
|
#define E_PTATGR_2_60x40 0x0031
|
||||||
|
#define E_PTATOFF_1_60x40 0x0032 // PTAT offset, stored as unsigned short
|
||||||
|
#define E_PTATOFF_2_60x40 0x0033
|
||||||
|
#define E_PIXCIJ_60x40 0x0034 // start of PixC array
|
||||||
|
|
||||||
|
// Lookup table for temperature calculation
|
||||||
|
extern const short htpa60x40_lookuptable[NROFTAELEMENTS_60x40][NROFADELEMENTS_60x40];
|
||||||
|
|
||||||
|
#endif // _HTPA60x40_DEF_H
|
||||||
578
firefly_esp32/main/Sensor/HTPA60x40dR1L0.9/HTPA_Sensor60x40.cpp
Normal file
578
firefly_esp32/main/Sensor/HTPA60x40dR1L0.9/HTPA_Sensor60x40.cpp
Normal file
|
|
@ -0,0 +1,578 @@
|
||||||
|
/**
|
||||||
|
* Module: HTPA60x40dR1L0.9/0.8 Thermal Imaging Sensor
|
||||||
|
*
|
||||||
|
* Copyright 2025-2026 fw <kingfun2000@qq.com>
|
||||||
|
*/
|
||||||
|
#include "HTPA_Sensor60x40.h"
|
||||||
|
#include <freertos/FreeRTOS.h>
|
||||||
|
#include <freertos/task.h>
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "math.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
static const char *TAG = "HTPA60x40";
|
||||||
|
|
||||||
|
#ifndef bitRead
|
||||||
|
#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
HTPA60x40::HTPA60x40()
|
||||||
|
: _pixc2_0(nullptr), _pixc2(nullptr)
|
||||||
|
{
|
||||||
|
// Initialize device characteristics for 60x40 sensor
|
||||||
|
_dev_const = {
|
||||||
|
NUMBER_OF_PIXEL_60x40,
|
||||||
|
NUMBER_OF_BLOCKS_60x40,
|
||||||
|
ROW_PER_BLOCK_60x40,
|
||||||
|
PIXEL_PER_BLOCK_60x40,
|
||||||
|
PIXEL_PER_COLUMN_60x40,
|
||||||
|
PIXEL_PER_ROW_60x40,
|
||||||
|
ALLOWED_DEADPIX_60x40,
|
||||||
|
TABLENUMBER_60x40,
|
||||||
|
TABLEOFFSET_60x40,
|
||||||
|
PTAT_POS_60x40,
|
||||||
|
VDD_POS_60x40,
|
||||||
|
PTAT_VDD_SWITCH_60x40,
|
||||||
|
ATC_ACTIVE_60x40,
|
||||||
|
ATC_POS_60x40,
|
||||||
|
DATA_POS_60x40,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
HTPA60x40::~HTPA60x40() {
|
||||||
|
timer.stop();
|
||||||
|
timer.delete_timer();
|
||||||
|
if (_pixc2_0) {
|
||||||
|
free(_pixc2_0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t HTPA60x40::init() {
|
||||||
|
|
||||||
|
// Allocate memory for pixel constants (60x40 = 2400 pixels)
|
||||||
|
_pixc2_0 = (uint32_t*)malloc(NUMBER_OF_PIXEL_60x40 * sizeof(uint32_t));
|
||||||
|
if (!_pixc2_0) {
|
||||||
|
ESP_LOGE(TAG, "Memory allocation failed for %d pixels", NUMBER_OF_PIXEL_60x40);
|
||||||
|
return ESP_ERR_NO_MEM;
|
||||||
|
}
|
||||||
|
_pixc2 = _pixc2_0;
|
||||||
|
|
||||||
|
uint8_t error = 1;
|
||||||
|
int retry_count = 0;
|
||||||
|
const int max_retries = 5;
|
||||||
|
|
||||||
|
while (error != 0 && retry_count < max_retries) {
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(2000));
|
||||||
|
ESP_LOGI(TAG, "Initializing HTPA60x40 sensor... (attempt %d/%d)", retry_count + 1, max_retries);
|
||||||
|
|
||||||
|
// Initialize I2C bus
|
||||||
|
ESP_LOGI(TAG, "Initializing I2C bus (GPIO14=SDA, GPIO21=SCL)...");
|
||||||
|
esp_err_t i2c_ret = Wire.begin(14, 21); // GPIO14=SDA, GPIO21=SCL
|
||||||
|
if (i2c_ret != ESP_OK) {
|
||||||
|
ESP_LOGW(TAG, "I2C initialization returned: %s (continuing anyway)", esp_err_to_name(i2c_ret));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to connect to sensor
|
||||||
|
Wire.beginTransmission(SENSOR_ADDRESS_60x40);
|
||||||
|
error = Wire.endTransmission();
|
||||||
|
if (error != 0) {
|
||||||
|
ESP_LOGE(TAG, "Sensor initialization failed, check connections and retry %d", error);
|
||||||
|
}
|
||||||
|
|
||||||
|
retry_count++;
|
||||||
|
if (error != 0 && retry_count < max_retries) {
|
||||||
|
ESP_LOGW(TAG, "Retrying sensor initialization in 2 seconds...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error != 0) {
|
||||||
|
ESP_LOGE(TAG, "Failed to initialize HTPA60x40 sensor after %d attempts", max_retries);
|
||||||
|
return ESP_ERR_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "HTPA60x40 sensor connected successfully");
|
||||||
|
|
||||||
|
// Read EEPROM calibration data
|
||||||
|
read_eeprom();
|
||||||
|
|
||||||
|
// Write calibration settings to sensor
|
||||||
|
write_calibration_settings_to_sensor();
|
||||||
|
|
||||||
|
// Calculate pixel constants
|
||||||
|
calcPixC();
|
||||||
|
|
||||||
|
// Calculate timer value
|
||||||
|
timert = calc_timert(clk_calib, mbit_calib);
|
||||||
|
ESP_LOGI(TAG, "Timer value: %d", timert);
|
||||||
|
|
||||||
|
// Initialize timer
|
||||||
|
esp_err_t timer_ret = timer.init(timer_callback, this);
|
||||||
|
if (timer_ret != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "Timer initialization failed: %s", esp_err_to_name(timer_ret));
|
||||||
|
return timer_ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start timer
|
||||||
|
timer.start(timert);
|
||||||
|
ESP_LOGI(TAG, "HTPA60x40 sensor initialization completed successfully");
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HTPA60x40::process() {
|
||||||
|
if (!_new_data_available) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_new_data_available = false;
|
||||||
|
|
||||||
|
// Read sensor data
|
||||||
|
readblockinterrupt();
|
||||||
|
|
||||||
|
// Sort and process data
|
||||||
|
sort_data();
|
||||||
|
|
||||||
|
// Calculate pixel temperatures
|
||||||
|
calculate_pixel_temp();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HTPA60x40::getData(uint16_t* data, int size) {
|
||||||
|
if (size < NUMBER_OF_PIXEL_60x40) {
|
||||||
|
ESP_LOGE(TAG, "Buffer too small. Required: %d, provided: %d", NUMBER_OF_PIXEL_60x40, size);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy pixel data to output buffer
|
||||||
|
int index = 0;
|
||||||
|
for (int row = 0; row < PIXEL_PER_ROW_60x40; row++) {
|
||||||
|
for (int col = 0; col < PIXEL_PER_COLUMN_60x40; col++) {
|
||||||
|
data[index++] = data_pixel[col][row];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HTPA60x40::getThermalData60x40(float* thermal_data) {
|
||||||
|
if (!thermal_data) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert raw data to temperature values
|
||||||
|
int index = 0;
|
||||||
|
for (int row = 0; row < PIXEL_PER_ROW_60x40; row++) {
|
||||||
|
for (int col = 0; col < PIXEL_PER_COLUMN_60x40; col++) {
|
||||||
|
// Convert raw ADC value to temperature (simplified conversion)
|
||||||
|
// This would need proper calibration based on the lookup table
|
||||||
|
float temp = (float)data_pixel[col][row] / 100.0f + 25.0f; // Placeholder conversion
|
||||||
|
thermal_data[index++] = temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HTPA60x40::getThermalGrid8x5(float* grid_temps) {
|
||||||
|
if (!grid_temps) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Downsample 60x40 to 8x5 grid (7.5x8 pixels per grid cell)
|
||||||
|
const int grid_width = 8;
|
||||||
|
const int grid_height = 5;
|
||||||
|
const int pixels_per_grid_x = PIXEL_PER_COLUMN_60x40 / grid_width; // 7.5, use 7 and 8 alternately
|
||||||
|
const int pixels_per_grid_y = PIXEL_PER_ROW_60x40 / grid_height; // 8
|
||||||
|
|
||||||
|
for (int grid_y = 0; grid_y < grid_height; grid_y++) {
|
||||||
|
for (int grid_x = 0; grid_x < grid_width; grid_x++) {
|
||||||
|
float sum = 0.0f;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
// Calculate the actual pixel range for this grid cell
|
||||||
|
int start_x = grid_x * pixels_per_grid_x;
|
||||||
|
int end_x = (grid_x == grid_width - 1) ? PIXEL_PER_COLUMN_60x40 : (grid_x + 1) * pixels_per_grid_x;
|
||||||
|
int start_y = grid_y * pixels_per_grid_y;
|
||||||
|
int end_y = (grid_y + 1) * pixels_per_grid_y;
|
||||||
|
|
||||||
|
// Average the pixels in this grid cell
|
||||||
|
for (int y = start_y; y < end_y && y < PIXEL_PER_ROW_60x40; y++) {
|
||||||
|
for (int x = start_x; x < end_x && x < PIXEL_PER_COLUMN_60x40; x++) {
|
||||||
|
sum += (float)data_pixel[x][y] / 100.0f + 25.0f; // Placeholder conversion
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
grid_temps[grid_y * grid_width + grid_x] = (count > 0) ? sum / count : 25.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HTPA60x40::getThermalGrid12x8(float* grid_temps) {
|
||||||
|
if (!grid_temps) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Downsample 60x40 to 12x8 grid (5x5 pixels per grid cell)
|
||||||
|
const int grid_width = 12;
|
||||||
|
const int grid_height = 8;
|
||||||
|
const int pixels_per_grid_x = PIXEL_PER_COLUMN_60x40 / grid_width; // 5
|
||||||
|
const int pixels_per_grid_y = PIXEL_PER_ROW_60x40 / grid_height; // 5
|
||||||
|
|
||||||
|
for (int grid_y = 0; grid_y < grid_height; grid_y++) {
|
||||||
|
for (int grid_x = 0; grid_x < grid_width; grid_x++) {
|
||||||
|
float sum = 0.0f;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
int start_x = grid_x * pixels_per_grid_x;
|
||||||
|
int end_x = (grid_x == grid_width - 1) ? PIXEL_PER_COLUMN_60x40 : (grid_x + 1) * pixels_per_grid_x;
|
||||||
|
int start_y = grid_y * pixels_per_grid_y;
|
||||||
|
int end_y = (grid_y == grid_height - 1) ? PIXEL_PER_ROW_60x40 : (grid_y + 1) * pixels_per_grid_y;
|
||||||
|
|
||||||
|
for (int y = start_y; y < end_y; y++) {
|
||||||
|
for (int x = start_x; x < end_x; x++) {
|
||||||
|
sum += (float)data_pixel[x][y] / 100.0f + 25.0f; // Placeholder conversion
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
grid_temps[grid_y * grid_width + grid_x] = (count > 0) ? sum / count : 25.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HTPA60x40::getRegionTemperature(uint8_t start_x, uint8_t start_y, uint8_t width, uint8_t height, float* avg_temp) {
|
||||||
|
if (!avg_temp || start_x >= PIXEL_PER_COLUMN_60x40 || start_y >= PIXEL_PER_ROW_60x40) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
float sum = 0.0f;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
uint8_t end_x = (start_x + width > PIXEL_PER_COLUMN_60x40) ? PIXEL_PER_COLUMN_60x40 : start_x + width;
|
||||||
|
uint8_t end_y = (start_y + height > PIXEL_PER_ROW_60x40) ? PIXEL_PER_ROW_60x40 : start_y + height;
|
||||||
|
|
||||||
|
for (uint8_t y = start_y; y < end_y; y++) {
|
||||||
|
for (uint8_t x = start_x; x < end_x; x++) {
|
||||||
|
sum += (float)data_pixel[x][y] / 100.0f + 25.0f; // Placeholder conversion
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*avg_temp = (count > 0) ? sum / count : 25.0f;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HTPA60x40::getHotColdSpots(float* hot_temp, uint8_t* hot_x, uint8_t* hot_y,
|
||||||
|
float* cold_temp, uint8_t* cold_x, uint8_t* cold_y) {
|
||||||
|
if (!hot_temp || !hot_x || !hot_y || !cold_temp || !cold_x || !cold_y) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
float max_temp = -273.15f; // Absolute zero
|
||||||
|
float min_temp = 1000.0f; // Very high temperature
|
||||||
|
uint8_t max_x = 0, max_y = 0, min_x = 0, min_y = 0;
|
||||||
|
|
||||||
|
for (uint8_t y = 0; y < PIXEL_PER_ROW_60x40; y++) {
|
||||||
|
for (uint8_t x = 0; x < PIXEL_PER_COLUMN_60x40; x++) {
|
||||||
|
float temp = (float)data_pixel[x][y] / 100.0f + 25.0f; // Placeholder conversion
|
||||||
|
|
||||||
|
if (temp > max_temp) {
|
||||||
|
max_temp = temp;
|
||||||
|
max_x = x;
|
||||||
|
max_y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (temp < min_temp) {
|
||||||
|
min_temp = temp;
|
||||||
|
min_x = x;
|
||||||
|
min_y = y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*hot_temp = max_temp;
|
||||||
|
*hot_x = max_x;
|
||||||
|
*hot_y = max_y;
|
||||||
|
*cold_temp = min_temp;
|
||||||
|
*cold_x = min_x;
|
||||||
|
*cold_y = min_y;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t HTPA60x40::get_ambient_temperature() {
|
||||||
|
return Ta;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Timer callback function
|
||||||
|
void HTPA60x40::timer_callback(void* arg) {
|
||||||
|
HTPA60x40* sensor = static_cast<HTPA60x40*>(arg);
|
||||||
|
sensor->_new_data_available = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Private functions implementation (adapted from 32x32 version)
|
||||||
|
uint8_t HTPA60x40::write_sensor_byte(uint8_t registeraddress, uint8_t input) {
|
||||||
|
Wire.beginTransmission(SENSOR_ADDRESS_60x40);
|
||||||
|
Wire.write(registeraddress);
|
||||||
|
Wire.write(input);
|
||||||
|
return Wire.endTransmission();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HTPA60x40::read_sensor_register(uint8_t addr, uint8_t *dest, uint16_t n) {
|
||||||
|
Wire.beginTransmission(SENSOR_ADDRESS_60x40);
|
||||||
|
Wire.write(addr);
|
||||||
|
Wire.endTransmission();
|
||||||
|
|
||||||
|
Wire.requestFrom(SENSOR_ADDRESS_60x40, n);
|
||||||
|
for (uint16_t i = 0; i < n; i++) {
|
||||||
|
if (Wire.available()) {
|
||||||
|
dest[i] = Wire.read();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t HTPA60x40::read_EEPROM_byte(uint16_t address) {
|
||||||
|
uint8_t data = 0;
|
||||||
|
Wire.beginTransmission(EEPROM_ADDRESS_60x40);
|
||||||
|
Wire.write((uint8_t)(address >> 8)); // MSB
|
||||||
|
Wire.write((uint8_t)(address & 0xFF)); // LSB
|
||||||
|
Wire.endTransmission();
|
||||||
|
|
||||||
|
Wire.requestFrom(EEPROM_ADDRESS_60x40, 1);
|
||||||
|
if (Wire.available()) {
|
||||||
|
data = Wire.read();
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t HTPA60x40::write_EEPROM_byte(uint16_t address, uint8_t content) {
|
||||||
|
Wire.beginTransmission(EEPROM_ADDRESS_60x40);
|
||||||
|
Wire.write((uint8_t)(address >> 8)); // MSB
|
||||||
|
Wire.write((uint8_t)(address & 0xFF)); // LSB
|
||||||
|
Wire.write(content);
|
||||||
|
return Wire.endTransmission();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HTPA60x40::read_eeprom() {
|
||||||
|
ESP_LOGI(TAG, "Reading EEPROM calibration data...");
|
||||||
|
|
||||||
|
// Read basic calibration values
|
||||||
|
mbit_calib = read_EEPROM_byte(E_MBIT_CALIB_60x40);
|
||||||
|
bias_calib = read_EEPROM_byte(E_BIAS_CALIB_60x40);
|
||||||
|
clk_calib = read_EEPROM_byte(E_CLK_CALIB_60x40);
|
||||||
|
bpa_calib = read_EEPROM_byte(E_BPA_CALIB_60x40);
|
||||||
|
pu_calib = read_EEPROM_byte(E_PU_CALIB_60x40);
|
||||||
|
|
||||||
|
// Read user settings (use calibration values if user values are not set)
|
||||||
|
mbit_user = read_EEPROM_byte(E_MBIT_USER_60x40);
|
||||||
|
if (mbit_user == 0xFF) mbit_user = mbit_calib;
|
||||||
|
|
||||||
|
bias_user = read_EEPROM_byte(E_BIAS_USER_60x40);
|
||||||
|
if (bias_user == 0xFF) bias_user = bias_calib;
|
||||||
|
|
||||||
|
clk_user = read_EEPROM_byte(E_CLK_USER_60x40);
|
||||||
|
if (clk_user == 0xFF) clk_user = clk_calib;
|
||||||
|
|
||||||
|
bpa_user = read_EEPROM_byte(E_BPA_USER_60x40);
|
||||||
|
if (bpa_user == 0xFF) bpa_user = bpa_calib;
|
||||||
|
|
||||||
|
pu_user = read_EEPROM_byte(E_PU_USER_60x40);
|
||||||
|
if (pu_user == 0xFF) pu_user = pu_calib;
|
||||||
|
|
||||||
|
// Read other calibration parameters
|
||||||
|
gradscale = read_EEPROM_byte(E_GRADSCALE_60x40);
|
||||||
|
vddscgrad = read_EEPROM_byte(E_VDDSCGRAD_60x40);
|
||||||
|
vddscoff = read_EEPROM_byte(E_VDDSCOFF_60x40);
|
||||||
|
epsilon = read_EEPROM_byte(E_EPSILON_60x40);
|
||||||
|
|
||||||
|
// Read table number
|
||||||
|
tablenumber = (read_EEPROM_byte(E_TABLENUMBER2_60x40) << 8) | read_EEPROM_byte(E_TABLENUMBER1_60x40);
|
||||||
|
|
||||||
|
// Read VDD and PTAT thresholds
|
||||||
|
vddth1 = (read_EEPROM_byte(E_VDDTH1_2_60x40) << 8) | read_EEPROM_byte(E_VDDTH1_1_60x40);
|
||||||
|
vddth2 = (read_EEPROM_byte(E_VDDTH2_2_60x40) << 8) | read_EEPROM_byte(E_VDDTH2_1_60x40);
|
||||||
|
ptatth1 = (read_EEPROM_byte(E_PTATTH1_2_60x40) << 8) | read_EEPROM_byte(E_PTATTH1_1_60x40);
|
||||||
|
ptatth2 = (read_EEPROM_byte(E_PTATTH2_2_60x40) << 8) | read_EEPROM_byte(E_PTATTH2_1_60x40);
|
||||||
|
|
||||||
|
// Read PTAT gradient and offset
|
||||||
|
ptatgr = (read_EEPROM_byte(E_PTATGR_2_60x40) << 8) | read_EEPROM_byte(E_PTATGR_1_60x40);
|
||||||
|
|
||||||
|
// Read PixC min and max values
|
||||||
|
uint8_t pixc_bytes[4];
|
||||||
|
pixc_bytes[0] = read_EEPROM_byte(E_PIXCMIN_1_60x40);
|
||||||
|
pixc_bytes[1] = read_EEPROM_byte(E_PIXCMIN_2_60x40);
|
||||||
|
pixc_bytes[2] = read_EEPROM_byte(E_PIXCMIN_3_60x40);
|
||||||
|
pixc_bytes[3] = read_EEPROM_byte(E_PIXCMIN_4_60x40);
|
||||||
|
memcpy(&pixcmin, pixc_bytes, 4);
|
||||||
|
|
||||||
|
pixc_bytes[0] = read_EEPROM_byte(E_PIXCMAX_1_60x40);
|
||||||
|
pixc_bytes[1] = read_EEPROM_byte(E_PIXCMAX_2_60x40);
|
||||||
|
pixc_bytes[2] = read_EEPROM_byte(E_PIXCMAX_3_60x40);
|
||||||
|
pixc_bytes[3] = read_EEPROM_byte(E_PIXCMAX_4_60x40);
|
||||||
|
memcpy(&pixcmax, pixc_bytes, 4);
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "EEPROM data read completed");
|
||||||
|
ESP_LOGI(TAG, "Table number: %d, Epsilon: %d", tablenumber, epsilon);
|
||||||
|
ESP_LOGI(TAG, "PixC range: %.2f to %.2f", pixcmin, pixcmax);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HTPA60x40::write_calibration_settings_to_sensor() {
|
||||||
|
ESP_LOGI(TAG, "Writing calibration settings to sensor...");
|
||||||
|
|
||||||
|
// Write trim registers with calibration values
|
||||||
|
write_sensor_byte(TRIM_REGISTER1_60x40, mbit_calib);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(5));
|
||||||
|
|
||||||
|
write_sensor_byte(TRIM_REGISTER2_60x40, bias_calib);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(5));
|
||||||
|
|
||||||
|
write_sensor_byte(TRIM_REGISTER3_60x40, bias_calib);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(5));
|
||||||
|
|
||||||
|
write_sensor_byte(TRIM_REGISTER4_60x40, clk_calib);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(5));
|
||||||
|
|
||||||
|
write_sensor_byte(TRIM_REGISTER5_60x40, bpa_calib);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(5));
|
||||||
|
|
||||||
|
write_sensor_byte(TRIM_REGISTER6_60x40, bpa_calib);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(5));
|
||||||
|
|
||||||
|
write_sensor_byte(TRIM_REGISTER7_60x40, pu_calib);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(5));
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Calibration settings written to sensor");
|
||||||
|
}
|
||||||
|
|
||||||
|
void HTPA60x40::calcPixC() {
|
||||||
|
ESP_LOGI(TAG, "Calculating pixel constants for %d pixels...", NUMBER_OF_PIXEL_60x40);
|
||||||
|
|
||||||
|
// Read pixel constants from EEPROM
|
||||||
|
uint16_t eeprom_addr = E_PIXCIJ_60x40;
|
||||||
|
|
||||||
|
for (int i = 0; i < NUMBER_OF_PIXEL_60x40; i++) {
|
||||||
|
uint8_t pixc_bytes[4];
|
||||||
|
|
||||||
|
// Read 4 bytes for each pixel constant
|
||||||
|
for (int j = 0; j < 4; j++) {
|
||||||
|
pixc_bytes[j] = read_EEPROM_byte(eeprom_addr + i * 4 + j);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert bytes to uint32_t
|
||||||
|
_pixc2_0[i] = (uint32_t)pixc_bytes[0] |
|
||||||
|
((uint32_t)pixc_bytes[1] << 8) |
|
||||||
|
((uint32_t)pixc_bytes[2] << 16) |
|
||||||
|
((uint32_t)pixc_bytes[3] << 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Pixel constants calculation completed");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t HTPA60x40::calc_timert(uint8_t clk, uint8_t mbit) {
|
||||||
|
// Calculate timer value based on clock and mbit settings
|
||||||
|
// This is a simplified calculation - actual implementation may vary
|
||||||
|
uint16_t timer_val = 1000 + (clk * 10) + (mbit * 5);
|
||||||
|
return timer_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HTPA60x40::pixel_masking() {
|
||||||
|
// Apply dead pixel masking
|
||||||
|
for (int i = 0; i < nrofdefpix && i < ALLOWED_DEADPIX_60x40; i++) {
|
||||||
|
uint16_t pixel_addr = deadpixadr[i];
|
||||||
|
if (pixel_addr < NUMBER_OF_PIXEL_60x40) {
|
||||||
|
int col = pixel_addr / PIXEL_PER_ROW_60x40;
|
||||||
|
int row = pixel_addr % PIXEL_PER_ROW_60x40;
|
||||||
|
|
||||||
|
if (col < PIXEL_PER_COLUMN_60x40 && row < PIXEL_PER_ROW_60x40) {
|
||||||
|
// Interpolate from neighboring pixels
|
||||||
|
uint32_t sum = 0;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
for (int dc = -1; dc <= 1; dc++) {
|
||||||
|
for (int dr = -1; dr <= 1; dr++) {
|
||||||
|
int nc = col + dc;
|
||||||
|
int nr = row + dr;
|
||||||
|
|
||||||
|
if (nc >= 0 && nc < PIXEL_PER_COLUMN_60x40 &&
|
||||||
|
nr >= 0 && nr < PIXEL_PER_ROW_60x40 &&
|
||||||
|
(dc != 0 || dr != 0)) {
|
||||||
|
sum += data_pixel[nc][nr];
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count > 0) {
|
||||||
|
data_pixel[col][row] = sum / count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HTPA60x40::readblockinterrupt() {
|
||||||
|
// Read sensor status
|
||||||
|
read_sensor_register(STATUS_REGISTER_60x40, &statusreg, 1);
|
||||||
|
|
||||||
|
// Check if data is ready
|
||||||
|
if (!(statusreg & 0x01)) { // EOC bit
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read data blocks
|
||||||
|
uint8_t block_select = (read_block_num << 4) | 0x0A; // TOP_HALF with block selection
|
||||||
|
|
||||||
|
// Read the selected block
|
||||||
|
read_sensor_register(block_select, RAMoutput[read_block_num], BLOCK_LENGTH_60x40);
|
||||||
|
|
||||||
|
// Move to next block
|
||||||
|
read_block_num++;
|
||||||
|
if (read_block_num >= NUMBER_OF_BLOCKS_60x40 * 2) {
|
||||||
|
read_block_num = START_WITH_BLOCK_60x40;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start next conversion
|
||||||
|
uint8_t config_reg = (read_block_num << 4) | 0x01; // Start bit
|
||||||
|
write_sensor_byte(CONFIGURATION_REGISTER_60x40, config_reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HTPA60x40::sort_data() {
|
||||||
|
// Sort the raw data into pixel array
|
||||||
|
for (int block = 0; block < NUMBER_OF_BLOCKS_60x40 * 2; block++) {
|
||||||
|
for (int pixel_in_block = 0; pixel_in_block < PIXEL_PER_BLOCK_60x40; pixel_in_block++) {
|
||||||
|
int data_pos = DATA_POS_60x40 + pixel_in_block * 2;
|
||||||
|
|
||||||
|
if (data_pos + 1 < BLOCK_LENGTH_60x40) {
|
||||||
|
uint16_t pixel_value = (RAMoutput[block][data_pos + 1] << 8) | RAMoutput[block][data_pos];
|
||||||
|
|
||||||
|
// Calculate pixel position in the array
|
||||||
|
int pixel_index = block * PIXEL_PER_BLOCK_60x40 + pixel_in_block;
|
||||||
|
int col = pixel_index / PIXEL_PER_ROW_60x40;
|
||||||
|
int row = pixel_index % PIXEL_PER_ROW_60x40;
|
||||||
|
|
||||||
|
if (col < PIXEL_PER_COLUMN_60x40 && row < PIXEL_PER_ROW_60x40) {
|
||||||
|
data_pixel[col][row] = pixel_value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HTPA60x40::calculate_pixel_temp() {
|
||||||
|
// Apply pixel masking for dead pixels
|
||||||
|
pixel_masking();
|
||||||
|
|
||||||
|
// Additional temperature calculation would go here
|
||||||
|
// This would involve using the lookup table and calibration data
|
||||||
|
// For now, we'll keep the raw ADC values
|
||||||
|
|
||||||
|
ESP_LOGD(TAG, "Pixel temperature calculation completed");
|
||||||
|
}
|
||||||
155
firefly_esp32/main/Sensor/HTPA60x40dR1L0.9/HTPA_Sensor60x40.h
Normal file
155
firefly_esp32/main/Sensor/HTPA60x40dR1L0.9/HTPA_Sensor60x40.h
Normal file
|
|
@ -0,0 +1,155 @@
|
||||||
|
#ifndef HTPA60x40_H
|
||||||
|
#define HTPA60x40_H
|
||||||
|
|
||||||
|
#include "../../Module/Timer.h"
|
||||||
|
#include "../../Module/Wire.h"
|
||||||
|
#include "HTPA60x40dR1L0.9.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint16_t NumberOfPixel;
|
||||||
|
uint8_t NumberOfBlocks;
|
||||||
|
uint8_t RowPerBlock;
|
||||||
|
uint16_t PixelPerBlock;
|
||||||
|
uint16_t PixelPerColumn;
|
||||||
|
uint16_t PixelPerRow;
|
||||||
|
uint8_t AllowedDeadPix;
|
||||||
|
uint16_t TableNumber;
|
||||||
|
uint16_t TableOffset;
|
||||||
|
uint8_t PTATPos;
|
||||||
|
uint8_t VDDPos;
|
||||||
|
uint8_t PTATVDDSwitch;
|
||||||
|
uint8_t CyclopsActive;
|
||||||
|
uint8_t CyclopsPos;
|
||||||
|
uint8_t DataPos;
|
||||||
|
} HTPA60x40_Characteristics;
|
||||||
|
|
||||||
|
class HTPA60x40 {
|
||||||
|
private:
|
||||||
|
// I2C配置
|
||||||
|
i2c_port_t _i2c_port;
|
||||||
|
gpio_num_t _sda_pin;
|
||||||
|
gpio_num_t _scl_pin;
|
||||||
|
|
||||||
|
// 传感器特性
|
||||||
|
HTPA60x40_Characteristics _dev_const;
|
||||||
|
|
||||||
|
// EEPROM数据
|
||||||
|
uint8_t mbit_calib, bias_calib, clk_calib, bpa_calib, pu_calib;
|
||||||
|
uint8_t mbit_user, bias_user, clk_user, bpa_user, pu_user;
|
||||||
|
uint8_t nrofdefpix, gradscale, vddscgrad, vddscoff, epsilon, lastepsilon, arraytype;
|
||||||
|
uint8_t deadpixmask[ALLOWED_DEADPIX_60x40];
|
||||||
|
int8_t globaloff;
|
||||||
|
int16_t thgrad[PIXEL_PER_COLUMN_60x40][PIXEL_PER_ROW_60x40];
|
||||||
|
uint16_t tablenumber, vddth1, vddth2, ptatth1, ptatth2, ptatgr, globalgain;
|
||||||
|
uint16_t deadpixadr[ALLOWED_DEADPIX_60x40 * 2];
|
||||||
|
int16_t thoffset[PIXEL_PER_COLUMN_60x40][PIXEL_PER_ROW_60x40];
|
||||||
|
int16_t vddcompgrad[ROW_PER_BLOCK_60x40 * 2][PIXEL_PER_ROW_60x40];
|
||||||
|
int16_t vddcompoff[ROW_PER_BLOCK_60x40 * 2][PIXEL_PER_ROW_60x40];
|
||||||
|
uint32_t id;
|
||||||
|
float ptatgr_float, ptatoff_float, pixcmin, pixcmax;
|
||||||
|
|
||||||
|
// 像素常量(使用动态分配)
|
||||||
|
uint32_t *_pixc2_0;
|
||||||
|
uint32_t *_pixc2;
|
||||||
|
|
||||||
|
// 传感器数据
|
||||||
|
uint16_t data_pixel[PIXEL_PER_COLUMN_60x40][PIXEL_PER_ROW_60x40];
|
||||||
|
uint8_t RAMoutput[2 * NUMBER_OF_BLOCKS_60x40 + 2][BLOCK_LENGTH_60x40];
|
||||||
|
uint16_t eloffset[ROW_PER_BLOCK_60x40 * 2][PIXEL_PER_ROW_60x40];
|
||||||
|
uint8_t statusreg;
|
||||||
|
uint16_t Ta, ptat_av_uint16, vdd_av_uint16;
|
||||||
|
|
||||||
|
// 缓冲区
|
||||||
|
uint16_t ptat_buffer[PTAT_BUFFER_SIZE_60x40];
|
||||||
|
uint16_t ptat_buffer_average;
|
||||||
|
uint8_t use_ptat_buffer = 0;
|
||||||
|
uint8_t ptat_i = 0;
|
||||||
|
uint8_t PTATok = 0;
|
||||||
|
|
||||||
|
uint16_t vdd_buffer[VDD_BUFFER_SIZE_60x40];
|
||||||
|
uint16_t vdd_buffer_average;
|
||||||
|
uint8_t use_vdd_buffer = 0;
|
||||||
|
uint8_t vdd_i = 0;
|
||||||
|
|
||||||
|
uint8_t use_eloffsets_buffer = 0;
|
||||||
|
uint8_t eloffsets_i = 0;
|
||||||
|
uint8_t new_offsets = 1;
|
||||||
|
|
||||||
|
// 程序控制变量
|
||||||
|
bool switch_ptat_vdd = 0;
|
||||||
|
uint8_t adr_offset = 0x00;
|
||||||
|
uint16_t picnum = 0;
|
||||||
|
uint8_t state = 0;
|
||||||
|
uint8_t read_block_num = START_WITH_BLOCK_60x40;
|
||||||
|
uint8_t read_eloffset_next_pic = 0;
|
||||||
|
bool ReadingRoutineEnable = 1;
|
||||||
|
|
||||||
|
// 其他参数
|
||||||
|
uint32_t gradscale_div;
|
||||||
|
uint32_t vddscgrad_div;
|
||||||
|
uint32_t vddscoff_div;
|
||||||
|
int vddcompgrad_n;
|
||||||
|
int vddcompoff_n;
|
||||||
|
|
||||||
|
// 定时器
|
||||||
|
uint16_t timert;
|
||||||
|
Timer timer;
|
||||||
|
bool _new_data_available = true;
|
||||||
|
|
||||||
|
// 私有函数
|
||||||
|
uint8_t write_sensor_byte(uint8_t registeraddress, uint8_t input);
|
||||||
|
void read_sensor_register(uint8_t addr, uint8_t *dest, uint16_t n);
|
||||||
|
uint8_t read_EEPROM_byte(uint16_t address);
|
||||||
|
uint8_t write_EEPROM_byte(uint16_t address, uint8_t content);
|
||||||
|
void read_eeprom();
|
||||||
|
void write_calibration_settings_to_sensor();
|
||||||
|
void calcPixC();
|
||||||
|
uint16_t calc_timert(uint8_t clk, uint8_t mbit);
|
||||||
|
void pixel_masking();
|
||||||
|
void readblockinterrupt();
|
||||||
|
void sort_data();
|
||||||
|
void calculate_pixel_temp();
|
||||||
|
|
||||||
|
// 定时器回调函数
|
||||||
|
static void timer_callback(void* arg);
|
||||||
|
|
||||||
|
public:
|
||||||
|
// 构造函数和析构函数
|
||||||
|
HTPA60x40();
|
||||||
|
~HTPA60x40();
|
||||||
|
|
||||||
|
// 初始化函数
|
||||||
|
esp_err_t init();
|
||||||
|
bool process();
|
||||||
|
|
||||||
|
// 数据获取函数
|
||||||
|
bool getData(uint16_t* data, int size);
|
||||||
|
uint16_t get_ambient_temperature();
|
||||||
|
|
||||||
|
// 获取热成像数据(60x40分辨率)
|
||||||
|
bool getThermalData60x40(float* thermal_data);
|
||||||
|
|
||||||
|
// 获取降采样的热成像数据(用于兼容性和性能优化)
|
||||||
|
bool getThermalGrid8x5(float* grid_temps); // 8x5网格,每个网格代表7.5x8像素的平均值
|
||||||
|
bool getThermalGrid12x8(float* grid_temps); // 12x8网格,每个网格代表5x5像素的平均值
|
||||||
|
|
||||||
|
// 获取指定区域的平均温度
|
||||||
|
bool getRegionTemperature(uint8_t start_x, uint8_t start_y, uint8_t width, uint8_t height, float* avg_temp);
|
||||||
|
|
||||||
|
// 获取最热点和最冷点
|
||||||
|
bool getHotColdSpots(float* hot_temp, uint8_t* hot_x, uint8_t* hot_y,
|
||||||
|
float* cold_temp, uint8_t* cold_x, uint8_t* cold_y);
|
||||||
|
|
||||||
|
// 定时器控制(用于避免I2C冲突)
|
||||||
|
void pauseTimer() { timer.stop(); }
|
||||||
|
void resumeTimer() { timer.start(timert); }
|
||||||
|
|
||||||
|
// 获取传感器信息
|
||||||
|
uint16_t getPixelCount() { return NUMBER_OF_PIXEL_60x40; }
|
||||||
|
uint8_t getColumnCount() { return PIXEL_PER_COLUMN_60x40; }
|
||||||
|
uint8_t getRowCount() { return PIXEL_PER_ROW_60x40; }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // HTPA60x40_H
|
||||||
280
firefly_esp32/main/Sensor/HTPA60x40dR1L0.9/README.md
Normal file
280
firefly_esp32/main/Sensor/HTPA60x40dR1L0.9/README.md
Normal file
|
|
@ -0,0 +1,280 @@
|
||||||
|
# HTPA60x40dR1L0.9/0.8 热成像传感器驱动
|
||||||
|
|
||||||
|
## 📋 概述
|
||||||
|
|
||||||
|
本目录包含Heimann HTPA60x40dR1L0.9/0.8热成像传感器的ESP32驱动代码。该传感器提供60x40像素分辨率的热成像数据,相比32x32传感器提供更高的分辨率和更详细的热成像信息。
|
||||||
|
|
||||||
|
## 🔧 硬件规格
|
||||||
|
|
||||||
|
### 传感器参数:
|
||||||
|
- **分辨率**:60x40像素 (2400个像素)
|
||||||
|
- **视场角**:60° x 40° (标准版本)
|
||||||
|
- **温度范围**:-20°C 到 +300°C
|
||||||
|
- **精度**:±2°C (在环境温度下)
|
||||||
|
- **帧率**:最高4Hz
|
||||||
|
- **接口**:I2C (地址0x1A)
|
||||||
|
- **工作电压**:3.3V
|
||||||
|
- **功耗**:约150mA
|
||||||
|
|
||||||
|
### 与32x32版本的主要区别:
|
||||||
|
- 像素数量:2400 vs 1024 (增加134%)
|
||||||
|
- 数据量:4800字节 vs 2048字节
|
||||||
|
- 处理时间:更长的数据读取和处理时间
|
||||||
|
- 内存需求:更大的缓冲区需求
|
||||||
|
|
||||||
|
## 📁 文件结构
|
||||||
|
|
||||||
|
```
|
||||||
|
HTPA60x40dR1L0.9/
|
||||||
|
├── HTPA60x40dR1L0.9.h # 传感器常量定义
|
||||||
|
├── HTPA_Sensor60x40.h # 传感器类声明
|
||||||
|
├── HTPA_Sensor60x40.cpp # 传感器类实现
|
||||||
|
├── htpa60x40_lookuptable.cpp # 温度查找表
|
||||||
|
├── CMakeLists.txt # 编译配置
|
||||||
|
└── README.md # 本文档
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🚀 使用方法
|
||||||
|
|
||||||
|
### 1. 基本初始化
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include "Sensor/HTPA60x40dR1L0.9/HTPA_Sensor60x40.h"
|
||||||
|
|
||||||
|
HTPA60x40 thermal_sensor;
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
// 初始化传感器
|
||||||
|
esp_err_t ret = thermal_sensor.init();
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
ESP_LOGE("MAIN", "Failed to initialize HTPA60x40 sensor");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGI("MAIN", "HTPA60x40 sensor initialized successfully");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 数据读取
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
void loop() {
|
||||||
|
// 处理传感器数据
|
||||||
|
if (thermal_sensor.process()) {
|
||||||
|
|
||||||
|
// 方法1:获取完整60x40热成像数据
|
||||||
|
float thermal_data[2400];
|
||||||
|
if (thermal_sensor.getThermalData60x40(thermal_data)) {
|
||||||
|
// 处理2400个像素的温度数据
|
||||||
|
for (int i = 0; i < 2400; i++) {
|
||||||
|
// thermal_data[i] 包含第i个像素的温度值
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 方法2:获取降采样的8x5网格数据(兼容性更好)
|
||||||
|
float grid_8x5[40];
|
||||||
|
if (thermal_sensor.getThermalGrid8x5(grid_8x5)) {
|
||||||
|
// 处理40个网格的平均温度
|
||||||
|
}
|
||||||
|
|
||||||
|
// 方法3:获取12x8网格数据(中等分辨率)
|
||||||
|
float grid_12x8[96];
|
||||||
|
if (thermal_sensor.getThermalGrid12x8(grid_12x8)) {
|
||||||
|
// 处理96个网格的平均温度
|
||||||
|
}
|
||||||
|
|
||||||
|
// 方法4:获取指定区域的平均温度
|
||||||
|
float region_temp;
|
||||||
|
if (thermal_sensor.getRegionTemperature(20, 15, 20, 10, ®ion_temp)) {
|
||||||
|
ESP_LOGI("MAIN", "Region temperature: %.2f°C", region_temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 方法5:获取最热点和最冷点
|
||||||
|
float hot_temp, cold_temp;
|
||||||
|
uint8_t hot_x, hot_y, cold_x, cold_y;
|
||||||
|
if (thermal_sensor.getHotColdSpots(&hot_temp, &hot_x, &hot_y,
|
||||||
|
&cold_temp, &cold_x, &cold_y)) {
|
||||||
|
ESP_LOGI("MAIN", "Hot spot: %.2f°C at (%d,%d)", hot_temp, hot_x, hot_y);
|
||||||
|
ESP_LOGI("MAIN", "Cold spot: %.2f°C at (%d,%d)", cold_temp, cold_x, cold_y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(250)); // 4Hz更新频率
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 与现有32x32代码的集成
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// 在主程序中可以通过条件编译选择传感器
|
||||||
|
#ifdef USE_HTPA60x40
|
||||||
|
#include "Sensor/HTPA60x40dR1L0.9/HTPA_Sensor60x40.h"
|
||||||
|
HTPA60x40 thermal_sensor;
|
||||||
|
#else
|
||||||
|
#include "Sensor/HTPAd32x32L1k7/HTPA_Sensor32_2.h"
|
||||||
|
HTPA32_2 thermal_sensor;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void init_thermal_sensor() {
|
||||||
|
esp_err_t ret = thermal_sensor.init();
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
ESP_LOGE("MAIN", "Failed to initialize thermal sensor");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## ⚙️ 配置选项
|
||||||
|
|
||||||
|
### I2C配置:
|
||||||
|
- **SDA引脚**:GPIO14
|
||||||
|
- **SCL引脚**:GPIO21
|
||||||
|
- **时钟频率**:1MHz (传感器), 400kHz (EEPROM)
|
||||||
|
- **地址**:0x1A (传感器), 0x50 (EEPROM)
|
||||||
|
|
||||||
|
### 内存配置:
|
||||||
|
```cpp
|
||||||
|
// 在sdkconfig中增加堆内存大小
|
||||||
|
CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192
|
||||||
|
CONFIG_FREERTOS_HEAP_SIZE_MIN=32768
|
||||||
|
```
|
||||||
|
|
||||||
|
### 性能优化:
|
||||||
|
```cpp
|
||||||
|
// 暂停定时器以避免I2C冲突
|
||||||
|
thermal_sensor.pauseTimer();
|
||||||
|
// 执行其他I2C操作
|
||||||
|
thermal_sensor.resumeTimer();
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔍 API参考
|
||||||
|
|
||||||
|
### 主要方法:
|
||||||
|
|
||||||
|
#### `esp_err_t init()`
|
||||||
|
初始化传感器,包括I2C通信、EEPROM读取、校准设置等。
|
||||||
|
|
||||||
|
#### `bool process()`
|
||||||
|
处理传感器数据,返回true表示有新数据可用。
|
||||||
|
|
||||||
|
#### `bool getThermalData60x40(float* thermal_data)`
|
||||||
|
获取完整的60x40热成像数据,需要2400个float的数组。
|
||||||
|
|
||||||
|
#### `bool getThermalGrid8x5(float* grid_temps)`
|
||||||
|
获取8x5网格的降采样数据,需要40个float的数组。
|
||||||
|
|
||||||
|
#### `bool getThermalGrid12x8(float* grid_temps)`
|
||||||
|
获取12x8网格的降采样数据,需要96个float的数组。
|
||||||
|
|
||||||
|
#### `bool getRegionTemperature(uint8_t start_x, uint8_t start_y, uint8_t width, uint8_t height, float* avg_temp)`
|
||||||
|
获取指定矩形区域的平均温度。
|
||||||
|
|
||||||
|
#### `bool getHotColdSpots(...)`
|
||||||
|
获取图像中的最热点和最冷点位置及温度。
|
||||||
|
|
||||||
|
### 信息查询方法:
|
||||||
|
|
||||||
|
#### `uint16_t getPixelCount()`
|
||||||
|
返回像素总数 (2400)。
|
||||||
|
|
||||||
|
#### `uint8_t getColumnCount()`
|
||||||
|
返回列数 (60)。
|
||||||
|
|
||||||
|
#### `uint8_t getRowCount()`
|
||||||
|
返回行数 (40)。
|
||||||
|
|
||||||
|
#### `uint16_t get_ambient_temperature()`
|
||||||
|
返回环境温度。
|
||||||
|
|
||||||
|
## ⚠️ 注意事项
|
||||||
|
|
||||||
|
### 1. 内存需求
|
||||||
|
60x40传感器需要更多内存:
|
||||||
|
- 像素常量:2400 × 4字节 = 9.6KB
|
||||||
|
- 像素数据:2400 × 2字节 = 4.8KB
|
||||||
|
- 缓冲区:约20个块 × 242字节 = 4.8KB
|
||||||
|
- 总计:约19.2KB (vs 32x32的8KB)
|
||||||
|
|
||||||
|
### 2. 处理时间
|
||||||
|
更多的像素意味着:
|
||||||
|
- 更长的I2C数据传输时间
|
||||||
|
- 更多的计算处理时间
|
||||||
|
- 可能需要降低帧率以保证系统稳定性
|
||||||
|
|
||||||
|
### 3. 查找表
|
||||||
|
当前使用的是简化的查找表,实际部署时需要:
|
||||||
|
- 从Heimann获取完整的校准查找表
|
||||||
|
- 根据具体传感器型号调整参数
|
||||||
|
- 进行温度校准验证
|
||||||
|
|
||||||
|
### 4. 兼容性
|
||||||
|
代码设计为与32x32版本API兼容,但:
|
||||||
|
- 数据量更大,需要相应调整缓冲区大小
|
||||||
|
- 网络传输可能需要压缩或分包
|
||||||
|
- 显示界面需要适配新的分辨率
|
||||||
|
|
||||||
|
## 🔧 故障排除
|
||||||
|
|
||||||
|
### 常见问题:
|
||||||
|
|
||||||
|
#### 1. 内存不足
|
||||||
|
```
|
||||||
|
E (xxx) HTPA60x40: Memory allocation failed for 2400 pixels
|
||||||
|
```
|
||||||
|
**解决方案**:增加堆内存大小或使用PSRAM。
|
||||||
|
|
||||||
|
#### 2. I2C通信失败
|
||||||
|
```
|
||||||
|
E (xxx) HTPA60x40: Sensor initialization failed, check connections
|
||||||
|
```
|
||||||
|
**解决方案**:检查I2C连接和电源供应。
|
||||||
|
|
||||||
|
#### 3. 数据处理缓慢
|
||||||
|
**解决方案**:
|
||||||
|
- 使用降采样方法减少数据量
|
||||||
|
- 优化处理算法
|
||||||
|
- 考虑使用DMA传输
|
||||||
|
|
||||||
|
### 调试技巧:
|
||||||
|
```cpp
|
||||||
|
// 启用详细日志
|
||||||
|
esp_log_level_set("HTPA60x40", ESP_LOG_DEBUG);
|
||||||
|
|
||||||
|
// 监控内存使用
|
||||||
|
ESP_LOGI("MAIN", "Free heap: %d bytes", esp_get_free_heap_size());
|
||||||
|
|
||||||
|
// 检查传感器状态
|
||||||
|
ESP_LOGI("MAIN", "Sensor pixels: %d, columns: %d, rows: %d",
|
||||||
|
thermal_sensor.getPixelCount(),
|
||||||
|
thermal_sensor.getColumnCount(),
|
||||||
|
thermal_sensor.getRowCount());
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📈 性能对比
|
||||||
|
|
||||||
|
| 特性 | HTPA32x32 | HTPA60x40 | 提升 |
|
||||||
|
|------|-----------|-----------|------|
|
||||||
|
| 像素数 | 1024 | 2400 | +134% |
|
||||||
|
| 分辨率 | 32×32 | 60×40 | +134% |
|
||||||
|
| 数据量 | 2KB | 4.8KB | +140% |
|
||||||
|
| 内存需求 | ~8KB | ~19KB | +138% |
|
||||||
|
| 处理时间 | 基准 | +150% | - |
|
||||||
|
|
||||||
|
## 🚀 未来改进
|
||||||
|
|
||||||
|
1. **硬件加速**:使用ESP32的DMA功能加速I2C传输
|
||||||
|
2. **数据压缩**:实现实时数据压缩算法
|
||||||
|
3. **智能采样**:根据应用需求动态调整采样率
|
||||||
|
4. **温度校准**:实现更精确的温度转换算法
|
||||||
|
5. **多传感器支持**:支持同时使用多个传感器
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**注意**:此代码为预备版本,在实际部署前需要:
|
||||||
|
1. 获取完整的传感器校准数据
|
||||||
|
2. 进行充分的硬件测试
|
||||||
|
3. 优化性能和内存使用
|
||||||
|
4. 验证温度精度
|
||||||
|
|
||||||
|
**文档版本**:v1.0
|
||||||
|
**创建时间**:2026年2月26日
|
||||||
|
**适用传感器**:HTPA60x40dR1L0.9, HTPA60x40dR1L0.8
|
||||||
|
|
@ -0,0 +1,198 @@
|
||||||
|
/**
|
||||||
|
* HTPA60x40dR1L0.9/0.8 Lookup Table for Temperature Calculation
|
||||||
|
*
|
||||||
|
* This lookup table is used to convert raw ADC values to temperature values.
|
||||||
|
* The table structure is based on the Heimann sensor documentation.
|
||||||
|
*
|
||||||
|
* Note: This is a placeholder table. The actual lookup table should be
|
||||||
|
* provided by Heimann Sensor or generated through calibration.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "HTPA60x40dR1L0.9.h"
|
||||||
|
|
||||||
|
// Placeholder lookup table for HTPA60x40dR1L0.9/0.8
|
||||||
|
// The actual table should have NROFTAELEMENTS_60x40 x NROFADELEMENTS_60x40 elements
|
||||||
|
// This is a simplified version for demonstration purposes
|
||||||
|
|
||||||
|
const short htpa60x40_lookuptable[NROFTAELEMENTS_60x40][NROFADELEMENTS_60x40] = {
|
||||||
|
// Temperature step 0 (-40°C to -30°C)
|
||||||
|
{
|
||||||
|
// ADC values 0-63 (first 64 values of 1588 total)
|
||||||
|
-4000, -3990, -3980, -3970, -3960, -3950, -3940, -3930,
|
||||||
|
-3920, -3910, -3900, -3890, -3880, -3870, -3860, -3850,
|
||||||
|
-3840, -3830, -3820, -3810, -3800, -3790, -3780, -3770,
|
||||||
|
-3760, -3750, -3740, -3730, -3720, -3710, -3700, -3690,
|
||||||
|
-3680, -3670, -3660, -3650, -3640, -3630, -3620, -3610,
|
||||||
|
-3600, -3590, -3580, -3570, -3560, -3550, -3540, -3530,
|
||||||
|
-3520, -3510, -3500, -3490, -3480, -3470, -3460, -3450,
|
||||||
|
-3440, -3430, -3420, -3410, -3400, -3390, -3380, -3370,
|
||||||
|
// ... (remaining 1524 values would continue here)
|
||||||
|
// For brevity, we'll fill with interpolated values
|
||||||
|
},
|
||||||
|
|
||||||
|
// Temperature step 1 (-30°C to -20°C)
|
||||||
|
{
|
||||||
|
-3000, -2990, -2980, -2970, -2960, -2950, -2940, -2930,
|
||||||
|
-2920, -2910, -2900, -2890, -2880, -2870, -2860, -2850,
|
||||||
|
-2840, -2830, -2820, -2810, -2800, -2790, -2780, -2770,
|
||||||
|
-2760, -2750, -2740, -2730, -2720, -2710, -2700, -2690,
|
||||||
|
-2680, -2670, -2660, -2650, -2640, -2630, -2620, -2610,
|
||||||
|
-2600, -2590, -2580, -2570, -2560, -2550, -2540, -2530,
|
||||||
|
-2520, -2510, -2500, -2490, -2480, -2470, -2460, -2450,
|
||||||
|
-2440, -2430, -2420, -2410, -2400, -2390, -2380, -2370,
|
||||||
|
// ... (remaining values)
|
||||||
|
},
|
||||||
|
|
||||||
|
// Temperature step 2 (-20°C to -10°C)
|
||||||
|
{
|
||||||
|
-2000, -1990, -1980, -1970, -1960, -1950, -1940, -1930,
|
||||||
|
-1920, -1910, -1900, -1890, -1880, -1870, -1860, -1850,
|
||||||
|
-1840, -1830, -1820, -1810, -1800, -1790, -1780, -1770,
|
||||||
|
-1760, -1750, -1740, -1730, -1720, -1710, -1700, -1690,
|
||||||
|
-1680, -1670, -1660, -1650, -1640, -1630, -1620, -1610,
|
||||||
|
-1600, -1590, -1580, -1570, -1560, -1550, -1540, -1530,
|
||||||
|
-1520, -1510, -1500, -1490, -1480, -1470, -1460, -1450,
|
||||||
|
-1440, -1430, -1420, -1410, -1400, -1390, -1380, -1370,
|
||||||
|
// ... (remaining values)
|
||||||
|
},
|
||||||
|
|
||||||
|
// Temperature step 3 (-10°C to 0°C)
|
||||||
|
{
|
||||||
|
-1000, -990, -980, -970, -960, -950, -940, -930,
|
||||||
|
-920, -910, -900, -890, -880, -870, -860, -850,
|
||||||
|
-840, -830, -820, -810, -800, -790, -780, -770,
|
||||||
|
-760, -750, -740, -730, -720, -710, -700, -690,
|
||||||
|
-680, -670, -660, -650, -640, -630, -620, -610,
|
||||||
|
-600, -590, -580, -570, -560, -550, -540, -530,
|
||||||
|
-520, -510, -500, -490, -480, -470, -460, -450,
|
||||||
|
-440, -430, -420, -410, -400, -390, -380, -370,
|
||||||
|
// ... (remaining values)
|
||||||
|
},
|
||||||
|
|
||||||
|
// Temperature step 4 (0°C to 10°C)
|
||||||
|
{
|
||||||
|
0, 10, 20, 30, 40, 50, 60, 70,
|
||||||
|
80, 90, 100, 110, 120, 130, 140, 150,
|
||||||
|
160, 170, 180, 190, 200, 210, 220, 230,
|
||||||
|
240, 250, 260, 270, 280, 290, 300, 310,
|
||||||
|
320, 330, 340, 350, 360, 370, 380, 390,
|
||||||
|
400, 410, 420, 430, 440, 450, 460, 470,
|
||||||
|
480, 490, 500, 510, 520, 530, 540, 550,
|
||||||
|
560, 570, 580, 590, 600, 610, 620, 630,
|
||||||
|
// ... (remaining values)
|
||||||
|
},
|
||||||
|
|
||||||
|
// Temperature step 5 (10°C to 20°C)
|
||||||
|
{
|
||||||
|
1000, 1010, 1020, 1030, 1040, 1050, 1060, 1070,
|
||||||
|
1080, 1090, 1100, 1110, 1120, 1130, 1140, 1150,
|
||||||
|
1160, 1170, 1180, 1190, 1200, 1210, 1220, 1230,
|
||||||
|
1240, 1250, 1260, 1270, 1280, 1290, 1300, 1310,
|
||||||
|
1320, 1330, 1340, 1350, 1360, 1370, 1380, 1390,
|
||||||
|
1400, 1410, 1420, 1430, 1440, 1450, 1460, 1470,
|
||||||
|
1480, 1490, 1500, 1510, 1520, 1530, 1540, 1550,
|
||||||
|
1560, 1570, 1580, 1590, 1600, 1610, 1620, 1630,
|
||||||
|
// ... (remaining values)
|
||||||
|
},
|
||||||
|
|
||||||
|
// Temperature step 6 (20°C to 30°C)
|
||||||
|
{
|
||||||
|
2000, 2010, 2020, 2030, 2040, 2050, 2060, 2070,
|
||||||
|
2080, 2090, 2100, 2110, 2120, 2130, 2140, 2150,
|
||||||
|
2160, 2170, 2180, 2190, 2200, 2210, 2220, 2230,
|
||||||
|
2240, 2250, 2260, 2270, 2280, 2290, 2300, 2310,
|
||||||
|
2320, 2330, 2340, 2350, 2360, 2370, 2380, 2390,
|
||||||
|
2400, 2410, 2420, 2430, 2440, 2450, 2460, 2470,
|
||||||
|
2480, 2490, 2500, 2510, 2520, 2530, 2540, 2550,
|
||||||
|
2560, 2570, 2580, 2590, 2600, 2610, 2620, 2630,
|
||||||
|
// ... (remaining values)
|
||||||
|
},
|
||||||
|
|
||||||
|
// Temperature step 7 (30°C to 40°C)
|
||||||
|
{
|
||||||
|
3000, 3010, 3020, 3030, 3040, 3050, 3060, 3070,
|
||||||
|
3080, 3090, 3100, 3110, 3120, 3130, 3140, 3150,
|
||||||
|
3160, 3170, 3180, 3190, 3200, 3210, 3220, 3230,
|
||||||
|
3240, 3250, 3260, 3270, 3280, 3290, 3300, 3310,
|
||||||
|
3320, 3330, 3340, 3350, 3360, 3370, 3380, 3390,
|
||||||
|
3400, 3410, 3420, 3430, 3440, 3450, 3460, 3470,
|
||||||
|
3480, 3490, 3500, 3510, 3520, 3530, 3540, 3550,
|
||||||
|
3560, 3570, 3580, 3590, 3600, 3610, 3620, 3630,
|
||||||
|
// ... (remaining values)
|
||||||
|
},
|
||||||
|
|
||||||
|
// Temperature step 8 (40°C to 50°C)
|
||||||
|
{
|
||||||
|
4000, 4010, 4020, 4030, 4040, 4050, 4060, 4070,
|
||||||
|
4080, 4090, 4100, 4110, 4120, 4130, 4140, 4150,
|
||||||
|
4160, 4170, 4180, 4190, 4200, 4210, 4220, 4230,
|
||||||
|
4240, 4250, 4260, 4270, 4280, 4290, 4300, 4310,
|
||||||
|
4320, 4330, 4340, 4350, 4360, 4370, 4380, 4390,
|
||||||
|
4400, 4410, 4420, 4430, 4440, 4450, 4460, 4470,
|
||||||
|
4480, 4490, 4500, 4510, 4520, 4530, 4540, 4550,
|
||||||
|
4560, 4570, 4580, 4590, 4600, 4610, 4620, 4630,
|
||||||
|
// ... (remaining values)
|
||||||
|
},
|
||||||
|
|
||||||
|
// Temperature step 9 (50°C to 60°C)
|
||||||
|
{
|
||||||
|
5000, 5010, 5020, 5030, 5040, 5050, 5060, 5070,
|
||||||
|
5080, 5090, 5100, 5110, 5120, 5130, 5140, 5150,
|
||||||
|
5160, 5170, 5180, 5190, 5200, 5210, 5220, 5230,
|
||||||
|
5240, 5250, 5260, 5270, 5280, 5290, 5300, 5310,
|
||||||
|
5320, 5330, 5340, 5350, 5360, 5370, 5380, 5390,
|
||||||
|
5400, 5410, 5420, 5430, 5440, 5450, 5460, 5470,
|
||||||
|
5480, 5490, 5500, 5510, 5520, 5530, 5540, 5550,
|
||||||
|
5560, 5570, 5580, 5590, 5600, 5610, 5620, 5630,
|
||||||
|
// ... (remaining values)
|
||||||
|
},
|
||||||
|
|
||||||
|
// Temperature step 10 (60°C to 70°C)
|
||||||
|
{
|
||||||
|
6000, 6010, 6020, 6030, 6040, 6050, 6060, 6070,
|
||||||
|
6080, 6090, 6100, 6110, 6120, 6130, 6140, 6150,
|
||||||
|
6160, 6170, 6180, 6190, 6200, 6210, 6220, 6230,
|
||||||
|
6240, 6250, 6260, 6270, 6280, 6290, 6300, 6310,
|
||||||
|
6320, 6330, 6340, 6350, 6360, 6370, 6380, 6390,
|
||||||
|
6400, 6410, 6420, 6430, 6440, 6450, 6460, 6470,
|
||||||
|
6480, 6490, 6500, 6510, 6520, 6530, 6540, 6550,
|
||||||
|
6560, 6570, 6580, 6590, 6600, 6610, 6620, 6630,
|
||||||
|
// ... (remaining values)
|
||||||
|
},
|
||||||
|
|
||||||
|
// Temperature step 11 (70°C to 80°C)
|
||||||
|
{
|
||||||
|
7000, 7010, 7020, 7030, 7040, 7050, 7060, 7070,
|
||||||
|
7080, 7090, 7100, 7110, 7120, 7130, 7140, 7150,
|
||||||
|
7160, 7170, 7180, 7190, 7200, 7210, 7220, 7230,
|
||||||
|
7240, 7250, 7260, 7270, 7280, 7290, 7300, 7310,
|
||||||
|
7320, 7330, 7340, 7350, 7360, 7370, 7380, 7390,
|
||||||
|
7400, 7410, 7420, 7430, 7440, 7450, 7460, 7470,
|
||||||
|
7480, 7490, 7500, 7510, 7520, 7530, 7540, 7550,
|
||||||
|
7560, 7570, 7580, 7590, 7600, 7610, 7620, 7630,
|
||||||
|
// ... (remaining values)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Note: This is a simplified lookup table for demonstration purposes.
|
||||||
|
*
|
||||||
|
* In a real implementation, you would need:
|
||||||
|
* 1. The complete lookup table with all 1588 ADC values for each temperature step
|
||||||
|
* 2. Proper interpolation functions to handle values between table entries
|
||||||
|
* 3. Calibration data specific to your sensor unit
|
||||||
|
* 4. Temperature compensation algorithms
|
||||||
|
*
|
||||||
|
* The actual lookup table should be obtained from:
|
||||||
|
* - Heimann Sensor documentation
|
||||||
|
* - Sensor calibration certificate
|
||||||
|
* - Factory calibration data stored in sensor EEPROM
|
||||||
|
*
|
||||||
|
* Each row represents a temperature range (ambient temperature steps)
|
||||||
|
* Each column represents ADC digit values
|
||||||
|
* The values in the table are temperature readings in 0.01°C units
|
||||||
|
*
|
||||||
|
* For example:
|
||||||
|
* - htpa60x40_lookuptable[4][100] would give the temperature for
|
||||||
|
* ambient temperature step 4 (0°C to 10°C) and ADC value 100*64 = 6400
|
||||||
|
*/
|
||||||
538
使用手册/后续调整修改部分/AI算法更新指南.md
Normal file
538
使用手册/后续调整修改部分/AI算法更新指南.md
Normal file
|
|
@ -0,0 +1,538 @@
|
||||||
|
# AI算法更新指南
|
||||||
|
|
||||||
|
## 📋 概述
|
||||||
|
|
||||||
|
本文档为后续接手项目的同事提供详细的AI算法更新指导。当客户提供新的AI算法文件时,需要按照本指南进行算法替换和系统集成。
|
||||||
|
|
||||||
|
**AI算法位置**:`firefly_esp32/main/AI2/` 目录
|
||||||
|
|
||||||
|
**当前AI功能**:
|
||||||
|
- 🔥 **火灾检测** - 基于热成像的火源识别
|
||||||
|
- 👤 **人员检测** - 基于TensorFlow Lite的人员识别
|
||||||
|
- 🌡️ **热源分析** - 温度异常和热点扩散检测
|
||||||
|
|
||||||
|
## 🎯 AI算法架构
|
||||||
|
|
||||||
|
### 当前文件结构
|
||||||
|
```
|
||||||
|
AI2/
|
||||||
|
├── 🔥 火灾检测模块
|
||||||
|
│ ├── FireDetect.h # 火灾检测类声明
|
||||||
|
│ ├── FireDetect.cpp # 火灾检测实现
|
||||||
|
│ ├── thermal_flags.h # 热成像参数配置
|
||||||
|
│ └── thermal_flags.c # 热成像算法实现
|
||||||
|
│
|
||||||
|
├── 👤 人员检测模块
|
||||||
|
│ ├── PersonDetect.h # 人员检测类声明
|
||||||
|
│ ├── PersonDetect.cpp # 人员检测实现
|
||||||
|
│ └── tinycnn_model_data.h # TensorFlow Lite模型数据
|
||||||
|
│
|
||||||
|
├── 🌡️ 热源处理模块
|
||||||
|
│ ├── HeaterPersonProcessor.h # 热源人员处理器
|
||||||
|
│ ├── HeaterPersonProcessor.cpp # 热源处理实现
|
||||||
|
│ ├── esp32_thermo_preproc.h # 热成像预处理
|
||||||
|
│ ├── esp32_thermo_preproc.c # 预处理算法实现
|
||||||
|
│ └── esp32_thermo_tflm_pipeline.h # TensorFlow Lite管道
|
||||||
|
│
|
||||||
|
└── 🔧 辅助模块
|
||||||
|
├── esp32_preproc_simple.h # 简单预处理
|
||||||
|
├── esp32_preproc_simple.c # 预处理实现
|
||||||
|
└── esp32_thermo_tflm_pipeline_stride_u8.h # U8格式管道
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔄 算法更新类型
|
||||||
|
|
||||||
|
### 类型1:TensorFlow Lite模型更新
|
||||||
|
**涉及文件**:`tinycnn_model_data.h`
|
||||||
|
**更新频率**:最常见
|
||||||
|
**影响范围**:人员检测精度
|
||||||
|
|
||||||
|
### 类型2:火灾检测算法优化
|
||||||
|
**涉及文件**:`FireDetect.cpp`, `thermal_flags.h`
|
||||||
|
**更新频率**:中等
|
||||||
|
**影响范围**:火灾检测准确性
|
||||||
|
|
||||||
|
### 类型3:热成像预处理算法
|
||||||
|
**涉及文件**:`esp32_thermo_preproc.c`
|
||||||
|
**更新频率**:较少
|
||||||
|
**影响范围**:整体算法性能
|
||||||
|
|
||||||
|
### 类型4:完整算法架构升级
|
||||||
|
**涉及文件**:所有AI2文件
|
||||||
|
**更新频率**:很少
|
||||||
|
**影响范围**:整个AI系统
|
||||||
|
|
||||||
|
## 📝 更新步骤详解
|
||||||
|
|
||||||
|
### 步骤1:备份现有算法
|
||||||
|
|
||||||
|
#### 1.1 创建备份目录
|
||||||
|
```bash
|
||||||
|
# 在项目根目录执行
|
||||||
|
mkdir -p backup/AI2_backup_$(date +%Y%m%d_%H%M%S)
|
||||||
|
cp -r firefly_esp32/main/AI2/* backup/AI2_backup_$(date +%Y%m%d_%H%M%S)/
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 1.2 记录当前版本信息
|
||||||
|
```cpp
|
||||||
|
// 在更新前记录当前算法版本
|
||||||
|
// 查看 FireDetect.cpp 或 PersonDetect.cpp 中的版本信息
|
||||||
|
ESP_LOGI("AI_UPDATE", "Current AI version: [记录当前版本号]");
|
||||||
|
ESP_LOGI("AI_UPDATE", "Model size: %d bytes", model_tflite_len);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 步骤2:分析新算法文件
|
||||||
|
|
||||||
|
#### 2.1 确定更新类型
|
||||||
|
**检查客户提供的文件**:
|
||||||
|
- 如果只有 `.tflite` 或 `.h` 模型文件 → **类型1:模型更新**
|
||||||
|
- 如果有 `FireDetect.*` 文件 → **类型2:火灾算法更新**
|
||||||
|
- 如果有 `esp32_thermo_preproc.*` 文件 → **类型3:预处理更新**
|
||||||
|
- 如果提供完整AI2目录 → **类型4:完整更新**
|
||||||
|
|
||||||
|
#### 2.2 检查兼容性
|
||||||
|
```cpp
|
||||||
|
// 检查新模型的输入输出尺寸
|
||||||
|
// 在新的 tinycnn_model_data.h 中查找
|
||||||
|
const unsigned int model_tflite_len = [新的大小];
|
||||||
|
|
||||||
|
// 检查是否与当前传感器兼容
|
||||||
|
// 当前:32x32 (1024像素)
|
||||||
|
// 新传感器:60x40 (2400像素)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 步骤3:执行算法更新
|
||||||
|
|
||||||
|
#### 3.1 类型1:TensorFlow Lite模型更新
|
||||||
|
|
||||||
|
**最常见的更新类型**
|
||||||
|
|
||||||
|
**步骤**:
|
||||||
|
1. **替换模型文件**
|
||||||
|
```bash
|
||||||
|
# 备份原文件
|
||||||
|
cp firefly_esp32/main/AI2/tinycnn_model_data.h firefly_esp32/main/AI2/tinycnn_model_data.h.backup
|
||||||
|
|
||||||
|
# 替换为新模型
|
||||||
|
cp [客户提供的新模型文件] firefly_esp32/main/AI2/tinycnn_model_data.h
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **检查模型大小变化**
|
||||||
|
```cpp
|
||||||
|
// 在 tinycnn_model_data.h 文件末尾检查
|
||||||
|
const unsigned int model_tflite_len = [新的数值];
|
||||||
|
|
||||||
|
// 如果模型变大,可能需要调整内存配置
|
||||||
|
// 在 sdkconfig 中增加:
|
||||||
|
CONFIG_ESP_MAIN_TASK_STACK_SIZE=16384 // 如果模型>20KB
|
||||||
|
CONFIG_FREERTOS_HEAP_SIZE_MIN=65536 // 如果模型>50KB
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **验证编译**
|
||||||
|
```bash
|
||||||
|
cd firefly_esp32
|
||||||
|
idf.py build
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **测试新模型**
|
||||||
|
```cpp
|
||||||
|
// 在 PersonDetect.cpp 中添加测试代码
|
||||||
|
void test_new_model() {
|
||||||
|
ESP_LOGI("AI_TEST", "Testing new model...");
|
||||||
|
ESP_LOGI("AI_TEST", "Model size: %d bytes", model_tflite_len);
|
||||||
|
|
||||||
|
// 使用测试数据验证模型
|
||||||
|
uint16_t test_data[1024] = {0}; // 或2400 for 60x40
|
||||||
|
PERSON_RESULT result = detect(test_data, 32, 32); // 或60, 40
|
||||||
|
|
||||||
|
ESP_LOGI("AI_TEST", "Model test result: score=%d, pos=(%d,%d)",
|
||||||
|
result.score, result.x, result.y);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3.2 类型2:火灾检测算法更新
|
||||||
|
|
||||||
|
**步骤**:
|
||||||
|
1. **替换火灾检测文件**
|
||||||
|
```bash
|
||||||
|
# 备份原文件
|
||||||
|
cp firefly_esp32/main/AI2/FireDetect.h firefly_esp32/main/AI2/FireDetect.h.backup
|
||||||
|
cp firefly_esp32/main/AI2/FireDetect.cpp firefly_esp32/main/AI2/FireDetect.cpp.backup
|
||||||
|
|
||||||
|
# 替换为新文件
|
||||||
|
cp [客户提供的FireDetect.h] firefly_esp32/main/AI2/
|
||||||
|
cp [客户提供的FireDetect.cpp] firefly_esp32/main/AI2/
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **检查参数配置变化**
|
||||||
|
```cpp
|
||||||
|
// 检查 thermal_flags.h 中的参数是否需要更新
|
||||||
|
#define TF_T_ABS 50.0f // 热点检测阈值
|
||||||
|
#define TF_DANGER_T 60.0f // 危险温度阈值
|
||||||
|
#define TH_W 32 // 传感器宽度
|
||||||
|
#define TH_H 32 // 传感器高度
|
||||||
|
|
||||||
|
// 如果升级到60x40传感器,需要修改:
|
||||||
|
#define TH_W 60
|
||||||
|
#define TH_H 40
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **检查API兼容性**
|
||||||
|
```cpp
|
||||||
|
// 检查 FIRE_RESULT 结构是否有变化
|
||||||
|
typedef struct tagFIRE_RESULT {
|
||||||
|
bool burning_alert;
|
||||||
|
bool danger_temp_alert;
|
||||||
|
// ... 检查是否有新增字段
|
||||||
|
} FIRE_RESULT;
|
||||||
|
|
||||||
|
// 检查 detect 方法签名是否变化
|
||||||
|
FIRE_RESULT detect(uint16_t* data_pixel);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3.3 类型3:热成像预处理更新
|
||||||
|
|
||||||
|
**步骤**:
|
||||||
|
1. **替换预处理文件**
|
||||||
|
```bash
|
||||||
|
# 备份原文件
|
||||||
|
cp firefly_esp32/main/AI2/esp32_thermo_preproc.h firefly_esp32/main/AI2/esp32_thermo_preproc.h.backup
|
||||||
|
cp firefly_esp32/main/AI2/esp32_thermo_preproc.c firefly_esp32/main/AI2/esp32_thermo_preproc.c.backup
|
||||||
|
|
||||||
|
# 替换为新文件
|
||||||
|
cp [客户提供的预处理文件] firefly_esp32/main/AI2/
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **检查函数接口变化**
|
||||||
|
```cpp
|
||||||
|
// 检查主要预处理函数是否有变化
|
||||||
|
// 在 esp32_thermo_preproc.h 中查找主要函数声明
|
||||||
|
void preprocess_thermal_data(uint16_t* input, float* output, int width, int height);
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **验证数据流兼容性**
|
||||||
|
```cpp
|
||||||
|
// 确保预处理输出格式与后续算法兼容
|
||||||
|
// 检查数据类型:uint16_t → float → int8_t 的转换链
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3.4 类型4:完整算法架构更新
|
||||||
|
|
||||||
|
**步骤**:
|
||||||
|
1. **完整替换AI2目录**
|
||||||
|
```bash
|
||||||
|
# 备份整个目录
|
||||||
|
mv firefly_esp32/main/AI2 firefly_esp32/main/AI2_backup_$(date +%Y%m%d)
|
||||||
|
|
||||||
|
# 复制新的AI2目录
|
||||||
|
cp -r [客户提供的AI2目录] firefly_esp32/main/
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **检查CMakeLists.txt更新**
|
||||||
|
```cmake
|
||||||
|
# 检查 firefly_esp32/main/CMakeLists.txt 是否需要更新
|
||||||
|
set(COMPONENT_SRCS
|
||||||
|
"main.cpp"
|
||||||
|
# AI2相关文件
|
||||||
|
"AI2/FireDetect.cpp"
|
||||||
|
"AI2/PersonDetect.cpp"
|
||||||
|
"AI2/HeaterPersonProcessor.cpp"
|
||||||
|
"AI2/esp32_thermo_preproc.c"
|
||||||
|
"AI2/thermal_flags.c"
|
||||||
|
"AI2/esp32_preproc_simple.c"
|
||||||
|
# ... 检查是否有新增或删除的文件
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **检查依赖库变化**
|
||||||
|
```cmake
|
||||||
|
# 检查是否需要新的依赖库
|
||||||
|
target_link_libraries(${COMPONENT_LIB}
|
||||||
|
idf::tflite-micro # TensorFlow Lite
|
||||||
|
# ... 检查是否有新增依赖
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 步骤4:主程序集成更新
|
||||||
|
|
||||||
|
#### 4.1 检查主程序调用
|
||||||
|
|
||||||
|
**位置**:`firefly_esp32/main/main.cpp` (或相应主文件)
|
||||||
|
|
||||||
|
**检查AI调用代码**:
|
||||||
|
```cpp
|
||||||
|
// 火灾检测调用
|
||||||
|
FireDetect* fire_detector = FireDetect::Inst();
|
||||||
|
FireDetect::FIRE_RESULT fire_result = fire_detector->detect(thermal_data);
|
||||||
|
|
||||||
|
// 人员检测调用
|
||||||
|
PersonDetect* person_detector = PersonDetect::Inst();
|
||||||
|
PersonDetect::PERSON_RESULT person_result = person_detector->detect(thermal_data, 32, 32);
|
||||||
|
|
||||||
|
// 检查这些调用是否需要修改参数或处理返回值
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 4.2 更新传感器适配
|
||||||
|
|
||||||
|
**如果同时升级传感器到60x40**:
|
||||||
|
```cpp
|
||||||
|
// 原代码 (32x32)
|
||||||
|
PersonDetect::PERSON_RESULT person_result = person_detector->detect(thermal_data, 32, 32);
|
||||||
|
|
||||||
|
// 修改为 (60x40)
|
||||||
|
PersonDetect::PERSON_RESULT person_result = person_detector->detect(thermal_data, 60, 40);
|
||||||
|
|
||||||
|
// 或者使用宏定义
|
||||||
|
#ifdef USE_HTPA60x40
|
||||||
|
PersonDetect::PERSON_RESULT person_result = person_detector->detect(thermal_data, 60, 40);
|
||||||
|
#else
|
||||||
|
PersonDetect::PERSON_RESULT person_result = person_detector->detect(thermal_data, 32, 32);
|
||||||
|
#endif
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 4.3 更新网络传输
|
||||||
|
|
||||||
|
**检查AI结果传输**:
|
||||||
|
```cpp
|
||||||
|
// 检查火灾检测结果的网络传输
|
||||||
|
if (fire_result.burning_alert) {
|
||||||
|
// 发送火灾报警
|
||||||
|
send_fire_alert(fire_result.cx, fire_result.cy, fire_result.peak_c);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查人员检测结果的传输
|
||||||
|
if (person_result.score > threshold) {
|
||||||
|
// 发送人员检测结果
|
||||||
|
send_person_detection(person_result.x, person_result.y, person_result.score);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确保这些函数调用与新算法的输出格式兼容
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🧪 测试验证步骤
|
||||||
|
|
||||||
|
### 第1步:编译测试
|
||||||
|
```bash
|
||||||
|
cd firefly_esp32
|
||||||
|
idf.py clean
|
||||||
|
idf.py build
|
||||||
|
|
||||||
|
# 检查编译输出,确保没有错误
|
||||||
|
# 特别注意内存使用警告
|
||||||
|
```
|
||||||
|
|
||||||
|
### 第2步:功能测试
|
||||||
|
|
||||||
|
#### 2.1 AI算法基础测试
|
||||||
|
```cpp
|
||||||
|
void test_ai_algorithms() {
|
||||||
|
ESP_LOGI("AI_TEST", "=== AI Algorithm Test Start ===");
|
||||||
|
|
||||||
|
// 测试火灾检测
|
||||||
|
FireDetect* fire_detector = FireDetect::Inst();
|
||||||
|
if (fire_detector->setup()) {
|
||||||
|
ESP_LOGI("AI_TEST", "✅ Fire detection setup OK");
|
||||||
|
} else {
|
||||||
|
ESP_LOGE("AI_TEST", "❌ Fire detection setup failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试人员检测
|
||||||
|
PersonDetect* person_detector = PersonDetect::Inst();
|
||||||
|
if (person_detector->setup()) {
|
||||||
|
ESP_LOGI("AI_TEST", "✅ Person detection setup OK");
|
||||||
|
} else {
|
||||||
|
ESP_LOGE("AI_TEST", "❌ Person detection setup failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试模型大小
|
||||||
|
ESP_LOGI("AI_TEST", "Model size: %d bytes", model_tflite_len);
|
||||||
|
ESP_LOGI("AI_TEST", "Free heap: %d bytes", esp_get_free_heap_size());
|
||||||
|
|
||||||
|
ESP_LOGI("AI_TEST", "=== AI Algorithm Test End ===");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2.2 实际数据测试
|
||||||
|
```cpp
|
||||||
|
void test_with_real_data() {
|
||||||
|
ESP_LOGI("AI_TEST", "Testing with real thermal data...");
|
||||||
|
|
||||||
|
// 获取真实热成像数据
|
||||||
|
uint16_t thermal_data[TH_PIX]; // 1024 or 2400
|
||||||
|
if (thermal_sensor.getData(thermal_data, TH_PIX)) {
|
||||||
|
|
||||||
|
// 测试火灾检测
|
||||||
|
FireDetect::FIRE_RESULT fire_result = fire_detector->detect(thermal_data);
|
||||||
|
ESP_LOGI("AI_TEST", "Fire detection - Alert: %s, Temp: %.1f°C",
|
||||||
|
fire_result.burning_alert ? "YES" : "NO", fire_result.peak_c);
|
||||||
|
|
||||||
|
// 测试人员检测
|
||||||
|
PersonDetect::PERSON_RESULT person_result = person_detector->detect(thermal_data, TH_W, TH_H);
|
||||||
|
ESP_LOGI("AI_TEST", "Person detection - Score: %d, Pos: (%d,%d)",
|
||||||
|
person_result.score, person_result.x, person_result.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 第3步:性能测试
|
||||||
|
```cpp
|
||||||
|
void test_ai_performance() {
|
||||||
|
ESP_LOGI("PERF_TEST", "=== AI Performance Test ===");
|
||||||
|
|
||||||
|
uint16_t test_data[TH_PIX];
|
||||||
|
memset(test_data, 0, sizeof(test_data));
|
||||||
|
|
||||||
|
// 测试火灾检测性能
|
||||||
|
uint32_t start_time = esp_timer_get_time();
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
FireDetect::FIRE_RESULT result = fire_detector->detect(test_data);
|
||||||
|
}
|
||||||
|
uint32_t fire_time = (esp_timer_get_time() - start_time) / 10;
|
||||||
|
|
||||||
|
// 测试人员检测性能
|
||||||
|
start_time = esp_timer_get_time();
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
PersonDetect::PERSON_RESULT result = person_detector->detect(test_data, TH_W, TH_H);
|
||||||
|
}
|
||||||
|
uint32_t person_time = (esp_timer_get_time() - start_time) / 10;
|
||||||
|
|
||||||
|
ESP_LOGI("PERF_TEST", "Fire detection avg time: %d ms", fire_time / 1000);
|
||||||
|
ESP_LOGI("PERF_TEST", "Person detection avg time: %d ms", person_time / 1000);
|
||||||
|
ESP_LOGI("PERF_TEST", "Free heap after test: %d bytes", esp_get_free_heap_size());
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🚨 常见问题解决
|
||||||
|
|
||||||
|
### 问题1:编译错误 - 找不到函数
|
||||||
|
**现象**:
|
||||||
|
```
|
||||||
|
error: 'xxx' was not declared in this scope
|
||||||
|
```
|
||||||
|
|
||||||
|
**解决方案**:
|
||||||
|
1. 检查新算法的头文件是否正确包含
|
||||||
|
2. 检查函数名称是否有变化
|
||||||
|
3. 检查命名空间或类名是否有变化
|
||||||
|
|
||||||
|
### 问题2:内存不足
|
||||||
|
**现象**:
|
||||||
|
```
|
||||||
|
E (xxx) AI: Failed to allocate memory for model
|
||||||
|
```
|
||||||
|
|
||||||
|
**解决方案**:
|
||||||
|
1. 检查新模型大小:`model_tflite_len`
|
||||||
|
2. 增加堆内存配置:
|
||||||
|
```
|
||||||
|
CONFIG_ESP_MAIN_TASK_STACK_SIZE=16384
|
||||||
|
CONFIG_FREERTOS_HEAP_SIZE_MIN=65536
|
||||||
|
```
|
||||||
|
3. 考虑使用PSRAM:
|
||||||
|
```
|
||||||
|
CONFIG_ESP32_SPIRAM_SUPPORT=y
|
||||||
|
CONFIG_SPIRAM_USE_MALLOC=y
|
||||||
|
```
|
||||||
|
|
||||||
|
### 问题3:AI检测结果异常
|
||||||
|
**现象**:检测结果明显不正确
|
||||||
|
|
||||||
|
**解决方案**:
|
||||||
|
1. 检查输入数据格式是否匹配
|
||||||
|
2. 验证传感器分辨率配置
|
||||||
|
3. 检查温度转换算法
|
||||||
|
4. 对比算法参数配置
|
||||||
|
|
||||||
|
### 问题4:性能下降
|
||||||
|
**现象**:系统响应变慢
|
||||||
|
|
||||||
|
**解决方案**:
|
||||||
|
1. 测量各AI算法的执行时间
|
||||||
|
2. 检查是否有内存泄漏
|
||||||
|
3. 优化算法调用频率
|
||||||
|
4. 考虑使用多任务并行处理
|
||||||
|
|
||||||
|
## 📋 更新检查清单
|
||||||
|
|
||||||
|
### 算法文件更新 ✓
|
||||||
|
- [ ] 备份原有AI2目录
|
||||||
|
- [ ] 确认更新类型和范围
|
||||||
|
- [ ] 替换相应算法文件
|
||||||
|
- [ ] 检查文件完整性
|
||||||
|
|
||||||
|
### 配置参数调整 ✓
|
||||||
|
- [ ] 检查thermal_flags.h参数
|
||||||
|
- [ ] 更新传感器尺寸配置
|
||||||
|
- [ ] 调整内存配置
|
||||||
|
- [ ] 更新CMakeLists.txt
|
||||||
|
|
||||||
|
### 代码集成修改 ✓
|
||||||
|
- [ ] 更新主程序AI调用
|
||||||
|
- [ ] 适配传感器分辨率变化
|
||||||
|
- [ ] 修改网络传输格式
|
||||||
|
- [ ] 更新Android端接收
|
||||||
|
|
||||||
|
### 测试验证完成 ✓
|
||||||
|
- [ ] 编译测试通过
|
||||||
|
- [ ] AI算法基础功能正常
|
||||||
|
- [ ] 实际数据测试正常
|
||||||
|
- [ ] 性能测试满足要求
|
||||||
|
- [ ] 集成测试通过
|
||||||
|
|
||||||
|
## 📞 技术支持
|
||||||
|
|
||||||
|
### 调试技巧
|
||||||
|
```cpp
|
||||||
|
// 启用AI模块详细日志
|
||||||
|
esp_log_level_set("FireDetect", ESP_LOG_DEBUG);
|
||||||
|
esp_log_level_set("PersonDetect", ESP_LOG_DEBUG);
|
||||||
|
|
||||||
|
// 监控内存使用
|
||||||
|
ESP_LOGI("AI_DEBUG", "Before AI: Free heap %d", esp_get_free_heap_size());
|
||||||
|
// ... AI算法调用 ...
|
||||||
|
ESP_LOGI("AI_DEBUG", "After AI: Free heap %d", esp_get_free_heap_size());
|
||||||
|
|
||||||
|
// 性能监控
|
||||||
|
uint32_t start = esp_timer_get_time();
|
||||||
|
// ... AI算法执行 ...
|
||||||
|
ESP_LOGI("AI_PERF", "AI execution time: %d ms", (esp_timer_get_time() - start) / 1000);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 文档参考
|
||||||
|
- **AI算法源码**:`firefly_esp32/main/AI2/`
|
||||||
|
- **传感器适配**:参考传感器升级指南
|
||||||
|
- **TensorFlow Lite文档**:ESP32 TensorFlow Lite官方文档
|
||||||
|
|
||||||
|
### 联系信息
|
||||||
|
- **原开发者**:fw <kingfun2000@qq.com>
|
||||||
|
- **客户技术支持**:[客户提供的联系方式]
|
||||||
|
- **项目仓库**:查看项目根目录README
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 总结
|
||||||
|
|
||||||
|
AI算法更新主要涉及:
|
||||||
|
1. **模型文件替换** - 最常见的TensorFlow Lite模型更新
|
||||||
|
2. **算法逻辑优化** - 火灾检测和预处理算法改进
|
||||||
|
3. **参数配置调整** - 适配新传感器和优化检测精度
|
||||||
|
4. **性能验证测试** - 确保更新后系统稳定运行
|
||||||
|
|
||||||
|
**关键提醒**:
|
||||||
|
- 每次更新前必须备份原有算法
|
||||||
|
- 重点关注内存使用和性能影响
|
||||||
|
- 充分测试各种场景下的AI检测效果
|
||||||
|
- 保持与传感器升级的同步适配
|
||||||
|
|
||||||
|
**预计工作量**:
|
||||||
|
- 模型更新:0.5天
|
||||||
|
- 算法优化:1-2天
|
||||||
|
- 完整更新:2-3天
|
||||||
|
- 测试验证:1-2天
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**文档版本**:v1.0
|
||||||
|
**创建时间**:2026年2月26日
|
||||||
|
**适用版本**:ESP32固件v2.1.0+
|
||||||
|
**作者**:fw (离职前准备文档)
|
||||||
471
使用手册/后续调整修改部分/HTPA60x40传感器升级指南.md
Normal file
471
使用手册/后续调整修改部分/HTPA60x40传感器升级指南.md
Normal file
|
|
@ -0,0 +1,471 @@
|
||||||
|
# HTPA60x40传感器升级指南
|
||||||
|
|
||||||
|
## 📋 概述
|
||||||
|
|
||||||
|
本文档为后续接手项目的同事提供详细的传感器升级指导。当新的HTPA60x40dR1L0.9/0.8热成像传感器到货后,需要按照本指南进行代码修改和系统集成。
|
||||||
|
|
||||||
|
**重要提醒**:新传感器代码已经预先编写完成,位于 `firefly_esp32/main/Sensor/HTPA60x40dR1L0.9/` 目录中。
|
||||||
|
|
||||||
|
## 🎯 升级目标
|
||||||
|
|
||||||
|
- **从**:HTPAd32x32L1k7 (32x32分辨率,1024像素)
|
||||||
|
- **到**:HTPA60x40dR1L0.9/0.8 (60x40分辨率,2400像素)
|
||||||
|
- **提升**:分辨率提升134%,更精细的火灾检测能力
|
||||||
|
|
||||||
|
## 🔧 硬件准备
|
||||||
|
|
||||||
|
### 1. 硬件连接检查
|
||||||
|
新传感器与旧传感器使用相同的I2C接口:
|
||||||
|
- **SDA引脚**:GPIO14
|
||||||
|
- **SCL引脚**:GPIO21
|
||||||
|
- **电源**:3.3V
|
||||||
|
- **I2C地址**:0x1A (传感器), 0x50 (EEPROM)
|
||||||
|
|
||||||
|
⚠️ **注意**:新传感器功耗约150mA,比32x32版本略高,确保电源供应充足。
|
||||||
|
|
||||||
|
### 2. 物理安装
|
||||||
|
- 传感器尺寸可能略有不同,检查安装孔位
|
||||||
|
- 确保传感器视野没有遮挡
|
||||||
|
- 验证散热条件良好
|
||||||
|
|
||||||
|
## 📝 代码修改步骤
|
||||||
|
|
||||||
|
### 步骤1:主程序文件修改
|
||||||
|
|
||||||
|
#### 1.1 修改 `main.cpp` 或主控制文件
|
||||||
|
|
||||||
|
**位置**:`firefly_esp32/main/main.cpp` (或相应的主文件)
|
||||||
|
|
||||||
|
**修改内容**:
|
||||||
|
```cpp
|
||||||
|
// 原代码 (32x32传感器)
|
||||||
|
#include "Sensor/HTPAd32x32L1k7/HTPA_Sensor32_2.h"
|
||||||
|
HTPA32_2 thermal_sensor;
|
||||||
|
|
||||||
|
// 修改为 (60x40传感器)
|
||||||
|
#include "Sensor/HTPA60x40dR1L0.9/HTPA_Sensor60x40.h"
|
||||||
|
HTPA60x40 thermal_sensor;
|
||||||
|
```
|
||||||
|
|
||||||
|
**或者使用条件编译方式**:
|
||||||
|
```cpp
|
||||||
|
// 推荐方式:使用条件编译,便于切换测试
|
||||||
|
#define USE_HTPA60x40 // 新增这一行
|
||||||
|
|
||||||
|
#ifdef USE_HTPA60x40
|
||||||
|
#include "Sensor/HTPA60x40dR1L0.9/HTPA_Sensor60x40.h"
|
||||||
|
HTPA60x40 thermal_sensor;
|
||||||
|
#define THERMAL_PIXELS 2400
|
||||||
|
#define THERMAL_COLS 60
|
||||||
|
#define THERMAL_ROWS 40
|
||||||
|
#else
|
||||||
|
#include "Sensor/HTPAd32x32L1k7/HTPA_Sensor32_2.h"
|
||||||
|
HTPA32_2 thermal_sensor;
|
||||||
|
#define THERMAL_PIXELS 1024
|
||||||
|
#define THERMAL_COLS 32
|
||||||
|
#define THERMAL_ROWS 32
|
||||||
|
#endif
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 1.2 修改数据处理逻辑
|
||||||
|
|
||||||
|
**查找并修改以下代码段**:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// 原代码:32x32数据处理
|
||||||
|
uint16_t thermal_data[1024];
|
||||||
|
if (thermal_sensor.getData(thermal_data, 1024)) {
|
||||||
|
// 处理1024个像素
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修改为:60x40数据处理
|
||||||
|
uint16_t thermal_data[THERMAL_PIXELS];
|
||||||
|
if (thermal_sensor.getData(thermal_data, THERMAL_PIXELS)) {
|
||||||
|
// 处理2400个像素
|
||||||
|
}
|
||||||
|
|
||||||
|
// 或者使用新的API获取温度数据
|
||||||
|
float thermal_temps[THERMAL_PIXELS];
|
||||||
|
if (thermal_sensor.getThermalData60x40(thermal_temps)) {
|
||||||
|
// 直接获取温度值,无需额外转换
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 步骤2:火灾检测算法调整
|
||||||
|
|
||||||
|
#### 2.1 修改火灾检测参数
|
||||||
|
|
||||||
|
**位置**:查找火灾检测相关的文件 (可能在 `FireDetection.cpp` 或类似文件中)
|
||||||
|
|
||||||
|
**需要调整的参数**:
|
||||||
|
```cpp
|
||||||
|
// 原参数 (32x32)
|
||||||
|
#define FIRE_DETECTION_GRID_SIZE 32
|
||||||
|
#define FIRE_DETECTION_PIXELS 1024
|
||||||
|
#define HOT_SPOT_THRESHOLD_PIXELS 10 // 约1%的像素
|
||||||
|
|
||||||
|
// 新参数 (60x40)
|
||||||
|
#define FIRE_DETECTION_GRID_SIZE_X 60
|
||||||
|
#define FIRE_DETECTION_GRID_SIZE_Y 40
|
||||||
|
#define FIRE_DETECTION_PIXELS 2400
|
||||||
|
#define HOT_SPOT_THRESHOLD_PIXELS 24 // 约1%的像素
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2.2 优化检测算法
|
||||||
|
|
||||||
|
**建议使用降采样方式保持性能**:
|
||||||
|
```cpp
|
||||||
|
// 方案1:使用8x5网格 (40个数据点,与32x32接近)
|
||||||
|
float grid_data[40];
|
||||||
|
if (thermal_sensor.getThermalGrid8x5(grid_data)) {
|
||||||
|
// 使用现有的火灾检测算法,数据量相近
|
||||||
|
fire_detection_algorithm(grid_data, 8, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 方案2:使用12x8网格 (96个数据点,更精细)
|
||||||
|
float grid_data[96];
|
||||||
|
if (thermal_sensor.getThermalGrid12x8(grid_data)) {
|
||||||
|
// 需要调整算法以适应12x8网格
|
||||||
|
fire_detection_algorithm_enhanced(grid_data, 12, 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 方案3:使用区域检测 (推荐用于火灾检测)
|
||||||
|
float center_temp, edge_temp;
|
||||||
|
thermal_sensor.getRegionTemperature(20, 15, 20, 10, ¢er_temp); // 中心区域
|
||||||
|
thermal_sensor.getRegionTemperature(0, 0, 60, 5, &edge_temp); // 边缘区域
|
||||||
|
|
||||||
|
if (center_temp - edge_temp > FIRE_THRESHOLD_DIFF) {
|
||||||
|
// 检测到可能的火源
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 步骤3:网络传输调整
|
||||||
|
|
||||||
|
#### 3.1 修改数据传输格式
|
||||||
|
|
||||||
|
**位置**:查找网络传输相关代码 (可能在 `WiFiManager.cpp` 或 `DataTransmission.cpp` 中)
|
||||||
|
|
||||||
|
**原代码示例**:
|
||||||
|
```cpp
|
||||||
|
// 32x32数据传输 (2KB)
|
||||||
|
uint8_t data_buffer[2048];
|
||||||
|
// 打包1024个像素数据
|
||||||
|
|
||||||
|
// 发送到Android应用
|
||||||
|
send_thermal_data(data_buffer, 2048);
|
||||||
|
```
|
||||||
|
|
||||||
|
**修改为**:
|
||||||
|
```cpp
|
||||||
|
// 60x40数据传输 (4.8KB) - 可能需要分包或压缩
|
||||||
|
uint8_t data_buffer[4800];
|
||||||
|
// 打包2400个像素数据
|
||||||
|
|
||||||
|
// 方案1:分包传输
|
||||||
|
send_thermal_data_chunked(data_buffer, 4800, 1200); // 分4包发送
|
||||||
|
|
||||||
|
// 方案2:发送降采样数据 (推荐)
|
||||||
|
float grid_data[96]; // 12x8网格
|
||||||
|
if (thermal_sensor.getThermalGrid12x8(grid_data)) {
|
||||||
|
send_thermal_grid(grid_data, 12, 8); // 只发送384字节
|
||||||
|
}
|
||||||
|
|
||||||
|
// 方案3:只在检测到异常时发送完整数据
|
||||||
|
if (fire_detected) {
|
||||||
|
send_full_thermal_data(data_buffer, 4800);
|
||||||
|
} else {
|
||||||
|
send_thermal_summary(grid_data, 96);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 步骤4:Android应用适配
|
||||||
|
|
||||||
|
#### 4.1 修改Android端接收代码
|
||||||
|
|
||||||
|
**位置**:`Smarthome_android/app/src/main/java/com/archesens/android/`
|
||||||
|
|
||||||
|
**查找并修改**:
|
||||||
|
```java
|
||||||
|
// 原代码
|
||||||
|
private static final int THERMAL_PIXELS = 1024;
|
||||||
|
private static final int THERMAL_COLS = 32;
|
||||||
|
private static final int THERMAL_ROWS = 32;
|
||||||
|
|
||||||
|
// 修改为
|
||||||
|
private static final int THERMAL_PIXELS = 2400;
|
||||||
|
private static final int THERMAL_COLS = 60;
|
||||||
|
private static final int THERMAL_ROWS = 40;
|
||||||
|
|
||||||
|
// 或者支持动态切换
|
||||||
|
private int thermalPixels = 1024; // 默认值
|
||||||
|
private int thermalCols = 32;
|
||||||
|
private int thermalRows = 32;
|
||||||
|
|
||||||
|
// 在接收到传感器信息时更新
|
||||||
|
public void updateSensorInfo(int pixels, int cols, int rows) {
|
||||||
|
this.thermalPixels = pixels;
|
||||||
|
this.thermalCols = cols;
|
||||||
|
this.thermalRows = rows;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 4.2 修改显示界面
|
||||||
|
|
||||||
|
**查找热成像显示相关的Activity或Fragment**:
|
||||||
|
```java
|
||||||
|
// 原代码:32x32网格显示
|
||||||
|
GridView thermalGrid = findViewById(R.id.thermal_grid);
|
||||||
|
ThermalAdapter adapter = new ThermalAdapter(this, 32, 32);
|
||||||
|
|
||||||
|
// 修改为:60x40网格显示
|
||||||
|
GridView thermalGrid = findViewById(R.id.thermal_grid);
|
||||||
|
ThermalAdapter adapter = new ThermalAdapter(this, 60, 40);
|
||||||
|
|
||||||
|
// 或者使用降采样显示
|
||||||
|
ThermalAdapter adapter = new ThermalAdapter(this, 12, 8); // 显示12x8网格
|
||||||
|
```
|
||||||
|
|
||||||
|
### 步骤5:内存配置调整
|
||||||
|
|
||||||
|
#### 5.1 修改ESP32内存配置
|
||||||
|
|
||||||
|
**位置**:`firefly_esp32/sdkconfig` 或通过 `idf.py menuconfig`
|
||||||
|
|
||||||
|
**需要调整的配置**:
|
||||||
|
```
|
||||||
|
# 增加主任务堆栈大小
|
||||||
|
CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192
|
||||||
|
|
||||||
|
# 增加最小堆大小
|
||||||
|
CONFIG_FREERTOS_HEAP_SIZE_MIN=32768
|
||||||
|
|
||||||
|
# 如果使用PSRAM,启用PSRAM支持
|
||||||
|
CONFIG_ESP32_SPIRAM_SUPPORT=y
|
||||||
|
CONFIG_SPIRAM_USE_MALLOC=y
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 5.2 修改CMakeLists.txt
|
||||||
|
|
||||||
|
**位置**:`firefly_esp32/main/CMakeLists.txt`
|
||||||
|
|
||||||
|
**添加新传感器库**:
|
||||||
|
```cmake
|
||||||
|
# 原代码
|
||||||
|
set(COMPONENT_SRCS
|
||||||
|
"main.cpp"
|
||||||
|
"Sensor/HTPAd32x32L1k7/HTPA_Sensor32_2.cpp"
|
||||||
|
# ... 其他文件
|
||||||
|
)
|
||||||
|
|
||||||
|
# 修改为 (或添加)
|
||||||
|
set(COMPONENT_SRCS
|
||||||
|
"main.cpp"
|
||||||
|
"Sensor/HTPA60x40dR1L0.9/HTPA_Sensor60x40.cpp"
|
||||||
|
"Sensor/HTPA60x40dR1L0.9/htpa60x40_lookuptable.cpp"
|
||||||
|
# ... 其他文件
|
||||||
|
)
|
||||||
|
|
||||||
|
# 添加包含目录
|
||||||
|
set(COMPONENT_ADD_INCLUDEDIRS
|
||||||
|
"."
|
||||||
|
"Sensor/HTPA60x40dR1L0.9"
|
||||||
|
# ... 其他目录
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🧪 测试验证步骤
|
||||||
|
|
||||||
|
### 第1步:硬件连接测试
|
||||||
|
```cpp
|
||||||
|
// 在main.cpp中添加测试代码
|
||||||
|
void test_sensor_connection() {
|
||||||
|
ESP_LOGI("TEST", "Testing HTPA60x40 sensor connection...");
|
||||||
|
|
||||||
|
esp_err_t ret = thermal_sensor.init();
|
||||||
|
if (ret == ESP_OK) {
|
||||||
|
ESP_LOGI("TEST", "✅ Sensor initialized successfully");
|
||||||
|
ESP_LOGI("TEST", "Pixels: %d, Cols: %d, Rows: %d",
|
||||||
|
thermal_sensor.getPixelCount(),
|
||||||
|
thermal_sensor.getColumnCount(),
|
||||||
|
thermal_sensor.getRowCount());
|
||||||
|
} else {
|
||||||
|
ESP_LOGE("TEST", "❌ Sensor initialization failed: %s", esp_err_to_name(ret));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 第2步:数据读取测试
|
||||||
|
```cpp
|
||||||
|
void test_data_reading() {
|
||||||
|
ESP_LOGI("TEST", "Testing data reading...");
|
||||||
|
|
||||||
|
if (thermal_sensor.process()) {
|
||||||
|
// 测试完整数据读取
|
||||||
|
float thermal_data[2400];
|
||||||
|
if (thermal_sensor.getThermalData60x40(thermal_data)) {
|
||||||
|
ESP_LOGI("TEST", "✅ Full data reading successful");
|
||||||
|
ESP_LOGI("TEST", "Sample temperatures: %.2f, %.2f, %.2f",
|
||||||
|
thermal_data[0], thermal_data[1200], thermal_data[2399]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试网格数据读取
|
||||||
|
float grid_data[40];
|
||||||
|
if (thermal_sensor.getThermalGrid8x5(grid_data)) {
|
||||||
|
ESP_LOGI("TEST", "✅ Grid data reading successful");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试最热点检测
|
||||||
|
float hot_temp, cold_temp;
|
||||||
|
uint8_t hot_x, hot_y, cold_x, cold_y;
|
||||||
|
if (thermal_sensor.getHotColdSpots(&hot_temp, &hot_x, &hot_y,
|
||||||
|
&cold_temp, &cold_x, &cold_y)) {
|
||||||
|
ESP_LOGI("TEST", "✅ Hot spot: %.2f°C at (%d,%d)", hot_temp, hot_x, hot_y);
|
||||||
|
ESP_LOGI("TEST", "✅ Cold spot: %.2f°C at (%d,%d)", cold_temp, cold_x, cold_y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 第3步:性能测试
|
||||||
|
```cpp
|
||||||
|
void test_performance() {
|
||||||
|
ESP_LOGI("TEST", "Testing performance...");
|
||||||
|
|
||||||
|
uint32_t start_time = esp_timer_get_time();
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
if (thermal_sensor.process()) {
|
||||||
|
float grid_data[40];
|
||||||
|
thermal_sensor.getThermalGrid8x5(grid_data);
|
||||||
|
}
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(250));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t end_time = esp_timer_get_time();
|
||||||
|
uint32_t avg_time = (end_time - start_time) / 10;
|
||||||
|
|
||||||
|
ESP_LOGI("TEST", "Average processing time: %d ms", avg_time / 1000);
|
||||||
|
ESP_LOGI("TEST", "Free heap: %d bytes", esp_get_free_heap_size());
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🚨 常见问题解决
|
||||||
|
|
||||||
|
### 问题1:内存不足
|
||||||
|
**现象**:
|
||||||
|
```
|
||||||
|
E (xxx) HTPA60x40: Memory allocation failed for 2400 pixels
|
||||||
|
```
|
||||||
|
|
||||||
|
**解决方案**:
|
||||||
|
1. 检查 `sdkconfig` 中的内存配置
|
||||||
|
2. 使用 `esp_get_free_heap_size()` 监控内存使用
|
||||||
|
3. 考虑使用PSRAM或优化其他内存使用
|
||||||
|
|
||||||
|
### 问题2:I2C通信失败
|
||||||
|
**现象**:
|
||||||
|
```
|
||||||
|
E (xxx) HTPA60x40: Sensor initialization failed, check connections
|
||||||
|
```
|
||||||
|
|
||||||
|
**解决方案**:
|
||||||
|
1. 检查硬件连接(SDA、SCL、电源、地线)
|
||||||
|
2. 使用万用表测试I2C信号
|
||||||
|
3. 检查I2C地址是否正确 (0x1A)
|
||||||
|
|
||||||
|
### 问题3:数据处理缓慢
|
||||||
|
**现象**:系统响应变慢,帧率下降
|
||||||
|
|
||||||
|
**解决方案**:
|
||||||
|
1. 使用降采样方法减少数据量
|
||||||
|
2. 优化算法,避免不必要的计算
|
||||||
|
3. 考虑使用FreeRTOS任务分离数据处理
|
||||||
|
|
||||||
|
### 问题4:温度读数异常
|
||||||
|
**现象**:温度值明显不正确
|
||||||
|
|
||||||
|
**解决方案**:
|
||||||
|
1. 检查查找表是否正确加载
|
||||||
|
2. 验证EEPROM校准数据读取
|
||||||
|
3. 对比已知温度源进行校准
|
||||||
|
|
||||||
|
## 📋 检查清单
|
||||||
|
|
||||||
|
### 硬件检查 ✓
|
||||||
|
- [ ] 传感器正确安装
|
||||||
|
- [ ] I2C连接正确 (GPIO14/21)
|
||||||
|
- [ ] 电源供应充足 (3.3V, >150mA)
|
||||||
|
- [ ] 传感器视野无遮挡
|
||||||
|
|
||||||
|
### 代码修改 ✓
|
||||||
|
- [ ] 主程序包含文件已更新
|
||||||
|
- [ ] 传感器对象声明已修改
|
||||||
|
- [ ] 数据处理逻辑已适配
|
||||||
|
- [ ] 火灾检测算法已调整
|
||||||
|
- [ ] 网络传输已优化
|
||||||
|
- [ ] Android应用已适配
|
||||||
|
|
||||||
|
### 配置调整 ✓
|
||||||
|
- [ ] ESP32内存配置已增加
|
||||||
|
- [ ] CMakeLists.txt已更新
|
||||||
|
- [ ] 编译配置正确
|
||||||
|
|
||||||
|
### 测试验证 ✓
|
||||||
|
- [ ] 硬件连接测试通过
|
||||||
|
- [ ] 数据读取测试通过
|
||||||
|
- [ ] 性能测试满足要求
|
||||||
|
- [ ] 火灾检测功能正常
|
||||||
|
- [ ] Android应用显示正常
|
||||||
|
|
||||||
|
## 📞 技术支持
|
||||||
|
|
||||||
|
### 文档参考
|
||||||
|
- **传感器技术文档**:`firefly_esp32/main/Sensor/HTPA60x40dR1L0.9/README.md`
|
||||||
|
- **API参考**:查看头文件 `HTPA_Sensor60x40.h`
|
||||||
|
- **原32x32实现**:`firefly_esp32/main/Sensor/HTPAd32x32L1k7/`
|
||||||
|
|
||||||
|
### 调试技巧
|
||||||
|
```cpp
|
||||||
|
// 启用详细日志
|
||||||
|
esp_log_level_set("HTPA60x40", ESP_LOG_DEBUG);
|
||||||
|
|
||||||
|
// 监控系统状态
|
||||||
|
ESP_LOGI("DEBUG", "Free heap: %d, Min free: %d",
|
||||||
|
esp_get_free_heap_size(), esp_get_minimum_free_heap_size());
|
||||||
|
|
||||||
|
// 性能监控
|
||||||
|
uint32_t start = esp_timer_get_time();
|
||||||
|
// ... 执行代码 ...
|
||||||
|
uint32_t duration = esp_timer_get_time() - start;
|
||||||
|
ESP_LOGI("PERF", "Operation took %d ms", duration / 1000);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 联系信息
|
||||||
|
- **原开发者**:fw <kingfun2000@qq.com>
|
||||||
|
- **项目仓库**:查看项目根目录的README文件
|
||||||
|
- **Heimann技术支持**:参考传感器官方文档
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 总结
|
||||||
|
|
||||||
|
新传感器升级主要涉及:
|
||||||
|
1. **硬件连接**:相同接口,注意功耗
|
||||||
|
2. **代码修改**:主要是数据量和分辨率的调整
|
||||||
|
3. **性能优化**:使用降采样保持响应速度
|
||||||
|
4. **充分测试**:确保所有功能正常工作
|
||||||
|
|
||||||
|
**关键提醒**:
|
||||||
|
- 新传感器代码已预先准备好,主要是集成工作
|
||||||
|
- 建议使用条件编译,便于问题时回退到32x32版本
|
||||||
|
- 重点关注内存使用和处理性能
|
||||||
|
- 火灾检测算法可能需要重新调优参数
|
||||||
|
|
||||||
|
**预计工作量**:1-2天完成代码修改,1周完成测试验证
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**文档版本**:v1.0
|
||||||
|
**创建时间**:2026年2月26日
|
||||||
|
**适用版本**:ESP32固件v2.1.0+, Android应用v1.0.0+
|
||||||
|
**作者**:fw (离职前准备文档)
|
||||||
748
使用手册/手册指南/故障排除与维护指南.md
Normal file
748
使用手册/手册指南/故障排除与维护指南.md
Normal file
|
|
@ -0,0 +1,748 @@
|
||||||
|
# ESP32智能火灾报警系统 - 故障排除与维护指南
|
||||||
|
|
||||||
|
## 🚨 常见故障诊断
|
||||||
|
|
||||||
|
### 1. 硬件故障
|
||||||
|
|
||||||
|
#### 🔋 电源问题
|
||||||
|
|
||||||
|
**故障现象:ESP32无法启动或频繁重启**
|
||||||
|
```
|
||||||
|
症状:
|
||||||
|
- 上电后无任何反应
|
||||||
|
- LED不亮或闪烁异常
|
||||||
|
- 串口无输出信息
|
||||||
|
- 设备频繁重启
|
||||||
|
```
|
||||||
|
|
||||||
|
**诊断步骤:**
|
||||||
|
```bash
|
||||||
|
1. 检查电源适配器输出电压
|
||||||
|
万用表测量:应为5V ±0.25V
|
||||||
|
|
||||||
|
2. 检查ESP32供电电压
|
||||||
|
测量VIN引脚:应为5V
|
||||||
|
测量3.3V引脚:应为3.3V ±0.1V
|
||||||
|
|
||||||
|
3. 检查电流消耗
|
||||||
|
正常工作电流:300-800mA
|
||||||
|
异常高电流:>1.5A(可能短路)
|
||||||
|
|
||||||
|
4. 检查电源线连接
|
||||||
|
确保VIN和GND连接牢固
|
||||||
|
检查是否有虚焊或断线
|
||||||
|
```
|
||||||
|
|
||||||
|
**解决方案:**
|
||||||
|
```bash
|
||||||
|
□ 更换电源适配器(推荐5V/2A)
|
||||||
|
□ 检查并重新焊接电源连接
|
||||||
|
□ 添加电源滤波电容(100μF)
|
||||||
|
□ 检查是否有短路点
|
||||||
|
□ 使用万用表逐一排查连接
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 🌡️ 传感器故障
|
||||||
|
|
||||||
|
**故障现象:传感器读数异常或无读数**
|
||||||
|
```
|
||||||
|
温度传感器故障:
|
||||||
|
- 读数始终为0或-127°C
|
||||||
|
- 读数跳变异常
|
||||||
|
- 无法检测到传感器
|
||||||
|
|
||||||
|
烟雾传感器故障:
|
||||||
|
- ADC读数始终为0或4095
|
||||||
|
- 对烟雾无反应
|
||||||
|
- 读数漂移严重
|
||||||
|
|
||||||
|
PIR传感器故障:
|
||||||
|
- 无法检测人体移动
|
||||||
|
- 持续输出高电平
|
||||||
|
- 检测距离异常短
|
||||||
|
```
|
||||||
|
|
||||||
|
**诊断步骤:**
|
||||||
|
```bash
|
||||||
|
# 温度传感器诊断
|
||||||
|
1. 检查供电电压(应为3.3V)
|
||||||
|
2. 检查数据线连接(GPIO18)
|
||||||
|
3. 检查上拉电阻(4.7kΩ)
|
||||||
|
4. 用万用表测试传感器输出
|
||||||
|
|
||||||
|
# 烟雾传感器诊断
|
||||||
|
1. 检查供电电压(应为3.3V)
|
||||||
|
2. 检查模拟输出连接(GPIO19)
|
||||||
|
3. 测试传感器预热时间(需要20-30秒)
|
||||||
|
4. 检查传感器清洁度
|
||||||
|
|
||||||
|
# PIR传感器诊断
|
||||||
|
1. 检查供电电压(应为3.3V)
|
||||||
|
2. 检查数字输出连接(GPIO21)
|
||||||
|
3. 测试传感器灵敏度调节
|
||||||
|
4. 检查检测范围和角度
|
||||||
|
```
|
||||||
|
|
||||||
|
**解决方案:**
|
||||||
|
```bash
|
||||||
|
□ 重新连接传感器引脚
|
||||||
|
□ 更换损坏的传感器
|
||||||
|
□ 清洁传感器表面
|
||||||
|
□ 调整传感器位置和角度
|
||||||
|
□ 检查代码中的GPIO配置
|
||||||
|
□ 添加软件滤波算法
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 📡 红外发射器故障
|
||||||
|
|
||||||
|
**故障现象:空调不响应红外控制**
|
||||||
|
```
|
||||||
|
症状:
|
||||||
|
- 空调完全无反应
|
||||||
|
- 只有部分按键有效
|
||||||
|
- 控制距离异常短
|
||||||
|
- 红外信号不稳定
|
||||||
|
```
|
||||||
|
|
||||||
|
**诊断步骤:**
|
||||||
|
```bash
|
||||||
|
1. 检查红外发射器供电
|
||||||
|
测量VCC:应为3.3V
|
||||||
|
|
||||||
|
2. 检查信号连接
|
||||||
|
确认DATA连接到GPIO4
|
||||||
|
|
||||||
|
3. 测试红外信号发射
|
||||||
|
用手机摄像头观察红外LED
|
||||||
|
应该看到紫色闪光
|
||||||
|
|
||||||
|
4. 检查发射距离和角度
|
||||||
|
最佳距离:1-3米
|
||||||
|
发射角度:对准空调接收窗口
|
||||||
|
|
||||||
|
5. 验证红外编码
|
||||||
|
检查日志中的红外数据
|
||||||
|
确认pattern数据正确
|
||||||
|
```
|
||||||
|
|
||||||
|
**解决方案:**
|
||||||
|
```bash
|
||||||
|
□ 重新连接红外发射器
|
||||||
|
□ 调整发射器位置和角度
|
||||||
|
□ 更换红外发射器模块
|
||||||
|
□ 检查GPIO4配置
|
||||||
|
□ 重新配对空调遥控器
|
||||||
|
□ 增加发射功率(如果支持)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 软件故障
|
||||||
|
|
||||||
|
#### 🌐 WiFi连接问题
|
||||||
|
|
||||||
|
**故障现象:无法连接WiFi或连接不稳定**
|
||||||
|
```
|
||||||
|
症状:
|
||||||
|
- 无法扫描到WiFi网络
|
||||||
|
- 连接后频繁断开
|
||||||
|
- 获取不到IP地址
|
||||||
|
- 网络速度异常慢
|
||||||
|
```
|
||||||
|
|
||||||
|
**诊断步骤:**
|
||||||
|
```bash
|
||||||
|
1. 检查WiFi配置
|
||||||
|
SSID和密码是否正确
|
||||||
|
WiFi频段是否为2.4GHz
|
||||||
|
|
||||||
|
2. 检查信号强度
|
||||||
|
RSSI应该 > -70dBm
|
||||||
|
距离路由器不超过10米(测试时)
|
||||||
|
|
||||||
|
3. 检查路由器设置
|
||||||
|
是否启用MAC地址过滤
|
||||||
|
是否限制设备数量
|
||||||
|
DHCP是否正常工作
|
||||||
|
|
||||||
|
4. 检查ESP32日志
|
||||||
|
查看WiFi连接错误信息
|
||||||
|
检查IP地址分配情况
|
||||||
|
```
|
||||||
|
|
||||||
|
**解决方案:**
|
||||||
|
```bash
|
||||||
|
□ 重置WiFi配置(长按GPIO0按钮)
|
||||||
|
□ 手动设置静态IP地址
|
||||||
|
□ 更换WiFi网络或路由器
|
||||||
|
□ 调整ESP32位置改善信号
|
||||||
|
□ 更新WiFi驱动程序
|
||||||
|
□ 检查路由器固件版本
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 📱 Android应用问题
|
||||||
|
|
||||||
|
**故障现象:应用崩溃或功能异常**
|
||||||
|
```
|
||||||
|
症状:
|
||||||
|
- 应用启动崩溃
|
||||||
|
- 无法发现ESP32设备
|
||||||
|
- 控制指令无响应
|
||||||
|
- 界面显示异常
|
||||||
|
```
|
||||||
|
|
||||||
|
**诊断步骤:**
|
||||||
|
```bash
|
||||||
|
1. 检查应用日志
|
||||||
|
adb logcat | grep "com.archesens.android"
|
||||||
|
|
||||||
|
2. 检查网络连接
|
||||||
|
手机和ESP32是否在同一网络
|
||||||
|
|
||||||
|
3. 检查权限设置
|
||||||
|
网络权限是否已授予
|
||||||
|
|
||||||
|
4. 检查SDK版本兼容性
|
||||||
|
Android版本是否支持
|
||||||
|
|
||||||
|
5. 测试网络通信
|
||||||
|
使用浏览器访问ESP32 IP地址
|
||||||
|
```
|
||||||
|
|
||||||
|
**解决方案:**
|
||||||
|
```bash
|
||||||
|
□ 清除应用数据和缓存
|
||||||
|
□ 重新安装APK
|
||||||
|
□ 检查Android版本兼容性
|
||||||
|
□ 手动输入ESP32 IP地址
|
||||||
|
□ 重启手机和ESP32设备
|
||||||
|
□ 更新应用到最新版本
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 🔧 编译和烧录问题
|
||||||
|
|
||||||
|
**故障现象:代码编译失败或烧录失败**
|
||||||
|
```
|
||||||
|
编译错误:
|
||||||
|
- 找不到头文件
|
||||||
|
- 链接错误
|
||||||
|
- 内存不足错误
|
||||||
|
|
||||||
|
烧录错误:
|
||||||
|
- 无法识别设备
|
||||||
|
- 烧录中断
|
||||||
|
- 校验失败
|
||||||
|
```
|
||||||
|
|
||||||
|
**诊断步骤:**
|
||||||
|
```bash
|
||||||
|
1. 检查开发环境
|
||||||
|
ESP-IDF版本:5.5.2
|
||||||
|
Python版本:3.12
|
||||||
|
|
||||||
|
2. 检查项目配置
|
||||||
|
sdkconfig是否正确
|
||||||
|
CMakeLists.txt是否完整
|
||||||
|
|
||||||
|
3. 检查串口连接
|
||||||
|
COM端口是否正确
|
||||||
|
波特率设置:460800
|
||||||
|
|
||||||
|
4. 检查USB驱动
|
||||||
|
设备管理器中是否识别ESP32
|
||||||
|
```
|
||||||
|
|
||||||
|
**解决方案:**
|
||||||
|
```bash
|
||||||
|
□ 重新安装ESP-IDF环境
|
||||||
|
□ 清理并重新编译项目
|
||||||
|
□ 更换USB数据线
|
||||||
|
□ 安装或更新USB驱动
|
||||||
|
□ 降低烧录波特率到115200
|
||||||
|
□ 手动进入下载模式
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 网络通信故障
|
||||||
|
|
||||||
|
#### 🌍 云端通信问题
|
||||||
|
|
||||||
|
**故障现象:无法上传报警数据到云端**
|
||||||
|
```
|
||||||
|
症状:
|
||||||
|
- HTTP请求超时
|
||||||
|
- 服务器返回错误
|
||||||
|
- 数据格式错误
|
||||||
|
- 认证失败
|
||||||
|
```
|
||||||
|
|
||||||
|
**诊断步骤:**
|
||||||
|
```bash
|
||||||
|
1. 检查网络连接
|
||||||
|
ping 云端服务器IP
|
||||||
|
|
||||||
|
2. 检查防火墙设置
|
||||||
|
端口30088是否开放
|
||||||
|
|
||||||
|
3. 检查数据格式
|
||||||
|
JSON格式是否正确
|
||||||
|
|
||||||
|
4. 检查服务器状态
|
||||||
|
使用curl测试API接口
|
||||||
|
|
||||||
|
5. 检查认证信息
|
||||||
|
设备ID是否正确
|
||||||
|
```
|
||||||
|
|
||||||
|
**解决方案:**
|
||||||
|
```bash
|
||||||
|
□ 检查网络防火墙设置
|
||||||
|
□ 验证云端服务器状态
|
||||||
|
□ 修正数据格式错误
|
||||||
|
□ 更新API接口地址
|
||||||
|
□ 重新生成设备认证信息
|
||||||
|
□ 增加重试机制
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔍 高级诊断工具
|
||||||
|
|
||||||
|
### 1. 硬件测试工具
|
||||||
|
|
||||||
|
#### 万用表测试清单:
|
||||||
|
```bash
|
||||||
|
电压测试:
|
||||||
|
□ 电源输入:5V ±0.25V
|
||||||
|
□ ESP32 3.3V输出:3.3V ±0.1V
|
||||||
|
□ 传感器供电:3.3V ±0.1V
|
||||||
|
□ GPIO输出电压:0V/3.3V
|
||||||
|
|
||||||
|
电阻测试:
|
||||||
|
□ 温度传感器上拉电阻:4.7kΩ ±5%
|
||||||
|
□ LED限流电阻:220Ω ±5%
|
||||||
|
□ 各连接点通断测试
|
||||||
|
|
||||||
|
电流测试:
|
||||||
|
□ 系统总电流:300-800mA
|
||||||
|
□ 各模块单独电流测试
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 示波器测试(如果可用):
|
||||||
|
```bash
|
||||||
|
信号测试:
|
||||||
|
□ GPIO4红外信号波形
|
||||||
|
□ I2C通信信号(SDA/SCL)
|
||||||
|
□ UART通信信号
|
||||||
|
□ PWM信号波形
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 软件调试工具
|
||||||
|
|
||||||
|
#### ESP32调试命令:
|
||||||
|
```bash
|
||||||
|
# 内存信息
|
||||||
|
esp_get_free_heap_size()
|
||||||
|
esp_get_minimum_free_heap_size()
|
||||||
|
|
||||||
|
# 任务信息
|
||||||
|
vTaskList()
|
||||||
|
vTaskGetRunTimeStats()
|
||||||
|
|
||||||
|
# WiFi信息
|
||||||
|
esp_wifi_get_config()
|
||||||
|
esp_wifi_sta_get_ap_info()
|
||||||
|
|
||||||
|
# 系统信息
|
||||||
|
esp_get_idf_version()
|
||||||
|
esp_restart_get_reason()
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 日志分析脚本:
|
||||||
|
```python
|
||||||
|
# log_analyzer.py
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
def analyze_esp32_log(log_file):
|
||||||
|
"""分析ESP32日志文件"""
|
||||||
|
errors = []
|
||||||
|
warnings = []
|
||||||
|
memory_usage = []
|
||||||
|
|
||||||
|
with open(log_file, 'r', encoding='utf-8') as f:
|
||||||
|
for line in f:
|
||||||
|
# 提取错误信息
|
||||||
|
if 'ERROR' in line or '❌' in line:
|
||||||
|
errors.append(line.strip())
|
||||||
|
|
||||||
|
# 提取警告信息
|
||||||
|
elif 'WARN' in line or '⚠️' in line:
|
||||||
|
warnings.append(line.strip())
|
||||||
|
|
||||||
|
# 提取内存使用信息
|
||||||
|
elif 'Free heap' in line:
|
||||||
|
match = re.search(r'Free heap: (\d+)', line)
|
||||||
|
if match:
|
||||||
|
memory_usage.append(int(match.group(1)))
|
||||||
|
|
||||||
|
# 生成报告
|
||||||
|
print(f"日志分析报告 - {datetime.now()}")
|
||||||
|
print(f"错误数量: {len(errors)}")
|
||||||
|
print(f"警告数量: {len(warnings)}")
|
||||||
|
|
||||||
|
if memory_usage:
|
||||||
|
print(f"内存使用: 最小 {min(memory_usage)} bytes, "
|
||||||
|
f"最大 {max(memory_usage)} bytes, "
|
||||||
|
f"平均 {sum(memory_usage)//len(memory_usage)} bytes")
|
||||||
|
|
||||||
|
# 显示最近的错误
|
||||||
|
if errors:
|
||||||
|
print("\n最近的错误:")
|
||||||
|
for error in errors[-5:]:
|
||||||
|
print(f" {error}")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
if len(sys.argv) > 1:
|
||||||
|
analyze_esp32_log(sys.argv[1])
|
||||||
|
else:
|
||||||
|
print("用法: python log_analyzer.py <log_file>")
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 网络诊断工具
|
||||||
|
|
||||||
|
#### 网络连接测试脚本:
|
||||||
|
```python
|
||||||
|
# network_test.py
|
||||||
|
import requests
|
||||||
|
import socket
|
||||||
|
import time
|
||||||
|
import json
|
||||||
|
|
||||||
|
def test_esp32_connection(ip_address):
|
||||||
|
"""测试ESP32网络连接"""
|
||||||
|
base_url = f"http://{ip_address}"
|
||||||
|
|
||||||
|
print(f"测试ESP32连接: {ip_address}")
|
||||||
|
|
||||||
|
# 1. Ping测试
|
||||||
|
try:
|
||||||
|
socket.create_connection((ip_address, 80), timeout=5)
|
||||||
|
print("✅ TCP连接成功")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ TCP连接失败: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# 2. HTTP状态测试
|
||||||
|
try:
|
||||||
|
response = requests.get(f"{base_url}/api/status", timeout=10)
|
||||||
|
print(f"✅ HTTP状态: {response.status_code}")
|
||||||
|
print(f" 响应时间: {response.elapsed.total_seconds():.2f}s")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ HTTP请求失败: {e}")
|
||||||
|
|
||||||
|
# 3. 功能接口测试
|
||||||
|
test_endpoints = [
|
||||||
|
"/api/sensors",
|
||||||
|
"/api/alarm/status",
|
||||||
|
"/api/system/info"
|
||||||
|
]
|
||||||
|
|
||||||
|
for endpoint in test_endpoints:
|
||||||
|
try:
|
||||||
|
response = requests.get(f"{base_url}{endpoint}", timeout=5)
|
||||||
|
print(f"✅ {endpoint}: {response.status_code}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ {endpoint}: {e}")
|
||||||
|
|
||||||
|
# 4. 空调控制测试
|
||||||
|
try:
|
||||||
|
data = {"keyType": "POWER"}
|
||||||
|
response = requests.post(
|
||||||
|
f"{base_url}/api/ac/control",
|
||||||
|
headers={"Content-Type": "application/json"},
|
||||||
|
data=json.dumps(data),
|
||||||
|
timeout=10
|
||||||
|
)
|
||||||
|
print(f"✅ 空调控制测试: {response.status_code}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ 空调控制测试失败: {e}")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# 自动发现ESP32设备
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
# 扫描局域网中的ESP32设备
|
||||||
|
for i in range(1, 255):
|
||||||
|
ip = f"192.168.1.{i}"
|
||||||
|
try:
|
||||||
|
result = subprocess.run(['ping', '-n', '1', '-w', '1000', ip],
|
||||||
|
capture_output=True, text=True)
|
||||||
|
if result.returncode == 0:
|
||||||
|
# 尝试连接HTTP服务
|
||||||
|
try:
|
||||||
|
response = requests.get(f"http://{ip}/api/status", timeout=2)
|
||||||
|
if response.status_code == 200:
|
||||||
|
print(f"发现ESP32设备: {ip}")
|
||||||
|
test_esp32_connection(ip)
|
||||||
|
break
|
||||||
|
except:
|
||||||
|
continue
|
||||||
|
except:
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
print("未发现ESP32设备,请手动指定IP地址")
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🛠️ 预防性维护
|
||||||
|
|
||||||
|
### 1. 定期检查清单
|
||||||
|
|
||||||
|
#### 每周检查(5分钟):
|
||||||
|
```bash
|
||||||
|
□ 检查设备运行状态LED
|
||||||
|
□ 测试报警功能(用打火机测试烟雾传感器)
|
||||||
|
□ 检查WiFi连接状态
|
||||||
|
□ 查看Android应用连接状态
|
||||||
|
□ 检查电源适配器温度
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 每月检查(30分钟):
|
||||||
|
```bash
|
||||||
|
□ 清洁传感器表面灰尘
|
||||||
|
□ 检查所有连接线是否松动
|
||||||
|
□ 测试所有空调控制功能
|
||||||
|
□ 检查系统日志是否有异常
|
||||||
|
□ 备份重要配置数据
|
||||||
|
□ 检查固件版本是否需要更新
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 每季度检查(2小时):
|
||||||
|
```bash
|
||||||
|
□ 全面功能测试
|
||||||
|
□ 性能数据分析
|
||||||
|
□ 硬件连接重新检查
|
||||||
|
□ 软件版本更新
|
||||||
|
□ 安全漏洞检查
|
||||||
|
□ 文档更新
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 维护工具和脚本
|
||||||
|
|
||||||
|
#### 自动健康检查脚本:
|
||||||
|
```python
|
||||||
|
# health_check.py
|
||||||
|
import requests
|
||||||
|
import json
|
||||||
|
import smtplib
|
||||||
|
from email.mime.text import MIMEText
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
class ESP32HealthChecker:
|
||||||
|
def __init__(self, esp32_ip, email_config=None):
|
||||||
|
self.esp32_ip = esp32_ip
|
||||||
|
self.base_url = f"http://{esp32_ip}"
|
||||||
|
self.email_config = email_config
|
||||||
|
self.issues = []
|
||||||
|
|
||||||
|
def check_connectivity(self):
|
||||||
|
"""检查网络连接"""
|
||||||
|
try:
|
||||||
|
response = requests.get(f"{self.base_url}/api/status", timeout=10)
|
||||||
|
if response.status_code != 200:
|
||||||
|
self.issues.append(f"HTTP状态异常: {response.status_code}")
|
||||||
|
except Exception as e:
|
||||||
|
self.issues.append(f"网络连接失败: {e}")
|
||||||
|
|
||||||
|
def check_sensors(self):
|
||||||
|
"""检查传感器状态"""
|
||||||
|
try:
|
||||||
|
response = requests.get(f"{self.base_url}/api/sensors", timeout=5)
|
||||||
|
if response.status_code == 200:
|
||||||
|
data = response.json()
|
||||||
|
|
||||||
|
# 检查温度传感器
|
||||||
|
if data.get('temperature', 0) < -50 or data.get('temperature', 0) > 100:
|
||||||
|
self.issues.append("温度传感器读数异常")
|
||||||
|
|
||||||
|
# 检查烟雾传感器
|
||||||
|
if data.get('smoke', 0) < 0 or data.get('smoke', 0) > 4095:
|
||||||
|
self.issues.append("烟雾传感器读数异常")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.issues.append(f"传感器检查失败: {e}")
|
||||||
|
|
||||||
|
def check_memory(self):
|
||||||
|
"""检查内存使用"""
|
||||||
|
try:
|
||||||
|
response = requests.get(f"{self.base_url}/api/system/info", timeout=5)
|
||||||
|
if response.status_code == 200:
|
||||||
|
data = response.json()
|
||||||
|
free_heap = data.get('free_heap', 0)
|
||||||
|
|
||||||
|
if free_heap < 50000: # 小于50KB
|
||||||
|
self.issues.append(f"内存不足: {free_heap} bytes")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.issues.append(f"内存检查失败: {e}")
|
||||||
|
|
||||||
|
def send_alert(self):
|
||||||
|
"""发送告警邮件"""
|
||||||
|
if not self.issues or not self.email_config:
|
||||||
|
return
|
||||||
|
|
||||||
|
subject = f"ESP32健康检查告警 - {datetime.now().strftime('%Y-%m-%d %H:%M')}"
|
||||||
|
body = f"发现以下问题:\n\n" + "\n".join(f"- {issue}" for issue in self.issues)
|
||||||
|
|
||||||
|
msg = MIMEText(body, 'plain', 'utf-8')
|
||||||
|
msg['Subject'] = subject
|
||||||
|
msg['From'] = self.email_config['from']
|
||||||
|
msg['To'] = self.email_config['to']
|
||||||
|
|
||||||
|
try:
|
||||||
|
with smtplib.SMTP(self.email_config['smtp_server'], 587) as server:
|
||||||
|
server.starttls()
|
||||||
|
server.login(self.email_config['username'], self.email_config['password'])
|
||||||
|
server.send_message(msg)
|
||||||
|
print("告警邮件发送成功")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"邮件发送失败: {e}")
|
||||||
|
|
||||||
|
def run_check(self):
|
||||||
|
"""运行完整健康检查"""
|
||||||
|
print(f"开始健康检查 - {datetime.now()}")
|
||||||
|
|
||||||
|
self.check_connectivity()
|
||||||
|
self.check_sensors()
|
||||||
|
self.check_memory()
|
||||||
|
|
||||||
|
if self.issues:
|
||||||
|
print("发现问题:")
|
||||||
|
for issue in self.issues:
|
||||||
|
print(f" ❌ {issue}")
|
||||||
|
self.send_alert()
|
||||||
|
else:
|
||||||
|
print("✅ 系统状态正常")
|
||||||
|
|
||||||
|
# 使用示例
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# 邮件配置(可选)
|
||||||
|
email_config = {
|
||||||
|
'smtp_server': 'smtp.gmail.com',
|
||||||
|
'username': 'your_email@gmail.com',
|
||||||
|
'password': 'your_password',
|
||||||
|
'from': 'your_email@gmail.com',
|
||||||
|
'to': 'admin@company.com'
|
||||||
|
}
|
||||||
|
|
||||||
|
checker = ESP32HealthChecker("192.168.1.100", email_config)
|
||||||
|
checker.run_check()
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 备份和恢复
|
||||||
|
|
||||||
|
#### 配置备份脚本:
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
# backup_config.sh
|
||||||
|
|
||||||
|
BACKUP_DIR="./backups/$(date +%Y%m%d_%H%M%S)"
|
||||||
|
mkdir -p "$BACKUP_DIR"
|
||||||
|
|
||||||
|
echo "开始备份配置..."
|
||||||
|
|
||||||
|
# 备份ESP32配置
|
||||||
|
cp firefly_esp32/sdkconfig "$BACKUP_DIR/"
|
||||||
|
cp firefly_esp32/partitions.csv "$BACKUP_DIR/"
|
||||||
|
|
||||||
|
# 备份Android配置
|
||||||
|
cp -r Smarthome_android/app/src/main/assets "$BACKUP_DIR/"
|
||||||
|
|
||||||
|
# 备份重要脚本
|
||||||
|
cp -r python_test "$BACKUP_DIR/"
|
||||||
|
|
||||||
|
# 创建备份说明
|
||||||
|
cat > "$BACKUP_DIR/README.txt" << EOF
|
||||||
|
备份时间: $(date)
|
||||||
|
ESP32固件版本: $(git describe --tags)
|
||||||
|
Android应用版本: $(grep versionName Smarthome_android/app/build.gradle.kts)
|
||||||
|
备份内容:
|
||||||
|
- ESP32配置文件
|
||||||
|
- Android应用配置
|
||||||
|
- Python测试脚本
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo "备份完成: $BACKUP_DIR"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📞 技术支持和联系方式
|
||||||
|
|
||||||
|
### 紧急故障处理流程:
|
||||||
|
1. **立即处理**:系统完全无法工作
|
||||||
|
2. **优先处理**:核心功能异常(火灾报警失效)
|
||||||
|
3. **正常处理**:次要功能问题(红外控制异常)
|
||||||
|
4. **计划处理**:性能优化和功能增强
|
||||||
|
|
||||||
|
### 故障报告模板:
|
||||||
|
```
|
||||||
|
故障报告
|
||||||
|
========
|
||||||
|
报告时间: [YYYY-MM-DD HH:MM]
|
||||||
|
报告人: [姓名]
|
||||||
|
设备信息: [ESP32 MAC地址/Android设备型号]
|
||||||
|
|
||||||
|
故障描述:
|
||||||
|
[详细描述故障现象]
|
||||||
|
|
||||||
|
复现步骤:
|
||||||
|
1. [步骤1]
|
||||||
|
2. [步骤2]
|
||||||
|
3. [步骤3]
|
||||||
|
|
||||||
|
环境信息:
|
||||||
|
- ESP32固件版本: [版本号]
|
||||||
|
- Android应用版本: [版本号]
|
||||||
|
- 网络环境: [WiFi信息]
|
||||||
|
- 硬件配置: [传感器型号等]
|
||||||
|
|
||||||
|
已尝试的解决方案:
|
||||||
|
[列出已经尝试过的解决方法]
|
||||||
|
|
||||||
|
日志信息:
|
||||||
|
[粘贴相关日志]
|
||||||
|
|
||||||
|
附件:
|
||||||
|
[截图、日志文件等]
|
||||||
|
```
|
||||||
|
|
||||||
|
### 维护记录模板:
|
||||||
|
```
|
||||||
|
维护记录
|
||||||
|
========
|
||||||
|
维护时间: [YYYY-MM-DD HH:MM]
|
||||||
|
维护人员: [姓名]
|
||||||
|
维护类型: [预防性维护/故障维修/升级更新]
|
||||||
|
|
||||||
|
维护内容:
|
||||||
|
[详细记录维护操作]
|
||||||
|
|
||||||
|
发现问题:
|
||||||
|
[记录发现的问题]
|
||||||
|
|
||||||
|
解决方案:
|
||||||
|
[记录采取的解决措施]
|
||||||
|
|
||||||
|
测试结果:
|
||||||
|
[记录测试验证结果]
|
||||||
|
|
||||||
|
下次维护建议:
|
||||||
|
[提出下次维护的建议]
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**重要提醒**:
|
||||||
|
1. 遇到问题时不要慌张,按步骤排查
|
||||||
|
2. 详细记录故障现象和解决过程
|
||||||
|
3. 定期进行预防性维护
|
||||||
|
4. 保持系统和文档的及时更新
|
||||||
|
5. 建立完善的备份和恢复机制
|
||||||
|
|
||||||
|
**文档版本**:v1.0
|
||||||
|
**最后更新**:2026年2月26日
|
||||||
378
使用手册/手册指南/硬件接线详细指南.md
Normal file
378
使用手册/手册指南/硬件接线详细指南.md
Normal file
|
|
@ -0,0 +1,378 @@
|
||||||
|
# ESP32智能火灾报警系统 - 硬件接线详细指南
|
||||||
|
|
||||||
|
## 🔌 详细接线图
|
||||||
|
|
||||||
|
### 1. ESP32引脚功能分配
|
||||||
|
|
||||||
|
```
|
||||||
|
ESP32-WROOM-32 引脚分配表:
|
||||||
|
┌──────────────────────────────────────────────────────────────┐
|
||||||
|
│ ESP32 引脚布局图 │
|
||||||
|
│ │
|
||||||
|
│ 3V3 ┌─────────────────────────────────────┐ GND │
|
||||||
|
│ EN │ │ GPIO23 │
|
||||||
|
│ VP │ │ GPIO22 │
|
||||||
|
│ VN │ │ GPIO1 │
|
||||||
|
│ GPIO34│ ESP32-WROOM-32 │ GPIO3 │
|
||||||
|
│ GPIO35│ │ GPIO21 │
|
||||||
|
│ GPIO32│ │ GPIO19 │
|
||||||
|
│ GPIO33│ │ GPIO18 │
|
||||||
|
│ GPIO25│ │ GPIO5 │
|
||||||
|
│ GPIO26│ │ GPIO17 │
|
||||||
|
│ GPIO27│ │ GPIO16 │
|
||||||
|
│ GPIO14│ │ GPIO4 │
|
||||||
|
│ GPIO12│ │ GPIO0 │
|
||||||
|
│ GND │ │ GPIO2 │
|
||||||
|
│ GPIO13│ │ GPIO15 │
|
||||||
|
│ GPIO9 └─────────────────────────────────────┘ GPIO8 │
|
||||||
|
│ GPIO10 GPIO7 │
|
||||||
|
│ GPIO11 GPIO6 │
|
||||||
|
│ VIN GND │
|
||||||
|
└──────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 核心功能接线
|
||||||
|
|
||||||
|
#### 🌡️ 温度传感器 (DS18B20)
|
||||||
|
```
|
||||||
|
DS18B20 → ESP32
|
||||||
|
┌─────────┬─────────────┬─────────────────────────────┐
|
||||||
|
│ 引脚 │ ESP32 GPIO │ 说明 │
|
||||||
|
├─────────┼─────────────┼─────────────────────────────┤
|
||||||
|
│ VDD │ 3.3V │ 电源正极 │
|
||||||
|
│ GND │ GND │ 电源负极 │
|
||||||
|
│ DQ │ GPIO18 │ 数据线(需要4.7kΩ上拉电阻)│
|
||||||
|
└─────────┴─────────────┴─────────────────────────────┘
|
||||||
|
|
||||||
|
接线示意图:
|
||||||
|
DS18B20
|
||||||
|
┌─────┐
|
||||||
|
│ VDD │──────── 3.3V
|
||||||
|
│ DQ │────┬─── GPIO18
|
||||||
|
│ GND │ │
|
||||||
|
└─────┘ │
|
||||||
|
┌┴┐
|
||||||
|
│R│ 4.7kΩ
|
||||||
|
│ │
|
||||||
|
└┬┘
|
||||||
|
│
|
||||||
|
3.3V
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 💨 烟雾传感器 (MQ-2)
|
||||||
|
```
|
||||||
|
MQ-2 → ESP32
|
||||||
|
┌─────────┬─────────────┬─────────────────────────────┐
|
||||||
|
│ 引脚 │ ESP32 GPIO │ 说明 │
|
||||||
|
├─────────┼─────────────┼─────────────────────────────┤
|
||||||
|
│ VCC │ 3.3V │ 电源正极 │
|
||||||
|
│ GND │ GND │ 电源负极 │
|
||||||
|
│ AOUT │ GPIO19 │ 模拟输出(ADC输入) │
|
||||||
|
│ DOUT │ 未连接 │ 数字输出(可选) │
|
||||||
|
└─────────┴─────────────┴─────────────────────────────┘
|
||||||
|
|
||||||
|
接线示意图:
|
||||||
|
MQ-2
|
||||||
|
┌─────────┐
|
||||||
|
│ VCC │──────── 3.3V
|
||||||
|
│ AOUT │──────── GPIO19 (ADC2_CH0)
|
||||||
|
│ DOUT │ (未使用)
|
||||||
|
│ GND │──────── GND
|
||||||
|
└─────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 👤 人体红外传感器 (PIR)
|
||||||
|
```
|
||||||
|
PIR → ESP32
|
||||||
|
┌─────────┬─────────────┬─────────────────────────────┐
|
||||||
|
│ 引脚 │ ESP32 GPIO │ 说明 │
|
||||||
|
├─────────┼─────────────┼─────────────────────────────┤
|
||||||
|
│ VCC │ 3.3V │ 电源正极 │
|
||||||
|
│ GND │ GND │ 电源负极 │
|
||||||
|
│ OUT │ GPIO21 │ 数字输出(检测到人体为高电平)│
|
||||||
|
└─────────┴─────────────┴─────────────────────────────┘
|
||||||
|
|
||||||
|
接线示意图:
|
||||||
|
PIR传感器
|
||||||
|
┌─────────┐
|
||||||
|
│ VCC │──────── 3.3V
|
||||||
|
│ OUT │──────── GPIO21
|
||||||
|
│ GND │──────── GND
|
||||||
|
└─────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 📡 红外发射器
|
||||||
|
```
|
||||||
|
红外发射器 → ESP32
|
||||||
|
┌─────────┬─────────────┬─────────────────────────────┐
|
||||||
|
│ 引脚 │ ESP32 GPIO │ 说明 │
|
||||||
|
├─────────┼─────────────┼─────────────────────────────┤
|
||||||
|
│ VCC │ 3.3V │ 电源正极 │
|
||||||
|
│ GND │ GND │ 电源负极 │
|
||||||
|
│ DATA │ GPIO4 │ 红外信号输入 │
|
||||||
|
└─────────┴─────────────┴─────────────────────────────┘
|
||||||
|
|
||||||
|
接线示意图:
|
||||||
|
红外发射器
|
||||||
|
┌─────────┐
|
||||||
|
│ VCC │──────── 3.3V
|
||||||
|
│ DATA │──────── GPIO4
|
||||||
|
│ GND │──────── GND
|
||||||
|
└─────────┘
|
||||||
|
|
||||||
|
注意:红外发射器需要对准空调接收窗口,建议距离1-3米
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 指示和报警设备
|
||||||
|
|
||||||
|
#### 💡 LED指示灯
|
||||||
|
```
|
||||||
|
LED → ESP32
|
||||||
|
┌─────────┬─────────────┬─────────────────────────────┐
|
||||||
|
│ 引脚 │ ESP32 GPIO │ 说明 │
|
||||||
|
├─────────┼─────────────┼─────────────────────────────┤
|
||||||
|
│ 正极 │ GPIO2 │ 通过220Ω电阻连接 │
|
||||||
|
│ 负极 │ GND │ 直接连接 │
|
||||||
|
└─────────┴─────────────┴─────────────────────────────┘
|
||||||
|
|
||||||
|
接线示意图:
|
||||||
|
LED
|
||||||
|
┌─┐
|
||||||
|
│+│────┬─── GPIO2
|
||||||
|
│-│ │
|
||||||
|
└─┘ │
|
||||||
|
┌┴┐
|
||||||
|
│R│ 220Ω
|
||||||
|
│ │
|
||||||
|
└┬┘
|
||||||
|
│
|
||||||
|
GND
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 🔊 蜂鸣器
|
||||||
|
```
|
||||||
|
蜂鸣器 → ESP32
|
||||||
|
┌─────────┬─────────────┬─────────────────────────────┐
|
||||||
|
│ 引脚 │ ESP32 GPIO │ 说明 │
|
||||||
|
├─────────┼─────────────┼─────────────────────────────┤
|
||||||
|
│ 正极 │ GPIO5 │ PWM控制引脚 │
|
||||||
|
│ 负极 │ GND │ 直接连接 │
|
||||||
|
└─────────┴─────────────┴─────────────────────────────┘
|
||||||
|
|
||||||
|
接线示意图:
|
||||||
|
蜂鸣器
|
||||||
|
┌─────┐
|
||||||
|
│ + │──────── GPIO5
|
||||||
|
│ - │──────── GND
|
||||||
|
└─────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. 可选模块接线
|
||||||
|
|
||||||
|
#### 📻 433MHz模块 (RTM300-433M)
|
||||||
|
```
|
||||||
|
RTM300-433M → ESP32
|
||||||
|
┌─────────┬─────────────┬─────────────────────────────┐
|
||||||
|
│ 引脚 │ ESP32 GPIO │ 说明 │
|
||||||
|
├─────────┼─────────────┼─────────────────────────────┤
|
||||||
|
│ VCC │ 3.3V │ 电源正极 │
|
||||||
|
│ GND │ GND │ 电源负极 │
|
||||||
|
│ SDA │ GPIO22 │ I2C数据线 │
|
||||||
|
│ SCL │ GPIO23 │ I2C时钟线 │
|
||||||
|
│ IRQ │ GPIO25 │ 中断信号线 │
|
||||||
|
│ RST │ GPIO26 │ 复位信号线 │
|
||||||
|
└─────────┴─────────────┴─────────────────────────────┘
|
||||||
|
|
||||||
|
接线示意图:
|
||||||
|
RTM300-433M
|
||||||
|
┌─────────────┐
|
||||||
|
│ VCC │──────── 3.3V
|
||||||
|
│ GND │──────── GND
|
||||||
|
│ SDA │──────── GPIO22
|
||||||
|
│ SCL │──────── GPIO23
|
||||||
|
│ IRQ │──────── GPIO25
|
||||||
|
│ RST │──────── GPIO26
|
||||||
|
│ ANT │──────── 外接天线
|
||||||
|
└─────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 📏 雷达传感器 (可选)
|
||||||
|
```
|
||||||
|
雷达传感器 → ESP32
|
||||||
|
┌─────────┬─────────────┬─────────────────────────────┐
|
||||||
|
│ 引脚 │ ESP32 GPIO │ 说明 │
|
||||||
|
├─────────┼─────────────┼─────────────────────────────┤
|
||||||
|
│ VCC │ 5V │ 电源正极(注意电压) │
|
||||||
|
│ GND │ GND │ 电源负极 │
|
||||||
|
│ TX │ GPIO16 │ UART发送(连接ESP32 RX) │
|
||||||
|
│ RX │ GPIO17 │ UART接收(连接ESP32 TX) │
|
||||||
|
└─────────┴─────────────┴─────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. 控制按钮
|
||||||
|
|
||||||
|
#### ⚙️ 配置按钮
|
||||||
|
```
|
||||||
|
配置按钮 → ESP32
|
||||||
|
┌─────────┬─────────────┬─────────────────────────────┐
|
||||||
|
│ 引脚 │ ESP32 GPIO │ 说明 │
|
||||||
|
├─────────┼─────────────┼─────────────────────────────┤
|
||||||
|
│ 一端 │ GPIO0 │ 启动配置模式 │
|
||||||
|
│ 另一端 │ GND │ 按下时拉低GPIO0 │
|
||||||
|
└─────────┴─────────────┴─────────────────────────────┘
|
||||||
|
|
||||||
|
接线示意图:
|
||||||
|
配置按钮
|
||||||
|
┌─────┐
|
||||||
|
│ │──────── GPIO0
|
||||||
|
│ │
|
||||||
|
│ │──────── GND
|
||||||
|
└─────┘
|
||||||
|
|
||||||
|
功能:长按3秒进入WiFi配置模式
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔧 接线工具和材料
|
||||||
|
|
||||||
|
### 必需工具:
|
||||||
|
- **烙铁和焊锡**:用于焊接连接
|
||||||
|
- **万用表**:测试电路连通性
|
||||||
|
- **剥线钳**:处理导线
|
||||||
|
- **螺丝刀套装**:固定模块
|
||||||
|
- **热缩管**:保护焊接点
|
||||||
|
|
||||||
|
### 必需材料:
|
||||||
|
- **杜邦线**:公对公、公对母、母对母各20根
|
||||||
|
- **面包板**:830孔大型面包板
|
||||||
|
- **电阻**:220Ω(LED用)、4.7kΩ(温度传感器上拉)
|
||||||
|
- **电容**:100μF电解电容(电源滤波)
|
||||||
|
- **导线**:22AWG单股线,多种颜色
|
||||||
|
|
||||||
|
## ⚡ 电源设计
|
||||||
|
|
||||||
|
### 电源要求:
|
||||||
|
```
|
||||||
|
总功耗分析:
|
||||||
|
┌─────────────────┬─────────────┬─────────────┐
|
||||||
|
│ 模块 │ 工作电流 │ 峰值电流 │
|
||||||
|
├─────────────────┼─────────────┼─────────────┤
|
||||||
|
│ ESP32 │ 160mA │ 240mA │
|
||||||
|
│ WiFi发送 │ +170mA │ +240mA │
|
||||||
|
│ 温度传感器 │ 1.5mA │ 1.5mA │
|
||||||
|
│ 烟雾传感器 │ 150mA │ 150mA │
|
||||||
|
│ PIR传感器 │ 50μA │ 50μA │
|
||||||
|
│ 红外发射器 │ 20mA │ 100mA │
|
||||||
|
│ LED指示灯 │ 20mA │ 20mA │
|
||||||
|
│ 蜂鸣器 │ 30mA │ 100mA │
|
||||||
|
│ 433MHz模块 │ 25mA │ 120mA │
|
||||||
|
├─────────────────┼─────────────┼─────────────┤
|
||||||
|
│ 总计 │ ~630mA │ ~1070mA │
|
||||||
|
└─────────────────┴─────────────┴─────────────┘
|
||||||
|
|
||||||
|
推荐电源:5V/2A开关电源适配器
|
||||||
|
```
|
||||||
|
|
||||||
|
### 电源接线:
|
||||||
|
```
|
||||||
|
电源分配示意图:
|
||||||
|
|
||||||
|
5V电源适配器
|
||||||
|
│
|
||||||
|
├─── ESP32 VIN (5V输入)
|
||||||
|
│
|
||||||
|
└─── 雷达传感器 VCC (如果需要5V)
|
||||||
|
|
||||||
|
ESP32内部3.3V输出
|
||||||
|
│
|
||||||
|
├─── 温度传感器 VDD
|
||||||
|
├─── 烟雾传感器 VCC
|
||||||
|
├─── PIR传感器 VCC
|
||||||
|
├─── 红外发射器 VCC
|
||||||
|
├─── LED正极(通过电阻)
|
||||||
|
├─── 蜂鸣器正极
|
||||||
|
└─── 433MHz模块 VCC
|
||||||
|
|
||||||
|
公共地线 (GND)
|
||||||
|
│
|
||||||
|
├─── 所有传感器 GND
|
||||||
|
├─── 所有指示器 GND
|
||||||
|
└─── 电源适配器 GND
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🛡️ 安全注意事项
|
||||||
|
|
||||||
|
### 电气安全:
|
||||||
|
1. **电压检查**:使用万用表确认各点电压正确
|
||||||
|
2. **短路保护**:安装保险丝或使用带保护的电源
|
||||||
|
3. **绝缘处理**:所有裸露连接点使用热缩管保护
|
||||||
|
4. **接地良好**:确保所有GND连接牢固
|
||||||
|
|
||||||
|
### 防护措施:
|
||||||
|
1. **防水处理**:如在潮湿环境使用,需要防水外壳
|
||||||
|
2. **散热设计**:ESP32和传感器需要适当散热空间
|
||||||
|
3. **抗干扰**:电源线和信号线分开布线
|
||||||
|
4. **固定牢固**:所有模块和连线需要可靠固定
|
||||||
|
|
||||||
|
## 🔍 接线验证步骤
|
||||||
|
|
||||||
|
### 1. 上电前检查:
|
||||||
|
```bash
|
||||||
|
□ 检查电源极性正确
|
||||||
|
□ 检查所有GND连接
|
||||||
|
□ 检查3.3V供电连接
|
||||||
|
□ 检查GPIO连接无短路
|
||||||
|
□ 检查传感器方向正确
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 上电测试:
|
||||||
|
```bash
|
||||||
|
□ 测量3.3V输出电压
|
||||||
|
□ 测量各传感器供电电压
|
||||||
|
□ 检查LED是否正常闪烁
|
||||||
|
□ 检查串口是否有启动信息
|
||||||
|
□ 测试配置按钮功能
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 功能测试:
|
||||||
|
```bash
|
||||||
|
□ 温度传感器读数正常
|
||||||
|
□ 烟雾传感器响应测试
|
||||||
|
□ PIR传感器检测测试
|
||||||
|
□ 红外发射器控制测试
|
||||||
|
□ WiFi连接功能测试
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📋 接线检查清单
|
||||||
|
|
||||||
|
### 必需连接检查:
|
||||||
|
- [ ] ESP32电源连接(5V → VIN,GND → GND)
|
||||||
|
- [ ] 温度传感器连接(VDD → 3.3V,DQ → GPIO18,GND → GND)
|
||||||
|
- [ ] 烟雾传感器连接(VCC → 3.3V,AOUT → GPIO19,GND → GND)
|
||||||
|
- [ ] PIR传感器连接(VCC → 3.3V,OUT → GPIO21,GND → GND)
|
||||||
|
- [ ] 红外发射器连接(VCC → 3.3V,DATA → GPIO4,GND → GND)
|
||||||
|
- [ ] LED指示灯连接(正极 → GPIO2,负极 → GND,含220Ω电阻)
|
||||||
|
- [ ] 蜂鸣器连接(正极 → GPIO5,负极 → GND)
|
||||||
|
- [ ] 配置按钮连接(一端 → GPIO0,另一端 → GND)
|
||||||
|
|
||||||
|
### 可选连接检查:
|
||||||
|
- [ ] 433MHz模块连接(如果使用)
|
||||||
|
- [ ] 雷达传感器连接(如果使用)
|
||||||
|
- [ ] 外部天线连接(如果使用)
|
||||||
|
|
||||||
|
### 最终验证:
|
||||||
|
- [ ] 所有连接牢固无松动
|
||||||
|
- [ ] 无短路和接触不良
|
||||||
|
- [ ] 电源指示灯正常
|
||||||
|
- [ ] 串口输出正常启动信息
|
||||||
|
- [ ] 各传感器功能正常
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**重要提醒**:
|
||||||
|
1. 接线前务必断电,避免损坏设备
|
||||||
|
2. 使用万用表验证连接正确性
|
||||||
|
3. 首次上电时观察是否有异常发热
|
||||||
|
4. 如有疑问,请参考ESP32官方文档或寻求技术支持
|
||||||
|
|
||||||
|
**文档版本**:v1.0
|
||||||
|
**最后更新**:2026年2月26日
|
||||||
633
使用手册/手册指南/软件配置详细指南.md
Normal file
633
使用手册/手册指南/软件配置详细指南.md
Normal file
|
|
@ -0,0 +1,633 @@
|
||||||
|
# ESP32智能火灾报警系统 - 软件配置详细指南
|
||||||
|
|
||||||
|
## 🖥️ 开发环境配置
|
||||||
|
|
||||||
|
### 1. ESP-IDF 5.5.2 安装配置
|
||||||
|
|
||||||
|
#### Windows环境安装:
|
||||||
|
```bash
|
||||||
|
# 1. 下载ESP-IDF 5.5.2离线安装包
|
||||||
|
下载地址:https://dl.espressif.com/dl/esp-idf/
|
||||||
|
|
||||||
|
# 2. 安装到指定目录
|
||||||
|
安装路径:D:\Espressif5.5.2\
|
||||||
|
|
||||||
|
# 3. 环境变量配置
|
||||||
|
IDF_PATH=D:\Espressif5.5.2\Espressif\frameworks\esp-idf-v5.5.2
|
||||||
|
PATH添加:
|
||||||
|
- D:\Espressif5.5.2\Espressif\tools\
|
||||||
|
- D:\Espressif5.5.2\Espressif\python_env\idf5.5_py3.12_env\Scripts\
|
||||||
|
|
||||||
|
# 4. 验证安装
|
||||||
|
打开命令行执行:
|
||||||
|
idf.py --version
|
||||||
|
# 应该显示:ESP-IDF v5.5.2
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 初始化ESP-IDF环境:
|
||||||
|
```bash
|
||||||
|
# 每次开发前执行(或添加到系统启动脚本)
|
||||||
|
D:\Espressif5.5.2\Espressif\frameworks\esp-idf-v5.5.2\export.ps1
|
||||||
|
|
||||||
|
# 验证环境
|
||||||
|
echo $IDF_PATH
|
||||||
|
which idf.py
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. ESP32项目配置
|
||||||
|
|
||||||
|
#### 项目结构说明:
|
||||||
|
```
|
||||||
|
firefly_esp32/
|
||||||
|
├── CMakeLists.txt # 项目构建配置
|
||||||
|
├── sdkconfig # ESP32配置文件
|
||||||
|
├── partitions.csv # 分区表配置
|
||||||
|
├── main/ # 主程序代码
|
||||||
|
│ ├── CMakeLists.txt # 主程序构建配置
|
||||||
|
│ ├── app_main.cpp # 主程序入口
|
||||||
|
│ ├── Module/ # 功能模块
|
||||||
|
│ │ ├── AlarmManager.cpp # 报警管理
|
||||||
|
│ │ ├── NetworkManager.cpp # 网络管理
|
||||||
|
│ │ ├── SensorManager.cpp # 传感器管理
|
||||||
|
│ │ └── IRController.cpp # 红外控制
|
||||||
|
│ └── include/ # 头文件
|
||||||
|
└── managed_components/ # ESP-IDF组件
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 重要配置文件详解:
|
||||||
|
|
||||||
|
##### sdkconfig 关键配置:
|
||||||
|
```bash
|
||||||
|
# CPU和内存配置
|
||||||
|
CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y
|
||||||
|
CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=240
|
||||||
|
CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192
|
||||||
|
|
||||||
|
# WiFi配置
|
||||||
|
CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=10
|
||||||
|
CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=32
|
||||||
|
CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=1
|
||||||
|
CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=32
|
||||||
|
|
||||||
|
# FreeRTOS配置
|
||||||
|
CONFIG_FREERTOS_HZ=1000
|
||||||
|
CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y
|
||||||
|
CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y
|
||||||
|
|
||||||
|
# 分区表配置
|
||||||
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
|
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
||||||
|
|
||||||
|
# 日志配置
|
||||||
|
CONFIG_LOG_DEFAULT_LEVEL_INFO=y
|
||||||
|
CONFIG_LOG_MAXIMUM_LEVEL_VERBOSE=y
|
||||||
|
```
|
||||||
|
|
||||||
|
##### partitions.csv 分区配置:
|
||||||
|
```csv
|
||||||
|
# Name, Type, SubType, Offset, Size, Flags
|
||||||
|
nvs, data, nvs, 0x9000, 0x6000,
|
||||||
|
phy_init, data, phy, 0xf000, 0x1000,
|
||||||
|
factory, app, factory, 0x10000, 0x1F0000,
|
||||||
|
storage, data, spiffs, 0x200000,0x200000,
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 项目编译配置
|
||||||
|
|
||||||
|
#### 编译环境设置:
|
||||||
|
```bash
|
||||||
|
cd d:\XinJiaPo\Firefly_code\smart-home\firefly_esp32
|
||||||
|
|
||||||
|
# 设置目标芯片
|
||||||
|
idf.py set-target esp32
|
||||||
|
|
||||||
|
# 配置项目(打开配置菜单)
|
||||||
|
idf.py menuconfig
|
||||||
|
```
|
||||||
|
|
||||||
|
#### menuconfig 重要配置项:
|
||||||
|
|
||||||
|
##### 1. Component config → ESP32-specific:
|
||||||
|
```
|
||||||
|
CPU frequency: 240 MHz
|
||||||
|
Main XTAL frequency: 40 MHz
|
||||||
|
RTC clock source: External 32kHz crystal
|
||||||
|
```
|
||||||
|
|
||||||
|
##### 2. Component config → Wi-Fi:
|
||||||
|
```
|
||||||
|
WiFi Task Core ID: Core 1
|
||||||
|
Max number of WiFi static RX buffers: 10
|
||||||
|
Max number of WiFi dynamic RX buffers: 32
|
||||||
|
Type of WiFi TX buffers: Dynamic
|
||||||
|
Max number of WiFi dynamic TX buffers: 32
|
||||||
|
WiFi AMPDU TX: Enabled
|
||||||
|
WiFi AMPDU RX: Enabled
|
||||||
|
```
|
||||||
|
|
||||||
|
##### 3. Component config → FreeRTOS:
|
||||||
|
```
|
||||||
|
Tick rate (Hz): 1000
|
||||||
|
Task watchdog timeout period (seconds): 5
|
||||||
|
Idle Task watchdog timeout period (seconds): 5
|
||||||
|
Enable task function wrapper: Yes
|
||||||
|
Check for stack overflow: Canary method
|
||||||
|
```
|
||||||
|
|
||||||
|
##### 4. Component config → HTTP Server:
|
||||||
|
```
|
||||||
|
Max HTTP Request Header Length: 1024
|
||||||
|
Max HTTP Response Header Length: 1024
|
||||||
|
Max HTTP URI Length: 512
|
||||||
|
```
|
||||||
|
|
||||||
|
##### 5. Component config → mDNS:
|
||||||
|
```
|
||||||
|
mDNS Hostname: esp32-fire-alarm
|
||||||
|
mDNS Instance Name: Fire Alarm System
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. 编译和烧录
|
||||||
|
|
||||||
|
#### 完整编译流程:
|
||||||
|
```bash
|
||||||
|
# 1. 清理之前的构建
|
||||||
|
idf.py fullclean
|
||||||
|
|
||||||
|
# 2. 编译项目
|
||||||
|
idf.py build
|
||||||
|
|
||||||
|
# 3. 检查编译结果
|
||||||
|
ls build/
|
||||||
|
# 应该看到:
|
||||||
|
# - bootloader/bootloader.bin
|
||||||
|
# - partition_table/partition-table.bin
|
||||||
|
# - smart-home.bin (主程序)
|
||||||
|
|
||||||
|
# 4. 烧录固件
|
||||||
|
idf.py -p COM3 flash
|
||||||
|
|
||||||
|
# 5. 监控运行日志
|
||||||
|
idf.py -p COM3 monitor
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 烧录参数说明:
|
||||||
|
```bash
|
||||||
|
# 完整烧录命令(包含所有分区)
|
||||||
|
esptool.py --chip esp32 --port COM3 --baud 460800 write_flash \
|
||||||
|
0x1000 build/bootloader/bootloader.bin \
|
||||||
|
0x8000 build/partition_table/partition-table.bin \
|
||||||
|
0x10000 build/smart-home.bin
|
||||||
|
|
||||||
|
# 仅更新应用程序(开发时常用)
|
||||||
|
idf.py -p COM3 app-flash
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📱 Android开发环境配置
|
||||||
|
|
||||||
|
### 1. Android Studio配置
|
||||||
|
|
||||||
|
#### 系统要求:
|
||||||
|
```
|
||||||
|
- Android Studio 2023.1.1+
|
||||||
|
- JDK 11 或更高版本
|
||||||
|
- Android SDK API Level 34
|
||||||
|
- Gradle 8.11.1
|
||||||
|
- 最小内存:8GB RAM
|
||||||
|
- 推荐内存:16GB RAM
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Android Studio安装配置:
|
||||||
|
```bash
|
||||||
|
# 1. 下载Android Studio
|
||||||
|
https://developer.android.com/studio
|
||||||
|
|
||||||
|
# 2. 安装SDK组件
|
||||||
|
Tools → SDK Manager → SDK Platforms:
|
||||||
|
- Android 14 (API level 34) ✓
|
||||||
|
- Android 13 (API level 33) ✓
|
||||||
|
- Android 12 (API level 32) ✓
|
||||||
|
|
||||||
|
Tools → SDK Manager → SDK Tools:
|
||||||
|
- Android SDK Build-Tools 34.0.0 ✓
|
||||||
|
- Android Emulator ✓
|
||||||
|
- Android SDK Platform-Tools ✓
|
||||||
|
- Intel x86 Emulator Accelerator (HAXM installer) ✓
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 项目配置
|
||||||
|
|
||||||
|
#### Gradle配置文件:
|
||||||
|
|
||||||
|
##### build.gradle.kts (Project level):
|
||||||
|
```kotlin
|
||||||
|
plugins {
|
||||||
|
id("com.android.application") version "8.11.1" apply false
|
||||||
|
id("org.jetbrains.kotlin.android") version "1.9.10" apply false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
##### build.gradle.kts (App level):
|
||||||
|
```kotlin
|
||||||
|
android {
|
||||||
|
namespace = "com.archesens.android"
|
||||||
|
compileSdk = 34
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
applicationId = "com.archesens.android"
|
||||||
|
minSdk = 24
|
||||||
|
targetSdk = 34
|
||||||
|
versionCode = 1
|
||||||
|
versionName = "1.0"
|
||||||
|
|
||||||
|
multiDexEnabled = true
|
||||||
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
isMinifyEnabled = false
|
||||||
|
proguardFiles(
|
||||||
|
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||||
|
"proguard-rules.pro"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility = JavaVersion.VERSION_11
|
||||||
|
targetCompatibility = JavaVersion.VERSION_11
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation("androidx.core:core-ktx:1.12.0")
|
||||||
|
implementation("androidx.appcompat:appcompat:1.6.1")
|
||||||
|
implementation("com.google.android.material:material:1.11.0")
|
||||||
|
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
|
||||||
|
|
||||||
|
// MultiDex支持
|
||||||
|
implementation("androidx.multidex:multidex:2.0.1")
|
||||||
|
|
||||||
|
// 网络请求
|
||||||
|
implementation("com.squareup.okhttp3:okhttp:4.12.0")
|
||||||
|
|
||||||
|
// JSON解析
|
||||||
|
implementation("com.google.code.gson:gson:2.10.1")
|
||||||
|
|
||||||
|
// Tiqiaa SDK
|
||||||
|
implementation(files("libs/TiqiaaSDKPlugin.aar"))
|
||||||
|
implementation(files("libs/tiqiaa-remote-1.0.0.jar"))
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
##### proguard-rules.pro:
|
||||||
|
```proguard
|
||||||
|
# Tiqiaa SDK保护规则
|
||||||
|
-keep class com.tiqiaa.** { *; }
|
||||||
|
-keepclassmembers class com.tiqiaa.** { *; }
|
||||||
|
|
||||||
|
# 枚举类保护
|
||||||
|
-keepclassmembers enum com.tiqiaa.remote.enums.** {
|
||||||
|
public static **[] values();
|
||||||
|
public static ** valueOf(java.lang.String);
|
||||||
|
}
|
||||||
|
|
||||||
|
# 反射调用保护
|
||||||
|
-keepclassmembers class * {
|
||||||
|
@android.webkit.JavascriptInterface <methods>;
|
||||||
|
}
|
||||||
|
|
||||||
|
# 网络请求保护
|
||||||
|
-keep class com.archesens.android.Esp32JsBridge { *; }
|
||||||
|
-keepclassmembers class com.archesens.android.Esp32JsBridge {
|
||||||
|
public *;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 关键代码配置
|
||||||
|
|
||||||
|
#### AndroidManifest.xml 权限配置:
|
||||||
|
```xml
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
|
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
|
||||||
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
|
|
||||||
|
<application
|
||||||
|
android:name=".SmartHomeApplication"
|
||||||
|
android:allowBackup="true"
|
||||||
|
android:icon="@mipmap/ic_launcher"
|
||||||
|
android:label="@string/app_name"
|
||||||
|
android:theme="@style/AppTheme">
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name=".MainActivity"
|
||||||
|
android:exported="true"
|
||||||
|
android:launchMode="singleTop">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
</application>
|
||||||
|
```
|
||||||
|
|
||||||
|
#### SmartHomeApplication.java:
|
||||||
|
```java
|
||||||
|
public class SmartHomeApplication extends MultiDexApplication {
|
||||||
|
@Override
|
||||||
|
public void onCreate() {
|
||||||
|
super.onCreate();
|
||||||
|
MultiDex.install(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔧 开发工具配置
|
||||||
|
|
||||||
|
### 1. VS Code配置(可选)
|
||||||
|
|
||||||
|
#### 推荐插件:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"recommendations": [
|
||||||
|
"ms-vscode.cpptools",
|
||||||
|
"espressif.esp-idf-extension",
|
||||||
|
"ms-python.python",
|
||||||
|
"redhat.java",
|
||||||
|
"vscjava.vscode-java-pack"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### ESP-IDF插件配置:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"idf.espIdfPath": "D:\\Espressif5.5.2\\Espressif\\frameworks\\esp-idf-v5.5.2",
|
||||||
|
"idf.toolsPath": "D:\\Espressif5.5.2\\Espressif\\tools",
|
||||||
|
"idf.pythonBinPath": "D:\\Espressif5.5.2\\Espressif\\python_env\\idf5.5_py3.12_env\\Scripts\\python.exe",
|
||||||
|
"idf.port": "COM3",
|
||||||
|
"idf.baudRate": "460800"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 串口调试工具
|
||||||
|
|
||||||
|
#### 推荐工具:
|
||||||
|
1. **PuTTY**:简单易用的串口终端
|
||||||
|
2. **Tera Term**:功能丰富的终端模拟器
|
||||||
|
3. **Arduino IDE串口监视器**:如果安装了Arduino IDE
|
||||||
|
4. **ESP-IDF Monitor**:官方推荐工具
|
||||||
|
|
||||||
|
#### 串口参数配置:
|
||||||
|
```
|
||||||
|
波特率:115200
|
||||||
|
数据位:8
|
||||||
|
停止位:1
|
||||||
|
校验位:None
|
||||||
|
流控制:None
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 网络调试工具
|
||||||
|
|
||||||
|
#### HTTP调试:
|
||||||
|
```bash
|
||||||
|
# 使用curl测试ESP32 HTTP接口
|
||||||
|
curl -X GET http://192.168.1.100/api/status
|
||||||
|
curl -X POST http://192.168.1.100/api/ac/control \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"keyType":"POWER"}'
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Python测试脚本:
|
||||||
|
```python
|
||||||
|
# test_esp32_api.py
|
||||||
|
import requests
|
||||||
|
import json
|
||||||
|
|
||||||
|
ESP32_IP = "192.168.1.100"
|
||||||
|
BASE_URL = f"http://{ESP32_IP}"
|
||||||
|
|
||||||
|
def test_status():
|
||||||
|
response = requests.get(f"{BASE_URL}/api/status")
|
||||||
|
print(f"Status: {response.status_code}")
|
||||||
|
print(f"Response: {response.text}")
|
||||||
|
|
||||||
|
def test_ac_control(key_type):
|
||||||
|
data = {"keyType": key_type}
|
||||||
|
response = requests.post(
|
||||||
|
f"{BASE_URL}/api/ac/control",
|
||||||
|
headers={"Content-Type": "application/json"},
|
||||||
|
data=json.dumps(data)
|
||||||
|
)
|
||||||
|
print(f"AC Control ({key_type}): {response.status_code}")
|
||||||
|
print(f"Response: {response.text}")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
test_status()
|
||||||
|
test_ac_control("POWER")
|
||||||
|
test_ac_control("TEMP_UP")
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🐛 调试配置
|
||||||
|
|
||||||
|
### 1. ESP32调试
|
||||||
|
|
||||||
|
#### 日志级别配置:
|
||||||
|
```cpp
|
||||||
|
// 在app_main.cpp中设置日志级别
|
||||||
|
esp_log_level_set("*", ESP_LOG_INFO);
|
||||||
|
esp_log_level_set("WIFI", ESP_LOG_DEBUG);
|
||||||
|
esp_log_level_set("HTTP", ESP_LOG_DEBUG);
|
||||||
|
esp_log_level_set("ALARM", ESP_LOG_VERBOSE);
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 调试宏定义:
|
||||||
|
```cpp
|
||||||
|
// 在main/include/debug.h中定义
|
||||||
|
#define DEBUG_ENABLED 1
|
||||||
|
|
||||||
|
#if DEBUG_ENABLED
|
||||||
|
#define DEBUG_PRINT(fmt, ...) ESP_LOGI("DEBUG", fmt, ##__VA_ARGS__)
|
||||||
|
#define DEBUG_ERROR(fmt, ...) ESP_LOGE("DEBUG", fmt, ##__VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define DEBUG_PRINT(fmt, ...)
|
||||||
|
#define DEBUG_ERROR(fmt, ...)
|
||||||
|
#endif
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Android调试
|
||||||
|
|
||||||
|
#### Logcat过滤配置:
|
||||||
|
```bash
|
||||||
|
# 过滤应用日志
|
||||||
|
adb logcat | grep "com.archesens.android"
|
||||||
|
|
||||||
|
# 过滤特定标签
|
||||||
|
adb logcat | grep "Esp32JsBridge"
|
||||||
|
|
||||||
|
# 保存日志到文件
|
||||||
|
adb logcat > debug.log
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 调试工具配置:
|
||||||
|
```java
|
||||||
|
// 在Esp32JsBridge.java中添加调试开关
|
||||||
|
private static final boolean DEBUG = BuildConfig.DEBUG;
|
||||||
|
|
||||||
|
private void debugLog(String message) {
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📊 性能监控配置
|
||||||
|
|
||||||
|
### 1. ESP32性能监控
|
||||||
|
|
||||||
|
#### 内存监控:
|
||||||
|
```cpp
|
||||||
|
// 在app_main.cpp中添加内存监控任务
|
||||||
|
void memory_monitor_task(void *pvParameters) {
|
||||||
|
while (1) {
|
||||||
|
size_t free_heap = esp_get_free_heap_size();
|
||||||
|
size_t min_free_heap = esp_get_minimum_free_heap_size();
|
||||||
|
|
||||||
|
ESP_LOGI("MEMORY", "Free heap: %d bytes, Min free: %d bytes",
|
||||||
|
free_heap, min_free_heap);
|
||||||
|
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(10000)); // 每10秒检查一次
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### CPU使用率监控:
|
||||||
|
```cpp
|
||||||
|
// 启用任务监控
|
||||||
|
#define configUSE_TRACE_FACILITY 1
|
||||||
|
#define configUSE_STATS_FORMATTING_FUNCTIONS 1
|
||||||
|
|
||||||
|
void cpu_monitor_task(void *pvParameters) {
|
||||||
|
char *task_list_buffer = malloc(2048);
|
||||||
|
while (1) {
|
||||||
|
vTaskList(task_list_buffer);
|
||||||
|
ESP_LOGI("CPU", "Task List:\n%s", task_list_buffer);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(30000)); // 每30秒检查一次
|
||||||
|
}
|
||||||
|
free(task_list_buffer);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 网络性能监控
|
||||||
|
|
||||||
|
#### WiFi信号强度监控:
|
||||||
|
```cpp
|
||||||
|
void wifi_monitor_task(void *pvParameters) {
|
||||||
|
wifi_ap_record_t ap_info;
|
||||||
|
while (1) {
|
||||||
|
if (esp_wifi_sta_get_ap_info(&ap_info) == ESP_OK) {
|
||||||
|
ESP_LOGI("WIFI", "RSSI: %d dBm, Channel: %d",
|
||||||
|
ap_info.rssi, ap_info.primary);
|
||||||
|
}
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(15000)); // 每15秒检查一次
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔐 安全配置
|
||||||
|
|
||||||
|
### 1. WiFi安全配置
|
||||||
|
|
||||||
|
#### WPA2企业级配置(可选):
|
||||||
|
```cpp
|
||||||
|
wifi_config_t wifi_config = {
|
||||||
|
.sta = {
|
||||||
|
.ssid = "YourSSID",
|
||||||
|
.password = "YourPassword",
|
||||||
|
.threshold.authmode = WIFI_AUTH_WPA2_PSK,
|
||||||
|
.pmf_cfg = {
|
||||||
|
.capable = true,
|
||||||
|
.required = false
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. HTTP安全配置
|
||||||
|
|
||||||
|
#### HTTPS配置(生产环境推荐):
|
||||||
|
```cpp
|
||||||
|
// 在HTTP服务器配置中启用HTTPS
|
||||||
|
httpd_ssl_config_t conf = HTTPD_SSL_CONFIG_DEFAULT();
|
||||||
|
conf.httpd.server_port = 443;
|
||||||
|
conf.cacert_pem = server_cert_pem_start;
|
||||||
|
conf.cacert_len = server_cert_pem_end - server_cert_pem_start;
|
||||||
|
conf.prvtkey_pem = server_key_pem_start;
|
||||||
|
conf.prvtkey_len = server_key_pem_end - server_key_pem_start;
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📝 配置文件模板
|
||||||
|
|
||||||
|
### 1. 环境配置脚本
|
||||||
|
|
||||||
|
#### setup_environment.bat:
|
||||||
|
```batch
|
||||||
|
@echo off
|
||||||
|
echo 正在设置ESP32开发环境...
|
||||||
|
|
||||||
|
set IDF_PATH=D:\Espressif5.5.2\Espressif\frameworks\esp-idf-v5.5.2
|
||||||
|
set PATH=%PATH%;D:\Espressif5.5.2\Espressif\tools\
|
||||||
|
|
||||||
|
call %IDF_PATH%\export.bat
|
||||||
|
|
||||||
|
echo 环境设置完成!
|
||||||
|
echo IDF_PATH: %IDF_PATH%
|
||||||
|
|
||||||
|
pause
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 编译脚本
|
||||||
|
|
||||||
|
#### build_and_flash.bat:
|
||||||
|
```batch
|
||||||
|
@echo off
|
||||||
|
echo 开始编译ESP32项目...
|
||||||
|
|
||||||
|
cd /d "d:\XinJiaPo\Firefly_code\smart-home\firefly_esp32"
|
||||||
|
|
||||||
|
echo 清理构建...
|
||||||
|
idf.py fullclean
|
||||||
|
|
||||||
|
echo 编译项目...
|
||||||
|
idf.py build
|
||||||
|
|
||||||
|
if %ERRORLEVEL% EQU 0 (
|
||||||
|
echo 编译成功!开始烧录...
|
||||||
|
idf.py -p COM3 flash
|
||||||
|
|
||||||
|
if %ERRORLEVEL% EQU 0 (
|
||||||
|
echo 烧录成功!启动监控...
|
||||||
|
idf.py -p COM3 monitor
|
||||||
|
) else (
|
||||||
|
echo 烧录失败!
|
||||||
|
)
|
||||||
|
) else (
|
||||||
|
echo 编译失败!
|
||||||
|
)
|
||||||
|
|
||||||
|
pause
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**重要提醒**:
|
||||||
|
1. 首次配置时请严格按照步骤执行
|
||||||
|
2. 遇到问题时查看详细错误信息
|
||||||
|
3. 保持开发环境版本一致性
|
||||||
|
4. 定期备份配置文件和项目代码
|
||||||
|
|
||||||
|
**文档版本**:v1.0
|
||||||
|
**最后更新**:2026年2月26日
|
||||||
636
使用手册/手册指南/项目运行指南.md
Normal file
636
使用手册/手册指南/项目运行指南.md
Normal file
|
|
@ -0,0 +1,636 @@
|
||||||
|
# 智能家居火灾报警系统 - 项目运行指南
|
||||||
|
|
||||||
|
## 📋 项目概述
|
||||||
|
|
||||||
|
本项目是一个基于ESP32的智能火灾报警系统,包含以下核心功能:
|
||||||
|
- **火灾检测**:温度传感器、烟雾传感器、人体移动检测
|
||||||
|
- **红外控制**:空调遥控器功能,支持开关、温度、模式控制
|
||||||
|
- **433MHz通信**:RTM300-433M模块支持
|
||||||
|
- **WiFi连接**:支持SoftAP配置和云端数据上报
|
||||||
|
- **Android应用**:完整的移动端控制界面
|
||||||
|
|
||||||
|
## 🏗️ 项目结构
|
||||||
|
|
||||||
|
```
|
||||||
|
smart-home/
|
||||||
|
├── firefly_esp32/ # ESP32固件代码
|
||||||
|
│ ├── main/ # 主程序代码
|
||||||
|
│ ├── managed_components/ # ESP-IDF组件
|
||||||
|
│ └── sdkconfig # ESP32配置文件
|
||||||
|
├── Smarthome_android/ # Android应用代码
|
||||||
|
│ └── app/ # Android应用主代码
|
||||||
|
├── cloud-backend-jdk8/ # 云端后台服务
|
||||||
|
├── python_test/ # Python测试脚本
|
||||||
|
└── ziyuan/ # SDK和资源文件
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 硬件运行指南
|
||||||
|
|
||||||
|
### 1. 硬件清单
|
||||||
|
|
||||||
|
#### 必需硬件:
|
||||||
|
- **ESP32开发板** (推荐ESP32-WROOM-32)
|
||||||
|
- **红外发射模块** (连接GPIO4)
|
||||||
|
- **温度传感器** (DS18B20或类似)
|
||||||
|
- **烟雾传感器** (MQ-2或类似)
|
||||||
|
- **人体红外传感器** (PIR)
|
||||||
|
- **蜂鸣器** (报警提示)
|
||||||
|
- **LED指示灯** (状态显示)
|
||||||
|
- **电源适配器** (5V/2A)
|
||||||
|
|
||||||
|
#### 可选硬件:
|
||||||
|
- **433MHz模块** (RTM300-433M)
|
||||||
|
- **雷达传感器** (距离检测)
|
||||||
|
- **外部天线** (提高WiFi信号)
|
||||||
|
|
||||||
|
### 2. 硬件连接图
|
||||||
|
|
||||||
|
```
|
||||||
|
ESP32 引脚连接:
|
||||||
|
┌─────────────────┬─────────────────┬─────────────────┐
|
||||||
|
│ ESP32 GPIO │ 连接设备 │ 功能说明 │
|
||||||
|
├─────────────────┼─────────────────┼─────────────────┤
|
||||||
|
│ GPIO4 │ 红外发射器 │ 空调控制信号 │
|
||||||
|
│ GPIO2 │ LED指示灯 │ 状态显示 │
|
||||||
|
│ GPIO5 │ 蜂鸣器 │ 报警提示 │
|
||||||
|
│ GPIO18 │ 温度传感器 │ 火灾检测 │
|
||||||
|
│ GPIO19 │ 烟雾传感器 │ 烟雾检测 │
|
||||||
|
│ GPIO21 │ PIR传感器 │ 人体移动检测 │
|
||||||
|
│ GPIO22 │ 433MHz模块(SDA) │ 无线通信 │
|
||||||
|
│ GPIO23 │ 433MHz模块(SCL) │ 无线通信 │
|
||||||
|
│ GPIO0 │ 配置按钮 │ WiFi配置模式 │
|
||||||
|
│ 3.3V │ 传感器电源 │ 供电 │
|
||||||
|
│ GND │ 公共地线 │ 接地 │
|
||||||
|
└─────────────────┴─────────────────┴─────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 硬件安装步骤
|
||||||
|
|
||||||
|
#### 步骤1:ESP32基础连接
|
||||||
|
```bash
|
||||||
|
1. 将ESP32开发板固定在面包板或PCB上
|
||||||
|
2. 连接电源线:5V → VIN,GND → GND
|
||||||
|
3. 连接USB数据线到电脑(用于烧录和调试)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 步骤2:传感器连接
|
||||||
|
```bash
|
||||||
|
# 温度传感器 (DS18B20)
|
||||||
|
VCC → 3.3V
|
||||||
|
GND → GND
|
||||||
|
DATA → GPIO18
|
||||||
|
|
||||||
|
# 烟雾传感器 (MQ-2)
|
||||||
|
VCC → 3.3V
|
||||||
|
GND → GND
|
||||||
|
AOUT → GPIO19
|
||||||
|
|
||||||
|
# PIR人体传感器
|
||||||
|
VCC → 3.3V
|
||||||
|
GND → GND
|
||||||
|
OUT → GPIO21
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 步骤3:红外发射器连接
|
||||||
|
```bash
|
||||||
|
# 红外发射器模块
|
||||||
|
VCC → 3.3V
|
||||||
|
GND → GND
|
||||||
|
DATA → GPIO4
|
||||||
|
|
||||||
|
注意:红外发射器需要对准空调接收窗口,距离建议1-3米
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 步骤4:433MHz模块连接(可选)
|
||||||
|
```bash
|
||||||
|
# RTM300-433M模块
|
||||||
|
VCC → 3.3V
|
||||||
|
GND → GND
|
||||||
|
SDA → GPIO22
|
||||||
|
SCL → GPIO23
|
||||||
|
IRQ → GPIO25
|
||||||
|
|
||||||
|
注意:433MHz模块需要外接天线以提高通信距离
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 步骤5:指示器连接
|
||||||
|
```bash
|
||||||
|
# LED指示灯
|
||||||
|
正极 → GPIO2
|
||||||
|
负极 → GND (通过220Ω电阻)
|
||||||
|
|
||||||
|
# 蜂鸣器
|
||||||
|
正极 → GPIO5
|
||||||
|
负极 → GND
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. 硬件测试验证
|
||||||
|
|
||||||
|
#### 基础功能测试:
|
||||||
|
```bash
|
||||||
|
1. 上电测试:LED应该闪烁,表示系统启动
|
||||||
|
2. WiFi测试:长按GPIO0按钮,进入配置模式
|
||||||
|
3. 传感器测试:用打火机测试烟雾传感器
|
||||||
|
4. 红外测试:对准空调测试遥控功能
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 💻 软件环境搭建
|
||||||
|
|
||||||
|
### 1. ESP32开发环境
|
||||||
|
|
||||||
|
#### 安装ESP-IDF 5.5.2:
|
||||||
|
```bash
|
||||||
|
# Windows环境
|
||||||
|
1. 下载ESP-IDF 5.5.2安装包
|
||||||
|
2. 安装到:D:\Espressif5.5.2\
|
||||||
|
3. 配置环境变量:
|
||||||
|
- IDF_PATH=D:\Espressif5.5.2\Espressif\frameworks\esp-idf-v5.5.2
|
||||||
|
- 添加到PATH:D:\Espressif5.5.2\Espressif\tools\
|
||||||
|
|
||||||
|
# 验证安装
|
||||||
|
idf.py --version
|
||||||
|
```
|
||||||
|
|
||||||
|
#### ESP32项目配置:
|
||||||
|
```bash
|
||||||
|
cd d:\XinJiaPo\Firefly_code\smart-home\firefly_esp32
|
||||||
|
|
||||||
|
# 配置项目
|
||||||
|
idf.py menuconfig
|
||||||
|
|
||||||
|
# 重要配置项:
|
||||||
|
- Component config → ESP32-specific → CPU frequency → 240 MHz
|
||||||
|
- Component config → FreeRTOS → Tick rate → 1000 Hz
|
||||||
|
- Component config → Wi-Fi → WiFi Task Core ID → Core 1
|
||||||
|
- Partition Table → Custom partition table CSV → partitions.csv
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Android开发环境
|
||||||
|
|
||||||
|
#### 安装要求:
|
||||||
|
```bash
|
||||||
|
- Android Studio 2023.1+
|
||||||
|
- JDK 11+
|
||||||
|
- Android SDK API 34
|
||||||
|
- Gradle 8.11.1
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 项目配置:
|
||||||
|
```bash
|
||||||
|
cd d:\XinJiaPo\Firefly_code\smart-home\Smarthome_android\Smarthome_android
|
||||||
|
|
||||||
|
# 同步项目
|
||||||
|
./gradlew sync
|
||||||
|
|
||||||
|
# 编译项目
|
||||||
|
./gradlew assembleDebug
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Python测试环境
|
||||||
|
|
||||||
|
#### 安装依赖:
|
||||||
|
```bash
|
||||||
|
pip install requests
|
||||||
|
pip install pyserial
|
||||||
|
pip install json
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 系统部署流程
|
||||||
|
|
||||||
|
### 1. ESP32固件烧录
|
||||||
|
|
||||||
|
#### 编译固件:
|
||||||
|
```bash
|
||||||
|
cd d:\XinJiaPo\Firefly_code\smart-home\firefly_esp32
|
||||||
|
|
||||||
|
# 清理构建
|
||||||
|
idf.py fullclean
|
||||||
|
|
||||||
|
# 编译固件
|
||||||
|
idf.py build
|
||||||
|
|
||||||
|
# 烧录固件
|
||||||
|
idf.py -p COM3 flash
|
||||||
|
|
||||||
|
# 监控日志
|
||||||
|
idf.py -p COM3 monitor
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 烧录验证:
|
||||||
|
```bash
|
||||||
|
# 查看启动日志
|
||||||
|
I (0) cpu_start: Starting scheduler on APP CPU.
|
||||||
|
I (1000) MAIN: 🔥 智能火灾报警系统启动
|
||||||
|
I (1010) WIFI: WiFi初始化完成
|
||||||
|
I (1020) HTTP: HTTP服务器启动在端口80
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Android应用安装
|
||||||
|
|
||||||
|
#### 编译APK:
|
||||||
|
```bash
|
||||||
|
cd d:\XinJiaPo\Firefly_code\smart-home\Smarthome_android\Smarthome_android
|
||||||
|
|
||||||
|
# 编译Debug版本
|
||||||
|
./gradlew assembleDebug
|
||||||
|
|
||||||
|
# APK位置:
|
||||||
|
app/build/outputs/apk/debug/app-debug.apk
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 安装到设备:
|
||||||
|
```bash
|
||||||
|
# 通过ADB安装
|
||||||
|
adb install app/build/outputs/apk/debug/app-debug.apk
|
||||||
|
|
||||||
|
# 或者直接拷贝APK到手机安装
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 系统配置
|
||||||
|
|
||||||
|
#### WiFi配置:
|
||||||
|
```bash
|
||||||
|
1. 长按ESP32的GPIO0按钮3秒
|
||||||
|
2. ESP32进入SoftAP模式,LED快速闪烁
|
||||||
|
3. 手机连接WiFi:ESP32-Config
|
||||||
|
4. 浏览器打开:192.168.4.1
|
||||||
|
5. 输入家庭WiFi信息并保存
|
||||||
|
6. ESP32重启后自动连接WiFi
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 设备配对:
|
||||||
|
```bash
|
||||||
|
1. 打开Android应用
|
||||||
|
2. 点击"添加设备"
|
||||||
|
3. 扫描局域网中的ESP32设备
|
||||||
|
4. 选择设备并完成配对
|
||||||
|
5. 测试空调控制功能
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔍 功能测试指南
|
||||||
|
|
||||||
|
### 1. 火灾报警测试
|
||||||
|
|
||||||
|
#### 温度报警测试:
|
||||||
|
```bash
|
||||||
|
# 使用热风枪或打火机加热温度传感器
|
||||||
|
# 预期结果:
|
||||||
|
- 温度超过60°C时触发报警
|
||||||
|
- 蜂鸣器响起
|
||||||
|
- LED红灯闪烁
|
||||||
|
- Android应用收到报警推送
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 烟雾报警测试:
|
||||||
|
```bash
|
||||||
|
# 在烟雾传感器附近点燃纸张
|
||||||
|
# 预期结果:
|
||||||
|
- 检测到烟雾时触发报警
|
||||||
|
- 蜂鸣器响起
|
||||||
|
- LED红灯闪烁
|
||||||
|
- 云端收到报警数据
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 红外控制测试
|
||||||
|
|
||||||
|
#### 空调控制测试:
|
||||||
|
```bash
|
||||||
|
# 在Android应用中测试:
|
||||||
|
1. 点击"电源"按钮 → 空调开关
|
||||||
|
2. 点击"温度+"按钮 → 温度上升
|
||||||
|
3. 点击"温度-"按钮 → 温度下降
|
||||||
|
4. 点击"模式"按钮 → 制冷/制热/除湿循环
|
||||||
|
5. 点击"风量"按钮 → 风量调节
|
||||||
|
|
||||||
|
# 验证方法:
|
||||||
|
- 观察空调面板显示变化
|
||||||
|
- 检查ESP32日志输出
|
||||||
|
- 确认红外信号发送成功
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 网络功能测试
|
||||||
|
|
||||||
|
#### WiFi连接测试:
|
||||||
|
```bash
|
||||||
|
# 检查ESP32日志:
|
||||||
|
I (5000) WIFI: WiFi连接成功
|
||||||
|
I (5010) WIFI: IP地址: 192.168.1.100
|
||||||
|
I (5020) HTTP: HTTP服务器启动成功
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 云端通信测试:
|
||||||
|
```bash
|
||||||
|
# 使用Python脚本测试:
|
||||||
|
cd d:\XinJiaPo\Firefly_code\smart-home\python_test
|
||||||
|
python test_cloud_alarm_integration.py
|
||||||
|
|
||||||
|
# 预期结果:
|
||||||
|
- 成功连接云端服务器
|
||||||
|
- 报警数据上传成功
|
||||||
|
- 收到服务器响应
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🛠️ 故障排除
|
||||||
|
|
||||||
|
### 1. 硬件问题
|
||||||
|
|
||||||
|
#### ESP32无法启动:
|
||||||
|
```bash
|
||||||
|
问题:上电后无反应
|
||||||
|
解决:
|
||||||
|
1. 检查电源电压(应为5V/2A)
|
||||||
|
2. 检查USB线连接
|
||||||
|
3. 按下RST按钮重启
|
||||||
|
4. 检查GPIO0是否被误触发
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 传感器无读数:
|
||||||
|
```bash
|
||||||
|
问题:传感器数据为0或异常
|
||||||
|
解决:
|
||||||
|
1. 检查传感器供电(3.3V)
|
||||||
|
2. 检查信号线连接
|
||||||
|
3. 用万用表测试传感器输出
|
||||||
|
4. 更换传感器模块
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 红外控制无效:
|
||||||
|
```bash
|
||||||
|
问题:空调不响应红外信号
|
||||||
|
解决:
|
||||||
|
1. 检查红外发射器方向
|
||||||
|
2. 减少发射距离(1-2米)
|
||||||
|
3. 检查GPIO4连接
|
||||||
|
4. 重新配对空调遥控器
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 软件问题
|
||||||
|
|
||||||
|
#### 编译错误:
|
||||||
|
```bash
|
||||||
|
问题:ESP32编译失败
|
||||||
|
解决:
|
||||||
|
1. 检查ESP-IDF版本(需要5.5.2)
|
||||||
|
2. 清理构建:idf.py fullclean
|
||||||
|
3. 检查sdkconfig配置
|
||||||
|
4. 更新组件:idf.py update-dependencies
|
||||||
|
```
|
||||||
|
|
||||||
|
#### WiFi连接失败:
|
||||||
|
```bash
|
||||||
|
问题:无法连接WiFi
|
||||||
|
解决:
|
||||||
|
1. 检查WiFi密码正确性
|
||||||
|
2. 确认WiFi为2.4GHz频段
|
||||||
|
3. 重置WiFi配置:长按GPIO0按钮
|
||||||
|
4. 检查路由器MAC过滤设置
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Android应用崩溃:
|
||||||
|
```bash
|
||||||
|
问题:应用启动崩溃
|
||||||
|
解决:
|
||||||
|
1. 检查Android版本兼容性
|
||||||
|
2. 清除应用数据和缓存
|
||||||
|
3. 重新安装APK
|
||||||
|
4. 查看logcat日志定位问题
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 网络问题
|
||||||
|
|
||||||
|
#### 设备发现失败:
|
||||||
|
```bash
|
||||||
|
问题:Android应用找不到ESP32设备
|
||||||
|
解决:
|
||||||
|
1. 确认手机和ESP32在同一WiFi网络
|
||||||
|
2. 检查路由器防火墙设置
|
||||||
|
3. 手动输入ESP32 IP地址
|
||||||
|
4. 重启路由器和设备
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 云端通信失败:
|
||||||
|
```bash
|
||||||
|
问题:无法上传报警数据
|
||||||
|
解决:
|
||||||
|
1. 检查网络连接
|
||||||
|
2. 验证云端服务器状态
|
||||||
|
3. 检查防火墙设置
|
||||||
|
4. 使用Python脚本测试API
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 性能监控
|
||||||
|
|
||||||
|
### 1. 系统监控指标
|
||||||
|
|
||||||
|
#### ESP32性能监控:
|
||||||
|
```bash
|
||||||
|
# 内存使用情况
|
||||||
|
I (10000) HEAP: 剩余内存: 180KB/320KB
|
||||||
|
|
||||||
|
# CPU使用率
|
||||||
|
I (10010) CPU: CPU使用率: 45%
|
||||||
|
|
||||||
|
# WiFi信号强度
|
||||||
|
I (10020) WIFI: RSSI: -45dBm (信号良好)
|
||||||
|
|
||||||
|
# 传感器读取频率
|
||||||
|
I (10030) SENSOR: 传感器更新频率: 1Hz
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 网络性能监控:
|
||||||
|
```bash
|
||||||
|
# HTTP响应时间
|
||||||
|
平均响应时间: 50ms
|
||||||
|
最大响应时间: 200ms
|
||||||
|
|
||||||
|
# 数据上传成功率
|
||||||
|
上传成功率: 98.5%
|
||||||
|
重试次数: 平均1.2次
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 日志分析
|
||||||
|
|
||||||
|
#### 关键日志标识:
|
||||||
|
```bash
|
||||||
|
🔥 - 系统启动和关键事件
|
||||||
|
✅ - 操作成功
|
||||||
|
⚠️ - 警告信息
|
||||||
|
❌ - 错误信息
|
||||||
|
🎯 - 调试信息
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 日志文件位置:
|
||||||
|
```bash
|
||||||
|
ESP32日志:通过串口监控获取
|
||||||
|
Android日志:adb logcat | grep "Esp32JsBridge"
|
||||||
|
云端日志:服务器日志文件
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📝 维护指南
|
||||||
|
|
||||||
|
### 1. 定期维护
|
||||||
|
|
||||||
|
#### 每周检查:
|
||||||
|
```bash
|
||||||
|
1. 检查设备运行状态
|
||||||
|
2. 清理传感器灰尘
|
||||||
|
3. 检查网络连接稳定性
|
||||||
|
4. 测试报警功能
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 每月维护:
|
||||||
|
```bash
|
||||||
|
1. 更新固件版本
|
||||||
|
2. 备份配置数据
|
||||||
|
3. 检查硬件连接
|
||||||
|
4. 性能数据分析
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 版本更新
|
||||||
|
|
||||||
|
#### ESP32固件更新:
|
||||||
|
```bash
|
||||||
|
cd d:\XinJiaPo\Firefly_code\smart-home\firefly_esp32
|
||||||
|
|
||||||
|
# 拉取最新代码
|
||||||
|
git pull origin main
|
||||||
|
|
||||||
|
# 编译新固件
|
||||||
|
idf.py build
|
||||||
|
|
||||||
|
# OTA更新(推荐)
|
||||||
|
python simple_ota.ps1
|
||||||
|
|
||||||
|
# 或串口更新
|
||||||
|
idf.py -p COM3 flash
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Android应用更新:
|
||||||
|
```bash
|
||||||
|
cd d:\XinJiaPo\Firefly_code\smart-home\Smarthome_android\Smarthome_android
|
||||||
|
|
||||||
|
# 更新版本号
|
||||||
|
# 编辑 app/build.gradle.kts
|
||||||
|
versionCode = 2
|
||||||
|
versionName = "1.1.0"
|
||||||
|
|
||||||
|
# 编译新版本
|
||||||
|
./gradlew assembleRelease
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📞 技术支持
|
||||||
|
|
||||||
|
### 联系信息
|
||||||
|
- **项目负责人**:[原开发者姓名]
|
||||||
|
- **技术文档**:项目根目录下的各种.md文件
|
||||||
|
- **代码仓库**:Git仓库地址
|
||||||
|
- **问题反馈**:GitHub Issues或内部问题跟踪系统
|
||||||
|
|
||||||
|
### 常用命令速查
|
||||||
|
```bash
|
||||||
|
# ESP32相关
|
||||||
|
idf.py build # 编译固件
|
||||||
|
idf.py -p COM3 flash # 烧录固件
|
||||||
|
idf.py -p COM3 monitor # 监控日志
|
||||||
|
idf.py menuconfig # 配置项目
|
||||||
|
|
||||||
|
# Android相关
|
||||||
|
./gradlew assembleDebug # 编译Debug版本
|
||||||
|
./gradlew assembleRelease # 编译Release版本
|
||||||
|
adb install app-debug.apk # 安装APK
|
||||||
|
adb logcat # 查看日志
|
||||||
|
|
||||||
|
# Python测试
|
||||||
|
python test_cloud_alarm_integration.py # 云端测试
|
||||||
|
python test_ir_control.py # 红外测试
|
||||||
|
python wifi_config_simple.py # WiFi配置
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ⚠️ 重要注意事项
|
||||||
|
|
||||||
|
1. **安全警告**:
|
||||||
|
- 火灾报警系统仅作为辅助设备,不能替代专业消防设备
|
||||||
|
- 定期测试系统功能,确保正常工作
|
||||||
|
- 传感器需要定期校准和清洁
|
||||||
|
|
||||||
|
2. **电气安全**:
|
||||||
|
- 使用合适的电源适配器(5V/2A)
|
||||||
|
- 避免短路和过载
|
||||||
|
- 在潮湿环境中注意防水
|
||||||
|
|
||||||
|
3. **网络安全**:
|
||||||
|
- 定期更新固件以修复安全漏洞
|
||||||
|
- 使用强密码保护WiFi网络
|
||||||
|
- 监控异常网络活动
|
||||||
|
|
||||||
|
4. **数据隐私**:
|
||||||
|
- 了解数据上传和存储政策
|
||||||
|
- 定期备份重要配置数据
|
||||||
|
- 注意个人隐私保护
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📚 相关文档
|
||||||
|
|
||||||
|
本项目包含以下详细指南文档:
|
||||||
|
|
||||||
|
### 核心文档:
|
||||||
|
- **[项目运行指南.md](./项目运行指南.md)** - 本文档,项目总体概述
|
||||||
|
- **[硬件接线详细指南.md](./硬件接线详细指南.md)** - 详细的硬件连接和电路图
|
||||||
|
- **[软件配置详细指南.md](./软件配置详细指南.md)** - 开发环境和软件配置
|
||||||
|
- **[故障排除与维护指南.md](./故障排除与维护指南.md)** - 故障诊断和维护流程
|
||||||
|
|
||||||
|
### 专项文档:
|
||||||
|
- **[433MHz_使用指南.md](./433MHz_使用指南.md)** - 433MHz模块配置和使用
|
||||||
|
- **[WiFi省电测试指南.md](./WiFi省电测试指南.md)** - WiFi功耗管理
|
||||||
|
- **[ESP32编译烧录指南.md](./ESP32编译烧录指南.md)** - 固件编译和烧录
|
||||||
|
|
||||||
|
### 技术文档:
|
||||||
|
- **[SDK_data_hex转红外脉冲算法详解.md](./SDK_data_hex转红外脉冲算法详解.md)** - 红外信号处理算法
|
||||||
|
- **[diagnose_ir_system.md](./diagnose_ir_system.md)** - 红外系统诊断
|
||||||
|
- **各种修复和优化文档** - 项目根目录下的其他.md文件
|
||||||
|
|
||||||
|
### 快速参考:
|
||||||
|
|
||||||
|
#### 🚀 快速启动流程:
|
||||||
|
1. **硬件连接** → 参考《硬件接线详细指南》
|
||||||
|
2. **软件配置** → 参考《软件配置详细指南》
|
||||||
|
3. **固件烧录** → 参考《ESP32编译烧录指南》
|
||||||
|
4. **功能测试** → 参考本文档的测试章节
|
||||||
|
5. **故障排除** → 参考《故障排除与维护指南》
|
||||||
|
|
||||||
|
#### 📞 获取帮助:
|
||||||
|
- **硬件问题** → 查看硬件接线详细指南
|
||||||
|
- **软件问题** → 查看软件配置详细指南
|
||||||
|
- **网络问题** → 查看WiFi配置相关文档
|
||||||
|
- **功能异常** → 查看故障排除与维护指南
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**文档版本**:v1.0
|
||||||
|
**最后更新**:2026年2月26日
|
||||||
|
**适用版本**:ESP32固件v2.1.0,Android应用v1.0.0
|
||||||
|
|
||||||
|
**文档完整性检查**:
|
||||||
|
- ✅ 项目运行指南.md
|
||||||
|
- ✅ 硬件接线详细指南.md
|
||||||
|
- ✅ 软件配置详细指南.md
|
||||||
|
- ✅ 故障排除与维护指南.md
|
||||||
4
使用手册/环境配置/配置教程网址.md
Normal file
4
使用手册/环境配置/配置教程网址.md
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
https://www.cnblogs.com/weizhixing/p/19036785
|
||||||
|
https://liefyuan.blog.csdn.net/article/details/124579583
|
||||||
|
配置网址如上,两个均可参考使用。
|
||||||
|
用的是esp-idf v5.5.2版本
|
||||||
BIN
使用手册/视频/场景A监控+火灾报警.mp4
Normal file
BIN
使用手册/视频/场景A监控+火灾报警.mp4
Normal file
Binary file not shown.
BIN
使用手册/视频/场景B空调.mp4
Normal file
BIN
使用手册/视频/场景B空调.mp4
Normal file
Binary file not shown.
BIN
使用手册/视频/电脑esp32项目烧录教程演示.mp4
Normal file
BIN
使用手册/视频/电脑esp32项目烧录教程演示.mp4
Normal file
Binary file not shown.
BIN
使用手册/视频/红外控制插排.mp4
Normal file
BIN
使用手册/视频/红外控制插排.mp4
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user