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

模拟输入捕获速率控制:Teensy电位器值突变抑制方案求助

解决方案:Teensy电位器快速下降时的速率控制

核心问题分析

你的伪代码存在几个关键问题:

  • 数组名拼写混乱(LatsVals/LastVals/lastVal),C语言数组索引从0开始,500元素数组的最后一个索引是499,不是500
  • sizeof(LastVals)返回数组总字节数(int数组为500*4=2000),不是元素个数,判断数组是否填满的逻辑错误
  • strcat是字符串拼接函数,不能用于int数组赋值
  • 循环语法错误(for(RawVal < 1023)缺少循环条件与增量)
  • 未定义变量(counter、lastVal)
  • 用500元素数组跟踪值过于冗余,既浪费内存又增加操作复杂度

优化方案:基于上一次输出值的速率限制

不需要大数组,仅记录上一次的有效输出值并设定允许的最大下降速率,即可实现电位器快速减小时的可控覆盖。以下是修正后的完整代码:

const int pwmPin = 5; 
const int pwmFrequency = 15000; 
const int pwmResolution = 8; 

const int analogPin = A5;
const float MAX_DOWN_RATE = 2.0; // 每次loop最多允许下降的数值,可按需调整
const int CHANGE_THRESHOLD = 50; // 触发速率控制的差值阈值,可按需调整

float AdjVal = 0;
int RawVal = 0;
int prevOutput = 90; // 初始值对应startingDC
int startingDC = 90;

void setup() { 
  pinMode(pwmPin, OUTPUT);
  analogWriteFrequency(pwmPin, pwmFrequency);
  analogWriteResolution(pwmResolution);
}

void loop() {            
  RawVal = analogRead(analogPin);
  AdjVal = RawVal / 16.0; // 用浮点数计算避免整数截断
  int targetOutput = startingDC + AdjVal;
  // 确保输出在8位PWM的有效范围(0-255)内
  targetOutput = constrain(targetOutput, 0, 255);

  // 速率控制逻辑:目标值比上一次输出小很多时,限制下降速率
  if (prevOutput - targetOutput > CHANGE_THRESHOLD) {
    // 按最大速率降低输出值,确保不会低于目标值
    prevOutput = max(prevOutput - MAX_DOWN_RATE, targetOutput);
  } else {
    // 正常跟随电位器数值
    prevOutput = targetOutput;
  }

  // 写入PWM值
  analogWrite(pwmPin, prevOutput);

  // 可选:添加小延迟避免采样过于频繁,可按需调整
  delay(5);
}

关键逻辑说明

  • MAX_DOWN_RATE:控制输出值的最大下降速度,数值越小,下降越平缓
  • CHANGE_THRESHOLD:设定触发速率控制的差值,当目标值比当前输出值小超过该阈值时,启动速率限制
  • constrain函数:确保输出值始终在8位PWM的有效范围内,避免超出范围导致错误
  • max函数:保证输出值不会低于目标值,最终会缓慢降到目标值,不会无限下降

进阶:基于时间的精准速率控制

如果需要更精准的速率控制(比如每秒最多下降50),可以用millis()记录时间戳,通过时间差调整速率:

const int pwmPin = 5; 
const int pwmFrequency = 15000; 
const int pwmResolution = 8; 

const int analogPin = A5;
const int MAX_DOWN_PER_SECOND = 50; // 每秒最多下降50,可按需调整
const int CHANGE_THRESHOLD = 50;

float AdjVal = 0;
int RawVal = 0;
int prevOutput = 90;
int startingDC = 90;
unsigned long lastTime = 0;

void setup() { 
  pinMode(pwmPin, OUTPUT);
  analogWriteFrequency(pwmPin, pwmFrequency);
  analogWriteResolution(pwmResolution);
  lastTime = millis();
}

void loop() {            
  unsigned long currentTime = millis();
  unsigned long elapsedTime = currentTime - lastTime;
  lastTime = currentTime;

  RawVal = analogRead(analogPin);
  AdjVal = RawVal / 16.0;
  int targetOutput = startingDC + AdjVal;
  targetOutput = constrain(targetOutput, 0, 255);

  if (prevOutput - targetOutput > CHANGE_THRESHOLD) {
    // 计算这段时间内允许下降的最大值
    float maxDown = (MAX_DOWN_PER_SECOND / 1000.0) * elapsedTime;
    prevOutput = max(prevOutput - maxDown, (float)targetOutput);
  } else {
    prevOutput = targetOutput;
  }

  analogWrite(pwmPin, (int)prevOutput);
}

为什么放弃500元素数组?

  • 内存浪费:500个int占2000字节,对于Teensy来说完全没必要
  • 操作复杂:需要维护数组滑动窗口(每次新值加入时移位),代码繁琐且效率低
  • 逻辑冗余:判断快速下降仅需对比当前值与一段时间前的旧值,用时间戳记录单个旧值即可,无需存储所有历史值

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 15:10:14