Skip to content

第9周小组作业:使用示波器测量 Grove 传感器

[查看小组作业完整内容]

任务概述

根据第9周课程大纲的要求,我们小组需要选择输入设备,使用示波器测量其电信号特性,分析并理解其工作原理。在本次作业中,我们将:

  1. XIAO ESP32C3 与 Grove DHT11 温湿度传感器测试教程(由冯磊编写)
  2. XIAO ESP32S3 与 ADXL345L 三轴加速度计测试教程(由刘鸿泰编写)

XIAO ESP32C3 与 Grove DHT11 温湿度传感器测试教程

我测量使用了 OWON EDS102CV 示波器,这是一款双通道数字存储示波器,采样率高达1GS/s,带宽100MHz,适合测量和分析各种电子信号。

OWON EDS102CV 示波器

主要技术规格

  • 带宽:100MHz
  • 通道数:2
  • 最大采样率:1GS/s
  • 时基范围:2ns/div - 100s/div
  • 垂直灵敏度:2mV/div - 10V/div
  • 显示屏:8英寸彩色LCD

示波器的功能说明,可以参考 Katherine 的文档:Week12. Input Devices

Grove DHT11温湿度传感器简介

Grove DHT11 是一款 Seeed Studio 制造的基本的数字温湿度传感器,专为入门级电子项目设计。以下是它的主要特点:

基本规格

  • 测量范围:温度0-50°C,湿度20-90%RH
  • 精度:温度±2°C,湿度±5%RH
  • 分辨率:温度1°C,湿度1%RH
  • 供电电压:3.3V-5.5V
  • 数据输出:单总线数字信号

特点

  • Grove接口:采用标准Grove接口设计,无需焊接,即插即用
  • 低功耗:平均工作电流0.5mA,待机电流为100μA左右
  • 体积小:传感器模块尺寸小,便于集成到各类项目中
  • 信号传输距离:标准条件下可达20米
  • 长期稳定性:校准系数存储在OTP内存中,确保长期稳定工作

工作原理

DHT11内部包含一个电阻式湿度测量元件和一个NTC温度测量元件。传感器采集环境数据后,通过单总线协议将数字信号输出到微控制器。一次完整的数据包含40位数据,包括湿度整数部分、湿度小数部分、温度整数部分、温度小数部分以及校验和。

通信协议

DHT11使用简化的单总线通信协议:

  1. 主机发送开始信号:拉低数据线至少18ms,然后拉高20-40μs
  2. 传感器响应:拉低数据线80μs,然后拉高80μs
  3. 数据传输:每个数据位由50μs低电平信号开始,接着的高电平长度决定数据位是"0"还是"1"
    • "0":高电平持续26-28μs
    • "1":高电平持续70μs

应用场景

  • 家庭自动化项目:室内环境监测
  • 气象站:简易天气监测
  • 教育项目:Arduino、树莓派和其他微控制器入门学习
  • 植物养护:室内植物生长环境监测
  • 简易温湿度显示器:与LCD/OLED显示屏结合

优缺点

优点

  • 价格低廉,适合初学者
  • 使用简单,代码库丰富
  • Grove接口便于快速原型设计

缺点

  • 精度相对较低,不适合高精度要求场景
  • 测量范围有限,不适合极端环境
  • 更新速率较慢,推荐测量间隔≥2秒

这款传感器是初学者学习输入设备和传感器通信协议的理想选择,特别适合MIT Fab Academy输入设备课程这样的教育环境。

材料准备

  • XIAO ESP32C3开发板
  • Grove DHT11温湿度传感器
  • OWON EDS102CV示波器
  • 示波器探头
  • 连接线
  • USB数据线
  • 电脑(安装Arduino IDE)

第一部分:硬件连接

  1. 连接DHT11到XIAO ESP32C3
    • 将Grove DHT11的VCC引脚连接到XIAO ESP32C3的3.3V
    • 将Grove DHT11的GND引脚连接到XIAO ESP32C3的GND
    • 将Grove DHT11的DATA引脚连接到XIAO ESP32C3的D2(数字引脚2)

