“第十九课--Microduino 内部基准源ADC采样/zh”的版本间的差异

来自Microduino Wikipedia
跳转至: 导航搜索
原理图
Pkj讨论 | 贡献
第1行: 第1行:
{{Language|第十九课--Microduino_内部基准源ADC采样}}
 
 
{| style="width: 800px;"
 
{| style="width: 800px;"
 
|-
 
|-
 
|
 
|
 
==目的==
 
==目的==
了解中断,并通过按键来学习掌握中断的用法。
+
前面讲过LM35采集时每升高10mv电压代表着温度上升1℃,两者成线性关系。因此对电压稳定性要求很高。本实验将通过调用Microduino 内部基准源(3.3V或1.1V电压)结合LM35采集温度。
==中断==
+
*'''[[Microduino-Core]]'''
===中断的基本原理===
+
*'''[[Microduino-FT232R]]'''
一个正在做的事情被外部的事情打断,当执行完外部事情后,继续做原本的事情。例如:老师在上课,有同学迟到要进教室突然打断老师上课请老师准许进教室,老师准许之后又开始讲课,这就是中断。
 
===中断概念===
 
所谓中断,是指CPU在正常运行程序时,由于内部/外部事件或由程序预先安排的事件,引起CPU中断正在运行的程序,而转到为内部/外部事件或为预先安排的事件服务的程序中去,服务完毕,再返回去执行波暂时中断的程序。
 
 
 
由于某个事件的发生,CPU暂停当前正在执行的程序,转而执行处理该事件的一个程序。该程序执行完成后,CPU接着执行被暂停的程序。这个过程称为中断。
 
===中断分类===
 
*中断源的位置
 
**中断源在CPU的内部,称为内部中断;
 
**中断源在CPU的外部,称为外部中断。
 
*中断引脚的不同或者CPU响应中断的不同条件:可屏蔽中断和不可屏蔽中断。
 
===中断好处===
 
*实行分时操作提高 CPU 的效率,只有当服务对象向CPU发出中断申请时才去为它服务,这样我们就可以利用中断功能同时为多个对象服务,从而大大提高了CPU的工作效率。
 
*实现实时处理,利用中断技术,各个服务对象可以根据需要随时向 CPU 发出中断申请,及时发现和处理中断请求。
 
==设备==
 
'''[[Microduino-Core]]'''
 
'''[[Microduino-FT232R]]'''
 
 
*其他硬件设备
 
*其他硬件设备
**面包板跳线 一盒   
+
**面包板跳线   一盒   
**面包板 一块
+
**面包板   一块  
**LED发光二极管 一个
+
**USB数据连接线 一根
**220欧姆电阻  一个
+
**LM35D温度传感器  一个
**按键         一个
+
**数字万用表 一个
**USB数据连接线  一根
 
 
==原理图==
 
==原理图==
*'''Microduino core:两路外部中断,分别为D2、D3;'''
+
原理图接法与以往一样LM35的VCC接5V,GND接GND,VOUT接A0.
*'''Microduino core+:三路路外部中断,分别为D2、D3和D6。'''
+
[[File:第十八课-原理图.jpg|600px|center|thumb]]
[[File:lesson19-schematic.jpg|600px|center|thumb]]
+
===实验一===
 
+
*用Microduino-Ft232RL供电
==程序==
+
**程序
*不使用外部中断
 
 
<source lang="cpp">
 
<source lang="cpp">
int botton= 2;          // 定义输入信号引脚
+
void setup() {
int pin = 13;
+
  Serial.begin(115200);        //使用115200速率进行串口通讯
volatile int state = LOW;
+
  pinMode(A0, INPUT);  
 
void setup()
 
{              
 
  // 设置输入信号引脚为输入状态、输出引脚为输出状态
 
  pinMode(botton,INPUT);
 
  pinMode(pin,OUTPUT);
 
 
}
 
}
+
void loop() {
void loop()                    
+
   int n = analogRead(A0);   //读取A0口的电压值
{
+
   double vol = n * (5.0 / 1024.0*100);  //使用双精度浮点数存储温度数据,温度数据由电压值换算得到
   state = digitalRead(botton);     //读取微动开关状态
+
   Serial.println(vol);                   //串口输出温度数据
+
  delay(1000);                       //等待1秒,控制刷新速度
   digitalWrite(ledOut, state);   //把读取的状态赋予LED指示灯
 
 
   //模拟一个长的流程或者复杂的任务
 
   for (int i = 0; i < 100; i++)
 
  {
 
    //延时10毫秒
 
    delay(10);  
 
  }
 
 
}
 
}
 
</source>
 
</source>
*使用外部中断
+
串口监视温度数据:
 +
[[File:第十八课-USB供电.jpg|600px|center|thumb]]
 +
===实验二===
 +
*用Microduino 内部基准源1.1V计算温度值
 +
**程序
 
<source lang="cpp">
 
<source lang="cpp">
int pin = 13;
+
void setup() {
volatile int state = LOW;
+
  Serial.begin(115200);         //使用115200速率进行串口通讯
 
+
  analogReference(INTERNAL); //调用板载1.1V基准源
void setup()
+
}
{
+
void loop() {
   pinMode(pin, OUTPUT);
+
   int n = analogRead(A0);   //读取A0口的电压值
   attachInterrupt(0, blink, RISING);
+
   double vol = n * (1.1 / 1024.0*100);    //使用双精度浮点数存储温度数据,温度数据由电压值换算得到
 +
  Serial.println(vol);                  //串口输出温度数据
 +
  delay(1000);                       //等待1秒,控制刷新速度
 
}
 
}
 +
</source>
 +
串口监视温度数据:
 +
[[File:第十八课-1.1V基准电源.jpg|600px|center|thumb]]
 +
===实验三===
 +
*用Microduino 内部基准源3.3V计算温度值
 +
'''注意:使用aref引脚电压作为基准源,需要将3.3V基准源接入Microduino的 aref接口。'''
 +
[[File:第十八课-3.3基准原理图.jpg|600px|center|thumb]]
  
void loop()
+
基准源3.3V作为外部基准源使用详细参考:http://www.geek-workshop.com/thread-5717-1-1.html
{
+
*程序
   digitalWrite(pin, state);//把读取的状态赋予LED指示灯
+
<source lang="cpp">
  //模拟一个长的流程或者复杂的任务
+
void setup() {
  for (int i = 0; i < 100; i++)
+
   Serial.begin(115200);         //使用115200速率进行串口通讯
  {
+
analogReference(EXTERNAL); //使用aref引脚电压作为基准源,需要将3.3V基准源接入Microduino的 aref接口
    //延时10毫秒
 
    delay(10);
 
  }
 
 
}
 
}
 
+
void loop() {
void blink()
+
  int n = analogRead(A0);    //读取A0口的电压值
{
+
   double vol = n * (3.3 / 1024.0*100);  //使用双精度浮点数存储温度数据,温度数据由电压值换算得到
   state = !state;
+
  Serial.println(vol);                  //串口输出温度数据
 +
  delay(1000);                           //等待1秒,控制刷新速度
 
}
 
}
 
</source>
 
</source>
 +
串口监视温度数据:
 +
[[File:第十八课-3.3V基准电源.jpg|600px|center|thumb]]
  
 +
==分析==
 +
本次使用三种不同方法,同一温度传感器得到不同数值。
 +
*使用USB供电稍微好一点,供电电压为4.99V,偏离5V电压0.2%。
 +
*调用内部1.1V和3.3V基准源,经过批量采样,1.1V内部基准源的平均误差范围在1.22%左右,最高达到2.2%。
 +
*在5V量程下,Arduino ADC的采样精度是10位也就是1024级,最小分辨率为5/1024=0.0048828125 V=4.8828125 mV
 +
*在3.3V内部基准源量程下,Arduino ADC的采样精度是10位,最小分辨率为3.3/1024=0.00322265625 V=3.22265625 mV
 +
*在1.1V内部基准源量程下,Arduino ADC的采样精度是10位,最小分辨率为1.1/1024=0.00107421875 V=1.07421875 mV
 +
*LM35是每10mV代表1℃,在5V量程下,分辨率接近0.5度;3.3V量程下分辨率接近0.3度;1.1V量程下分辨率接近0.1度。
 
==结果==
 
==结果==
结果
+
通过以上分析换算,这次使用USB供电时,基准源误差相对于其他更小一些,USB供电温度更接近真实温度,但是当供电环境不稳定时,内部基准源就发挥作用了。如果进一步要求更高级精度,那么就需要使用精密外部基准源。基准误差越小,ADC的精度也就越高,根据需求环境选用合适的基准源在各种制作中也是很重要的一个环节。
未使用中断时按下开关,按住一会儿LED状态才能改变,使用中断之后LED状态就会立刻变化。
 
==中断语法==
 
*语法:
 
**attachInterrupt(interrupt, function, mode)
 
*参数:
 
**interrupt:中断引脚数
 
**function:中断发生时调用的函数,该函数会取代正在执行的程序,此函数必须不带参数和不返回任何值。该函数有时被称为中断服务程序。
 
**mode:定义何时发生中断以下四个contstants预定有效值:
 
***LOW: 当引脚为低电平时,触发中断
 
***CHANGE: 当引脚电平发生改变时,触发中断
 
***RISING :当引脚由低电平变为高电平时,触发中断
 
***FALLING :当引脚由高电平变为低电平时,触发中断.
 
===重新分配中断===
 
中断可以再任何时候通过attachInterrupt()命令进行改变。当重新使用attachInterrupt()时,先前分配的中断就会从对应引脚上移除。
 
===启用\停止中断===
 
microduino也可以忽略所有中断。如果你需要在一段代码中不执行中断,只需要执行 noInterrupts()命令。当这段代码执行完以后,你可以使用 interrupts()命令重新启用中断。
 
===删除中断===
 
终端也可以通过detachInterrupt(interrupt_number)命令进行删除。
 
==注意事项==
 
当中断函数发生时,delya()和millis()的数值将不会继续变化。当中断发生时,串口收到的数据可能会丢失。你应该声明一个变量来在未发生中断时储存变量。
 
  
 +
==视频==
 
|}
 
|}

