15、数据收集小工具:Arduino 传感器数据处理与采集

数据收集小工具:Arduino 传感器数据处理与采集

在电子项目中,数据的准确收集和处理至关重要。本文将详细介绍如何使用 Arduino 进行传感器数据的收集和处理,包括按钮消抖、模拟数据采集以及批量数据收集等内容。

1. 简单的 Arduino 传感器数据输入

按钮是常见的输入设备,但读取按钮信号时存在一个问题:按钮会产生抖动。在按钮最终稳定连接之前,会有间歇性的接触。为了解决这个问题,我们采用了一种更复杂的消抖算法,而不是简单的忙等待设计。

消抖算法依赖于 millis() 函数来记录按钮处于某个状态的时间。以下是消抖函数的代码:

const int BUTTON_IN = 7;
unsigned long debounce() {
  static unsigned long rise_time = 0;
  static int button_state = LOW;
  int probe = digitalRead(BUTTON_IN);  
  // 前沿
  if (probe == HIGH && button_state == LOW) {
    rise_time = millis();
    button_state = probe;
    return 0;
  }
  unsigned long duration = millis() - rise_time;
  // 后沿
  if (probe == LOW && button_state == HIGH) {
    button_state = probe;
    return duration;
  }
  return 0;
}

该函数使用两个静态变量 button_state rise_time 分别保存按钮的上一个状态和按钮按下的时间。当按钮按下时,信号从 LOW 变为 HIGH,记录此时的时间;当按钮释放时,信号变回 LOW,计算按下的持续时间。

loop() 函数中使用该消抖函数:

const int BUTTON_LED = 8;
void loop() {
  static int button = LOW;
  unsigned long push = debounce();
  if (push >= 10) { 
      // 改变按钮 LED 状态
      if (button == LOW) { button = HIGH; }
      else { button = LOW; }
      digitalWrite(BUTTON_LED, button);
  }
  heartbeat();
}

如果按钮按下的持续时间大于 10 毫秒,认为是一次有效的按下,改变 LED 的状态。同时, heartbeat() 函数用于提供视觉反馈,表明程序正在运行。

按钮与 LED 的接线示意图中,按钮使用了一个 10 KΩ 的下拉电阻,以确保输入引脚有合适的 LOW 电压状态。LED 需要 2.5 V 的电压,因此需要 180 Ω 的电阻。

2. 模拟数据采集

我们的目标是从模拟距离传感器收集数据。以 GP2Y0A21YK 传感器为例,它有三个连接引脚:Vo、GND 和 Vcc。传感器朝上时,最左边的引脚是 Vo,连接到 Arduino 的 A0 引脚提供模拟输入;中间引脚是 GND,连接到 Arduino 的 GND 引脚;最右边的引脚是 Vcc,连接到 Arduino 的 +5 V 引脚。

连接传感器时要注意线的颜色编码可能与预期不同,连接错误可能导致短路,使 Arduino 板停止工作。

使用 analogRead() 函数从 A0 引脚收集输入值,该值是 0 到 1024 之间的整数,反映了 0 到 5 V 的电压水平。可以通过公式 V = 5 * s / 1024 计算实际电压。

以下是简单的读取距离设备的代码:

int samples[4];
void gather_data() {
  for (int i = 0; i != 4; ++i) {
      samples[i] = analogRead(IR_IN);
  }
}
void share_data() {
  for (int i = 0; i != 4; ++i) {
    Serial.print(samples[i], DEC);
    Serial.print("\t");
  }
  Serial.println();
}

setup() 函数中,需要打开串口输出端口:

void setup() {
  pinMode(LED, OUTPUT);
  digitalWrite(LED, LOW);
  Serial.begin(9600);
}

loop() 函数每 2 秒收集一次数据:

void loop() {
    static unsigned long last = 0;
    unsigned long now = millis();
    if (now - last > 2000) {
      gather_data();
      share_data();
      last = now;
    }
    heartbeat();
}

打开 Arduino IDE 的串口监视器窗口,可以看到传感器输出的数据。即使物体静止,IR 距离传感器的输出也会有小的波动。

3. 批量数据收集

为了进行更精确的校准,我们需要收集更多的数据。首先,扩展 IR 传感器读取代码,等待传感器显示稳定读数,然后收集 16 个样本。

以下是扩展后的 gather_data() 函数:

unsigned long start_time, end_time;
int raw_reading;
#define MODE_LIMIT 6
int reading[MODE_LIMIT];
int count[MODE_LIMIT];
const int TIME_LIMIT = 5000; // 微秒
// 读取 IR 数据,计算不超过 16 个不同值的众数
// 在 TIME_LIMIT 微秒后,返回众数
void gather_data() {
  // 开始收集
  start_time = micros();
  for (int i = 0; i != MODE_LIMIT; ++i) { reading[i] = -1; count[i] = 0; }
  // 下一个样本
  while (micros() - start_time < TIME_LIMIT) {
    int next = analogRead(IR_IN);
    for (int i = 0; i != MODE_LIMIT; ++i) {
      if (reading[i] == next) {
        count[i] += 1;
        break;
      }
      else if (reading[i] == -1) {
        reading[i] = next;
        break;
      }
    }
  }
  // 结束处理
  int mx = 0;
  for (int i = 1; i != MODE_LIMIT; ++i) {
    if (reading[i] == -1) break;
    if (count[i] > count[mx]) mx = i;
  }
  raw_reading = reading[mx];
  end_time = micros();
}

该函数使用 micros() 函数记录开始和结束时间,使用数组 reading count 记录读取的值和出现的次数。通过比较次数,找到出现次数最多的值,即众数。

4. 控制数据收集

