以下是一个基于ESP32-C2和ESP-IDF框架的工业温度振动传感器详细实现方案,包含波形录播、滤波算法和MQTT上传功能。
硬件准备
- ESP32-C2开发板
- 工业振动传感器(如ADXL345或IIS3DWB)
- 温度传感器(如DS18B20或MAX31865)
- 电源模块(建议3.3V稳压)
软件架构
- 使用FreeRTOS任务管理
- 双缓冲机制实现波形录播
- 数字滤波处理振动数据
- MQTT协议上传到云平台
传感器初始化(以IIS3DWB为例)
#include "iis3dwb_reg.h"
static iis3dwb_ctx_t dev_ctx;
static float acceleration_mg[3];
void iis3dwb_init(void) {
dev_ctx.write_reg = i2c_write;
dev_ctx.read_reg = i2c_read;
dev_ctx.handle = &i2c_handle;
// Check device ID
uint8_t whoami;
iis3dwb_device_id_get(&dev_ctx, &whoami);
if(whoami != IIS3DWB_ID) {
ESP_LOGE(TAG, "IIS3DWB not found");
return;
}
// Configure sensor
iis3dwb_block_data_update_set(&dev_ctx, PROPERTY_ENABLE);
iis3dwb_xl_data_rate_set(&dev_ctx, IIS3DWB_XL_ODR_26k7Hz);
iis3dwb_xl_full_scale_set(&dev_ctx, IIS3DWB_16g);
}
振动数据采集与滤波
#define SAMPLE_RATE 1000 // Hz
#define WINDOW_SIZE 128
// 移动平均滤波器
typedef struct {
float buffer[WINDOW_SIZE];
uint16_t index;
float sum;
} MovingAverageFilter;
void init_filter(MovingAverageFilter* filter) {
memset(filter->buffer, 0, sizeof(filter->buffer));
filter->index = 0;
filter->sum = 0.0f;
}
float update_filter(MovingAverageFilter* filter, float new_sample) {
filter->sum -= filter->buffer[filter->index];
filter->buffer[filter->index] = new_sample;
filter->sum += new_sample;
filter->index = (filter->index + 1) % WINDOW_SIZE;
return filter->sum / WINDOW_SIZE;
}
// IIR低通滤波器
float iir_lowpass_filter(float input, float* prev_output, float alpha) {
float output = alpha * input + (1 - alpha) * (*prev_output);
*prev_output = output;
return output;
}
波形录播功能实现
#define BUFFER_SIZE 2048
typedef struct {
float x[BUFFER_SIZE];
float y[BUFFER_SIZE];
float z[BUFFER_SIZE];
uint32_t timestamp[BUFFER_SIZE];
uint16_t write_idx;
bool ready_for_upload;
} WaveformBuffer;
WaveformBuffer buffer_a, buffer_b;
WaveformBuffer* active_buffer = &buffer_a;
void record_waveform_task(void* pvParameters) {
MovingAverageFilter filter_x, filter_y, filter_z;
init_filter(&filter_x);
init_filter(&filter_y);
init_filter(&filter_z);
float iir_prev_x = 0, iir_prev_y = 0, iir_prev_z = 0;
const float iir_alpha = 0.1f; // 截止频率约为采样率的1/10
while(1) {
// 读取原始数据
int16_t raw_acc[3];
iis3dwb_acceleration_raw_get(&dev_ctx, raw_acc);
// 转换为g值并应用滤波
float x = update_filter(&filter_x, raw_acc[0] * 0.049f); // 0.049 mg/LSB @ 16g
float y = update_filter(&filter_y, raw_acc[1] * 0.049f);
float z = update_filter(&filter_z, raw_acc[2] * 0.049f);
x = iir_lowpass_filter(x, &iir_prev_x, iir_alpha);
y = iir_lowpass_filter(y, &iir_prev_y, iir_alpha);
z = iir_lowpass_filter(z, &iir_prev_z, iir_alpha);
// 存储到缓冲区
active_buffer->x[active_buffer->write_idx] = x;
active_buffer->y[active_buffer->write_idx] = y;
active_buffer->z[active_buffer->write_idx] = z;
active_buffer->timestamp[active_buffer->write_idx] = xTaskGetTickCount() * portTICK_PERIOD_MS;
if(++active_buffer->write_idx >= BUFFER_SIZE) {
active_buffer->ready_for_upload = true;
active_buffer = (active_buffer == &buffer_a) ? &buffer_b : &buffer_a;
active_buffer->write_idx = 0;
}
vTaskDelay(pdMS_TO_TICKS(1000/SAMPLE_RATE));
}
}
MQTT上传实现
#include "mqtt_client.h"
esp_mqtt_client_handle_t mqtt_client;
void mqtt_event_handler(void* handler_args, esp_event_base_t base, int32_t event_id, void* event_data) {
esp_mqtt_event_handle_t event = event_data;
switch(event->event_id) {
case MQTT_EVENT_CONNECTED:
ESP_LOGI(TAG, "MQTT connected");
break;
case MQTT_EVENT_DISCONNECTED:
ESP_LOGI(TAG, "MQTT disconnected");
break;
case MQTT_EVENT_DATA:
// 处理接收到的消息
break;
}
}
void init_mqtt() {
esp_mqtt_client_config_t mqtt_cfg = {
.uri = "mqtt://your.cloud.server:1883",
.username = "device_user",
.password = "device_password",
};
mqtt_client = esp_mqtt_client_init(&mqtt_cfg);
esp_mqtt_client_register_event(mqtt_client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
esp_mqtt_client_start(mqtt_client);
}
void upload_waveform_data(WaveformBuffer* buffer) {
char topic[50];
snprintf(topic, sizeof(topic), "device/%s/waveform", "your_device_id");
cJSON* root = cJSON_CreateObject();
cJSON* x_array = cJSON_CreateFloatArray(buffer->x, BUFFER_SIZE);
cJSON* y_array = cJSON_CreateFloatArray(buffer->y, BUFFER_SIZE);
cJSON* z_array = cJSON_CreateFloatArray(buffer->z, BUFFER_SIZE);
cJSON* time_array = cJSON_CreateIntArray(buffer->timestamp, BUFFER_SIZE);
cJSON_AddItemToObject(root, "x", x_array);
cJSON_AddItemToObject(root, "y", y_array);
cJSON_AddItemToObject(root, "z", z_array);
cJSON_AddItemToObject(root, "timestamp", time_array);
char* json_str = cJSON_PrintUnformatted(root);
esp_mqtt_client_publish(mqtt_client, topic, json_str, 0, 1, 0);
cJSON_Delete(root);
free(json_str);
}
主任务调度
void app_main() {
// 初始化硬件和外设
i2c_init();
iis3dwb_init();
temperature_sensor_init();
init_mqtt();
// 创建任务
xTaskCreate(record_waveform_task, "waveform_task", 4096, NULL, 5, NULL);
xTaskCreate(temperature_task, "temp_task", 2048, NULL, 3, NULL);
xTaskCreate(upload_task, "upload_task", 4096, NULL, 4, NULL);
}
void upload_task(void* pvParameters) {
while(1) {
if(buffer_a.ready_for_upload) {
upload_waveform_data(&buffer_a);
buffer_a.ready_for_upload = false;
}
if(buffer_b.ready_for_upload) {
upload_waveform_data(&buffer_b);
buffer_b.ready_for_upload = false;
}
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
数据库设计建议
云服务数据库建议采用时间序列数据库结构:
CREATE TABLE vibration_data (
device_id VARCHAR(32),
timestamp BIGINT,
x_value FLOAT,
y_value FLOAT,
z_value FLOAT,
temperature FLOAT,
rms_value FLOAT,
PRIMARY KEY (device_id, timestamp)
);
CREATE TABLE waveform_records (
record_id UUID PRIMARY KEY,
device_id VARCHAR(32),
start_time BIGINT,
end_time BIGINT,
sample_rate INT,
data_url TEXT
);
高级滤波算法实现
对于更复杂的振动分析,可添加频域处理:
#include "dsps_fft2r.h"
void fft_analysis(float* time_domain, float* freq_domain, size_t len) {
float* fft_input = malloc(len * sizeof(float));
float* fft_output = malloc(len * sizeof(float));
// 复制数据并加窗
for(int i=0; i<len; i++) {
fft_input[i] = time_domain[i] * (0.54 - 0.46 * cos(2*M_PI*i/(len-1))); // Hamming窗
}
// 执行FFT
dsps_fft2r_init_fc32(NULL, len);
dsps_fft2r_fc32(fft_input, len);
dsps_bit_rev_fc32(fft_input, len);
dsps_cplx2real_fc32(fft_input, len, fft_output);
// 计算幅值
for(int i=0; i<len/2; i++) {
freq_domain[i] = sqrtf(fft_output[2*i]*fft_output[2*i] +
fft_output[2*i+1]*fft_output[2*i+1]);
}
free(fft_input);
free(fft_output);
}
注意事项
- 实际应用中需要添加错误处理和重连机制
- 振动传感器采样率应根据实际需求调整
- 滤波参数需要根据信号特性优化
- MQTT传输应考虑数据压缩以减少带宽
- 对于长期运行,需要实现数据本地存储功能
完整项目应包含以下组件:
- 传感器驱动层
- 数据处理层(滤波/FFT)
- 数据缓冲层
- 通信协议层
- 云端对接层
可根据具体硬件型号调整传感器初始化参数,并优化滤波算法以满足不同工业场景的需求。
193

被折叠的 条评论
为什么被折叠?



