友情提示:380元/半年,儿童学编程,就上码丁实验室。
通过上两次的介绍,大家应该对Arduino有了一个大致的概念。Arduino无非就是读入一个模拟信号,然后按照你编制的程序给出一个对应的输出信号,这个输出信号又去驱动一个执行件。那么好,这一篇我们暂时放开Arduino面板本身,来介绍一个叫做“库”的东西。为什么要说这个“库”呢?正是因为Arduino拥有很多“库”,所以它才会这么容易上手。
为了说清楚什么是“库”,这一篇我打算回答两个问题:
1)“库”是用来做什么的?
2)Arduino中有什么库?(举例)
先讲第一个问题,“库”是用来做什么的?
“库”这个概念其实广泛存在于各种编程语言中,有的编程语言本身就是一个大“库”。任何问题都讲究一个来龙去脉,先说为什么会出现这种概念,它是基于什么原因和背景而出现的。那么好,先讲讲为什么会有“库”这种概念出现。大家上学的时候应该基本都接触过C语言,C语言很多人说它很难,但是有的人说JAVA这种语言很难,其实我觉得这个难不难要看你处于什么阶段,C语言是上手容易精通难,JAVA是上手难精通容易。为啥?因为C语言内容相对少,基本上就是给你介绍数据结构,然后教你一个指针,剩下的你就自己运用这些简单工具去拼凑代码即可;而JAVA相反,JAVA一上来给你很多命令,一种命令对应解决一个特定问题,世界上问题千千万万,所以JAVA命令也千千万万。这样一来就会发现看书的时候C一下子看完了,但是轮到写代码的时候一头雾水,JAVA看了半天一半还没看完,不过好像用起来挺方便,遇到啥问题直接查有没有对应解决问题的命令即可。这就像C给了你一把锤子和一个锯子让你去盖楼,学着容易真正要盖楼那太难;JAVA是给你一整套工程机械,学起来巨痛苦,但是学会了以后各种效率高,摩天大厦也不在话下。
OK,讲到这里有同学可能说:“这些尼玛和库有半毛钱关系?”,别急马上说到了。既然C这么难用,那我们不用C了呗,用好用的编程语言,比如Python,号称一周上手。但是我们看问题要从历史角度看,C是低级语言,又是最早发明的语言之一(我不知道是不是最早的那一个,但肯定属于最早的之一)那个年代人们没啥选择只能用低级语言,低级语言都一个样“难用”,于是有人就想:“我可不可以采用类似”函数“的方式,在C语言的基础上创造一些新的命令,然后人们只需要直接调用这些命令而不需要自己从头去搭建算法?”(相信看过上一篇文章的同学会很容易理解什么叫“函数”),当然可以啊,于是这帮人创造了一大批的“函数”这些函数能够直接解决某一领悟基本上所有问题,然后这帮人把这些“函数”打了个包,我们叫这一大包的函数为“库”。所以“库”就是一堆函数的集合。概念就这么简单,不过按照惯例我还是要举个例子,以便更加通俗地解释一下。其实光看“库”这个名字就很形象,库就是工具库,例如我有一整套的厨具,然后这套厨具的分类非常细,里面的工具可以针对不同的刀工和食物,就拿做鱼来讲,可能去鳞会有专门的去鳞刨子,然后去内脏有专门的钩子,去骨又有专门的小弯刀,拔刺还会有专门的镊子,最后切鱼肉还有专门的刺身刀。这些工具组成了一个专门的库,叫“杀鱼库”;库里面全是有针对性的工具(函数),这些工具又是怎么做出来的呢?其实还是靠原始工具(相当于C语言)敲敲打打做出来的嘛。那么作为我们普通人,直接买一套“杀鱼库”就可以很方便的杀鱼了,杀起来搞不好比古代的专业厨师也不逊色,这就是“库”的意义。像Matlab,就可以看成一个巨大无比的库,Matlab本身就是一个美国教授为了让他的研究生更加快捷地进行数学计算,从而在C的基础上二次开发出来的一套函数命令集。例如,为了给一串数字1,2,3,4,5从小到大排序,C语言要写一堆代码来实现,然而Matlab可能就一个命令就完成了sort(1,2,3,4),回车(意思下,语法可能不是这样写的),而在这个命令sort的背后则是打包好的一堆C语言指令,对你来说就是黑匣子,不必知道其运行原理,你只管用就可以了。所以库里面有很多很多的函数可以用。
好了,讲完了“库”出现的背景和其意义,接下来说一下Arduino里面有什么“库”。
举个例子来说,舵机控制在Arduino中就是通过一个“库”来完成的,如图1和图2。先看图1,大家注意看第一行命令:#include<Servo.h>;这句话的意思就是调用伺服电机库,所谓伺服电机就是舵机。因为伺服电机的运动方式是按照角度运动的,所以人们通常用它来当“舵”来控制飞机或船的方向,所以也叫“舵机”。当然,有的同学可能懂舵机的控制原理,其实舵机就是按照第一篇中讲的PWM控制方式来控制,按照不同的“占空比”来控制舵机旋转角度。所以如果你懂这个底层原理,你也可以不调用伺服电机库,完全通过自己写代码来控制“占空比”进而实现舵机旋转。但是你会发现如果使用“伺服电机库”,你会非常容易控制舵机,你要做的就是给出一个旋转角度,然后传给Arduino即可。当然图1中的代码我还添加了串口通信,能够通过电脑实时控制舵机转角,所以代码会复杂一些。


