【任务导航】

1.认识光敏电阻,认识分压电路
2.掌握光敏电阻的分压电路连接方式
3.掌握analogRead()函数
4.掌握Mixly编程中相关的程序模块的使用

【知识加油站】

1.光敏电阻

光敏电阻是利用半导体的光电导效应制成的一种特殊电阻器,其工作原理是基于内光电效应。光照愈强,阻值就愈低,随着光照强度的升高,电阻值迅速降低,亮电阻可小至1KΩ以下。光敏电阻对光线十分敏感,其在无光照时,呈高阻状态,暗电阻一般可达1.5MΩ。光敏电阻的特殊性能,随着科技的发展将得到极其广泛应用。
光敏电阻器一般用于光的测量、光的控制和光电转换(将光的变化转换为电的变化)。常用的光敏电阻器是用半导体材料硫化镉制成。光敏电阻器对光的敏感性(即光谱特性)与人眼对可见光(波长在0.4~0.76μm)的响应很接近,只要人眼可感受的光,都会引起它的阻值变化。设计光控电路时,都用白炽灯泡(小电珠)光线或自然光线作控制光源,使设计大为简化。常见的光敏电阻如图2.5.1所示。
第五节 LED光控 - 图1
图2.5.1 常见光敏电阻
光敏电阻的主要参数:
(1)光电流、亮电阻。光敏电阻器在一定的外加电压下,当有光照射时,流过的电流称为光电流,外加电压与光电流之比称为亮电阻。
(2)暗电流、暗电阻。光敏电阻在一定的外加电压下,当没有光照射的时候,流过的电流称为暗电流。外加电压与暗电流之比称为暗电阻。
(3)灵敏度。灵敏度是指光敏电阻不受光照射时的电阻值(暗电阻)与受光照射时的电阻值(亮电阻)的相对变化值。
(4)光谱响应。光谱响应又称光谱灵敏度,是指光敏电阻在不同波长的单色光照射下的灵敏度。若将不同波长下的灵敏度画成曲线,就可以得到光谱响应的曲线。
(5)光照特性。光照特性指光敏电阻输出的电信号随光照度而变化的特性。在大多数情况下,该特性为非线性。

2.分压电路

在说分压电路之前,首选需要了解串联电路和并联电路。两个电阻首尾相连后再连接到电路中,这两个电阻叫串联电路;两个电阻首首相连后并排连接到电路中,这两个电阻叫并联电路。具体电路如图2.5.2所示。
第五节 LED光控 - 图2
图2.5.2 串联电路和并联电路示例
在串联电路中,各电阻上的电流相等,各电阻两端的电压之和等于总电路中的电压。每个电阻上的电压小于电路总电压,故串联电阻具有分压作用;在并联电路中,各电阻两端的电压相等,各电阻上的电流之和等于总电流(干路电流)。每个电阻上的电流小于总电流(干路电流),故并联电阻具有分流作用。
根据以上知识的学习我们知道,分压电路其实质就是串联电路。具体运用在光敏电阻的分压电路时,就是选取一个定值电阻和一个光敏电阻串联后再连接到电源的正极和GND之间去,通过亮度的不同,光敏电阻将会呈现出不同的电阻值,从而影响分到的电压。

3.analogRead(pin)函数
analogRead(pin)函数将会从指定的模拟引脚读取数据值。Arduino UNO板包含一个 6 通道(Mini 和 Nano 有 8 个通道,Mega 有 16 个通道)10位模拟数字转换器。这意味着它能将 0 至 5V之间的输入电压映射到0至1023之间的整数值,换句话说,Arduino可以将5V平均分成1024份。0V的输入信号对应着数值0,而5V的输入信号对应着1023,映射的精度为5 V/1024 个单位,每个单位0.0049 V或4.89mV。输入范围和精度可以使用 analogReference()改变。analogRead(pin)函数读取数据需要大约 100 us(0.0001s)的时间,所以最大的读取速度是每秒 10000 次。
调用analogRead(pin)函数后将会返回一个0-1023之间的一个整数值,此值和读取的模拟输入引脚pin上的电压值成正比关系,所以在调用此函数时,通常需要创建一个变量来存储函数返回的值。调用此函数之前,不需要再用pinMode()函数设置引脚的工作模式。
如果模拟输入引脚没有连接任何电路,由 analogRead()返回的值将根据多项因素(例如其他模拟输入引脚,你的手靠近板子等)产生波动,更多的是一个随机数。

【自己动手】

任务1:串口发送光敏电阻分压电路的模拟值

1.任务要求
①在面包板上搭建光敏电阻的分压电路,从定值电阻和光敏电阻中间引出模拟电压信号连接到Arduino主板的模拟引脚A0。编写程序获取光敏电阻的分压值后发送到Arduino串口监视器查看。
②在完成①的基础上,把光敏电阻分到的电压值换算出来后发送到串口监视器查看。

2.所需硬件
Arduino UNO/NANO主板1块,面包板1块,光敏电阻1个,直插式10K定值电阻1个,对应Arduino主板的USB下载线1根,面包板专用连接线若干。

3.参考电路
第五节 LED光控 - 图3
图2.5.3 电路连接参考图
4参考程序
Arduino IDE参考程序

  1. int analogPin = 0; //模拟引脚
  2. int val = 0; //定义变量来存储读取的数值
  3. void setup()
  4. {
  5. Serial.begin(9600); //设置波特率(9600)
  6. }
  7. void loop()
  8. {
  9. val = analogRead(analogPin); //从输入引脚读取数值
  10. Serial.println(val); //显示读取的数值
  11. delay(500);
  12. }

  1. int analogPin = 0; //模拟引脚
  2. int val = 0; //定义变量来存储读取的数值
  3. void setup()
  4. {
  5. Serial.begin(9600); //设置波特率(9600)
  6. }
  7. void loop()
  8. {
  9. val = analogRead(analogPin); //从输入引脚读取数值
  10. Serial.print("模拟读取值是:");
  11. Serial.println(val); //显示读取的数值
  12. Serial.print("电压是:");
  13. Serial.print((val*4.89));
  14. Serial.println("mv");
  15. delay(500);
  16. }

