本篇介绍Arduino模拟输入功能,通过读取电位器输入的电压值来控制LED灯的亮度。另外补充通过纯软件编程的方式再做同样的操作,旨在提高读者对AnalogRead和AanlogWrite函数这两个函数的理解,并了解使用电位器调光的原理。
实验要求
3.1 Arduino 模数转换函数 AnalogRead的用法
(在哪些引脚上可用,给出一个以可变电阻分压为输入,从串口输出模数转换数值的例程)
3.2 用电位器实现调光LED灯(使用AanlogWrite函数,即项目2中的2.2方式)
(Fritzing绘制的电路图、工作原理的说明,包含完整注释的源代码)
3.3 用电位器实现调光LED灯(使用软件编程的方法,即项目2中的2.1方式)
(工作原理的说明,包含完整注释的源代码,与2.1代码的比较)
实验的基本原理
- 模拟输入引脚是带有ADC(Analog-to-Digital Converter,模数转换器)功能的引脚。它可以将外部输入的模拟信号转换为芯片运算时可以识别的数字信号,从而实现读入模拟值的功能。
- Arduino 模拟输入功能有10位精度,即可以将0~5V的电压信号转换为0~1023的整数形式表示。
- 我们通过使用analogRead() 函数读取电位器输入的电压值,然后通过analogWrite()函数来控制LED灯亮度。
- 最后使用纯软件编程的方法(使用delay函数控制占空比和时间)实现电位器调光,突破了模拟输入端口个数的限制,走向了更普遍化的引脚。
(一)模数转换函数 AnalogRead的用法与电位器的工作原理介绍
函数介绍
-
AnalogRead:模拟引脚( IO口)读取函数
1.说明:用于从Arduino的输入引脚读取数值。Arduino 模拟输入功能有10位数模转换通道,意味着可以将0~5V的电压信号转换为0~1023的整数形式表示。
注意:在模拟输入引脚没有任何连接的情况下,用analogRead指令读取该引脚,这时获得的返回值为不固定的数值。这个数值可能受多种因素的影响,如将手靠近引脚也可能会引起返回值的变化。
2.语法:AnalogRead(pin)
3.参数:1个 。例如AnalogRead(pin),pin表示被读取的模拟引脚号,也就是A0~A5引脚,因为能输入模拟信号的只有这6个引脚,所以不用指定第二个参数。
4.返回值:0~1023之间的整数
元器件介绍——电位器
电位器是一个可调的电阻,具有三个引出端、阻值可按某种变化规律调节的电阻元件。电位器通常由电阻体和可移动的电刷组成。当电刷沿电阻体移动时,在输出端即获得与位移量成一定关系的电阻值或电压。
电位器既可作三端元件使用也可作二端元件使用。后者可视作一可变电阻器,由于它在电路中的作用是获得与输入电压(外加电压)成一定关系的输出电压,因此称之为电位器。
其原理如下图所示:
通过旋转旋钮改变2号脚位置,从而改变2号脚到两端的阻值。实验中将1脚和3脚分别接到开发板的5V和GND,再通过模拟输入引脚A0(A0~A5都可以)来读取电位器2号脚分得的电压,其范围在0V和5V之间。
示例程序
在本示例中,我们将电位器的3个引脚分别接在5V、A0引脚和GND,通过调节电位器,A0模拟引脚的输入电压在0-5V之间,在Arduino内置的模拟数字功能转化下,将该输入电压映射到数值0~1023。这一数值将通过串口监视器显示。至于串口监视器,你现在只需要知道它是Arduino板与其他设备相互通信的方式就可以了,如果你感兴趣的话,https://www.jianshu.com/p/a102ebeb1f1f里有详细的关于串口监视器的介绍。
下面是实物连接图:
由于没有直接可观察的输出,所以我们调节电位器并不能知道Arduino内部的工作机制,所以下一步就是通过写代码,利用软件的方式解决我们的疑惑,正所谓软硬兼施嘛!(代码可直接复制使用)
int pin=A0;//定义变量pin,为模拟输入接口
int val=0;//暂存来自电位器的变量数值
void setup() {
//Arduino串口通讯初始化
Serial.begin(9600);//设置波特率为9600
}
void loop() {
//读取引脚A0输入信号
val = analogRead(pin);//读取传感器的模拟值并赋值给val,也就是将A0输入的值转化为0~1023之间的数值
Serial.println(val);//通过串口显示变量val的值
}
下一步就是在我们的编译环境中运行代码,首先确保你的硬件连接已经准确无误的完成(如示例连接图),然后点击上传。
上传成功后,旋转你的电位器,咦?怎么没什么变化?因为我们现在没有接任何输出设备,当然是看不到外在的变化的。不过我们可以通过Arduino IDE的串口监视器查看旋转电位器之后究竟发生了什么。
好了,现在你可以打开你的串口监视器了,也就是右上角的搜索放大镜,打开后旋转电位器你就会发现一串从小到大(或从大到小)的数字飞速从你的眼前流过,从0到1023。如下图:
如果你能看到的话,那么恭喜你已经成功完成串口输出模数转换并掌握了analogRead函数的用法!
(二)使用AanlogWrite函数和电位器实现调光LED
我们已经学会了用电位器调节输出0~5V的电压,下一步就是用LED灯将最终的结果显示出来。
实验材料:
- Arduino Nano开发板
- 配套USB数据线
- 面包板及配套连接线
- 1个LED灯
- 1个470Ω限流电阻
- 1个电位器
搭建电路图:
Arduino板5v和GND分别用跳线连接到面包板的上下两排对应的位置。直插LED灯正极连接限流电阻,电阻另一端连接开发板第10引脚,LED灯负极接开发板GND(也就是蓝色排)。电位器1号脚和3号脚分别连接开发板5V(红排)和GND(蓝排),2号脚连接开发板A0(模拟输入)引脚。
Fritzing绘制连接图:
实物连接图如下:
编写代码:
下一步就是通过代码将程序上传到你的Arduino开发板上,你可以复制下面的代码到IDE中,连接你的开发板,选择好端口,保存并上传。
int potpin = 0; //定义模拟输入接口0
int ledPin = 10;//定义数字输出接口10
int val = 0; //暂存来自电位器的变量数值
void setup() {
pinMode(ledPin, OUTPUT);//定义数字接口10为输出
Serial.begin(9600);//设置波特率为9600,可以省略
//注意:模拟接口自动设置为输入
}
void loop() {
val = analogRead(potpin);//读取传感器的模拟值并赋值给val
Serial.println(val);//显示变量val的值,可以省略
analogWrite(ledPin, val/4); //打开LED并设置亮度(PWM 输出最大255)
}
(注意:为什么这里定义的端口要用potpin?)
因为电位器的英文名是Potentiometer,这里取自它的前几个字母,以便与其他引脚区分开。
实际操作图:
实验现象
通过旋转电位器旋钮,LED灯亮度改变。如果用串口监视的话,就会在监视器显示相应的数值。
函数介绍
-
AnalogWrite
1.说明:将一个模拟数值写进Arduino引脚。这个操作可以用来控制LED的亮度,或者控制电机的转速。Arduino每一次对引脚执行AnalogWrite命令,都会给该引脚一个固定频率的PWM信号。
AnalogWrite()函数支持以下引脚:3,5,6,9,10,11。
在调用AnalogWrite函数前,您无需使用pinMode()函数来设置该引脚。
2.语法:analogWrite(pin,value)
3.参数:
pin:被读取的模拟引脚号码
value:0到255之间的PWM频率值,0对应off,255对应on
4.返回值:无
程序分析
程序中通过analogRead()函数来读取模拟输入值,这个输入值的范围是0到1023之间,然后通过analogWrite()函数来改变LED灯占空比,范围是0到255之间,从而改变亮度。
*占空比
所谓占空比就是调整led通过电流和不通过电流的时间比来控制的,由于人眼有视觉暂留特性,所以只要频率比较高是看不出来闪烁的,当然通过电流比不通过电流的时间比例越大,led做的功就越多,这样也就越亮,需要注意的是led芯片的温升和最大电流值不要超标,不然会影响其寿命。
低占空比意味着输出的能量低,因为在一个周期内大部分时间信号处于关闭状态,如果pwm控制的负载为led,则具体表现例如led灯很暗。
高占空比意味着输出的能量高,在一个周期内,大部分时间信号处于on状态,具体表现为Led比较亮。
当占空比为100%时,表示 fully on,也就是在一个周期内,信号都处于on状态,具体表现为led亮度到达100%。
为0%时则表示 totally off,在一个周期内,一直处于off状态,具体表现为led熄灭。
现在一切都已明了:脉冲宽度调制,这个宽,不是物体的宽度,而是高电平信号在一个调制周期中持续时间长短,它可以用占空比去衡量,占空比越大,脉冲宽度越宽。
(三)使用纯软件编程和电位器实现调光LED(不使用analogwrite函数,引脚更通用)
基本原理
通过调整PWM的占空比,来调节通过LED灯的电流时间长度,改变LED灯的做功大小,从而实现调光LED灯的亮度。
在此代码中,手动设置一个PWM信号,其信号中高低电压的时间长短是根据输入端口的值 val 来改变的。val的值是运用analogRead()函数读取的模拟输入端口的值,范围为0~1023,当我们调节电位器时,val就会发生改变,这时LED灯的亮度就会随val的值变化。
电路连接
电路图与3.2相同,只将输出端口改为13号。由于我们使用的是13号引脚,在arduino开发板上直接连接者一个LED灯,所以我们可以单独使用一个LED灯,也可以直接用开发板上的。具体如图所示:
使用单独的LED灯:
不使用单独的LED灯:
Fritzing绘制连接图:
编写代码
int ledpin = 13; //定义端口13
int potpin=0; //定义端口0
int val=0; //定义变量val,初始值为0
void setup() {
pinMode(ledpin, OUTPUT); //定义端口13为输出
Serial.begin(9600); //设置波特率为9600
}
void loop(){
val=analogRead(potpin); //读取传感器的模拟值并赋值给val
Serial.println(val); //显示变量val的值
digitalWrite(ledpin, HIGH); //设置输出端口输入高电压
delayMicroseconds(val); //延迟val长度的时间
digitalWrite(ledpin, LOW); //设置输出端口为低电压
delayMicroseconds(1000 - val); //延迟1000-val长度的时间
}
所用函数
analogRead () 函数
1.说明:从指定的模拟引脚读取值。
2.语法:�analogRead(pin)
3.参数:
pin:要读取的模拟输入引脚的名称(大多数板上的A0到A5,
Mini和Nano上的A0到A7)。
4.返回值:� 引脚上的模拟读数(int)。
digitalWrite () 函数
1.说明:将数字HIGH或LOW值写入数字引脚。
2.句法:
digitalWrite(pin, value)
3.参数:
pin:引脚号
value:HIGH或LOW
4.返回值:无
delayMicroseconds () 函数
1.说明:暂停程序指定为参数的时间量(以微秒为单位)。
2句法:
delayMicroseconds(us)
3.参数:
us:暂停的微秒数(unsigned int)
4.返回值:无
(四)比较两种方式的区别与联系
(五)实践过程中遇到的问题
1. 找不到哪个是电位器?
由于刚刚接触arduino,所以很多小零件都没见过,就只认识个LED灯和Nano开发板,而且很多部件都标着英文,也看不懂。所以对于这个陌生的名词,只好猜吧,看看凭感觉哪个像,亦或者问问老师。
但是这种方法是行不通的,既耗时又耗力,还不利于个人自主学习与探究。经过反思,后来我们的解决办法是:先到网上搜集有关电位器的信息,从百度百科上看到电位器的图片和基本介绍,对照着信息,我们终于在一堆乱七八糟的零件中找到了它!
2. 不知道纯软件编程的含义是啥?
听起来觉得可能很高大上,让人难懂,但是说得通俗点就是不使用analogwrite函数,而是使用更通用的方式(digitalwrite与delay函数结合),使得引脚更通用更灵活的一种方法。通过手动控制占空比,利用电位器可以使LED灯实现调光。
经过在网上搜集资料并研究,我们终于还是实现了手动调光,并且比较了二者的区别与联系。
3.编译时出现错误
在进行纯软件编程的时候,在代码编译时出现了错误,提示缺少定义输出端口的代码:
我们翻译了一下错误消息,然后找到红色提示的一行,发现缺少定义的变量,往上找代码,原因是在复制代码的时候漏了一行,导致在编译时找不到ledpin这个变量。所以在以后一定要注意仔细检查代码是否完整,学会看各种提示错误,不断积累经验。
4.恍然大悟——手动调光原来还可以这样
在使用纯软件编程的时候,我们只是单纯地将引脚由10号改成13号,然后旋转电位器调光。但是细心的小园同学发现arduino开发板上的另一个红灯亮了,之前是不亮的。所以我们恍然大悟,原来13号引脚就直接连着一个LED灯,我们可以不用再外接一个LED灯了(但是电阻还是要接的)。不过有追求完美可观的同学可以外接一个,更容易观察。
5.还有一个未解之疑:手动调光LED灯为什么不能完全熄灭?
我们在进行纯软件编程的时候,发现无论如何旋转电位器,都不能使LED灯完全熄灭,总是会带有一点红光:
截至目前为止,我们已经使用了很多方法,比如修改代码(delay函数的参数)、检查电路、更换电阻等等。但是由于知识有限,还不能解决这一问题,哪位大佬可以帮忙解答一下啊~
(六)总结与体会
经过本次有关Arduino项目的实践,我们对Arduino开发板、各种元件以及函数的使用又有了更深刻的认识,使得知识不仅仅停留在书面上,更多是表现在外面的技能以及思维的活跃方面。
主要包括:1.Arduino软件安装以及与电脑连通方式;2.程序编译、上传等基本方式;3.面包板的使用方式,Fritzing的使用;4.学会了控制LED的亮灭;5.区分数字端口中的模拟端口并学会使用;6.完成电位器调光LED灯等等。在后续的学习中也在不断积累有关Arduino更深入的知识,不断提高能力。
通过小组的合作学习,使得我们在学习上总会产生思维的碰撞,大家相互争论,相互帮助,共同完成项目。尽管在完成的过程中遇到了各种问题,当时确实是很头疼,但是通过各种途径解决之后,再回过头来看就发现每个人真的成长了很多。
只有想不到的,没有做不到的。创意的思维总是千奇百怪,各有不同,因此也就显得特别珍贵,所以对于每个人的创新思维,都值得我们去保护。未来的人工智能领域是如此,教育亦是如此,创新和实践总是贯穿其中,总让人不由自主的接近和了解它。
现在,让我们积极思维与实践,一起打开Arduino世界的大门!