活动介绍
file-type

LSM-Tree算法:优化索引变更与降低磁盘开销

7Z文件

下载需积分: 9 | 96KB | 更新于2025-03-04 | 102 浏览量 | 5 下载量 举报 1 收藏
download 立即下载
LSM树(Log-Structured Merge-Tree)是一种数据结构,主要用于大规模数据存储系统,如NoSQL数据库和大数据处理平台中,用以提升写操作性能。LSM树的设计理念来源于日志结构文件系统,它将数据的修改顺序地记录在磁盘上,而不是立即更新原有数据项,从而减少对磁盘的随机写操作,提高效率。 重要知识点包括: 1. **LSM树的基本原理**: - LSM树通过将所有的写操作首先写入到内存中的数据结构(如SSTable—Sorted String Table),这部分内存通常被称为MemTable。 - 当MemTable达到一定大小后,将其转换为不可变的存储结构并写入到磁盘中,这个过程被称为Compaction(合并)。 - 为了查找和合并的方便,LSM树通常将数据分割成多个层次(Level),每个Level的数据大小按某种规则递增。 - LSM树操作过程中涉及的磁盘读写开销远小于传统的B树结构,因为B树需要频繁地进行磁盘读写以维护树的平衡性。 2. **LSM树的优势**: - **写入性能的提升**:LSM树主要通过延迟写入和顺序写入的策略提高了写操作的效率。 - **减少磁盘臂移动**:由于数据是顺序存储的,与传统B树相比,LSM树显著减少了磁盘臂移动的次数,这在机械硬盘上表现尤为明显。 - **空间放大问题的缓解**:随着数据的写入和删除,LSM树通过Compaction过程能够减少存储空间的浪费。 3. **LSM树的缺点**: - **读取性能牺牲**:由于数据可能分布在不同层的多个文件中,LSM树的读取操作相比B树来说更加复杂和耗时,需要在多个文件中查找,或者在读取时等待Compaction过程完成。 - **Compaction开销**:Compaction过程本身会占用一定的CPU和I/O资源,可能会对系统性能产生影响,尤其是在数据量大、访问热点集中时。 - **空间放大**:数据的删除和更新会使得相同的数据在多个层次中重复存储,增加了存储空间的需求。 4. **Compaction策略**: - **大小合并(Size-tiered Compaction)**:这是LSM树最初采用的策略,其中较旧的、较小的数据块被合并成较大的数据块。 - **Leveled Compaction**:在这种策略中,数据被分布在多个层次上,每个层次都有固定的大小,且层数越多,数据越旧。 - **其他变种**:为了应对不同工作负载和特定需求,研究者和实践者们还发展出了许多其他类型的Compaction策略。 5. **应用**: - **数据库**:像Cassandra、HBase等NoSQL数据库系统就采用了LSM树作为其核心的数据存储结构。 - **搜索引擎**:部分搜索引擎在倒排索引的构建中使用LSM树,以提高索引构建的效率。 - **大数据处理**:Hadoop生态中的部分存储系统也使用了LSM树的概念,如LevelDB等。 6. **LSM-Tree.pdf和LSM.txt内容推测**: - LSM-Tree.pdf可能是一份关于LSM树的详细技术文档或白皮书,包含了LSM树的设计原理、性能分析、Compaction机制、适用场景以及实际应用案例等内容。 - LSM.txt可能是一份简短的说明性文档,概括了LSM树的关键点、操作流程以及可能的应用示例。 通过对LSM树结构、工作原理、优势、缺点、Compaction策略以及应用场景的理解,可以更好地掌握它在现代大数据处理和存储系统中的重要性与应用。

相关推荐

filetype