2014年4月22日 (二) 03:31的版本

目的

前面讲过LM35采集时每升高10mv电压代表着温度上升1℃,两者成线性关系。因此对电压稳定性要求很高。本实验将通过调用Microduino 内部基准源(3.3V或1.1V电压)结合LM35采集温度。

  • Microduino-Core
  • Microduino-FT232R
  • 其他硬件设备
    • 面包板跳线 一盒
    • 面包板 一块
    • USB数据连接线 一根
    • LM35D温度传感器 一个
    • 数字万用表 一个

原理图

原理图接法与以往一样LM35的VCC接5V,GND接GND,VOUT接A0.

第十八课-原理图.jpg

实验一

  • 用Microduino-Ft232RL供电
    • 程序
void setup() {
   Serial.begin(115200);         //使用115200速率进行串口通讯
   pinMode(A0, INPUT); 
}
void loop() {
  int n = analogRead(A0);    //读取A0口的电压值
  double vol = n * (5.0 / 1024.0*100);   //使用双精度浮点数存储温度数据,温度数据由电压值换算得到
  Serial.println(vol);                   //串口输出温度数据
  delay(1000);                       //等待1秒,控制刷新速度
}

串口监视温度数据:

第十八课-USB供电.jpg

实验二

  • 用Microduino 内部基准源1.1V计算温度值
    • 程序
