Arduino Mega 2560能够读取0 ~ 5V将电压转换为10bit即0~1023级数字信号。怎么理解?
如上图所示,如果分辨率为2bit(即22) ,意味着将5V分为0~3级数字信号,每级精度5V /4 = 1250mV。若分辨率为10bit,即0~1023,每级是5V / 1024 = 4.88mV;如果是12bit,即0~4096,每级是5V / 4096 = 1.22mV。分辨率越高,分级越小,精度越高。
得到0~1023级测量结果后,简单转换程序中的电压(无复杂函数,仅乘除法)。接线图如下:
问题是,如何显示电压?这里使用最简单的IDE串口监视器,连接开发板,直接显示在电脑屏幕上,但我们必须先使用它Serial.begin()启动串口通信,然后通过Serial.print()在屏幕上打印电压:
/*
作者:Ardui.Co
效果:串口显示模拟端口的电压值
版本:1.0
更新时间:2017年1月8日
*/
void setup()
{
Serial.begin(9600); ///指定串口通信比率为9600
}
void loop()
{
int v = analogRead(A0); //从A模拟端口电压测量范围为0-5V,返回的值为0-1024
float volt = v * (5.0 / 1024.0); ///将返回值转换为电压
Serial.print(volt); //串口输出电压值
Serial.println(" V"); ///输出单位,换行
delay(1000); ///输出后等待1s,降低刷新速度
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/*
作者:Ardui.Co
效果:串口显示模拟端口的电压值
版本:1.0
更新时间:2017年1月8日
*/
voidsetup()
{
Serial.begin(9600)
}
voidloop()
{
intv=analogRead(A0);//从A0口读取电压,模拟端口电压测量范围为0-5V,返回的值为0-1024
floatvolt=v*(5.0/1024.0)
Serial.print(volt);//串口输出电压值
Serial.println(" V");///输出单位,换行
delay(1000)s,降低刷新速度
}
通过A读取电压范围不得超过50V,否则会损坏开发板,但要测量更高的电压怎么办?实际上,我们可以通过分压电路来实现:
根据欧姆定律,Va0 = V * R1/(R1 R2) = V * 10/20 = 1/2 V
即:V = 2 Va0
因此,调整转换句可以获得实际电压:
float volt = v * (5.0 / 1024.0) * 2
1
floatvolt=v*(5.0/1024.0)*2
但测量分压电路会降低分辨率(R1 R2)/ R如果分压电阻1倍(上述电路为2倍)R1 = 10K,R2 = 20K,可以测量0 ~ 15V,但是分辨率降低了3倍。换句话说,电压测量越高,分辨率越低。
我们将介绍温度传感器实验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 Mega 2560为5V;resolution模拟端口ADC bit,Arduino Mega 2560模拟端口为10bit,Result数值为0~1023.程序如下:
/*
作者:Ardui.Co
效果:LM35 温度测量简单
版本:1.0
更新时间:2017年1月9日
*/
int LM35 = A0; //指定A0端口读取LM35
float Vin; //存储传感器电压
float temperature; ///
void setup()
{
Serial.begin(9600); //初始化串口连接
}
void loop()
{
Vin = analogRead(LM35) * 5.0 / 1024; //计算出A0电压,单位为V
temperature = Vin * 1000.0 / 10.0; //将A将0电压转换成mV,根据LM35转换系数10mV/°C,除以10,得到温度
Serial.print("Temperature: "); //在串口监视器输出结果
Serial.print(temperature);
Serial.println(" *C");
delay(500); //延时0.5s
}
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;//将A将0电压转换成mV,根据LM35转换系数10mV/°C,除以10,得到温度
Serial.print("Temperature: ");////
Serial.print(temperature);
Serial.println(" *C");
delay(500).5s
}
ADC测量精度问题:p
对于5V参考电压来说,每级为5V / 1024 = 4.88mV,转化为温度,每级分辨率就是0.488 °C。如果环境温度为T,Arduino Mega 2560的测量结果是0.488 Result,但Result是0 ~ 1023的正整数,误差τ就是
τ = T mod 0.488 (mod为求余运算)
Arduino Mega 2560内置了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的内部参考电压:
/*
作者:Ardui.Co
效果:LM35 使用1.1内部参考电压提高分辨率
版本:1.0
更新时间:2017年1月9日
*/
int LM35 = A0; //指定A0端口读取LM35
float Vin; //存储传感器电压
float temperature; //存储温度测量结果
void setup()
{
analogReference(INTERNAL); //使用内部参考电压
Serial.begin(9600);
}
void loop()
{
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);
}
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 Mega 2560内部参考电压就万事大吉,其误差更高达5%。因此,使用内部基准源在提高分辨能力的同时,也引入了额外的测量误差,所以要用稳定性高的参考电压。
其实,也有一个折中的方案。Arduino Mega 2560内部提供了一块LDO(低压差稳压IC),为3.3V端口供电。LDO一般为德州仪器的 LP2985-33DBVR,其误差小于1.5%,用它来做外部参考电压,相对5V来说分辨率更高,相对1.1V内部参考电压来说,测量误差更小。
要使用外部参考电压,将Aref连接到3.3V端口:
我们将3.3V的端口跟Aref链接,并在内部程序中声明:
/*
作者:Ardui.Co
效果:LM35 使用3.3外部参考电压提高分辨率
版本:1.0
更新时间:2017年1月10日
*/
int LM35 = A0; //指定A0端口读取LM35
float Vin; //存储传感器电压
float temperature; //存储温度测量结果
void setup()
{
analogReference(EXTERNAL); //使用内部参考电压
Serial.begin(9600);
}
void loop()
{
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);
}
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以上分辨率。
参考链接