share_data() 函数需要扩展以输出 raw_reading 的值,同时为了更深入的分析和调试,还可以打印 start_time end_time 以及 reading count 数组的值。

修改 main loop() 函数:

void loop() {
    unsigned long push = debounce();
    // 后续可添加其他逻辑
}

总结

通过以上步骤,我们可以使用 Arduino 进行按钮消抖、模拟数据采集和批量数据收集。消抖算法确保了按钮输入的准确性,模拟数据采集让我们能够获取传感器的电压信息,批量数据收集则为更精确的校准提供了数据支持。在实际应用中,我们可以根据需要调整代码,以满足不同的项目需求。

流程图

graph TD;
    A[开始] --> B[初始化];
    B --> C[读取按钮状态];
    C --> D{是否按下};
    D -- 是 --> E[消抖处理];
    E --> F{是否有效按下};
    F -- 是 --> G[改变 LED 状态];
    D -- 否 --> H[读取模拟数据];
    H --> I[收集数据];
    I --> J[处理数据];
    J --> K[输出数据];
    G --> L[继续循环];
    K --> L;
    L --> C;

表格

变量名 作用
BUTTON_IN 按钮输入引脚
BUTTON_LED 按钮对应的 LED 引脚
IR_IN 模拟输入引脚
start_time 数据收集开始时间
end_time 数据收集结束时间
raw_reading 原始读取值
MODE_LIMIT 数组大小限制
TIME_LIMIT 数据收集时间限制

通过以上内容,我们可以看到如何使用 Arduino 构建一个功能强大的数据收集系统,从简单的按钮输入到复杂的模拟数据采集,都可以通过合理的代码设计和硬件连接实现。希望这些内容对您的电子项目有所帮助。

5. 数据处理与分析

在收集到数据之后,我们需要对其进行处理和分析,以获取有用的信息。对于模拟距离传感器的数据,我们可以通过计算众数来确定稳定的读数,进而将其转换为实际的距离值。

5.1 众数计算

在前面的批量数据收集部分,我们已经实现了计算众数的功能。 gather_data() 函数通过记录每个读取值出现的次数,最终找到出现次数最多的值作为众数。这个众数可以认为是当前传感器的稳定读数。

5.2 数据校准

要将传感器的原始读数转换为实际的距离值,需要进行校准。校准的过程通常是在不同的距离下收集传感器的读数,然后建立读数与距离之间的关系。

例如,我们可以将传感器指向不同距离的物体,记录每个距离下的传感器读数,然后通过线性回归或其他方法拟合出读数与距离之间的函数关系。假设我们得到的关系为 $d = f(s)$,其中 $d$ 是距离,$s$ 是传感器的原始读数。

5.3 代码示例

以下是一个简单的示例,展示如何根据校准后的函数将原始读数转换为距离值:

// 假设校准函数为线性关系 d = a * s + b
const float a = 0.1; // 斜率
const float b = 10;  // 截距

float convertToDistance(int raw_reading) {
    return a * raw_reading + b;
}

void loop() {
    unsigned long push = debounce();
    if (push >= 10) {
        gather_data();
        float distance = convertToDistance(raw_reading);
        Serial.print("Distance: ");
        Serial.print(distance);
        Serial.println(" cm");
    }
    heartbeat();
}

6. 实际应用与拓展

6.1 应用场景
  • 智能家居 :可以使用距离传感器检测人体的接近或离开,实现自动开关灯、调节空调温度等功能。
  • 机器人导航 :机器人可以通过距离传感器检测周围环境的障碍物,从而实现自主导航。
  • 工业自动化 :在工业生产线上,距离传感器可以用于检测物体的位置和尺寸,实现自动化生产。
6.2 拓展功能
  • 多传感器融合 :可以同时使用多个不同类型的传感器,如温度传感器、湿度传感器等,获取更全面的环境信息。
  • 无线数据传输 :通过无线模块(如 Wi-Fi、蓝牙等)将收集到的数据传输到远程服务器,实现远程监控和控制。
  • 数据存储 :将收集到的数据存储到 SD 卡或其他存储设备中,以便后续的分析和处理。

7. 注意事项

7.1 硬件连接
  • 在连接传感器和其他硬件设备时,要确保引脚连接正确,避免短路和损坏设备。
  • 注意电源的稳定性,避免电压波动对传感器的读数产生影响。
7.2 代码优化
  • 尽量减少代码中的延迟和阻塞操作,以提高系统的响应速度。
  • 合理使用内存,避免内存泄漏和溢出问题。
7.3 数据准确性
  • 由于传感器本身的误差和环境因素的影响,收集到的数据可能存在一定的误差。在进行数据分析和决策时,要考虑到这些误差。

流程图

graph TD;
    A[开始] --> B[数据收集];
    B --> C[计算众数];
    C --> D[数据校准];
    D --> E[转换为距离值];
    E --> F[输出距离信息];
    F --> G[继续循环];
    G --> B;

表格

功能 实现方法
众数计算 gather_data() 函数中记录每个读取值出现的次数,找到出现次数最多的值
数据校准 在不同距离下收集传感器读数,建立读数与距离之间的函数关系
转换为距离值 根据校准后的函数将原始读数转换为距离值
多传感器融合 同时连接多个不同类型的传感器,分别读取数据
无线数据传输 使用无线模块(如 Wi-Fi、蓝牙等)将数据发送到远程服务器
数据存储 将数据存储到 SD 卡或其他存储设备中

通过以上内容,我们详细介绍了如何使用 Arduino 进行数据收集、处理和分析,以及如何将其应用到实际项目中。希望这些内容能够帮助您构建更加复杂和功能强大的电子系统。在实际应用中,您可以根据具体需求对代码和硬件进行调整和优化,以实现更好的效果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值