关于Arduino的历史、定位、功能等等的介绍,维基百科已有很详细的阐述,建议初学者都去看看,能对Arduino有更深入了解。本文基于Getting Started With Arduino(建议初学者购买),重点连载从零开始学习Arduino的基础编程知识和详细程序实现,只针对刚拿到Arduino但基本无编程经验的同学,高手请绕行。
NO.1:点亮你的第一个LED灯
打开Arduino IDE,新建Sketch,参考以下代码,重点请看注释部分:
#define LED 13 //定义D13为LED正极口,将LED灯连接到板子上D12引脚 void setup() //此函数代码只会在程序刚开始时执行一次 { pinMode(LED, OUTPUT); //定义LED也就是D13引脚模式为输出 } void loop() //此程序在会Arduino通电后反复执行 { digitalWrite(LED, HIGH); //输出13引脚信号为HIGH即高电平,开 delay(1000); //持续1S digitalWrite(LED, LOW); //输出13引脚信号为LOW即低电平,关 delay(1000); //持续1S }
将此代码上传至Arduino并连接好LED灯,你就可以看到LED在闪烁。
NO.2 添加开关来控制LED(GND端串联10K欧姆电阻,+5V)
#define LED 13 //定义LED引脚为D13 #define BUTTON 7 //定义开关BUTTON引脚为D7 int val = 0; //变量val,并赋值0,用来存储按钮状态 void setup() { pinMode(LED, OUTPUT); //LED引脚设置为输出模式 pinMode(BUTTON, INPUT); //BUTTON引脚设置为输入模式 } void loop() { val = digitalRead(BUTTON); //读取BUTTON数值 if (val == HIGH)//当val为HIGH的情况下 { digitalWrite(LED,HIGH); //点亮LED }else{ digitalWrite(LED, LOW); //关闭LED } }
上传看看效果。
NO.3:打开按钮后LED常亮
#define LED 13 //定义LED引脚为D13 #define BUTTON 7 //定义开关BUTTON引脚为D7 int val = 0; //变量val,并赋值0,用来存储按钮状态 int state = 0; //变量state,定义0表示关闭,1表示打开 void setup() { pinMode(LED, OUTPUT); //LED引脚设置为输出模式 pinMode(BUTTON, INPUT); //BUTTON引脚设置为输入模式 } void loop() { val = digitalRead(BUTTON); //读取BUTTON数值 if (val == HIGH) //当val为HIGH的情况下 { state = 1 - state; } if(state == 1) { digitalWrite(LED, HIGH); //打开LED }else{ digitalWrite(LED, LOW); //LED关闭状态 } }
上传看效果,你会发现会出现当你按开关LED灯关闭的问题,原因是程序中使用变量state储存0或者1来记忆灯的状态,当按下按钮时,state已被赋值为1,所以当Arduino再去读取开关状态时,当开关状态为HIGH,此时state被再次赋值为0,为关闭状态。
这其实是程序设计缺陷,如果来解决?继续往下:
#define LED 13 //定义LED引脚为D13 #define BUTTON 7 //定义开关BUTTON引脚为D7 int val = 0; //变量val,并赋值0,用来存储按钮状态 int old_val = 0; //存储变量val的上一个值 int state = 0; //变量state,定义0表示关闭,1表示打开 void setup() { pinMode(LED, OUTPUT); //LED引脚设置为输出模式 pinMode(BUTTON, INPUT); //BUTTON引脚设置为输入模式 } void loop() { val = digitalRead(BUTTON); //读取BUTTON数值 if ((val == HIGH) &&(old_val == LOW)) //当val为HIGH并且old_val为LOW的情况下 { state = 1 - state; } old_val = val; //val此时已经是旧的了,让数值赋给old_var if(state == 1) { digitalWrite(LED, HIGH); //打开LED }else{ digitalWrite(LED, LOW); //LED关闭状态 } }
写到此时,我已完全被LED灯闪瞎了眼。程序依然没有正常工作!现在的问题是由于按钮的机械构造造成的,按钮由两片金属的接触实现电路的导通,在现实中,金属之间的接触并不是完全密合,尤其是金属尚未到底的瞬间和按钮弹回的时候,会产生杂波。
当杂波出现的时候,Arduino会接受到一连串开关交错的信号。要克服这个杂波,有几种不通方式,对上边的简单程序来讲,只需要在程序中加入10~50毫秒的延迟指令就可以改善。参考以下代码:
#define LED 13 //定义LED引脚为D13 #define BUTTON 7 //定义开关BUTTON引脚为D7 int val = 0; //变量val,并赋值0,用来存储按钮状态 int old_val = 0; //存储变量val的上一个值 int state = 0; //变量state,定义0表示关闭,1表示打开 void setup() { pinMode(LED, OUTPUT); //LED引脚设置为输出模式 pinMode(BUTTON, INPUT); //BUTTON引脚设置为输入模式 } void loop() { val = digitalRead(BUTTON); //读取BUTTON数值 if ((val == HIGH) &&(old_val == LOW)) //当val为HIGH并且old_val为LOW的情况下 { state = 1 - state; delay(50); } old_val = val; //val此时已经是旧的了,让数值赋给old_var if(state == 1) { digitalWrite(LED, HIGH); //打开LED }else{ digitalWrite(LED, LOW); //LED关闭状态 } }
NO.4:使用PWM的方式来控制LED灯亮度
PWM被成为脉冲宽度调制,如果我们改变延迟函数的数值,直到你看不出LED灯亮和灭的时间间隔为止,你会发现LED灯亮度只有原来的50%,如果继续改变时间间隔,你会发现灯的亮度只有原来的25%。这就是PWM。
Arduino电路板上使用的处理器可以在处理其他事情的同时点亮3各LED使其闪烁,这部分PWM输出接口为D9、D10、D11,这3个输出接口可以由analogWrite()函数控制。analogwrite()指令中PWM参数的可设范围为0~255,255代表最亮,0代表最暗,如果你使用analogwrite(9, 128)则代表D9引脚接的LED灯亮度为50%。
逐渐改变亮度的LED灯(使用LED等串联一个470~1K欧姆的电阻,并接到D9引脚,负极接GND):
#define LED 9 //定义LED为D9引脚 int i = 0; //定义变量i,用来从上到下计数 void setup() { pinMode(LED,OUTPUT); //LED为输出 } void loop() { for(i = 0; i < 255 ; i++){ //循环255次,从小到大 analogWrite(LED, i); //PWM参数,亮度从小到大 delay(10); //延迟10毫秒,因为anaWrite()参数执行瞬间完成 } for(i = 255; i > 0; i--){ //循环255次,从大到小 analogWrite(LED, i); //PWM参数,两大从大到小 delay(10); //延迟10毫秒 } }
上传看看,是不是很神奇?
NO.5:按下松下按钮开关LED,长按开关调节LED灯亮度(NO.2+NO.4两个小电路积木结合)
#define LED 9 // 定义LED为D9引脚 #define BUTTON 7 //定义按钮为D7引脚 int val = 0; //变量val存储按钮数值状态 int old_val = 0; //存储val的上一个数值 int state = 0; //0为关闭LED,1为打开LED int brightness = 128; //存储亮度值 unsigned long startTime = 0; //存储按下按钮的开始时间 void setup() { pinMode(LED, OUTPUT); //LED引脚为输出 pinMode(BUTTON, INPUT); //BUTTON引脚为输入 } void loop() { val = digitalRead(BUTTON); //读取按钮数值并存储到val变量 if ((val == HIGH) && (old_val == LOW)) { state = 1 - state; startTime = millis(); // millis()是Arduino的时钟,存储最后一次按下按钮的时间,单位毫秒 delay(10); } if ((val == HIGH) && (old_val == HIGH)) { if (state == 1 && (millis() - startTime) > 500) { //如果按钮被按了超过500毫秒 brightness++; // 亮度值递增 delay(10); if (brightness > 255) { //如果亮度值超出255 brightness = 0; //重置亮度为0 } } } old_val = val; //执行了一次之后,val已变成旧值,存储到old_val if (state == 1) { analogWrite(LED, brightness); //以当前亮度值打开LED }else{ analogWrite(LED, 0); //关闭LED } }
是不是很酷?当然,你可以尝试把开关换成其他敏感元件,如光敏电阻、热敏电阻等其他传感器,来制作更有趣的场景。
以上我们进行的都是基于数字I/O引脚的试验,接下来开始尝试模拟I/O引脚(模拟引脚默认为输入状态)。模拟输入引脚analog in不仅可以读出是否有电压输入(数字引脚只能读出有或无),还能读出电压值的大小。我们使用analogRead()函数来读取输入电压值,该参数的返回值范围为0~1023,分别对应0~5V间的电压。如,在模拟口输入2.5V电压,analogRead()返回的值为512。以下开始模拟口的尝试:
NO.6:根据模拟输入值大小来设定LED闪烁频率
硬件环境需要先使用光敏电阻串联10K欧姆电阻,串联电阻一端接GND,一端接5V引脚,同时,在10K欧姆电阻的并联方向引出A0引脚接口。LED灯正极接D13,负极串联1K欧姆电阻接GND。
#define LED 13 //定义D13引脚为LED int val = 0; //变量val,存储模拟口读取的数值 void setup(){ pinMode(LED,OUTPUT); //LED为输出 } void loop(){ val = analogRead(0); //读取A0并赋值给val digitalWrite(LED,HIGH); //点亮LED delay(val); //延迟时间为val的数值 digitalWrite(LED,LOW); //关闭LED delay(val); //延迟时间为val的数值 }
一闪一闪亮晶晶!
NO.7:根据模拟输入值来调整LED灯亮度
#define LED 9 //定义D9引脚为LED,D9为PWM引脚 int val = 0; //变量val,存储模拟口读取的数值 void setup(){ pinMode(LED,OUTPUT); //LED为输出 } void loop(){ val = analogRead(0); //读取A0并赋值给val analogWrite(LED, val/4); //PWM输出最大值为255 delay(10); //延迟10毫秒 }
有了上边的编程基础,你可以变换出任意的积木式组合、扩展性场景。
接下来看下Arduino的串口通信,通过串口通信,我们可以让Arduino和计算机或其他控制机之间互相通信,让Arduino把数据传回计算机,并能接收来自计算机的指令。要实现这一功能,可以在Arduino程序中通过Serail()函数,此函数包含了串口通信所需的所有程序代码。
NO.8:从计算机串口读取Arduino模拟传感器输入数据
硬件环境依照NO.7的光敏电阻电路,程序如下:
#define SERSOR 0 //定义传感器输入口为A0 int val = 0; //变量val来存储读取的数值 void setup(){ Serial.begin(9600); //打开串口并设置通信波特率为9600 } void loop(){ val = analogRead(0); //从A0读取传感器反馈值并赋值给val Serial.println(val); //串口监视窗口显示传感器的反馈值 delay(100); //每100毫秒发送一次数据 }
上传至Arduino,在Arduino工具菜单的串口监视窗口打开看看,你所看到的值可以通过0~5V换算成电压,根据各传感器的Datasheet,可以得出你想要的现实环境中的某项数值。
最新评论