接线图如下图所示。

XIAO ESP32C3 与 Grove DHT11 的接线图

  1. 连接示波器探头
    • 将示波器CH1探头的探针连接到DHT11的DATA引脚
    • 将示波器CH1探头的接地夹连接到电路的GND
  2. 连接XIAO ESP32C3到电脑
    • 使用USB数据线将XIAO ESP32C3连接到电脑

设备链接后如下图所示。

设备实际连接的现场图片

第二部分:软件设置

  1. 安装必要的库
    • 打开Arduino IDE
    • 进入"工具" > "管理库"
    • 搜索并安装"DHT sensor library"和"Adafruit Unified Sensor"库
    • 搜索并安装"Seeed XIAO ESP32C3"板支持(如果尚未安装)
  2. 基础代码编写
    • 创建新的Arduino草图
    • 复制以下代码:
cpp
// Example testing sketch for various DHT humidity/temperature sensors
  // Written by ladyada, public domain
  
  // REQUIRES the following Arduino libraries:
  // - DHT Sensor Library: https://github.com/adafruit/DHT-sensor-library
  // - Adafruit Unified Sensor Lib: https://github.com/adafruit/Adafruit_Sensor
  
  #include "DHT.h"
  
  #define DHTPIN D2   // Digital pin connected to the DHT sensor
  
  #define DHTTYPE DHT11   // DHT 11
  
  DHT dht(DHTPIN, DHTTYPE);
  
  void setup() {
    Serial.begin(9600);
    Serial.println(F("DHTxx test!"));
  
    dht.begin();
  }
  
  void loop() {
    // Wait a few seconds between measurements.
    delay(2000);
  
    // Reading temperature or humidity takes about 250 milliseconds!
    // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
    float h = dht.readHumidity();
    // Read temperature as Celsius (the default)
    float t = dht.readTemperature();
    // Read temperature as Fahrenheit (isFahrenheit = true)
    float f = dht.readTemperature(true);
  
    // Check if any reads failed and exit early (to try again).
    if (isnan(h) || isnan(t) || isnan(f)) {
      Serial.println(F("Failed to read from DHT sensor!"));
      return;
    }
  
    // Compute heat index in Fahrenheit (the default)
    float hif = dht.computeHeatIndex(f, h);
    // Compute heat index in Celsius (isFahreheit = false)
    float hic = dht.computeHeatIndex(t, h, false);
  
    Serial.print(F("Humidity: "));
    Serial.print(h);
    Serial.print(F("%  Temperature: "));
    Serial.print(t);
    Serial.print(F("°C "));
    Serial.print(f);
    Serial.print(F("°F  Heat index: "));
    Serial.print(hic);
    Serial.print(F("°C "));
    Serial.print(hif);
    Serial.println(F("°F"));
  }
  1. 上传代码
    • 选择正确的开发板:"工具" > "开发板" > "Seeed Studio XIAO Series" > "Seeed Studio XIAO ESP32C3"
    • 选择正确的端口:"工具" > "端口" > 选择XIAO连接的COM端口
    • 点击上传按钮

如果硬件连接正常,在 Arduino 的串口监视器可以看到下图所示的传感器数据,用示波器测量的时候,保持传感器持续输出数据。

保持 Arduino IDE 的串口监视器始终能看到传感器输出的数据

第三部分:示波器测量

  1. 配置示波器设置
    • 打开OWON EDS102CV示波器。
    • 设置时基(Time/Div)为2ms/div,开始观察。
    • 设置电压刻度(Volts/Div)为1V/div。
    • 确保CH1被选中并显示。
  2. 观察DHT11通信信号
    • 观察示波器显示的波形
    • DHT11使用单总线协议,您应该能看到以下特征:
      • 开始信号:低电平持续至少18ms,然后高电平80μs。
      • 数据传输:每个位由50μs低电平+26-28μs高电平(表示"0")或50μs低电平+70μs高电平(表示"1")组成。
  3. 调整示波器设置
    • 如果信号不清晰,尝试调整触发电平。
    • 使用示波器的单次(Single)按钮触发功能捕获完整的通信过程,成果捕获数据后,。左上角的 Run/Stop 按钮会变红暂停,如下图所示。