Mixly参考程序

第五节 LED光控 - 图4

第五节 LED光控 - 图5

任务2:根据环境亮度控制LED的亮度

1.任务要求
通过光敏电阻采集环境中的亮度信息去控制LED灯的亮度。控制要求是环境越亮,LED控制越暗;环境越暗,LED控制越亮。以实现模拟亮度调节小夜灯的效果。

2,所需硬件
Arduino UNO/NANO主板1块、面包板1块、直插LED灯1个、470Ω直插电阻1个、10K直插电阻1个、光敏电阻1个、面包板专用连接线若干、Arduino主板对应数据线1根。

3.参考电路
电路连接图请参看电路连接图2.5.4,具体引脚连接方式参照下表。
表2.5.1 LED光控电路引脚连接方式表

元器件 Arduino主板 元器件 Arduino主板
470Ω电阻 1 GND 光敏电阻 1 VCC
2 LED阴 2 A0
10K电阻 1 A0 LED D3
2 GND 470Ω_2

第五节 LED光控 - 图6
图2.5.4 光控LED电路连接图
4.参考程序
Arduino IDE参考程序

  1. int analogPin = 0; //模拟引脚
  2. int val = 0; //定义变量来存储读取的数值
  3. void setup()
  4. {
  5. Serial.begin(9600); //设置波特率(9600)
  6. }
  7. void loop()
  8. {
  9. val = analogRead(analogPin); //从输入引脚读取数值
  10. Serial.print("模拟读取值是:");
  11. Serial.println(val); //显示读取的数值
  12. analogWrite(3,(255-(val/4))); //PWM驱动LED的亮度
  13. delay(100);
  14. }

Mixly参考程序
第五节 LED光控 - 图7

【拓展学习】

参考电压

在任务1的要求②中,我们计算光敏电阻上分到的电压时,默认是认为Arduino的供电电压为5.00V,或者说是5000mV,但是在实际的使用过程中,这个供电电压不可能是标准的5000MV,有可能是4900mV,也可能是5100mV。所以我们默认用5000mV来当做供电电压计算,得到的测量电压是不准的。所以在需要高精度测量模拟信号的时候,就需要知道准确的供电电压是多少,这样才才能测量得到高精度的测量电压。
在实际的使用过程中,通常会选取一路Arduino模拟输入,接入一个高精度的固定电压,通过测量这个高精度的固定电压来反向推到出Arduino的供电电压。常用的高精度固定电压产生的电子元件是TL431,如图2.5.5所示,中a是TL431产生高精度2.5V电压的电路。通过调节下图中R2和R3的阻值就可以调节输出2.5V-36V之间的任意电压。
第五节 LED光控 - 图8
图2.5.5 TL431常用电路
我们通过模拟引脚读取得到数据,需要转换为电压时,需要用到Arduino的供电电压,那是因为Arduino默认的参考电压是供电压。因为供电电压是5V,所以我们说模拟输入读取到的数据一个单位是5V被分成1024份的值,就是4.89mV。如果我想提高精度,比如我想把2.5V分为1024份,更或者想把1V分成1024份,那这样得到的一份就会更小,精度就会更高。为了满足这样要求,Arduino专门设有一个可以接入参考电压的引脚和专门设置参考电压的函数。

analogReference()函数

analogReference()函数就是用于配置模拟输入的基准电压(即输入范围的最大值)。选项有:
DEFAULT:默认5V(Arduino 板为 5V)或 3.3 伏特(Arduino 板为 3.3V)为基准电压。
INTERNAL:在 ATmega168 和 ATmega328 上以 1.1V 为基准电压,以及在 ATmega8 上以2.56V 为基准电压(Arduino Mega 无此选项)
INTERNAL1V1:以 1.1V 为基准电压(此选项仅针对 Arduino Mega)
INTERNAL2V56:以 2.56V 为基准电压(此选项仅针对Arduino Mega)
EXTERNAL:以 AREF 引脚(0 至 5V)的电压作为基准电压。
通过以上的说明可知,Arduino UNO/NANO主板可以用默认的供电电压,或者1.1V基准电压和外接输入参考电压。外接输出参考电压引脚为AREF引脚。

map()函数

map(value, fromLow, fromHigh, toLow, toHigh)函数可以将一个数从一个范围等比例映射到另外一个范围。也就是说,会将fromLow 到fromHigh之间的值等比例缩放到toLow在toHigh之间的值。
注意,两个范围中的“下限”可以比“上限”更大或者更小,因此 map() 函数可以用来翻转数值的范围,例如:
y = map(x, 1, 50, 50, 1);
map() 函数使用整型数据进行运算,因此不会产生小数,小数的余数部分会被舍去,不会四舍五入或者平均。该函数可以处理负数。
在任务2中,因为模拟输入引脚的值和PWM输出的值刚好的4倍的关系,所以我们可以直接除以4来进行数据的缩放,但是在一般的使用情况下,更多的时候数据不是这样简单的比例关系,这时就可以通过map()函数来快速的将采集数据转换为目标数据。更为详细的使用使用轻参看Arduino手册相关部分。

【思考与讨论】

1.如何通过模拟输入引脚测量出Arduino主板的供电电压?
2.能否通过模拟输入引脚测量出某一电路中的电流?如若能测,试想如何搭建电路,如何测量?
3.Arduino的模拟输入还能用再哪些方面?