最近在学校里开设了一门Arduino课程,因为是高一学生,所以几乎没有什么基础,不说编程,甚至基本的电路知识也没有。所以基本整个学期就是让他们接 触一下Arduino,玩一下Arduino控制Led灯。为了方便学生学习,我打算将课程里的东西写成博客,其实这也算最基础的Arduino教程了 吧......
首先如何安装Arduino驱动,如何打开软件等等都不谈了。先来说写入的第一段程序。
这段程序来自与Arduino软件例子里的Blink程序
————————————————————————————————————————————
// Pin 13 has an LED connected on most Arduino boards.
// give it a name:
int led = 13;
// the setup routine runs once when you press reset:
void setup() {
// initialize the digital pin as an output.
pinMode(led, OUTPUT);
}
// the loop routine runs over and over again forever:
void loop() {
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
}
————————————————————————————————————————
首先程序中的“//”后面跟的是注释语言,并不会运行。“”中间的也是注释语言,不会运行。所以上面程序其实真正运行的只有如下:
————————————————————————————————————————————
int led = 13;
=====================
void setup() {
pinMode(led, OUTPUT);
}
========================
void loop() {
digitalWrite(led, HIGH);
delay(1000);
digitalWrite(led, LOW);
delay(1000);
}
————————————————————————————————————
首先上面程序其实可以分成三部分(已经用========隔开)
第一部分是变量定义部分,其实就是命名一些量,比如说
int led = 13;
意思就是命名一个量,这个量的名字叫“led”,它是一个“int”类型的量,“int”类型就是说明这是一个数字,并且是整数。然后这个名叫“led”的量它等于13。
第二部分是初始化部分,“void setup() { ...........}”,大括号中间的是需要初始化的语句。
pinMode(led, OUTPUT);
pinMode是Arduino的内置函数,就是说Arduino它认得pinMode。这句程序的意思就是让led这个量所指的接口,其实这里就是13号数字输出口,把这个端口设为OUTPUT,就是输出端口。
第三部分才是最重要的主要程序部分void loop() {.........},大括号中间的就是我们所要让Arduino运行的程序,loop的意思就是大括号中的程序不停的重复执行,从头执行到尾,然后再回到头再执行一遍。
下面来看看上面程序执行的是什么。
digitalWrite(led, HIGH);
这句话光看字面意思就已经很明白了,就是“数字写入”,让led(其实就是代表13号数字端口)为“HIGH”,HIGH就是会使这个端口的电平达到5V左右。如果我们让一个LED的一极接在13号端口,另一极接在GND(接地端),那么当led为HIGH时,这个led灯就会发光了。
delay(1000);
这句简单,就是休息1000毫秒(等待1秒)。
再后面相信已经不用我解释了,这样最后程序写入Arduino后,执行的结果就是一端接13号端口,一端接gnd的led灯会亮一秒然后再灭一秒然后再.......周而复始。
看到这里,相信你已经可以用程序来控制一盏led灯的发光了,而且可以自己设定让它如何发光,试试看吧.....
----------------------
上次讲了一下Arduino自带例程序里的blink程序学习了下面几个程序语句:
pinMode(led, OUTPUT);
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT);
buttonState = digitalRead(buttonPin);
if (buttonState == HIGH) {
digitalWrite(ledPin, HIGH);
}
else {
digitalWrite(ledPin, LOW);
}
buttonState = digitalRead(buttonPin);
if (buttonState == HIGH) {
digitalWrite(ledPin, HIGH);
}
else {
digitalWrite(ledPin, LOW);
}
pinMode(ledPin, OUTPUT); //将ledPin端口定义为输出
pinMode(buttonPin, INPUT); //将buttonPin端口定义为输入
buttonState = digitalRead(buttonPin); //buttonState变量值等于buttonPin端的输入
if (buttonState == HIGH) { //如果buttonState等于HIGH,即2端口接5V
digitalWrite(ledPin, HIGH); //使ledPin端口为5V
}
else { // 否则
digitalWrite(ledPin, LOW); //使ledPin端口为接地。
} }
pinMode(ledPin1, OUTPUT); //将ledPin1端口定义为输出
pinMode(ledPin2, OUTPUT); //将ledPin2端口定义为输出
pinMode(buttonPin, INPUT); //将buttonPin端口定义为输入
buttonState = digitalRead(buttonPin); //buttonState变量值等于buttonPin端的输入
if (buttonState == HIGH) { //如果buttonState等于HIGH,即2端口接5V
digitalWrite(ledPin1, HIGH); //使ledPin1端口为5V
}
else { // 否则
digitalWrite(ledPin2, HIGH); //使ledPin2端口为5V
digitalWrite(ledPin1, LOW); //使ledPin1端口为接地。
} }
pinMode(ledPin, OUTPUT); //将ledPin端口定义为输出
pinMode(buttonPin, INPUT); //将buttonPin端口定义为输入
buttonState = digitalRead(buttonPin); //buttonState变量值等于buttonPin端的输入
if (buttonState == HIGH) { //如果buttonState等于HIGH,即2端口接5V
digitalWrite(ledPin, HIGH); //使ledPin端口为5V,第一次亮
delay(500); //亮500毫秒
digitalWrite(ledPin, HIGH); //使ledPin端口为5V,第二次亮
delay(500); //亮500毫秒
digitalWrite(ledPin, HIGH); //使ledPin端口为5V,第三次亮
delay(500); //亮500毫秒
}
else { // 否则
digitalWrite(ledPin, LOW); //使ledPin端口为接地。
} }
pinMode(13, OUTPUT); //将13端口定义为输出
pinMode(2, INPUT); //将2端口定义为输入
buttonState = digitalRead(2); //buttonState变量值等于buttonPin端的输入
if (buttonState == HIGH) { //如果buttonState等于HIGH,即2端口接5V
digitalWrite(13, HIGH); //使ledPin端口为5V
}
else { // 否则
digitalWrite(13, LOW); //使ledPin端口为接地。
} }
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT);
bts = digitalRead(buttonPin); //让bts等于此刻开关的状态
//假如开关此刻的状态不等于过去的状态,并且此刻开关为闭合时,执行下面语句
if (bts !=btsb&&bts==1) { //&&为并且的意思,就是bts!=btsb和bts=1两个同时满足
if(leds==0) //假如灯的状态为灭,用leds的值来记录灯的亮和灭
{digitalWrite(ledPin, HIGH); //将灯变亮
leds=1; } //让记录灯状态的leds=1,即灯已经亮了
else //否则,如果灯的状态为亮
{ digitalWrite(ledPin, LOW); //将灯变灭
leds=0; } //让记录灯的状态的leds=0,即灯已经灭了
btsb=bts; //最后让btsb灯过去的状态值等于现在的状态值,即现
if (bts !=btsb&&bts==0) {
btsb=bts; //只执行灯过去状态记录量btsb的改变。
} }
int led = 13;
digitalWrite(led, HIGH);
delay(1000);
只有输出,没有输入,今天我们来学习一下输入。
最简单的输入当然是开关信号的输入了,自带程序中同样有一个例子,第二项里的第2个button程序:
——————————————————————————————
const int buttonPin = 2;
const int ledPin = 13;
int buttonState = 0;
void setup() {
}
void loop(){
}
————————————————————————————————————————————————
以上已经去掉了注释语句。
来看一下新出现的几句程序:
pinMode(buttonPin, INPUT);
这句相信不用解释了,就是buttonPin这个端口(也就是2号端口)为输入端口
这句意思也简单,就是读取buttonPin这个端口的电平,然后将结果赋值于buttonState(注意在程序中大小写也是要严格区分的),如果buttonPin这个端口电平为高,则buttonState这个值为“HIGH”(或者说等于1),否则为“LOW”(或者说等于0)。
if......else....语句为判断语句,意思就是假如......否则......
翻译一下上述语句就是
假如(buttonState等于"HIGH")
就使ledPin端口位于高电平
否则
就是ledPin端口位于低电平
看到这里,就就能读懂这段程序的结果,那就是当你按下按钮时,灯亮,断开按钮,灯灭,就这么简单......
下面在来说说这个接线问题
当开关断开是,2号端口与GND之间用一个电阻连接,这样2号端口实际上是低电平,开关闭合时2号端口接到了5V,位于高电平。
------------------------------------------------------------------------------
第三节 尝试自己编程控制灯
一、编程是不需要每个字都自己编写,可以通过改变现有程序。例如这次我们来改写例程中的Button程序来完成下面的任务。改写之前可以先将程序中原有的注释语句删除。
const int buttonPin = 2; //将2号端口命名为buttonPi ,“const”说明这个量为之后不变
const int ledPin = 13; //将13号端口命名为ledPin
int buttonState = 0; //命名一个变量,它的初始值为0,这个量之后可以改变
void setup() {
}
void loop(){
二、 任务1,用一个开关来控制2个Led灯,当开关弹起时,灯1亮,当开关按下时,灯2亮。
思考:
1、需要利用几个端口,有哪些是输出,哪些是输入?
2、这段程序中的判断语句,if……else……语句该如何写?
3、思考线路该如何连
4、编写完后写入Arduino,观察运行结果。
三、 任务2,用一个开关来控制一个Led灯,当开关按下时灯会闪烁三次后熄灭。
思考:
1、需要利用几个端口,有哪些是输出,哪些是输入?
2、判断语句中,如果开关按下,接下去灯的闪烁改如何编写。
3、编写完后写入Arduino,观察运行结果。
四、 任务答案:
1、任务一答案:
const int buttonPin = 2; //将2号端口命名为buttonPi ,“const”说明这个量为之后不变
const int ledPin1 = 12; //将12号端口命名为ledPin1
const int ledPin2 = 13; //将13号端口命名为ledPin2
int buttonState = 0; //命名一个变量,它的初始值为0,这个量之后可以改变
void setup() {
}
void loop(){
digitalWrite(ledPin2, LOW); //使ledPin2端口为接地。
2、任务二答案
const int buttonPin = 2; //将2号端口命名为buttonPi ,“const”说明这个量为之后不变
const int ledPin = 13; //将13号端口命名为ledPin
int buttonState = 0; //命名一个变量,它的初始值为0,这个量之后可以改变
void setup() {
}
void loop(){
digitalWrite(ledPin, LOW); //使ledPin端口为接地。
delay(500); //灭500毫秒
digitalWrite(ledPin, LOW); //使ledPin端口为接地。
delay(500); //灭500毫秒
digitalWrite(ledPin, LOW); //使ledPin端口为接地。
delay(500); //灭500毫秒
-------------------------------------------------------------------------------------------------------
第四节 像Arduino一样思考
一、 像程序一样思考
有一个轻触开关,一个led灯,如果要实现按下开关led灯亮,松开开关led灯灭,该如何实现?
思考:
1、输入和输出器材分别是什么,如何将这些器材的动作变成电的信号?
2、逐步思考整个过程,包括任何细节部分。
3、 该命名几个量来记录这些信号?
4、 该如何编写程序来实现这些功能?
解答:
输入器材为轻触式开关,此种开关有两端,当按下时两端连接,松开时两端断开。也就是开关能给出两种信号,一种是断开,一种是闭合。那么如何将断开与闭合两种状态变成相应的电信号呢?如图:
让2号端口来接受这个信号,当开关闭合时,2号端口直接与5V相连,然后又通过电阻与地相连,这是2号端口上的电压为5V。当开关断开是,2号端口只通过电阻与地相连,这时其上电压为0V。通过这个电路就可以将开关的开与关信号转变成2号端口上的0V与5V的电压信号。(如果2号端口什么都没接,则其上的电压为不确定)
这样我们就把现实生活中开关的状态转变成了电信号。那么如何让电信号去转变为led灯的亮与灭呢?其实原理也是类似的,将led的正极(长的一端),接到13号端口,负极接到GND端,当13号端口上电压为5V时,led灯就会发光,否则就灭。这样就完成了电信号转变为灯光亮与灭的过程。
上几节我们已经了解了Arduino程序的执行过程,那就是loop(){……}内的语句不停的循环执行,如果没有delay()语句的话,每执行一遍大概在几十微秒。所以接下去我们的思考就变成了:
每遍程序执行时,当2号端口电压为5V时,就使13号端口电压为5V,2号端口电压为0V时,就使13号端口电压也为0V。那么接下去就可以进行程序的编写了。
该命名几个量呢?其实只需要一个量来记录2号端口的值就够了。所以语句可以设计成:
int buttonState = 0; //命名一个变量,它的初始值为0,这个量之后可以改变
void setup() {
}
void loop(){
观察上述语句与上节课所使用的语句的差别?
有时候为了使程序更加简介,修改更加方便,往往将程序中多次出现的值定义一个量来表示,例如:
const int ledPin = 13; //命名一个量ledPin,其值为13.
这样接下去的程序中,就可以用ledPin来代替13了,这有什么好处呢?如果你想修改程序,让12号端口来当作输出端口,如果按照未定义前,你的找到程序中所有13的地方,都修改成12,但是如果你定义了ledPin,那么只需要将“const int ledPin = 13;”改成“const int ledPin = 12;”就可以了,而不用改动程序中的其他语句。
二、 任务:
一个轻触开关,一个led灯,如果要实现第一次按下开关led灯亮,松开开关led灯不灭;第二次按下开关led灯灭,松开继续灭;第三次按下开关led灯亮,松开继续亮……该如何实现?
思考:
1、输入量和输出量有几个?
2、逐步逐步思考具体的实现过程。
3、需要定义几个量?
4、具体程序如何?
解答:
输入量和输出量与上个任务相同,下面来逐步思考整个过程:
开始时灯是灭的,开关没有按下;然后按下开关,开关的状态从开到关,灯从灭到亮;然后断开开关,开关状态从关到开,灯的状态不变,继续亮;接下去再按下开关,开关状态冲从开到关,灯从亮到灭;最后松开开关,开关状态从关到开,灯的状态不变……
每次灯的状态改变发生在开关按下,即从开到关改变瞬间。那么怎么样解释“改变”呢?改变的意思是事物产生显著的差别。用程序的思考改变就是现在的状态与过去的状态不同,也就是说必须要有一个量来记录过去的状态,还有一个量来记录现在的状态,注意,这里所谓的过去和现在都是针对某一遍程序执行来说的。当记录现在的量和记录过去的量不同时,即是发生改变的时刻。
当然,开关状态的改变瞬间找到后,还需要关注灯的状态,因为每次开关改变的瞬间都要改变灯的状态,如果亮就要变灭,如果灭就要变量,这样就必须还得定义一个量来记录灯的状态。
下面我们将上述过程像程序一样来进行思考:
先命名一个变量bts来记录开关现在的状态,当开关闭合时,bts=1;当开关断开是,bts=0;然后再命名一个变量btsb来记录开关过去的状态。然后再命名一个变量leds来记录灯的状态,如果leds=1就是灯亮,否则就是灭。
然后开始思考loop()程序每次循环需要执行的语句。
首先btsb、bts、leds都等于0。然后当开关闭合一瞬间,bts就会等于1,这时bts就不等于了btsb,那么用if()语句来找到这个瞬间,if(bts!=btsb),就执行改变灯亮灭的程序;然后再将此刻的开关状态变成过去的开关状态,也就是btsb=bts;这样下一遍执行时开关状态就应该是现在的状态。但是开关断开的一瞬间其实也会出现bts!=btsb,这时我们就不需要执行改变灯的程序了,不过记录开关过去状态的btsb还是需要改变。那么改变灯亮灭的程序该怎么写呢?其实很简单,那就是如果leds=0;就把灯变亮,然后再使leds=1,因为下遍执行时灯的状态其实已经是亮了。如果leds=1;就把灯变灭,然后再使leds=0;下面是具体的程序:
int buttonPin = 2;
int ledPin = 12;
int bts = 0;
int btsb=0;
int leds=0;
void setup() {
}
void loop(){
} //在马上就要变成过去了。
//假如开关此刻的状态不等于过去的状态,并且此刻开关为断开时,执行下面语句