void setup() {
  Serial.begin(115200);         //使用115200速率进行串口通讯
  analogReference(INTERNAL);  //调用板载1.1V基准源
}
void loop() {
  int n = analogRead(A0);    //读取A0口的电压值
  double vol = n * (1.1 / 1024.0*100);    //使用双精度浮点数存储温度数据,温度数据由电压值换算得到
  Serial.println(vol);                   //串口输出温度数据
  delay(1000);                        //等待1秒,控制刷新速度
}

串口监视温度数据:

第十八课-1.1V基准电源.jpg

实验三

  • 用Microduino 内部基准源3.3V计算温度值

注意:使用aref引脚电压作为基准源,需要将3.3V基准源接入Microduino的 aref接口。

第十八课-3.3基准原理图.jpg

基准源3.3V作为外部基准源使用详细参考:http://www.geek-workshop.com/thread-5717-1-1.html

  • 程序
void setup() {
  Serial.begin(115200);         //使用115200速率进行串口通讯 
 analogReference(EXTERNAL);  //使用aref引脚电压作为基准源,需要将3.3V基准源接入Microduino的 aref接口
}
void loop() {
  int n = analogRead(A0);    //读取A0口的电压值
  double vol = n * (3.3 / 1024.0*100);   //使用双精度浮点数存储温度数据,温度数据由电压值换算得到
  Serial.println(vol);                   //串口输出温度数据
  delay(1000);                           //等待1秒,控制刷新速度
}

串口监视温度数据:

第十八课-3.3V基准电源.jpg

分析

本次使用三种不同方法,同一温度传感器得到不同数值。

  • 使用USB供电稍微好一点,供电电压为4.99V,偏离5V电压0.2%。
  • 调用内部1.1V和3.3V基准源,经过批量采样,1.1V内部基准源的平均误差范围在1.22%左右,最高达到2.2%。
  • 在5V量程下,Arduino ADC的采样精度是10位也就是1024级,最小分辨率为5/1024=0.0048828125 V=4.8828125 mV
  • 在3.3V内部基准源量程下,Arduino ADC的采样精度是10位,最小分辨率为3.3/1024=0.00322265625 V=3.22265625 mV
  • 在1.1V内部基准源量程下,Arduino ADC的采样精度是10位,最小分辨率为1.1/1024=0.00107421875 V=1.07421875 mV
  • LM35是每10mV代表1℃,在5V量程下,分辨率接近0.5度;3.3V量程下分辨率接近0.3度;1.1V量程下分辨率接近0.1度。

结果

通过以上分析换算,这次使用USB供电时,基准源误差相对于其他更小一些,USB供电温度更接近真实温度,但是当供电环境不稳定时,内部基准源就发挥作用了。如果进一步要求更高级精度,那么就需要使用精密外部基准源。基准误差越小,ADC的精度也就越高,根据需求环境选用合适的基准源在各种制作中也是很重要的一个环节。

视频