使用右侧的 单次(Single)按钮,可以自动捕获 Grove DHT11 的数据传输周期

- 使用“添加测量>快照全部”功能测量信号的综合报告,如下图所示。

“添加测量>快照全部”功能可以获得信号的综合报告

第四部分:测量与分析

基于示波器给出的报告,以下是测量参数的列表形式报告:

参数中文名称测量值
周期 (T)93.095μs
频率 (F)10.74KHz
平均值 (V)1.526V
峰峰值 (Vp)3.380V
均方根值 (Vk)2.250V
最小值 (Mi)-20.00mV
底端值 (Vb)-20.00mV
过冲 (Os)1.2%
上升时间 (RT)<10.000μs
正脉宽 (PW)20.000μs
正占空比 (D)20.0%
延迟 (PD)?
周期均方根 (TR)370.9mV
工作周期 (WP)20.0%
最大值 (Ma)3.360V
顶端值 (Vt)3.320V
幅度 (Va)3.340V
顶冲 (Ps)0.0%
下降时间 (FT)<10.000μs
负脉宽 (NW)80.000μs
负占空比 (~D)80.0%
失真 (ND)?
同标均方根 (CR)0.000mV
相位 (RP)0.000rad

这些参数全面描述了DHT11传感器通信信号的电气特性、时间特性和频率特性,为分析数据传输协议提供了重要依据。

1. 通信周期分析

通过 OWON EDS102CV 示波器的单次(Single)触发模式捕获,我们观察到完整的 DHT11 数据传输周期为:

  • 周期(T): 93.095μs
  • 频率(F): 10.74KHz

这表明DHT11传感器在数据传输阶段的基本位脉冲周期约为 93μs,与 DHT11 规格说明中的 80-100μs 的典型值范围相符。

2. 数据位特征分析

从示波器图像可以观察到:

  • 波形特征:方波信号,呈现高低电平交替
  • 峰峰值(Vp): 3.380V,表明信号从接近 0V 摆动到约 3.3V,符合 3.3V 供电逻辑电平
  • 占空比
    • 正占空比(D): 20.0%
    • 负占空比(~D): 80.0%

这个占空比数据非常重要,它显示 DHT11 在传输数据时,高电平占用约20%的时间,低电平占用约80%的时间。这符合 DHT11 通信协议中"0"和"1"的编码方式——通过高电平持续时间的不同来区分数据位的值。

3. 电压特性分析

  • 平均电压值(V): 1.526V
  • 最大值(Ma): 3.360V
  • 顶端值(Vt): 3.320V
  • 峰值(Vp): 3.380V

电压特性显示高电平稳定在 3.3V 左右,这与 XIAO ESP32C3 的 3.3V 逻辑电平匹配。平均电压为 1.526V,反映了低电平状态占用了更多的时间比例。

4. 时间特性分析

  • 上升时间(RT): <10.000μs
  • 下降时间(FT): <10.000μs
  • 正脉宽(PW): 20.000μs
  • 负脉宽(NW): 80.000μs

这些时间参数与 DHT11 协议规范一致。特别是正脉宽 20μs 和负脉宽 80μs 的比例,刚好对应于20%:80%的占空比。

观察结果与分析

  1. 信号完整性 观察到的波形显示信号稳定清晰,没有明显的噪声干扰或信号畸变,表明连接良好且传感器工作正常。
  2. 协议特性 捕获的波形清晰展示了 DHT11 的单总线通信特性:
    • 数据以连续的脉冲串形式传输
    • 每个数据位以固定的低电平开始,后跟可变长度的高电平
    • 整体时序稳定,没有明显的抖动
  3. 位编码验证 根据 DHT11 协议,"0"位由 50μs 低电平 +26-28μs 高电平组成,"1"位由 50μs 低电平+70μs 高电平组成。从示波器测量结果看,负脉宽(低电平)约为80μs,正脉宽(高电平)约为20μs,这表明我们捕获的主要是表示"0"的数据位。

