arduino最大电压_Arduino Mega 2560测量电压与ADC精度

54707bc970eb239cf7702e9cab60b482.pngArduino Mega 2560能够读取0 ~ 5V的电压,并转换为10bit即0~1023级的数字信号。这怎么理解呢?

b500381702a3b358889b87f7e43585f8.png

如上图,若分辨率为2bit(即2²) ,意味着将5V分为0~3级的数字信号,每级精度是5V /4 = 1250mV。如果分辨率为10bit,即0~1023,每级是5V / 1024 = 4.88mV;如果是12bit,即0~4096,每级是5V / 4096 = 1.22mV。分辨率越高,每级分得越小,精度就越高。

得到0~1023级测量结果后,在程序内简单转化一下(没有复杂函数,只用乘除法),就能直观读出电压。接线图如下:

851612b1868ed797c76297b999a40505.png

问题来了,怎样显示电压呢?这里使用最简单的IDE串口监视器,连着开发板,直接在电脑屏幕上显示,但我们先要使用Serial.begin()启动串口通信,然后通过Serial.print()将电压在屏幕打印出来:

/*

作者:Ardui.Co

效果:串口显示模拟端口的电压值

版本:1.0

更新时间:2017年1月8日

*/

void setup()

{

Serial.begin(9600); //指定串口通讯比特率为9600

}

void loop()

{

int v = analogRead(A0); //从A0口读取电压,模拟端口电压测量范围为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);//指定串口通讯比特率为9600

}

voidloop()

{

intv=analogRead(A0);//从A0口读取电压,模拟端口电压测量范围为0-5V,返回的值为0-1024

floatvolt=v*(5.0/1024.0);//将返回值换算成电压

Serial.print(volt);//串口输出电压值

Serial.println(" V");//输出单位,并且换行

delay(1000);//输出后等待1s,降低刷新速度

}

通过A0读取电压范围不能超过5V,否则会损坏开发板,但要测量更高的电压怎么办?其实,我们可以通过分压电路来实现:

b08d4620241d23e4fa92bb8a4ae9d167.png

根据欧姆定律,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)/ R1倍(上述电路为2倍),如果分压式电阻R1 = 10K,R2 = 20K,可以测量0 ~ 15V,但分辨率降低3倍。换句话说,分压测量越高的电压,分辨率就越底。

我们会用温度传感器实验,来介绍ADC的分辨率,同时会学到怎样利用Arduino内部参考电压提高测量精度。

LM35是美国国家半导体(现被TI收购)推出的精密温度传感,其信号输出为模拟量:电压值与温度(摄氏)呈正比。不仅体积非常小(常见TO-92封装),而且不需额外的校正,就能获得较高的精度。

77f5501c9c5573fa74e7d0b217c36107.png

其主要特性:

供电电压: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。接线方式如下:

865a03d0253d9ce51fbbc14e5d8f3d58.png

电压转换方式:

969deef3ad73b099c6e9d0dd0e24fa5a.gif

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; //将A0电压要转换成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;//将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 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端口:

ab1f4960642288485abbdd85d416b8ed.png

我们将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以上分辨率。

参考链接

  • 4
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
首先,你需要连接 DHT11 传感器到 Arduino 开发板的数字引脚上,然后在 Arduino IDE 中安装 DHT 库。接着,你可以使用以下代码来读取 DHT11 传感器的数据并将温度和湿度值打印到串口监视器: ```C++ #include <DHT.h> #define DHTPIN 2 // DHT11 传感器连接到 Arduino 的数字引脚 2 #define DHTTYPE DHT11 // DHT11 传感器类型 DHT dht(DHTPIN, DHTTYPE); void setup() { Serial.begin(9600); dht.begin(); } void loop() { delay(2000); // 读取间隔时间为 2 秒 float humidity = dht.readHumidity(); // 读取湿度值 float temperature = dht.readTemperature(); // 读取温度值(摄氏度) if (isnan(humidity) || isnan(temperature)) { // 检查传感器是否正常工作 Serial.println("Failed to read from DHT sensor!"); return; } Serial.print("Humidity: "); Serial.print(humidity); Serial.print("%\t"); Serial.print("Temperature: "); Serial.print(temperature); Serial.println("°C"); } ``` 如果你想将温度值转换为华氏度,可以使用以下代码: ```C++ float temperatureF = temperature * 1.8 + 32; Serial.print("Temperature: "); Serial.print(temperatureF); Serial.println("°F"); ``` 在上面的代码中,我们使用 esp_adc_cal 库来校准 ADC(模拟数字转换器)的值。这个库可以帮助我们获得更准确的 ADC 值,从而获得更准确的传感器读数。你可以使用以下代码来读取 DHT11 传感器的数据并将温度和湿度值打印到串口监视器: ```C++ #include <DHT.h> #include <esp_adc_cal.h> #define DHTPIN 2 // DHT11 传感器连接到 Arduino 的数字引脚 2 #define DHTTYPE DHT11 // DHT11 传感器类型 #define V_REF 1100 // 参考电压为 1100mV DHT dht(DHTPIN, DHTTYPE); esp_adc_cal_characteristics_t adc_cal; void setup() { Serial.begin(9600); dht.begin(); // 初始化 ADC 校准 esp_adc_cal_value_t cal_type = esp_adc_cal_characterize(ADC_UNIT_0, ADC_ATTEN_DB_11, ADC_WIDTH_BIT_12, V_REF, &adc_cal); } void loop() { delay(2000); // 读取间隔时间为 2 秒 // 读取原始的 ADC 值 uint32_t adc_raw = analogRead(A0); // 将 ADC 值转换为电压值 float voltage = esp_adc_cal_raw_to_voltage(adc_raw, &adc_cal); // 将电压值转换为温度值(摄氏度) float temperature = (voltage - 500.0) / 10.0; float humidity = dht.readHumidity(); // 读取湿度值 if (isnan(humidity) || isnan(temperature)) { // 检查传感器是否正常工作 Serial.println("Failed to read from DHT sensor!"); return; } Serial.print("Humidity: "); Serial.print(humidity); Serial.print("%\t"); Serial.print("Temperature: "); Serial.print(temperature); Serial.println("°C"); } ``` 在上面的代码中,我们使用 ADC 单元 0 和 11 dB 的衰减来读取连接到 A0 引脚的传感器的原始 ADC 值。然后,我们使用 esp_adc_cal 库将 ADC 值转换为电压值,并将电压值转换为温度值(摄氏度)。最后,我们使用 DHT 库来读取湿度值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值