以伺服电机为例子,图1和图2中我只讲打了红框的几条语句,它们都属于伺服电机库中的语句,其余的语句有的属于串口通信,有的只是一些循环和赋值代码,纯粹是编程的一些逻辑问题就暂时先不讲了,后面有机会专开一篇来讲编程的逻辑。
1)#include<Servo.h>;——这句话前面讲了,意思就是调用“伺服电机库”;你只有调用了这个库,然后才能使用这个库里面的命令。
2)Servo servo1;——这句话可能会比较难解释一点。先说下含义,这句话是定义一个“类”,这个“类”的名字叫servo1。那么什么是“类”呢?类的概念其实和函数很相似,所以在很多书上讲解的非常让人费解,他们会说”类“是面向对象的一种方法,“函数”是面向过程的一种方法。我这里尝试着用自己的理解来说明。先说一下简单定义:““类“就是一堆拥有特殊用途的“函数”,这些函数只能用在某一种特定的问题上。” 有点抽象对吧,下面来举例说明。”类“就是种类的意思,比如“猫”我们说是一个种类,但是具体到描述猫的行为的时候,电脑需要你先指明是什么猫,比如我家的猫,小张家的猫等等,在指明了是哪儿来的猫以后才能够开始对猫进行操作。所以这里我们需要先把Servo这个类对象化,也就是指明现在有一个Servo类,它的名字叫servo1,然后才能够对它进行操作,当然你也可以随便取名,a,b,c,bike,plane都可以只要你自己过几天还知道啥意思就可以。在图1和图2 中,这就相当于你给你要控制的舵机取了一个名字,叫servo1。servo1 就是你要控制的舵机。不需要纠结为啥非要取个名字,反正你得取一个就是了。
3)servo1.attach(5);servo1.write(angle);——这两句话我打算一起说,因为都是一个话题。上面我们说到给伺服电机取名字,好,现在取完名字了,接下去就可以开始对伺服电机进行操作了。servo1.attach(5)就是说把5号数字接口作为舵机的控制口;servo1.write(angle);意思就是往5号口里面写入angle这个角度值。这样舵机就会旋转一个等于angle的角度,当然在这代码背后,这个角度会被转化成相应的占空比然后才能操控舵机,不过这都是库帮你完成的,你不用管了,所以很方便。好,其实功能已经讲完了,舵机也可以运转了,不过结合这两条语句,我想再进一步讲解下“类”这个概念。类这个概念确实和函数很相似,以至于我觉得完全可以只有函数而不需要类,但是为什么还是出现了“函数”和“类”这两种概念呢?我猜可能基于以下这种发展过程:
很久很久以前有一个智者,基于上一篇我讲过的酒吧点菜场景的缘由,他为了方便别人编程打算写一大堆函数。这些函数中有一些是简单的函数,可以实现自动排序功能,比如无论你给出1,2,3,4,5还是6,8,7,9,2,排序函数都可以完美地帮你排序,因为背后的算法是一样的,也就是说用一套统一的算法就可以完成所有场景下的排序问题。好,随着智者工作的深入,他开始写一些高级的函数了,其中有个函数叫climbTree函数,也就是爬树函数,这个函数可以让一只机器猫实现爬树的动作,而且用起来很方便,你只需要直接调用climbTree即可,背后怎么个爬法这位智者都写好了。然而第二天他发现一个问题,因为今天他想写另一个爬树函数,但是是控制机器昆虫的,由于机器昆虫的爬树机理和机器猫的机理不一样,所以他不能够用昨天那条climbTree命令,这个很好理解吧,机器猫爬树可能是通过四肢抱紧树干然后爬上去,机器昆虫可能根本就没有四条腿,它们可能只有两条触角,然后通过锋利的触角插入树干从而获得爬升力的。所以他必须重新写一个爬树函数,这个爬树函数是根据机器昆虫的爬树方式写的,写完后他想取个名字,为了区别他取名为Bug.climbTree, 也就是说这个爬树函数是给虫子用的,那么好昨天那个爬树程序他也干脆重新取了一个名字,叫cat.climbTree,用来和虫子的爬树函数进行区分。随着这位智者写的函数越来越多,他发现不同对象的同一种行为往往会有不同的机理,所以他不能够采用相同的函数一揽子全概括进去,也就是说虽然都叫爬树,但是虫子和猫的方式和机理是不同的,然后壁虎也会爬树并且壁虎的爬树机理又自成一体,也就是说它们的爬树方法背后的算法都是不同的,为了区别这些不同对象的爬树动作,于是这位智者发明了“类”这个概念,也就是说你先要讲清楚让谁爬树,然后我才能根据你的对象给你推荐算法。这就是我理解的“类”出现的原因。当然,按照这种解释,类其实可以完全用“一般函数”代替掉的,因为既然猫和虫子的爬树机理不同,那我也懒得去区分猫和虫子了,对于猫爬树我直接叫“攀登”;对于虫子爬树我叫“爬树”就好了,所以以后你想控制机器猫爬树,你就用“攀登”函数,你想让虫子爬树“你就用”爬树“函数。” 当然可以了,只不过世界上物种千千万,采用“类”这种方法还是最简洁最清晰的。
讲了这么多,既有“库”也有“类”,你可以简单理解为“类”是一种特殊的函数,它和普通函数不同,它需要先对象化才能够使用(事实上“类”不仅仅有“类的函数”,“类”还有“属性”一说,不过对于Arduino编程来说你可以不用了解那么多),然后不管是特殊的函数“类”还是普通的函数,它们可以被打包成一个“库”。所以,在Arduino开发过程中,你要控制的所有传感器和集成芯片都可以有一个对应的库来帮你简化控制程序的编写,让你的编程更加贴近直观感受,所以Arduino才这么容易上手。最后说一句,这么多的库是哪儿来的呢?网上各种爱好者和大牛编写的,他们写好一个库,然后你可以下载下来,放到Arduino的目录中使用。这就是所谓的开源,Arduino是开源系统,谁都可以给它写“库”,这些库你可以直接上Arduino官网上下载或者上gitHub上下载。也正是这样,同样是控制舵机,你也会找到很多种不同的”库”,你可以选一个最容易使用的来用。