#include <zephyr/kernel.h> #include <zephyr/device.h> #include <zephyr/devicetree.h> #include <zephyr/drivers/i2c.h> #include <zephyr/logging/log.h> #include <stdio.h> #include <math.h> #include "GVL.h" #include "data_preprocess.h" #define LOG_MODULE_NAME LSM6DSOWTR_thread LOG_MODULE_REGISTER(LOG_MODULE_NAME); // LSM6DSOWTR 寄存器定义 #define LSM6DSOWTR_REG_WHO_AM_I 0x0F #define LSM6DSOWTR_REG_CTRL1_XL 0x10 #define LSM6DSOWTR_REG_CTRL2_G 0x11 #define LSM6DSOWTR_REG_CTRL3_C 0x12 #define LSM6DSOWTR_REG_OUTX_L_G 0x22 #define LSM6DSOWTR_REG_OUTX_H_G 0x23 #define LSM6DSOWTR_REG_OUTY_L_G 0x24 #define LSM6DSOWTR_REG_OUTY_H_G 0x25 #define LSM6DSOWTR_REG_OUTZ_L_G 0x26 #define LSM6DSOWTR_REG_OUTZ_H_G 0x27 #define LSM6DSOWTR_REG_OUTX_L_XL 0x28 #define LSM6DSOWTR_REG_OUTX_H_XL 0x29 #define LSM6DSOWTR_REG_OUTY_L_XL 0x2A #define LSM6DSOWTR_REG_OUTY_H_XL 0x2B #define LSM6DSOWTR_REG_OUTZ_L_XL 0x2C #define LSM6DSOWTR_REG_OUTZ_H_XL 0x2D // 配置参数 #define LSM6DSOWTR_WHO_AM_I_VAL 0x6C #define LSM6DSOWTR_ODR_XL_104HZ 0x40 // 加速度计 104Hz #define LSM6DSOWTR_FS_XL_2G 0x00 // ±2g 量程 #define LSM6DSOWTR_ODR_G_104HZ 0x40 // 陀螺仪 104Hz #define LSM6DSOWTR_FS_G_245DPS 0x00 // ±245dps 量程 #define LSM6DSOWTR_REG_STATUS_REG 0x1E #define ACCEL_SENSITIVITY_2G 0.000061f #define GYRO_SENSITIVITY_245DPS 0.00875f // 8.75 mdps/LSB // 压力传感器LPS28DFW 寄存器定义 // LPS28DFW 寄存器定义 #define LPS28DFW_WHO_AM_I 0x0F #define LPS28DFW_CTRL_REG1 0x10 #define LPS28DFW_CTRL_REG2 0x11 #define LPS28DFW_CTRL_REG3 0x12 #define LPS28DFW_PRESS_OUT_XL 0x28 #define LPS28DFW_PRESS_OUT_L 0x29 #define LPS28DFW_PRESS_OUT_H 0x2A #define LPS28DFW_TEMP_OUT_L 0x2B #define LPS28DFW_TEMP_OUT_H 0x2C #define LPS28DFW_INTERRUPT_CFG 0x0B #define LPS28DFW_THS_P_L 0x0C #define LPS28DFW_THS_P_H 0x0D // 配置值 #define LPS28DFW_WHO_AM_I_VAL 0xB4 #define LPS28DFW_ODR_50HZ 0x50 // 50Hz输出数据率 #define LPS28DFW_LPF_ENABLE 0x08 // 启用低通滤波器 #define LPS28DFW_BDU_ENABLE 0x08 // 启用块数据更新 #define LPS28DFW_WATER_MODE 0x40 // 水压测量模式 #define SAMPLE_INTERVAL_MS 100 //MS5837压力传感器 #define MS5837_CMD_RESET 0x1E #define MS5837_CMD_CONVERT_D1_OSR1024 0x44 #define MS5837_CMD_CONVERT_D2_OSR1024 0x54 #define MS5837_CMD_ADC_READ 0x00 #define MS5837_PROM_READ_BASE 0xA0 struct ms5837_calib { uint16_t factory; // PROM word 0 (厂商数据) uint16_t c1; // 压力灵敏度 uint16_t c2; // 压力偏移 uint16_t c3; // 温度系数-压力灵敏度 uint16_t c4; // 温度系数-压力偏移 uint16_t c5; // 参考温度 uint16_t c6; // 温度系数 uint16_t crc; // CRC校验 }; // 等待数据就绪 static bool wait_for_data_ready(const struct i2c_dt_spec *dev_spec) { uint8_t status; int retries = 10; while (retries-- > 0) { if (i2c_reg_read_byte_dt(dev_spec, LSM6DSOWTR_REG_STATUS_REG, &status) == 0) { // 检查加速度计和陀螺仪数据就绪位 (bit0 & bit1) if ((status & 0x03) == 0x03) return true; } k_msleep(1); } return false; } static int init_LPS28DFW_water(const struct i2c_dt_spec *dev_spec) { const int max_retries = 5; uint8_t whoami; int ret; int retries = 0; LOG_INF("Starting LPS28DFW initialization..."); LOG_DBG("Verifying I2C connection to device at 0x%02X", dev_spec->addr); do { ret = i2c_reg_read_byte_dt(dev_spec, LPS28DFW_WHO_AM_I, &whoami); if (ret == 0 && whoami == LPS28DFW_WHO_AM_I_VAL) break; if (ret != 0) { LOG_WRN("I2C read error: %d (attempt %d)", ret, retries+1); } else { LOG_WRN("Unexpected WHO_AM_I: 0x%02X (expected 0x%02X) attempt %d", whoami, LPS28DFW_WHO_AM_I_VAL, retries+1); } i2c_recover_bus(dev_spec->bus); k_msleep(10); } while (++retries < max_retries); if (retries >= max_retries) { LOG_ERR("Device detection failed after %d attempts", max_retries); return -ENODEV; } uint8_t ctrl_reset=0x04; ret = i2c_reg_write_byte_dt(dev_spec, LPS28DFW_CTRL_REG2, ctrl_reset); k_msleep(10); if (ret) { LOG_ERR("ctrl_reg2 reset failed: %d", ret); return ret; } uint8_t ctrl_reset_value; ret = i2c_reg_read_byte_dt(dev_spec, LPS28DFW_CTRL_REG2, &ctrl_reset_value); if (ret == 0) { // 检查关键位 const uint8_t critical_bits_mask_reset = 0x04; if (ctrl_reset_value == critical_bits_mask_reset) { LOG_DBG("CTRL_REG2 reset verified: 0x%02X", ctrl_reset_value); } else{ LOG_WRN("CTRL_REG2 reset failed: read 0x%02X", ctrl_reset_value); } } uint8_t ctrl_reg1=0x50; ret = i2c_reg_write_byte_dt(dev_spec, LPS28DFW_CTRL_REG1, ctrl_reg1); if (ret) { LOG_ERR("ctrl_reg1 set failed: %d", ret); return ret; } uint8_t ctrl_reg2 =0x18; ret = i2c_reg_write_byte_dt(dev_spec, LPS28DFW_CTRL_REG2, ctrl_reg2); if (ret) { LOG_ERR("ctrl_reg1 set failed: %d", ret); return ret; } uint8_t reg_value1; uint8_t reg_value2; uint8_t reg_value3; ret = i2c_reg_read_byte_dt(dev_spec, LPS28DFW_CTRL_REG1, ®_value1); if (ret == 0) { // 检查关键位 const uint8_t critical_bits_mask1 = 0x50; if (reg_value1 == critical_bits_mask1) { LOG_DBG("CTRL_REG1 verified: 0x%02X", reg_value1); } else{ LOG_WRN("CTRL_REG1 failed: read 0x%02X", reg_value1); } } ret = i2c_reg_read_byte_dt(dev_spec, LPS28DFW_CTRL_REG2, ®_value2); if (ret == 0) { // 检查关键位 const uint8_t critical_bits_mask2 = 0x18; if (reg_value2 == critical_bits_mask2) { LOG_DBG("CTRL_REG2 verified: 0x%02X", reg_value2); } else{ LOG_WRN("CTRL_REG2 failed: read 0x%02X", reg_value2); } } uint8_t ctrl_reg3 =0x01; ret = i2c_reg_write_byte_dt(dev_spec, LPS28DFW_CTRL_REG3, ctrl_reg3); if (ret) { LOG_ERR("ctrl_reg3 set failed: %d", ret); return ret; } ret = i2c_reg_read_byte_dt(dev_spec, LPS28DFW_CTRL_REG3, ®_value3); if (ret == 0) { // 检查关键位 const uint8_t critical_bits_mask3 = 0x01; if (reg_value3 == critical_bits_mask3) { LOG_DBG("CTRL_REG3 verified: 0x%02X", reg_value3); } else{ LOG_WRN("CTRL_REG3 failed: read 0x%02X", reg_value3); } } LOG_INF("LPS28DFW initialized successfully"); return 0; } // 读取原始压力数据 (24位有符号整数) static int32_t read_raw_pressure(const struct i2c_dt_spec *dev_spec) { uint8_t press_data[3]; int ret; ret = i2c_burst_read_dt(dev_spec, LPS28DFW_PRESS_OUT_XL, press_data, sizeof(press_data)); if (ret != 0) { LOG_ERR("Pressure read failed: %d", ret); return 0; } int32_t raw_pressure = ((int32_t)press_data[2] << 16) | ((int32_t)press_data[1] << 8) | press_data[0]; if (raw_pressure & 0x00800000) { raw_pressure |= 0xFF000000; } return raw_pressure; } // 读取原始温度数据 (16位有符号整数) static int16_t read_raw_temperature(const struct i2c_dt_spec *dev_spec) { uint8_t temp_data[2]; int ret; ret = i2c_burst_read_dt(dev_spec, LPS28DFW_TEMP_OUT_L, temp_data, sizeof(temp_data)); if (ret != 0) { LOG_ERR("Temperature read failed: %d", ret); return 0; } // 组合16位有符号整数 (小端格式) return (int16_t)((temp_data[1] << 8) | temp_data[0]); } // 读取带温度补偿的水压 static double read_compensated_water_pressure(const struct i2c_dt_spec *dev_spec) { // 读取原始压力值 int32_t raw_pressure = read_raw_pressure(dev_spec); // 读取原始温度值 int16_t raw_temp = read_raw_temperature(dev_spec); // 转换为摄氏度 (100 LSB/°C) double temperature = (double)raw_temp / 100.0f; // 转换为hPa double pressure_hPa = (double)raw_pressure / 4096.0f; // 温度补偿因子 (根据数据手册的典型特性) // 实际应用中应根据传感器校准数据调整 double comp_factor = 1.0f + (0.0001f * temperature); // 应用温度补偿 pressure_hPa *= comp_factor; // 转换为米水柱 return pressure_hPa*100.0; } // 读取水深 (单位: 米) static double read_water_depth(const struct i2c_dt_spec *dev_spec) { // 读取补偿后的水压 double pressure_mH2O = read_compensated_water_pressure(dev_spec); // 水深 = 水压值 (忽略大气压影响) return pressure_mH2O; } static double read_compensated_water_depth(const struct i2c_dt_spec *dev_spec, double atmospheric_pressure) { // 读取补偿后的水压(单位:米水柱) //double absolute_pressure_mH2O = read_compensated_water_pressure(dev_spec); double raw_press = read_raw_pressure(dev_spec) / 0.4096f; double raw_temp = read_raw_temperature(dev_spec) / 100.0f; // double absolute_pressure_Pa = read_compensated_water_pressure(dev_spec); // 转换为Pa (1 mH2O = 9806.65 Pa) //double temp_depth = (absolute_pressure_Pa - atmospheric_pressure) / (1000.0 * 9.80665); //double temp_depth = (sensor_data_PWM.pressure/10.0f - atmospheric_pressure/10.0f) / (1000.0 * 9.80665); double temp_depth = (raw_press/10.0f - atmospheric_pressure/10.0f) / (1000.0 * 9.80665); LOG_INF("raw temp:%.2f raw pressure: %.2f atmospheric_pressure: %.2f kPa (%.4f mH2O)", raw_temp,raw_press/10.f,atmospheric_pressure/10.0f, temp_depth); // 水深 = (绝对压力 - 大气压) / (水密度 * 重力加速度) //return (absolute_pressure_Pa - atmospheric_pressure) / (1000.0f * 9.80665f); return (raw_press/10.0f - atmospheric_pressure/10.0f) / (1000.0f * 9.80665f); } // 初始化 LSM6DS0 传感器 static int init_lsm6dsowtr(const struct i2c_dt_spec *dev_spec) { uint8_t whoami; int ret; LOG_INF("Initializing LSM6DSOWTR sensor..."); // 读取 WHO_AM_I 寄存器 ret = i2c_reg_read_byte_dt(dev_spec, LSM6DSOWTR_REG_WHO_AM_I, &whoami); if (ret != 0) { LOG_ERR("Failed to read WHO_AM_I: %d", ret); return ret; } if (whoami != LSM6DSOWTR_WHO_AM_I_VAL) { LOG_ERR("Unexpected WHO_AM_I: 0x%02X (expected 0x%02X)", whoami, LSM6DSOWTR_WHO_AM_I_VAL); return -ENODEV; } LOG_INF("LSM6DSOWTR detected (WHO_AM_I=0x%02X)", whoami); // 配置加速度计 uint8_t ctrl1_xl = LSM6DSOWTR_ODR_XL_104HZ | LSM6DSOWTR_FS_XL_2G; ret = i2c_reg_write_byte_dt(dev_spec, LSM6DSOWTR_REG_CTRL1_XL, ctrl1_xl); if (ret != 0) { LOG_ERR("Failed to write CTRL1_XL: %d", ret); return ret; } // 配置陀螺仪 uint8_t ctrl2_g = LSM6DSOWTR_ODR_G_104HZ | LSM6DSOWTR_FS_G_245DPS; ret = i2c_reg_write_byte_dt(dev_spec, LSM6DSOWTR_REG_CTRL2_G, ctrl2_g); if (ret != 0) { LOG_ERR("Failed to write CTRL2_G: %d", ret); return ret; } uint8_t reg_val; ret = i2c_reg_read_byte_dt(dev_spec, LSM6DSOWTR_REG_CTRL1_XL, ®_val); if (ret != 0 || reg_val != ctrl1_xl) { LOG_ERR("CTRL1_XL verification failed: wrote 0x%02X, read 0x%02X", ctrl1_xl, reg_val); return -EIO; } ret = i2c_reg_read_byte_dt(dev_spec, LSM6DSOWTR_REG_CTRL2_G, ®_val); if (ret != 0 || reg_val != ctrl2_g) { LOG_ERR("CTRL2_G verification failed: wrote 0x%02X, read 0x%02X", ctrl2_g, reg_val); return -EIO; } // 配置控制寄存器3 ret = i2c_reg_write_byte_dt(dev_spec, LSM6DSOWTR_REG_CTRL3_C, 0x04); // BDU=1 (块数据更新) if (ret != 0) { LOG_ERR("Failed to write CTRL3_C: %d", ret); return ret; } LOG_INF("LSM6DSOWTR initialized successfully"); return 0; } // 读取加速度计数据 static void read_accelerometer(const struct i2c_dt_spec *dev_spec, double *x, double *y, double *z) { if (!wait_for_data_ready(dev_spec)) { LOG_WRN("Accel data not ready"); *x = *y = *z = NAN; return; } uint8_t data[6]; int ret = i2c_burst_read_dt(dev_spec, LSM6DSOWTR_REG_OUTX_L_XL, data, sizeof(data)); if (ret != 0) { LOG_ERR("Accelerometer read failed: %d", ret); *x = *y = *z = NAN; return; } // 组合16位数据(小端格式) int16_t raw_x = (int16_t)((data[1] << 8) | data[0]); int16_t raw_y = (int16_t)((data[3] << 8) | data[2]); int16_t raw_z = (int16_t)((data[5] << 8) | data[4]); // 转换为 g (重力加速度) - ±2g 量程,灵敏度 0.061 mg/LSB *x = raw_x * ACCEL_SENSITIVITY_2G; *y = raw_y * ACCEL_SENSITIVITY_2G; *z = raw_z * ACCEL_SENSITIVITY_2G; } // 读取陀螺仪数据 static void read_gyroscope(const struct i2c_dt_spec *dev_spec, double *x, double *y, double *z) { if (!wait_for_data_ready(dev_spec)) { LOG_WRN("Gyro data not ready"); *x = *y = *z = NAN; return; } uint8_t data[6]; int ret = i2c_burst_read_dt(dev_spec, LSM6DSOWTR_REG_OUTX_L_G, data, sizeof(data)); if (ret != 0) { LOG_ERR("Gyroscope read failed: %d", ret); *x = *y = *z = NAN; return; } // 组合16位数据(小端格式) int16_t raw_x = (int16_t)((data[1] << 8) | data[0]); int16_t raw_y = (int16_t)((data[3] << 8) | data[2]); int16_t raw_z = (int16_t)((data[5] << 8) | data[4]); // 转换为 dps (度/秒) - ±245dps 量程,灵敏度 8.75 mdps/LSB *x = raw_x * GYRO_SENSITIVITY_245DPS; *y = raw_y * GYRO_SENSITIVITY_245DPS; *z = raw_z * GYRO_SENSITIVITY_245DPS; } // 将浮点值转换为定点表示(用于存储) static int32_t sensor_value_to_int(double value, int scale_factor) { return (int32_t)(value * scale_factor); } // 主传感器线程 void lsm6dsowtr_thread(void) { LOG_INF("LSM6DSOWTR sensor thread started"); // 获取六轴传感器设备规范 static const struct i2c_dt_spec lsm6dsowtr_dev = I2C_DT_SPEC_GET(DT_NODELABEL(lsm6dsowtr)); if (!device_is_ready(lsm6dsowtr_dev.bus)) { LOG_ERR("I2C bus not ready: %s", lsm6dsowtr_dev.bus->name); return; } // 获取压力传感器设备规范 static const struct i2c_dt_spec pressure_dev = I2C_DT_SPEC_GET(DT_NODELABEL(mysensor)); if (!device_is_ready(pressure_dev.bus)) { LOG_ERR("I2C bus %s is not ready!", pressure_dev.bus->name); return; } // 初始化传感器 int init_result; // 初始化压力传感器 init_result = init_LPS28DFW_water(&pressure_dev); if (init_result != 0) { LOG_ERR("Pressure sensor initialization failed: %d", init_result); } else { LOG_INF("Pressure sensor initialized successfully"); } // struct ms5837_calib calib_data; // int ms5837_init_ret = init_MS5837(&pressure_dev, &calib_data); // if (ms5837_init_ret != 0) { // LOG_ERR("MS5837 initialization failed: %d", ms5837_init_ret); // // 非致命错误,继续运行其他传感器 // } else { // LOG_INF("MS5837 initialized successfully"); // } // 初始化六轴传感器 init_result = init_lsm6dsowtr(&lsm6dsowtr_dev); if (init_result != 0) { LOG_ERR("LSM6DSOWTR initialization failed: %d", init_result); } else { LOG_INF("LSM6DSOWTR initialized successfully"); } LOG_INF("Starting sensor data collection..."); // 主循环变量 int64_t last_sample_time = k_uptime_get(); int64_t last_batch_time = last_sample_time; static int datacount = 0; static double press_a = 0; static double depth_comp = 0; static int depth_count = 0; while (1) { double press = read_raw_pressure(&pressure_dev); double temp = read_raw_temperature(&pressure_dev); double compensated_depth; if(datacount < 20){ press_a = press_a + press/4096.0f; datacount++; // LOG_INF("press_a: %.4f Pa,datacount:%d", press_a,datacount); } else{ press_a = press_a/20.0f; // LOG_INF("press_a: %.4f Pa,datacount:%d", press_a,datacount); press_a = press_a*10000; // sensor_data_PWM.pressure = press_a*10000; compensated_depth = read_compensated_water_depth(&pressure_dev, press_a); if(depth_count < 20){ depth_comp = depth_comp + compensated_depth; depth_count++; // LOG_INF("press_a: %.4f Pa,datacount:%d", press_a,datacount); } else{ depth_comp = depth_comp/20.0f; LOG_INF("depth_comp: %.4f Pa,depth_count:%d", depth_comp,depth_count); depth_count = 0; depth_comp = 0; } datacount = 0; press_a = 0; } // if(depth_count < 20){ // depth_comp = depth_comp + compensated_depth/4096.0f; // datacount++; // // LOG_INF("press_a: %.4f Pa,datacount:%d", press_a,datacount); // } else{ // press_a = press_a/20.0f; // // LOG_INF("press_a: %.4f Pa,datacount:%d", press_a,datacount); // press_a = press_a*10000; // compensated_depth = read_compensated_water_depth(&pressure_dev, press_a); // datacount = 0; // press_a = 0; // } double accel_x, accel_y, accel_z; double gyro_x, gyro_y, gyro_z; read_accelerometer(&lsm6dsowtr_dev, &accel_x, &accel_y, &accel_z); read_gyroscope(&lsm6dsowtr_dev, &gyro_x, &gyro_y, &gyro_z); //float magnitude = calculate_acceleration_magnitude(accel_x, accel_y, accel_z); // LOG_INF("Accel: X=%.3f g, Y=%.3f g, Z=%.3f g", // accel_x, accel_y, accel_z); // LOG_INF("Gyro: X=%.2f dps, Y=%.2f dps, Z=%.2f dps", // gyro_x, gyro_y, gyro_z); // 获取当前时间戳 int64_t current_time = k_uptime_get(); // 准备数据点 // sensor_data_point_t data_point = { // .timestamp = current_time, // .pressure = sensor_value_to_int(press, 1000), // kPa * 1000 = milli-kPa // .temp = sensor_value_to_int(temp, 100), // °C * 100 = centi-°C // .acc_x = sensor_value_to_int(accel_x, 1000), // g * 1000 = milli-g // .acc_y = sensor_value_to_int(accel_y, 1000), // .acc_z = sensor_value_to_int(accel_z, 1000), // .gyro_x = sensor_value_to_int(gyro_x, 1000), // dps * 1000 = milli-dps // .gyro_y = sensor_value_to_int(gyro_y, 1000), // .gyro_z = sensor_value_to_int(gyro_z, 1000) // }; sensor_data_point_t data_point = { .timestamp = current_time, .pressure = sensor_value_to_int(press/4096.0f, 10000), // kPa * 1000 = milli-kPa .temp = sensor_value_to_int(temp, 100), // °C * 100 = centi-°C .acc_x = sensor_value_to_int(accel_x, 1000), // g * 1000 = milli-g .acc_y = sensor_value_to_int(accel_y, 1000), .acc_z = sensor_value_to_int(accel_z, 1000), .gyro_x = sensor_value_to_int(gyro_x, 1000), // dps * 1000 = milli-dps .gyro_y = sensor_value_to_int(gyro_y, 1000), .gyro_z = sensor_value_to_int(gyro_z, 1000) }; // LOG_INF("data filter"); data_point = filter_sensor_data(&data_point); atmospheric_pressure = data_point.pressure; //double compensated_depth = read_compensated_water_depth(&pressure_dev, atmospheric_pressure); // double compensated_depth = read_compensated_water_depth(&pressure_dev, press/4096.0f); // LOG_INF("Compensated Depth: %.4f m",compensated_depth); // // 安全地添加到批量缓冲区 // k_mutex_lock(&data_mutex, K_FOREVER); // // 检查当前批次缓冲区是否有效 // if (sensor_batch.count == 0) { // // 新批次,记录起始时间戳 // sensor_batch.start_timestamp = current_time; // } // // 添加数据点到批次 // if (sensor_batch.count < BATCH_SIZE) { // sensor_batch.data[sensor_batch.count] = data_point; // sensor_batch.count++; // // 检查批次是否已满 // if (sensor_batch.count >= BATCH_SIZE) { // // 批次已满,标记为就绪 // sensor_batch.ready = true; // LOG_DBG("Batch filled (%d points)", BATCH_SIZE); // } // } else { // LOG_WRN("Batch buffer full, discarding data point"); // } // // 检查是否超时(即使批次未满) // if ((current_time - sensor_batch.start_timestamp) >= (MAX_BATCH_TIMEOUT * 1000)) { // if (sensor_batch.count > 0) { // sensor_batch.ready = true; // LOG_DBG("Batch timeout with %d points", sensor_batch.count); // } // } // // 如果批次就绪,通知BLE线程 // if (sensor_batch.ready) { // k_sem_give(&batch_ready_sem); // LOG_DBG("Notified BLE thread of data ready"); // } // k_mutex_unlock(&data_mutex); // 计算下一个采样点的时间 int64_t elapsed = k_uptime_get() - last_sample_time; int32_t sleep_time = SAMPLE_INTERVAL_MS - elapsed; if (sleep_time > 0) { k_msleep(sleep_time); } else { LOG_WRN("Sampling behind schedule by %d ms", -sleep_time); } last_sample_time = k_uptime_get(); } } // 定义传感器线程 K_THREAD_DEFINE(lsm6dsowtr_thread_id, 4096, lsm6dsowtr_thread, NULL, NULL, NULL, 7, 0, 0);对原始压力值进行中值滤波

