友情提示:380元/半年,儿童学编程,就上码丁实验室。
我是潘,曾经是个工程师。这是 “Arduino 公开课” 系列的入门教程。第8课我们会用温度传感器实验,来介绍 ADC 的分辨率,同时会学到怎样利用 Arduino 内部参考电压提高测量精度。有任何疑问请在评论区提出,我会逐一回答。
LM35 是美国国家半导体(现被 TI 收购)推出的精密温度传感,其信号输出为模拟量:电压值与温度(摄氏)呈正比。不仅体积非常小(常见TO-92封装),而且不需额外的校正,就能获得较高的精度。
其主要特性:
供电电压:4~35V
工作范围:与芯片有关,LM35A为-55~150°C 常见 LM35D 为 0~100°C
测量范围:与封装和电路有关,常用 TO-92为 2 ~150°C
测量精度:与芯片有关,LM35A 性能最优,这次实验用的 LM35D最差,其典型值为 ±0.8°C,最大值 ±2°C
电压与温度的关系: Vout = Temperature × 10mV/°C
想了解更多,可以参考官方 DataSheet。接线方式如下:
电压转换方式:
Vin为输入(被测量)电压;Vref 是参考电压,若不设置就是供电电压,Arduino UNO 为 5V;resolution 是模拟端口的 ADC bit,Uno 模拟端口为10bit,Result 为 模拟端口的测量结果,数值为0~1023。程序如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
/*
作者:Ardui.Co
效果:LM35 简单温度测量
版本:1.0
更新时间:2017年1月9日
*/
intLM35=A0;//指定A0端口读取LM35
floatVin;//存储传感器电压
floattemperature;//存储温度测量结果
voidsetup()
{
Serial.begin(9600);//初始化串口连接
}
voidloop()
{
Vin=analogRead(LM35)*5.0/1024;//计算出A0的电压,单位为V
temperature=Vin *1000.0/10.0;//将A0电压要转换成mV,根据LM35转换系数10mV/°C,除以10,得出温度
Serial.print(“Temperature: “);//在串口监视器输出结果
Serial.print(temperature);
Serial.println(” *C”);
delay(500);//延时0.5s
}
|
ADC 测量精度问题:
对于 5V 参考电压来说,每级为 5V / 1024 = 4.88mV,转化为温度,每级分辨率就是 0.488 °C。如果环境温度为 T ,Arduino Uno 的测量结果是 0.488 Result ,但 Result 是 0 ~ 1023 的正整数,误差 τ 就是
τ = T mod 0.488 (mod 为求余运算)
Arduino Uno 内置了1.1v 参考电压,使用这个参考电压,每级为 1.1V / 1024 = 1.07mV,每级分辨率提高到 0.107°C。
如果环境温度为10°C,取5V参考电压的分辨率为 0.24°C,取1.1V 参考电压则为 0.049°C;如果环境温度为25°C,取5V参考电压的误差为 0.112°C,取1.1V 参考电压则为 0.069°C。
接线不变,调整一下程序,引入Arduino 的内部参考电压:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
/*
作者:Ardui.Co
效果:LM35 使用1.1内部参考电压提高分辨率
版本:1.0
更新时间:2017年1月9日
*/
intLM35=A0;//指定A0端口读取LM35
floatVin;//存储传感器电压
floattemperature;//存储温度测量结果
voidsetup()
{
analogReference(INTERNAL);//使用内部参考电压
Serial.begin(9600);
}
voidloop()
{
Vin=analogRead(LM35)*1.1/1024;//计算出A0的电压,单位为V
temperature=Vin *1000.0/10.0;//将A0电压要转换成mV,根据LM35转换系数10mV/°C,除以10,得出温度
Serial.print(“Temperature: “);//在串口监视器输出结果
Serial.print(temperature);
Serial.println(” *C”);
delay(500);
}
|
参考电压稳定性:
由于参考电压跟 Vin 和温度成正比,实际中的电源电压往往十分不稳定,电池电压会随着电量变化(比如:单个锂离子放电电压约为 4.25V ~ 2.95V),开关电源会有 50 ~ 200mV 纹波,常见的USB电源在不同负载上约有 ±4% 的变化。
但别以为用 Arduino Uno 内部参考电压就万事大吉,其误差更高达 5%。因此,使用内部基准源在提高分辨能力的同时,也引入了额外的测量误差,所以要用稳定性高的参考电压。
其实,也有一个折中的方案。Arduino Uno 内部提供了一块 LDO(低压差稳压IC),为 3.3V 端口供电。LDO 一般为德州仪器的 LP2985-33DBVR,其误差小于 1.5%,用它来做外部参考电压,相对5V来说分辨率更高,相对 1.1V 内部参考电压来说,测量误差更小。
要使用外部参考电压,将 Aref 连接到 3.3V 端口:
我们将 3.3V 的端口跟 Aref 链接,并在内部程序中声明:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
/*
作者:Ardui.Co
效果:LM35 使用3.3外部参考电压提高分辨率
版本:1.0
更新时间:2017年1月10日
*/
intLM35=A0;//指定A0端口读取LM35
floatVin;//存储传感器电压
floattemperature;//存储温度测量结果
voidsetup()
{
analogReference(EXTERNAL);//使用内部参考电压
Serial.begin(9600);
}
voidloop()
{
Vin=analogRead(LM35)*3.3/1024;//计算出A0的电压,单位为V
temperature=Vin *1000.0/10.0;//将A0电压要转换成mV,根据LM35转换系数10mV/°C,除以10,得出温度
Serial.print(“Temperature: “);//在串口监视器输出结果
Serial.print(temperature);
Serial.println(” *C”);
delay(500);
}
|
我们还可以 Aref 连接到 Arduino 开发板之外的参考源上,以获取更精确的测量结果。
另外,要提高的分辨率,除了改变参考电压,也可以采用高位数的 ADC 芯片,不少精密 ADC 可达16bit 以上分辨率,我们会在提高篇中来讲解。
练习6.1:尝试结合第6课的内容,根据温度来控制风扇的速度。