用于月球上的自助交通灯
地球的直径只有月球的3.6倍,地球能拥有月球这么大的卫星确实很神奇,月球无时无刻不在保护着地球。当然,人类探索月球的最大动力,还是因为月球上没有蚊子。
中国的探月飞船已经成功在月球上着陆,随着月球城市建设的兴起,月球城市自助交通灯的研究显得尤为重要。基于Arduino的月球自助交通灯需求如图1所示,除了机动车道有交通灯,人行道也要设有交通灯,并有自助过马路按钮。
图1 自助交通灯
交通灯的初始状态为机动车道亮绿灯,人行道亮红灯。当有行人要过马路时,按下过马路按钮,交通灯开始变灯,机动车道的交通灯将由绿灯经黄灯变为红灯,同时人行道的交通灯由红灯变为绿灯,使汽车停下来,允许行人安全通过。30秒后变灯结束,交通灯恢复到初始状态,机动车道亮绿灯,人行道亮红灯。
为防止频繁变灯导致交通拥堵,规定连续触发变灯的时间间隔必须在3分钟以上,也就是说,从本次交通灯变灯结束恢复到初始状态(机动车道亮绿灯,人行道亮红灯),在3分钟之内如果再次按下过马路按钮,则操作无效。
在这个项目中,除了控制交通灯外,还需要检测用户行为,这是你第一次与Arduino互动,当Arduino检测到按钮状态改变时,它将产生相应的动作。在这个项目中你还将学习到如何在代码里创建自己的函数。
1. 需要的元件
交通灯用不同颜色的LED代替,行人用的按钮用按键代替,项目所需元件清单如下:
绿色LED,2个
黄色LED,1个
红色LED,2个
电阻(220),5个
电阻(10k),1个
按键,1个
自助交通灯的原理图如图2所示,Arduino Uno开发板的引脚2配置为为输入,用于检测按键是否按下,引脚5、6、1012配置为输出,控制人行道和机动车道的交通灯,其中人行道只需要红绿两种颜色的交通灯即可。按键K通过10k的上拉电阻接+5V,当按键K未被按下时,由于上拉电阻的作用,引脚2处为稳定的高电平;按下按键后,引脚2接地,输入变为低电平。交通灯用相应颜色的LED代替,采用共阴极接法,当控制交通灯的对应引脚输出高电平时,相应的LED被点亮。
图2 自助交通灯原理图
2. 搭建电路
参照图2的自助交通灯原理图,在面包板上搭建电路,如图3所示。
图3 自助交通灯连线图
3.输入代码
打开Arduino IDE,输入以下程序代码:
// 项目 -- 自助交通灯
int carRed = 12; //机动车交通灯
int carYellow = 11;
int carGreen = 10;
int perGreen = 5; //行人交通灯
int perRed = 6;
int button = 2; //按键输入
int crossTime = 25000; //人行道绿灯常亮时间,25秒
unsigned long intervalTime =0; //按键按下的时间
void setup() {
pinMode(button,INPUT);
pinMode(carGreen,OUTPUT);
pinMode(carYellow,OUTPUT);
pinMode(carRed,OUTPUT);
pinMode(perGreen,OUTPUT);
pinMode(perRed,OUTPUT);
digitalWrite(carGreen,HIGH); //默认机动车道亮绿灯
digitalWrite(carYellow,LOW);
digitalWrite(carRed,LOW);
digitalWrite(perRed,HIGH); //默认人行道亮红灯
digitalWrite(perGreen,LOW);
}
void loop() {
int state = digitalRead(button); //读取按键状态
if (state == LOW && (millis() - intervalTime) > 180000l)
changeLights(); //转入变灯函数
}
void changeLights()
{
digitalWrite(carGreen,LOW); //机动车道绿灯灭
digitalWrite(carYellow,HIGH); //机动车道黄灯亮
delay(20000); //等待2秒
digitalWrite(carYellow,LOW); //机动车黄灯灭
digitalWrite(carRed,HIGH); //机动车道红灯亮
digitalWrite(perRed,LOW); //人行道红灯灭
digitalWrite(perGreen,HIGH); //人行道绿灯亮
delay(crossTime); //等待行人通过,绿灯常亮25秒
//人行道绿灯闪烁4秒
for (int x=0; x<8; x++)
{
digitalWrite(perGreen,HIGH);
delay(250);
digitalWrite(perGreen,LOW);
delay(250);
}
//人行道红灯亮,延迟一秒后机动车道绿灯亮
digitalWrite(perRed,HIGH);
delay(1000);
digitalWrite(carRed,LOW);
digitalWrite(carGreen,HIGH);
//记录本次变灯的时间
intervalTime = millis();
}
4. 代码详解
在setup()函数里,初始化引脚2为数字输入端口,引脚5、6、1012为数字输出端口,默认状态为机动车道的交通灯亮绿灯,允许车辆通行,人行道亮红灯,禁止行人过马路。
在loop()函数里监测按键button的状态,当行人按下按键时,程序判断当前时间与上一次变灯结束的时间间隔,为避免机动车道拥堵,如果当前按键时间距上次变灯结束间隔不足3分钟,则不响应按键,交通灯的状态不变。如果超过3分钟,则响应行人的按键请求,调用changeLights()函数,交通灯开始变灯。
changeLights()函数完成变灯过程,变灯结束后恢复到初始状态。机动车道的交通灯先由绿灯变为为黄灯;2秒钟后,红灯亮起,禁止车辆通行,同时人行道的交通灯变为绿灯;25秒后,人行道的绿灯开始闪烁,再过4秒,人行道的交通灯变为红灯,禁止行人通行;但为了安全起见,此时机动车道的交通灯依然为红灯,延迟1秒钟后才变为绿灯,允许机动车继续通行。
在程序的主循环(loop()函数)里用如下语句检查引脚2的状态:
int state = digitalRead(button);
if (state == LOW && (millis() - intervalTime) > 180000l) {
changeLights();
}
程序引入一个整数state,并设置state的数值为引脚2的状态。
if语句是程序控制语句的一种,它的目的是检查当前条件是否满足,如果满足,则执行代码块{…}中的代码。由于该代码块中只有一条语句,就是调用changeLights()函数,所以该代码块的一对大括号也可以去掉。
这里要检查两个条件是否同时满足要求。第一个条件是state变量的状态是否为LOW,state变量存放的是引脚2的状态,当按键按下时,state为LOW。第二个条件是millis()的值减去intervalTime是否大于180000毫秒,由于该数值已经超过了整型值所能表达的范围,为保证计算精度,在180000后面加了一个小写字母“l”,将该值转换为长整型。
前面已经提及,millis()函数是Arduino库函数,它返回以毫秒为单位的从Arduino板通电到当前的时间。变量intervalTime是无符号长整型,取值范围为0到4294967295,存放的是上次从millis()函数读取的值。将millis()-intervalTime放在括号里,保证比较的是state与本次计算的结果,而不是millis()函数的返回值。
在state==LOW和millis()-intervalTime之间有符号&&,这是一个逻辑运算符,意思是进行逻辑与运算,逻辑运算符有三种:
-
&& -- 逻辑与
-
|| -- 逻辑或
-
!-- 逻辑非
逻辑与运算(&&)的含义是当两个操作数都是真时,逻辑运算的结果为真,例如当x为5、y为10时,下面这个if语句的条件为真:
if (x==5 && y==10) {…}
逻辑或运算(||)的含义是两个操作数中只要有一个为真,结果就为真,例如当x为5、y为6时,下面这个if语句的条件为真:
if (x==5 || y==10) {…}
逻辑非运算(!)的含义是如果操作数为假,则结果为真,因此如果x是假(用0表示),下面这个if语句的条件为真:
if (!x) {…}
可以将操作符放在括号中使用,以增加程序的可读性。
主程序loop()函数只是不断检测人行道的按钮是否被按下,如果按钮被按下并且符合变灯条件,则调用changeLights()函数,程序执行函数中的代码,函数运行完成后,返回if语句changeLights()函数的下一条代码继续执行。函数changeLights()是自动交通灯程序的核心代码,负责控制机动车道和人行道上的交通灯,禁止机动车通行,允许行人通行;函数执行完毕后恢复原来交通灯的设置,允许机动车通行,禁止行人通行。
函数是有名称的独立代码块,调用时可以给函数传递参数,函数也可以返回数值,但在这个例子里,没有传递给函数任何参数,也没有让函数返回任何数值。
在程序中引入函数的意义是可以在其他地方被多次调用,尤其当一个函数传递了参数,或者返回数值时,它的优点才更能凸显出来。这个程序完全可以不使用changeLights()函数,而是把这段代码都放在loop()函数里,引入changeLights()只是为了给出自定义函数的概念,并改善代码的可读性。
当你的才华还撑不起你的野心的时候,你就应该静下心来学习;当你的能力还驾驭不了你的目标时,就应该沉下心来历练;梦想,不是浮躁,而是沉淀和积累,只有拼出来的美丽,没有等出来的辉煌,机会永远是留给最渴望的那个人,学会与内心深处的你对话,问问自己,想要怎样的人生,静心学习,耐心沉淀。
--end--
声明:本文章由网友投稿作为教育分享用途,如有侵权原作者可通过邮件及时和我们联系删除:freemanzk@qq.com