实验报告结论

硬件连接评估

XIAO ESP32C3 与 Grove DHT11 的连接方式简单有效,使用 D2 引脚作为数据线足以实现稳定通信。示波器的连接未对信号产生明显干扰,成功捕获了完整的通信波形。

DHT11通信协议特点

通过示波器观测,我们验证了 DHT11 使用的单总线通信协议具有以下特点:

  1. 信号电平范围为0-3.3V,与微控制器逻辑电平匹配。
  2. 基本通信周期约为 93μs,频率为 10.74KHz。
  3. 数据编码采用占空比编码方式,通过高电平持续时间区分"0"和"1"
  4. 信号具有良好的边沿特性,上升和下降时间均小于10μs

应用场景分析

基于观测结果,DHT11 传感器适用于:

  1. 非高精度环境监测系统,如家庭气象站。
  2. 教育和学习单总线通信协议的演示。
  3. 简易的环境控制系统,如温室控制。
  4. 低成本物联网设备的环境感知组件。

XIAO ESP32S3 与 ADXL345L 三轴加速度计测试教程

Seeed Studio Grove 3-Axis Digital Compass

任务目标

  1. 建立 XIAO ESP32S3 与 ADXL345L 的 I2C 通信连接
  2. 通过逻辑分析仪捕获 I2C 协议通信波形
  3. 解析 0x32 起始寄存器数据获取三轴加速度值

ADXL345L 技术规格

核心参数

参数规格值
通信协议I2C/SPI(本教程使用I2C)
测量范围±2g/±4g/±8g/±16g
分辨率(±2g)4mg/LSB
输出数据速率0.1Hz - 3200Hz
工作电压2.0V - 3.6V
I2C 地址0x53 (SDO=GND)
三轴数据寄存器0x32-0x37(X/Y/Z LSB)

寄存器功能说明

0x32:X轴数据低字节(X0)
0x33:X轴数据高字节(X1)
0x34:Y轴数据低字节(Y0)
0x35:Y轴数据高字节(Y1)
0x36:Z轴数据低字节(Z0)
0x37:Z轴数据高字节(Z1)


硬件连接指南

1. XIAO ESP32S3 与 ADXL345L 接线

ADXL345L 引脚XIAO ESP32S3 引脚
VCC3.3V
GNDGND
SDAD4(I2C_SDA)
SCLD5(I2C_SCL)
SDOGND(地址0x53)

2. 逻辑分析仪连接

逻辑分析仪通道连接点
CH0SDA 线(白色线)
CH1SCL 线(红色线)
GND电路板GND

将ADX345L 与 XIAO ESP32S3 连接,并连接逻辑分析仪

软件实现

1. Arduino 代码框架

cpp
#include <Wire.h>
#include <ADXL345.h>


ADXL345 adxl; //variable adxl is an instance of the ADXL345 library

