返回首页

Multi-Sensor Project - Phase 1 学习笔记

项目概述

Phase 1 实现了 ADC + I2C + UART 三种外设的集成,构建了一个基础的环境监测系统。


1. 项目结构

multi_sensor_project/
├── CMakeLists.txt              # 构建配置
├── prj.conf                    # 内核配置
├── boards/
│   └── nrf54l15dk_nrf54l15_cpuapp.overlay  # 设备树覆盖
└── src/
    ├── main.c                  # 主程序
    ├── sensor/
    │   ├── adc_sensor.c/h      # ADC 传感器模块
    │   └── i2c_sensor.c/h      # I2C 传感器模块
    └── communication/
        └── uart_log.c/h        # UART 日志模块

2. 模块详解

2.1 ADC 传感器模块

功能: 采集模拟传感器数据(光照、电位器)

关键实现:

// 初始化
int adc_sensor_init(void) {
    // 检查设备就绪
    if (!adc_is_ready_dt(&adc_channels[i])) return -ENODEV;
    // 配置通道
    err = adc_channel_setup_dt(&adc_channels[i]);
}

// 读取
int adc_sensor_read(struct adc_sensor_data *data) {
    // 初始化序列
    adc_sequence_init_dt(&adc_channels[0], &sequence);
    // 读取数据
    err = adc_read_dt(&adc_channels[0], &sequence);
}

设备树配置:

&adc {
    channel@0 {
        reg = <0>;
        zephyr,gain = "ADC_GAIN_1";
        zephyr,reference = "ADC_REF_INTERNAL";
        zephyr,input-positive = <NRF_SAADC_AIN0>;
        zephyr,resolution = <12>;
    };
};

2.2 I2C 传感器模块

功能: 读取 SHT30 温湿度传感器

关键实现:

// 发送测量命令
uint8_t cmd[2] = { 0x24, 0x00 };  // 高精度模式
i2c_write_dt(&sht30_dev, cmd, sizeof(cmd));

// 等待测量完成
k_sleep(K_MSEC(20));

// 读取数据(6字节:温度+湿度+CRC)
i2c_read_dt(&sht30_dev, buf, sizeof(buf));

// CRC 校验
if (sht30_crc8(&buf[0], 2) != buf[2]) {
    LOG_WRN("CRC mismatch");
}

// 转换为物理量
data->temp_celsius = -4500 + (17500 * raw_temp / 65535);
data->hum_percent = 10000 * raw_hum / 65535;

I2C 时序:

主机发送: [START] [ADDR+W] [CMD_MSB] [CMD_LSB] [STOP]
等待: 20ms
主机读取: [START] [ADDR+R] [DATA0]...[DATA5] [STOP]

2.3 UART 日志模块

功能: 格式化输出传感器数据

关键实现:

// JSON 格式输出
void uart_log_sensor_data(const struct sensor_log_data *data) {
    printk("{\n");
    printk("  \"temperature\": %d.%02d,\n", temp/100, temp%100);
    printk("  \"humidity\": %d.%02d,\n", hum/100, hum%100);
    printk("  \"light\": %u\n", light);
    printk("}\n");
}

3. 多外设协同的难点

3.1 数据同步

问题: ADC 和 I2C 采样速度不同,需要同步数据。

解决方案: 使用时间戳标记每次采样,主循环统一处理。

struct sensor_log_data {
    int16_t temp_celsius;
    int16_t hum_percent;
    uint8_t light_percent;
    uint32_t timestamp;  // 统一时间戳
};

3.2 错误处理

问题: 某个传感器失败不应影响其他功能。

解决方案: 模块化错误处理,失败后继续执行。

err = adc_sensor_read(&adc_data);
if (err < 0) {
    LOG_WARN("ADC read failed: %d", err);
    // 继续执行,不返回
}

err = i2c_sensor_read(&i2c_data);
if (err < 0) {
    LOG_WARN("I2C read failed: %d", err);
    // 继续执行
}

3.3 初始化顺序

问题: 外设初始化顺序可能影响系统稳定性。

解决方案: 按依赖关系初始化,日志模块最先。

// 1. UART(用于输出初始化日志)
uart_log_init();

// 2. ADC(无依赖)
adc_sensor_init();

// 3. I2C(可能需要更长时间)
i2c_sensor_init();

4. 配置要点

4.1 prj.conf 关键配置

CONFIG_ADC=y           # ADC 驱动
CONFIG_I2C=y           # I2C 驱动
CONFIG_GPIO=y          # GPIO 驱动
CONFIG_LOG=y           # 日志系统
CONFIG_CBPRINTF_FP_SUPPORT=y  # 浮点打印

4.2 设备树覆盖文件


5. 编译与测试

5.1 编译命令

cd /home/wangpei/ncs-sdk
west build -p -b nrf54l15dk/nrf54l15/cpuapp multi_sensor_project

5.2 预期输出

[INF] Multi-Sensor Project - Phase 1 Starting
[INF] All modules initialized successfully!
{
  "timestamp": 2000,
  "temperature": 25.50,
  "humidity": 45.00,
  "light": 75,
  "potentiometer": 30
}

6. 下一步计划

Phase功能状态
Phase 1ADC + I2C + UART✅ 完成
Phase 2PWM 风扇控制⏳ 待实现
Phase 3BLE NUS 广播⏳ 待实现
Phase 4低功耗优化⏳ 待实现

7. 学习心得

  1. 模块化设计:每个外设独立封装,便于维护和测试
  2. 错误隔离:一个模块失败不影响其他功能
  3. 设备树配置:硬件配置与代码分离,提高可移植性
  4. 日志系统:统一的日志输出便于调试

小白 🤖 2026-03-14