ADC 读取电位器旋钮,用回差消除临界值档位跳动

文章介绍了如何使用电位器通过ADC转换控制风扇的10个速度档位,以及如何通过引入回差机制解决ADC读数微小变化导致的档位跳动问题。回差原理类似于迟滞比较器,确保在阈值附近ADC值的小幅波动不会改变档位。此外,文章还讨论了在存在较大干扰时采用档位惯性(连续多次采样确认)来增强系统的稳定性。
摘要由CSDN通过智能技术生成

就是比如,用电位器当旋钮做风扇调速,划分出10 个速度档位,对应10 个ADC 转换结果的阈值。如果直接比较阈值,当旋钮拧到临近阈值的地方时,ADC 结果的微小跳动会导致风扇档位在两个级别之间不停左右横跳,因此想到了利用回差来消除抖动。

回差原理

原理很简单,类似拿运放正反馈当迟滞比较器。如果只有两个档位,阈值是500,超过500 是2 档,低于500 是1 档,回差数值是100。那么如果当前位于1 档,电位器往大拧,想要调到2 档,ADC 的值要大于500 + 100 = 600。而如果当前位于2 档,要降回1 档,ADC 的值要小于500 - 100 = 400。

也就是说,阈值是动态的,和当前的位置有关。如果ADC 的值刚好是601,跳到了2 档,然后跳回1 档的阈值就瞬间变成了400,ADC 必须下降200 以上才能跳回1 档。同理,如果下降到400 跳回了1 档,再要到2 档就得上升200。所以只要ADC 的微小抖动范围不超过两倍回差,档位就不会跳动。其实这就是用一个区间替代了单一的阈值,然后原先跟阈值做的比较就变成了和区间上下界的比较。

在这里插入图片描述

回差实现

那么如果有很多档位,又该如何实现回差呢?也很简单,就是先保存当前的档位,判断阈值的时候,大于等于当前档位的所有阈值加上回差,小于的则减去回差,用图来表示就是下面这样:

在这里插入图片描述
图中的意思是,假设ADC 的结果最大值是2000,从0 开始,把ADC 的取值划分为四个档位,进入四个档位的阈值分别是0、500、1000、1500,如果0 < ADC < 500,就代表第一个档位。实际程序中是只用上界来判断档位的,比如:

int 阈值[] = {500, 1000, 1500};

// 根据ADC 的值计算出对应的档位
int 计算档位() {
	for(int i = 0; i < sizeof(阈值); ++i) {
		if(ADC < 阈值[i]){    // 只用上界,也就是只用小于判断
			return i;
		}
	}
	return 3;
}

如果ADC 小于500,则为第0 档,否则ADC 肯定大于等于500,后面不用重复判断下界,只用接着判断ADC 是否小于1000。如果表查完了,说明ADC 大于1500,所以返回第3 档。用这种查表法的好处是:

  1. 省去复杂的乘除法。如果单片机不支持硬件直接算乘法,用查表可以省下调用乘法库函数的开销;
  2. 区间划分更灵活,可以方便的按实际需求做修正,实现不均匀的区间;
  3. 可以直观的实现回差,和上面的图对应;

也可以用累加:

int 计算档位() {
	int 阈值 = 500;
	for(int i = 0; i < 3; ++i) {
		if(ADC < 阈值){
			return i;
		}
		阈值 += 500;
	}
	
	return 3;
}

缺点就是不方便实现不均匀的划分。实际应用经常遇到非线性的传感元件,比如光敏或热敏电阻,可以用非线性的阈值表负负得正,给它修正成近似线性的。

然后按上面说的思路,在函数里加上对回差的处理:

int 阈值[] = {500, 1000, 1500};
int 回差 = 100;

// 计算ADC 的值对应的档位,需要输入当前的档位来计算回差
int 计算档位(int current) {
	for(int i = 0; i < sizeof(阈值); ++i) {
		int r = 阈值[i];
		if(i >= current) { // 如果是大于等于当前档位的阈值,就加上回差
			r += 回差;
		}
		else {  // 否则减去回差
			r -= 回差;
		}
		
		if(ADC < r){    // 再用叠加了回差的阈值判断档位
			return i;
		}
	}
	return 3;
}

用累加法的和这个差不多,就不重复写了。

档位惯性

要是加了回差还不行,比如可能存在一些幅度较大的干扰信号,那么可以考虑再加上惯性:如果要从当前档位跳到其他档位,ADC 必须连续多次采样都跳出了当前档位。也可以叫做弹性吧,一松手就回去了。这和按键消抖的算法差不多,就不写例子了。

  • 13
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值