void setup() {
    Serial.begin(9600);
    adxl.powerOn();

    //set activity/ inactivity thresholds (0-255)
    adxl.setActivityThreshold(75); //62.5mg per increment
    adxl.setInactivityThreshold(75); //62.5mg per increment
    adxl.setTimeInactivity(10); // how many seconds of no activity is inactive?

    //look of activity movement on this axes - 1 == on; 0 == off
    adxl.setActivityX(1);
    adxl.setActivityY(1);
    adxl.setActivityZ(1);

    //look of inactivity movement on this axes - 1 == on; 0 == off
    adxl.setInactivityX(1);
    adxl.setInactivityY(1);
    adxl.setInactivityZ(1);

    //look of tap movement on this axes - 1 == on; 0 == off
    adxl.setTapDetectionOnX(0);
    adxl.setTapDetectionOnY(0);
    adxl.setTapDetectionOnZ(1);

    //set values for what is a tap, and what is a double tap (0-255)
    adxl.setTapThreshold(50); //62.5mg per increment
    adxl.setTapDuration(15); //625us per increment
    adxl.setDoubleTapLatency(80); //1.25ms per increment
    adxl.setDoubleTapWindow(200); //1.25ms per increment

    //set values for what is considered freefall (0-255)
    adxl.setFreeFallThreshold(7); //(5 - 9) recommended - 62.5mg per increment
    adxl.setFreeFallDuration(45); //(20 - 70) recommended - 5ms per increment

    //setting all interrupts to take place on int pin 1
    //I had issues with int pin 2, was unable to reset it
    adxl.setInterruptMapping(ADXL345_INT_SINGLE_TAP_BIT,   ADXL345_INT1_PIN);
    adxl.setInterruptMapping(ADXL345_INT_DOUBLE_TAP_BIT,   ADXL345_INT1_PIN);
    adxl.setInterruptMapping(ADXL345_INT_FREE_FALL_BIT,    ADXL345_INT1_PIN);
    adxl.setInterruptMapping(ADXL345_INT_ACTIVITY_BIT,     ADXL345_INT1_PIN);
    adxl.setInterruptMapping(ADXL345_INT_INACTIVITY_BIT,   ADXL345_INT1_PIN);

    //register interrupt actions - 1 == on; 0 == off
    adxl.setInterrupt(ADXL345_INT_SINGLE_TAP_BIT, 1);
    adxl.setInterrupt(ADXL345_INT_DOUBLE_TAP_BIT, 1);
    adxl.setInterrupt(ADXL345_INT_FREE_FALL_BIT,  1);
    adxl.setInterrupt(ADXL345_INT_ACTIVITY_BIT,   1);
    adxl.setInterrupt(ADXL345_INT_INACTIVITY_BIT, 1);
}

void loop() {

    //Boring accelerometer stuff
    int x, y, z;
    adxl.readXYZ(&x, &y, &z); //read the accelerometer values and store them in variables  x,y,z
    // Output x,y,z values
    Serial.print("values of X , Y , Z: ");
    Serial.print(x);
    Serial.print(" , ");
    Serial.print(y);
    Serial.print(" , ");
    Serial.println(z);

    double xyz[3];
    double ax, ay, az;
    adxl.getAcceleration(xyz);
    ax = xyz[0];
    ay = xyz[1];
    az = xyz[2];
    Serial.print("X=");
    Serial.print(ax);
    Serial.println(" g");
    Serial.print("Y=");
    Serial.print(ay);
    Serial.println(" g");
    Serial.print("Z=");
    Serial.print(az);
    Serial.println(" g");
    Serial.println("**********************");
    delay(500);

}

逻辑分析仪验证

1. 典型I2C通信波形

抓取读取三轴数据是的逻辑数据

波形特征解析

  • Start Condition:SCL高电平时SDA由高→低
  • Address Frame:0x53 (7位地址+R/W位)
  • Register Write:发送0x32寄存器地址
  • Data Read:连续读取6字节数据(每个字节后跟随ACK)

ADX345L 数据手册

2. 数据解析验证

从数据手册可得三轴的GAIN如下

  • X: 0.00376390
  • Y: 0.00376009
  • Z: 0.00349265
寄存器地址原始值(HEX)计算实际加速度(g)
0x32 (X0)0x3452 * 0.00376390+0.1957228g
0x33 (X1)0x00
0x34 (Y0)0x05-251 * 0.00376009-0.94378259g
0x35 (Y1)0xFF
0x36 (Z0)0x4367 * 0.00349265+0.23400755g
0x35 (Z1)0x00

实际读取结果符合预取

计算结果验证以及展示

实验报告结论

1. 协议验证结果

• I2C时序符合标准规范,SCL时钟频率实测为 100kHz
• 寄存器读取顺序与数据手册完全一致
• 数据解析算法验证通过,误差范围在±0.005g内

2. 工程应用建议

运动检测:结合阈值中断功能实现跌落检测
姿态识别:通过三轴数据计算设备倾角
低功耗优化:调整输出数据速率降低功耗