
买Arduino套装的时候,盒子里几乎都躺着一两个带旋钮的小圆片,很多人一开始不知道它是干嘛的,其实它就是电位器。调节音量、调灯的亮度、给舵机定角度,背后都是它在转。今天这篇就把电位器接Arduino这事儿从头到尾讲一遍:原理、接线、读数、调光,最后说说几个新手最容易踩的坑。
电位器是个什么器件
电位器本质上是一个可调分压器。它内部是一圈电阻体,旋钮带动一个滑动触点在电阻体上滑动,把整段电阻分成两半。它有三个引脚:两边的引脚一个接GND、一个接VCC,中间的引脚是输出脚,输出的是分压之后的电压。
旋转角度决定了输出电压的大小。旋钮从0°转到最大角度(我们叫它ANGLE_MAX),中间脚的电压就从0V线性升到VCC电压。也就是说,转多少角度,就输出多少比例的电压,关系非常直观。
常见型号的旋钮角度上限各厂家不完全一样,一般常见的是300°左右,也有270°的。不过日常使用里我们基本不用关心这个角度,因为Arduino读到的是ADC数值,直接拿来用就行。要说清楚一点:GND脚和VCC脚是可以互换的,互换后只是旋钮方向反过来,功能不受影响。
接线:三根线搞定
接线非常简单,电位器一共就占三个口。两边两个脚分别接Arduino的5V和GND,中间那个脚(信号输出脚)接到模拟输入口A0。旋转电位器,A0上的电压就在0V到5V之间连续变化。


如果觉得杜邦线容易松,想做一个长期摆着用的项目,可以给Arduino加一个接线端子扩展板(Screw Shield),把电位器的线拧到端子上固定,比杜邦线牢靠得多。
analogRead读数与map()映射
Arduino的A0到A5都能当模拟输入用。模拟口把0到5V的电压换算成0到1023的整数,也就是大家常说的ADC值。注意,Arduino读到的既不是角度也不是电压,就是一个0到1023之间的整数,想把它变成有意义的东西,得自己做换算。
读取的代码就一行:
analogValue = analogRead(A0);想换算成角度,用map()函数把0-1023映射到0-ANGLE_MAX;想换算成电压,就映射到0-5V;想控制别的东西(音量、速度、亮度),就映射到对应的最小值和最大值。
angle = map(analogValue, 0, 1023, 0, ANGLE_MAX);还有一点要知道:map()只能返回int或long类型的值。如果换算目标需要小数精度,比如电压要显示到0.01V,就得自己写个floatMap()函数来做浮点映射,下面的完整示例代码里就有。
用旋钮调LED亮度
这是电位器最常见的用法。LED的亮度用PWM控制,analogWrite的取值范围是0到255,0是全灭,255是最亮。所以只要把ADC读数从0-1023映射到0-255,就能让旋钮直接控制亮度:
brightness = map(analogValue, 0, 1023, 0, 255);想让LED从"夜灯亮度"调到最亮,而不是从全灭开始,就把下限改一下:
nightlight = 100; // depending on your desired brightness
brightness = map(analogValue, 0, 1023, nightlight , 255);把映射出来的brightness值塞进analogWrite(ledPin, brightness),LED就跟着旋钮平滑地变亮变暗了。接法也简单:LED正极串一个220Ω电阻接数字口(比如D9),负极接GND。
完整示例:串口监视器看数值
先把代码跑起来验证接线是否正确。下面这段代码每秒读一次A0,把ADC值和换算出的电压一起打到串口监视器,波特率9600:
/*
* Created by ArduinoGetStarted.com
*
* This example code is in the public domain
*
* Tutorial page: https://arduinogetstarted.com/tutorials/arduino-potentiometer
*/
float floatMap(float x, float in_min, float in_max, float out_min, float out_max) {
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
// the setup routine runs once when you press reset:
void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
}
// the loop routine runs over and over again forever:
void loop() {
// read the input on analog pin A0:
int analogValue = analogRead(A0);
// Rescale to potentiometer's voltage (from 0V to 5V):
float voltage = floatMap(analogValue, 0, 1023, 0, 5);
// print out the value you read:
Serial.print("Analog: ");
Serial.print(analogValue);
Serial.print(", Voltage: ");
Serial.println(voltage);
delay(1000);
}
烧录进板子,打开串口监视器,慢慢转旋钮,输出会像这样变化:Analog: 0, Voltage: 0.00,转到头就是Analog: 1023, Voltage: 5.00。能看到数值跟着旋钮线性走,说明接线和读数都正常。
读数抖动怎么办:简单均值滤波
实际用的时候你会发现,旋钮不动,串口里的数值也会上下跳几个点。这很正常,电位器滑动触点有接触噪声,再加上Arduino的ADC本身就有一两个点的抖动。如果拿这种读数去控制舵机或者亮度,肉眼就能看到轻微闪动。
最简单的对策是均值滤波:连续读十几次,把每次的analogRead结果加起来求平均,用平均值参与控制。比如连读16次求平均,抖动基本就被抹平了。进阶一点的做法是先去掉最大和最小的几个异常值再平均,效果更好。对新手项目来说,简单均值就够用了。
另外可以在代码里加一个小判断:新读数和上一次的差值小于2就忽略,不更新输出,这样输出会更稳。
常见坑,提前避开
第一个坑:两端接反了,读数方向相反。本来顺时针越转数值越大,接反之后就变成越转越小。这个不算故障,GND和VCC本来就是可互换的,只是方向反了不舒服,把两边线对调一下就好。
第二个坑:中间脚没接A0,接到了数字口。数字口读出来只有0和1,你会得到一堆乱跳的数值却找不到原因。模拟器件一律走A0到A5。
第三个坑:滑动触点接触不良。电位器用久了或者买到劣质货,转动的时候数值会突然跳变、出现断档。可以转动几十圈用串口观察数值是否连续来甄别,坏了就换,别在代码上浪费时间。
电位器算是模拟输入里最好上手的一个器件,接线三根线、代码几行搞定。把它吃透了,后面的光敏电阻、热敏传感器这些模拟量器件就是同一套路子。











上个月刚给自己折腾了个音量旋钮,用的就是电位器接A0这套,当时接反了还以为是坏的,白白重焊了一次,看到文里说两端互换只是方向反,真是后知后觉。补充一个我实测的小细节:3296那种蓝色多圈精密电位器也能这么接,读数一样是0-1023,只是旋钮要转好几圈才走完全程,拿来做需要细调的场景(比如设定比较阈值)比普通单圈的舒服很多。另外map()那个float的坑我也踩过,电压显示两位小数用map会全变成整数,后来照着floatMap抄了个函数才解决,新手遇到同样的现象别怀疑板子,就是函数选错了。
均值滤波真有用,我加了个连读16次取平均,舵机抖动直接消失
接反读数反向这个坑太经典了,第一个项目就中招过
串口监视器看Analog和Voltage两个值跟着变,这招验证接线确实快