美文网首页程序员我爱编程
Arduino菜鸟通俗版解读系列(2)数字接口/模拟接口

Arduino菜鸟通俗版解读系列(2)数字接口/模拟接口

作者: 要啥用户名 | 来源:发表于2018-07-15 15:29 被阅读1424次

            这一篇主要延续上一讲中的内容来实际做一个控制LED小灯发光程度的项目,这个项目中主要用到的就是上一篇中讲到的模拟输入和数字输出,还有软件编程和一点点的硬件小知识。

    这一篇的主要内容先罗列一下:

    1)硬件的搭建:LED灯,分压器(变阻器),面包版;

    2)软件的搭建:Arduino的编程环境,项目的程序讲解;

    图1

            首先看硬件的搭建,图1是这个项目的硬件搭建方式。为啥这样接线呢?首先你得了解面包板是怎么回事。见图2,这就是一块面包版,为啥叫面包版?因为它有一个厚度,由于我们图中是俯视所以你看不到它有多厚,然后由于它又带有很多孔,所以看上去就像一块切开的面包。这块面包版被黑色虚线分为上下两部分,上下两部分之间是独立的也是绝缘的。由于上下两部分是镜像关系,所以我们只看上面一半即可,下面这一半和上面一模一样。红色线连接的孔代表着这些孔之间是导通关系,里面是用铜线连接在一起的;而没有用红线连接起来的任意两个孔之间是不导通的,就这么简单。

    图2

            好,回过头继续看图1,我将Arduino上的5V接口和GND(接地)接口分别连接到面包版上1和2所示的孔上,按照前面说的面包版的走线规则1号孔这一整行上所有的孔都和5V连通了,2号孔这一整行上所有孔都接地了,另外这个5V接口是直接从USB或者外部电源那里把电导过来作为一个供电接口用,3.3V接口也是一个道理都是供电接口,当然你也可以自己找电源供电不一定非要用Arduino上的这俩接口,不过前提是你知道怎么选合适的外部电源,因为弄不好你会把板子烧了。一般对一个大型的项目来讲,像电机这种耗电的执行件我们给它独立供电,然后一些IC元件我们就用Arduino自带的5V或者3.3V电源接口来供电,具体细节后面碰到会详细介绍(千万记住在接线或者在搭载元器件的时候,一定要先给Arduino断电,不然容易烧板子)。

            处理完电源和接地接下来就开始往上面放元器件了,一个是变阻器,一个是LED灯。这个变阻器是啥?就是高中学的滑动变阻器,这个我就不解释了。不过这个变阻器的引脚我要稍微介绍下,见图3和图1,3号和5号脚分别是这个电阻的两头,需要分别接5V高电平和接地,反过来也可以,电阻不分正负极的;4号脚是从这个电阻中间引出来的,取出来的是0~5V中间的一个电压值,假如我们把变阻器旋钮转到中间位置,那么分出来的就是2.5V电压。好了这就是变阻器。那么现在我们知道图1中的3号脚应该接到5V上,5号脚接到GND上,4号脚作为分压出来的电压信号当然就要输入Arduino用于后续逻辑判断啰,4号脚接哪儿?上一篇说过模拟接口是读取传感器输入的,所以4号脚可以接A0~A5的任意一个接口,这里我就接A0好了,变阻器接线完成!

    图3 图4

            LED灯是怎么回事呢?就是通上电就会发光的二极管,这够简单了吧!不过有三点要讲:

    1)二极管有正负极之分:二极管不像电阻,二极管分正负极,正极接高电平,负极接低电平才有电流通过才会发光,接反了可不会亮的。那怎么区别发光二极管的正负极呢?看图4,长脚为正极,短脚为负极。

    2)二极管的亮度可控:通过二极管的电流越大,二极管越亮。现在我们想实现控制二极管的亮度,那我们当然就不能简单地把二极管正极接到5V上,这样一来电压不变,电流也就不变了,二极管亮度也就不会变了。咳咳,慢着,有同学说接上5V电压然后通过改变电阻来改变电流,从而让二极管亮度也改变。当然可以啊,不过这样就不关Arduino什么事儿了,这就不是嵌入式的解决方法了嘛。其实这里我们想要实现的是通过改变输入电压来控制二极管亮度,那怎么控制输入电压呢?上一篇我们讲过了,数字输出引脚可以输出“调制的模拟信号”,换句话说就是:数字接口不仅仅可以输出5V或者0V这种单一电压,也可以通过改变“占空比”输出0V到5V之间的电压,不过还记得上一篇说过的吗?只有带“~”的数字接口才拥有输出“调制模拟信号”的功能。所以我们需要把发光二极管的长脚也就是正极接到带有“~”的数字接口上,而带有“~”的数字接口是3,5,6,9,10,11号。按照图1所示,我们就接到6号吧!六六大顺我喜欢。

    3)电阻:5V电压对于二极管来说太高了,容积把二极管击穿,所以要加一个电阻来限流,给多大阻值呢?220欧姆好了,其他阻值也可以,只要保证别太大搞的LED亮不起来就好,具体你可以自己计算。

    好了二极管也接好了硬件电路搭建完毕。接下来讲编程了,这个项目的程序极其简单包学包会,我也尽可能多讲一些我认为在编程中会让人困惑的问题,这些问题都曾经困扰过我,搞懂它们或许对你也有帮助。

    现在来看软件部分,见图5。对于软件我打算讲两部分:

    1)对于Arduino编程环境的介绍;

    2)对这个项目的程序逐条解释。

    图5

    首先是对于Arduino编程操作环境的介绍。图5中给出了几个常用的按钮:

    1)编译:一般需要手动编译的语言常见的就是C语言,而很多高级语言直接运行即可例如Python,VBA。而Arduino的IDE保留了手动编译按钮。编译的作用是什么呢?我们都知道计算机只认识0和1,它内部的所有运行过程都是0和1构成的,我们叫这种0和1构成的代码为计算机语言,直观地讲就是我们在电影《黑客帝国》里看到的一堆0和1,普通人类是看不懂的;那么好,为了能够让普通人类比较方便地和计算机沟通对话,人们创造了程序语言比如C语言,这种语言的出现是为了让人类能够比较容易理解和使用,所以用的都是符合人类逻辑的一些符号,比如用英文符号if,else等等。好的,说到这里我们有了两个概念:机器语言,程序语言。那么所谓编译就是计算机自动地把程序语言翻译成机器语言的过程。打一个比方,我写了一篇中文的行动报告给一个美国人,这个美国人先把中文翻译成英文,然后他才开始按照行动报告来行动(别问我这个美国人看得懂中文为啥还要翻译成英文再行动)。这里的中文行动报告对我来说就相当于C语言写的程序,这个翻译后的英文版行动报告就相当于机器语言,这个美国人就相当于计算机,然后他把中文翻译成英文的过程就叫“编译”。所以,在计算机运行程序之前都会编译一下,一来是必须先转换成机器语言才能运行,二来也是检查你写的程序有没有语法问题,假如有语法问题,那么编译就会报错,这时候你就要去查看程序是不是写错了什么。

    2)上传:这个按钮按下去,程序就通过USB线传入了Arduino。这里需要说一点的是,这个上传按钮按下去以后,电脑会自动编译,如果有语法错误,就会上传失败,然后提示你哪儿有问题需要修改。所以,在上传前你可以不需要按“编译”键,但是我建议你编译一下看看程序语法是否有错误。

    3)新建:就是重新打开一个编程窗口。

    4)打开,保存:不用说了吧。

    5)串口通信监控窗口:按下这个按钮,就会跳出一个新的窗口,这个窗口上面会显示Arduino通过串口传回计算机的信息,这个后面讲到串口通信会详细介绍。这个窗口非常有用,因为Arduino不像计算机有个显示器,Arduino的Debug全靠将计算结果传到这个窗口来进行。debug就是调试的意思。

    6)错误提示框:就是当编译出现错误时,提示编译错误的框。

    编程环境介绍完了,接下来讲解程序语句。

    int val;------这句话定义了一个整型变量,变量名叫val。在Arduino的IDE中编程,和C语言一样,所有变量都要先定义类型,然后才能使用!高级语言例如Python,VBA则不需要事先定义,可以直接使用。什么叫整型变量?你就理解为整数就可以了,也就是说val这个未知数在接下去的赋值过程中只能赋给它整数。比如它可以是1,100,56......但是不能是1.2,3.14......也不能够是“Hi”,“a"。另外,每一句语句写完必须用“;”结尾,表示这句话结束了,不然Arduino可不知道你说完没有。计算机就是这么傻,你必须把它当成一个弱智来交流,你必须把每一步细节都交代清楚,否则程序就会出错。

    void setup() {...}------这是一个函数,void表示这个函数没有返回值,或者说返回值为空(NULL)。好的,这里可能会比较难解释一些。什么是函数?这可不是数学里的那个函数,程序中的函数的意思你可以简单理解为“具有特定功能的一堆语句,并且它们被用一个名字来代表”这个名字就叫函数名,此处函数名叫setup;然后函数运行完毕后可以返回一个值,也可以不返回值。嗯~我觉得可能有些同学还是没太明白,让我举个例子:比如我经常去酒吧喝酒,然后每次去我都会习惯性地要一杯99年干红,然后点上一份7分熟的菲力牛排。然后我发现一个问题,就是每次去那个酒吧服务员都要问我喝点什么,然后我回答干红,然后服务员又问我:“几几年的?”我说:“99年的”,服务员又问:“吃点什么?”我说:“牛排”,服务员又问:“什么类型的?”我说:“菲力”服务员还要问:“几分熟?”我实在懒得回答,但是还是得说:“老样子,7分熟”;每次我都被烦的想打人,但是聪明的我想出一个办法,我和服务员约定如果下次来酒吧我还是打算消费这些东西的话,我就说“套餐1”来代替。所以以后每次去酒吧,我会潇洒地吼一声“套餐1”,于是服务员就麻溜地开始准备99年干红和7分熟的菲力牛排。在这个例子中,我通过把这个准备过程取名为“套餐1”来简化了服务员和我的沟通,相当于我把这一整套的食物准备过程和沟通过程打包成了一个函数,”套餐1“就是函数名,我在写程序的时候只需要写”套餐1“而不需要每次都把具体实施过程再写一遍了,这就是函数的作用。不过在这个例子中的setup函数是一个自带的默认函数,你不用去修改它,也不用问为啥这里会出现它。这个函数的作用你可以理解为就是一个空间,你写的代码都要在这个函数的{...}里面,下面我们还会遇到一个和setup类似的函数,叫loop。它俩的区别在于setup函数范围内的代码只运行一次,loop函数范围内的代码会自动循环,一遍遍地运行下去。

    pinMode(6,OUTPUT);------定义6号数字引脚为输出引脚。通常在setup函数里,我们会定义引脚状态和其他一些初始设置,因为这些内容只需要确定一次就可以了,不需要一遍遍地重复,所以不需要放在loop函数下,那你非要说全放在loop函数下,setup里面啥也不放那也可以运行,但是效率低了。回过头来继续说,每一个在前面硬件部分用到的数字引脚都需要在这里定义,定义的目的就是让Arduino知道你是想让这个引脚接受信号还是输出信号。在这个例子中,6号引脚被用来给发光二极管供电,所以就是输出OUTPUT,记得要大写。另外提一句,只写6就代表了是数字引脚6,如果是模拟引脚你可以写成A0这种形式。好的,说到这有同学会问:“你说要定义所有用到过的引脚,但是我只看你定义了数字引脚6,那模拟引脚A0我们也用了,你怎么没定义?”是这样,模拟引脚默认状态都是输入,即读取状态,所以不需要定义,但是如果你写了pinMode(A0,INPUT)也没啥问题。

    void Loop(){...} ------奇怪了,怎么又冒出来一个函数。呵呵,这就是Arduino的独特之处,Arduino有两个主体函数,区别在于Setup函数里的语句只会运行一次,而loop内的语句会自动无限循环下去。其实这个也好理解,因为Arduino作为一块单片机,它需要不停地去查看引脚状态,确认是否有信号进来,然后做出反应,所以Arduino需要这样一个自动循环的函数,于是你也就会领悟到,我们所有涉及引脚的重复操作都要放到loop函数里才可以(定义操作不算,因为定义只需要定义一次就可以了,比如上面的pinMode()指令)。

    val=analogRead(A0);------这句话是让Arduino读取A0接口的模拟信号,然后赋值给val变量。analogRead按照英文字面理解就是“模拟读入”。还有一个命令叫digitalRead(),是用来读入数字信号的,当然你不能在A0口上用digitalRead()命令,因为模拟口读取模拟量,数字口读取数字量另外,数字口的输出功能多一些,数字口既可以输出数字量(digitalWrite)也可以输出“调制的模拟量”(analogWrite)。继续往下讲,还记得上一篇说的模数转换吗?在这里analogRead(A0)读入的就是模数转换后的数字,例如我对A0输入5V,那么赋值给val的就是1023这个数,假如我给A0输入2.5V,那么val将会被赋值为512,具体给A0输入多少V的电平这就取决于我们刚才说的分压器了,当你转动分压器的时候,分压器的4号引脚(见图1)就会将变化的电平信号输入A0引脚,然后通过A0内部的模数转换器将这个电平转换成对应的数字,最后这个数字会由val=analogRead(A0)这个语句赋值给val,这就是模拟信号从外界传入Arduino内部的整个过程。

    val=map(val,0,1023,0,255);------这句语句应该是整个项目中最关键的一句了。先说一下这句语句的含义吧,map就是"映射"的意思,对谁映射呢?就是对括号里面的第一个参数val进行映射;怎么个映射法呢?就是把第2个参数对应为第4个参数,把第3个参数对应为第5个参数。换句话说就是在这条语句中,val的初始值范围是0到1023之间,然后我们把val的这个初始范围转换为0到255之间,所以初始值中的0变成了后来值中的0,初始值中的1023变成了后来值中的255,以此类推初始值中的512就应该变为后来值中的127,最后再把映射后的val 值重新赋值给val自身。有的同学会问:“为什么刚好是把0~1023转换成0~ 255呢?”这又回到上一讲中的内容了,所以说我的连载说的全是重点,并且一定会立刻用到,大家一定要注意哦:)上一讲中我们说过模拟接口用的是10位二进制空间来进行模数转换,它的范围就是0~1023;数字接口的“调制模拟信号”用的是8位二进制空间进行模拟,它的范围是0~255,所以在这个LED灯发光的项目中,我们从A0中获取的变阻器分压信号会被模数转换成0~1023之间的某一个数字,然后我们需要把这个数字作为指令来控制数字接口6的输出电压,但是数字接口6的输出电压在控制的时候代表数字最大不能超过255,所以我们要实施映射转变,否则假如A0口获得一个数字是500,然后你直接把500发送给6号口,那就溢出了,这样6号口就不能够输出正确的电压来点亮LED灯。

    analogWrite(6,val);------最后这一句语句,意味着把val值输出到6号数字接口上,根据我们上一篇讲的,6号口会根据val的值来定义对应的“占空比”,然后特定的“占空比”会产生0~5V之间的某一个电压值,最后这个电压值就会驱动LED灯亮。那么随着我们改变变阻器的阻值,A0口接收到的值也会随着改变,进而map获得的val值也会随着改变,于是6号口的输出电压也会变,这样LED灯的亮度就改变了,这就是整个项目的工作原理。 

            这一讲全部讲完了,用USB线连接Arduino和电脑,然后点击上传按钮录入程序,你的LED灯就可以按照你的意愿变换亮度了!其实舵机,直流电机在Arduino上的驱动也是一个道理,只不过把LED灯换成了电机。所以理论上现在你可以自己做一个电动飞机了,只不过你还需要学习无线串口通信才能实现遥控。

            下一讲我们讲一讲库的概念,这个东西对于Arduino来说很重要,因为Arduino之所以容易上手就是因为里面有很多“库”。

    讲完库后,就讲一讲串口通信。

    相关文章

      网友评论

        本文标题:Arduino菜鸟通俗版解读系列(2)数字接口/模拟接口

        本文链接:https://www.haomeiwen.com/subject/exqkpftx.html