模拟输入捕获速率控制: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
相关产品推荐
相关产品推荐

