You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

不使用delay()实现时移?Arduino电位器波形延迟故障求助

问题分析与解决方案

原代码核心问题

  1. calc函数逻辑错误:
    • 原代码每次调用calc()都会把缓冲区所有元素覆盖为当前输入uk,完全无法实现延迟效果。
    • 访问x[k]属于数组越界(数组下标范围是0到k-1),会导致内存访问错误,这是延迟波形无输出的直接原因。
  2. 变量类型不匹配:
    • 输入uk是unsigned int类型,但缓冲区x是int类型,可能导致模拟读数(0-1023)被错误转换。
    • k作为缓冲区长度,应该用整数类型(如uint16_t),避免浮点数运算带来的精度问题。
  3. 构造参数错误:
    • 初始化delayBox1时传入的延迟时间是0.3秒,与需求的0.5秒不符。

修正后的完整代码

unsigned int data;
const float sample_time = 0.01f;
const float delay_time = 0.5f;
uint32_t start_Time;
uint32_t MicroSampleTime;

class delayBox
{
public:
    delayBox(float delay_time, float Ts);
    ~delayBox();
    void calc();
public:
    unsigned int uk;       // 当前输入
    unsigned int yk;       // 延迟输出
private:
    unsigned int* buffer;  // 延迟缓冲区
    uint16_t buffer_len;   // 缓冲区长度(延迟样本数)
};

delayBox* delayBox1;

void setup() {
    Serial.begin(115200);
    // 传入正确的延迟时间0.5秒
    delayBox1 = new delayBox(delay_time, sample_time);
    MicroSampleTime = static_cast<uint32_t>(sample_time * 1e6);
    start_Time = micros() + MicroSampleTime;
}

void loop() {
    data = analogRead(A0);

    delayBox1->uk = data;
    delayBox1->calc();

    Serial.print(data);
    Serial.print(" ");
    Serial.println(delayBox1->yk);

    // 非阻塞延时逻辑(保持原逻辑)
    while (!((start_Time - micros()) & 0x80000000));
    start_Time += MicroSampleTime;
}

delayBox::delayBox(float delay_time, float Ts) {
    // 计算需要的样本数,强制转换为整数
    buffer_len = static_cast<uint16_t>(delay_time / Ts);
    // 分配缓冲区内存,类型匹配为unsigned int
    buffer = new unsigned int[buffer_len];
    // 初始化缓冲区为0
    for (uint16_t i = 0; i < buffer_len; ++i) {
        buffer[i] = 0;
    }
}

void delayBox::calc() {
    // 缓冲区移位:将所有元素向前移动一位,丢弃最旧的元素
    for (uint16_t i = 0; i < buffer_len - 1; ++i) {
        buffer[i] = buffer[i + 1];
    }
    // 将当前输入放入缓冲区末尾
    buffer[buffer_len - 1] = uk;
    // 输出缓冲区最前面的元素(即k个样本前的输入)
    yk = buffer[0];
}

delayBox::~delayBox() {
    // 释放缓冲区内存,避免内存泄漏
    delete[] buffer;
}

关键修正点说明

  1. 缓冲区逻辑:
    • calc()函数改为移位缓冲区:每次将缓冲区元素向前移动一位,把当前输入放到缓冲区最后,然后取出缓冲区第一个元素作为延迟输出,实现k = delay_time/sample_time个样本的延迟(即0.5秒)。
  2. 类型修正:
    • 缓冲区buffer改为unsigned int类型,与输入uk、模拟读数类型一致,避免数据转换错误。
    • buffer_len用uint16_t类型,确保是正整数,符合数组长度要求。
  3. 内存管理:
    • 析构函数中添加delete[] buffer,避免Arduino长时间运行后的内存泄漏。
  4. 参数修正:
    • 初始化delayBox1时传入delay_time(0.5秒),匹配需求。

修改后,串口绘图仪将正常显示电位器波形和延迟0.5秒的波形,且全程不使用delay()函数。

内容的提问来源于stack exchange,提问作者o01

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 01:15:45