filetype
JFM7VX690T型SRAM型现场可编程门阵列技术手册主要介绍的是上海复旦微电子集团股份有限公司(简称复旦微电子)生产的高性能FPGA产品JFM7VX690T。该产品属于JFM7系列,具有现场可编程特性,集成了功能强大且可以灵活配置组合的可编程资源,适用于实现多种功能,如输入输出接口、通用数字逻辑、存储器、数字信号处理和时钟管理等。JFM7VX690T型FPGA适用于复杂、高速的数字逻辑电路,广泛应用于通讯、信息处理、工业控制、数据中心、仪表测量、医疗仪器、人工智能、自动驾驶等领域。 产品特点包括: 1. 可配置逻辑资源(CLB),使用LUT6结构。 2. 包含CLB模块,可用于实现常规数字逻辑和分布式RAM。 3. 含有I/O、BlockRAM、DSP、MMCM、GTH等可编程模块。 4. 提供不同的封装规格和工作温度范围的产品,便于满足不同的使用环境。 JFM7VX690T产品系列中,有多种型号可供选择。例如: - JFM7VX690T80采用FCBGA1927封装,尺寸为45x45mm,使用锡银焊球,工作温度范围为-40°C到+100°C。 - JFM7VX690T80-AS同样采用FCBGA1927封装,但工作温度范围更广,为-55°C到+125°C,同样使用锡银焊球。 - JFM7VX690T80-N采用FCBGA1927封装和铅锡焊球,工作温度范围与JFM7VX690T80-AS相同。 - JFM7VX690T36的封装规格为FCBGA1761,尺寸为42.5x42.5mm,使用锡银焊球,工作温度范围为-40°C到+100°C。 - JFM7VX690T36-AS使用锡银焊球,工作温度范围为-55°C到+125°C。 - JFM7VX690T36-N使用铅锡焊球,工作温度范围与JFM7VX690T36-AS相同。 技术手册中还包含了一系列详细的技术参数,包括极限参数、推荐工作条件、电特性参数、ESD等级、MSL等级、重量等。在产品参数章节中,还特别强调了封装类型,包括外形图和尺寸、引出端定义等。引出端定义是指对FPGA芯片上的各个引脚的功能和接线规则进行说明,这对于FPGA的正确应用和电路设计至关重要。 应用指南章节涉及了FPGA在不同应用场景下的推荐使用方法。其中差异说明部分可能涉及产品之间的性能差异;关键性能对比可能包括功耗与速度对比、上电浪涌电流测试情况说明、GTH Channel Loss性能差异说明、GTH电源性能差异说明等。此外,手册可能还提供了其他推荐应用方案,例如不使用的BANK接法推荐、CCLK信号PCB布线推荐、JTAG级联PCB布线推荐、系统工作的复位方案推荐等,这些内容对于提高系统性能和稳定性有着重要作用。 焊接及注意事项章节则针对产品的焊接过程提供了指导,强调焊接过程中的注意事项,以确保产品在组装过程中的稳定性和可靠性。手册还明确指出,未经复旦微电子的许可,不得翻印或者复制全部或部分本资料的内容,且不承担采购方选择与使用本文描述的产品和服务的责任。 上海复旦微电子集团股份有限公司拥有相关的商标和知识产权。该公司在中国发布的技术手册,版权为上海复旦微电子集团股份有限公司所有,未经许可不得进行复制或传播。 技术手册提供了上海复旦微电子集团股份有限公司销售及服务网点的信息,方便用户在需要时能够联系到相应的服务机构,获取最新信息和必要的支持。同时,用户可以访问复旦微电子的官方网站(***以获取更多产品信息和公司动态。
filetype
标题“100余款高清原厂车标开机logo”所指的是一份资源集合,其中包含了超过100个汽车制造商的高清品牌标志,这些标志是专为开机画面或车载娱乐系统的启动界面设计的。在车载信息娱乐系统中,车标的开机logo通常会在车辆启动时展示,增添品牌形象,提升用户体验。 描述中的信息告诉我们这份资源提供了三种不同的分辨率:1024x600、800x480和222x124。这些尺寸对应了不同车载屏幕的常见分辨率,确保了在各种车型上都能有良好的显示效果。"任你选择"意味着用户可以根据自己的车辆屏幕尺寸选择合适的logo。"还等什么快上车"是一句促销用语,鼓励用户立即下载并使用这些高清车标。 标签“车机logo”明确了这个压缩包的内容是与汽车相关的开机图形标识,主要应用于车载信息系统。 至于文件名称列表中提到的“drawable-hdpi-v4”,这是Android开发中的一个目录名,用于存放不同密度(hdpi:高密度)的图像资源。在Android系统中,为了适应不同屏幕密度的设备,开发者会将图片资源按照ldpi(低密度)、mdpi(中密度)、hdpi、xhdpi、xxhdpi等分类存储。"v4"可能表示这些资源兼容Android 4.0(API级别14)及以上版本的系统,以确保广泛的设备兼容性。 这份压缩包是一个丰富的汽车品牌开机logo库,适合用于各种车载信息娱乐系统,提供了适配不同屏幕尺寸和分辨率的选项,并且遵循了Android应用开发的标准,保证在多数现代Android设备上可以正常显示。对于汽车电子设备开发者、UI设计师或者车友来说,这都是一份极具价值的资源
小瓶盖的猪猪侠
  • 粉丝: 276
上传资源 快速赚钱