Arduino教程02 做一个S.O.S求救信号灯「DFR0100 」

2013-12-1315.2万
精华项目
AI 快速预览详细 收起
本篇Arduino教程介绍了如何使用入门套件DFR0100制作一个SOS求救信号灯。通过简单的电路连接和代码编写,实现LED的长闪烁和短闪烁来表示摩斯码SOS信号。教程详细讲解了for循环的使用方法,并提供了具体的代码示例。适合初学者学习摩斯码和循环语句的应用,适用于STEM教育和编程启蒙。
【本篇课程内容于 2024年8月2日更新】


Arduino教程02项目 - SOS求救信号器


本项目将继续使用【闪烁第一个LED】所搭建的电路(注意引脚有所更换),只需要对代码进行一定的改动,就能让我们的LED发出SOS求救信号了。
国际摩斯码是一种独特的字符编码系统,其精妙之处在于它利用简单的两种信号:横杠(长音)和点(短音),通过不同的组合方式来代表英文中的每一个字母以及数字。这种设计极大地简化了信息传递的复杂性,因为仅需两种基本信号形态,就能构建出完整的通信语言。这种创造性的编码方式展现了前人非凡的智慧与创新能力,确实令人钦佩不已。
我们正好可以通过LED发光的长短来代表不同的字母。通过长闪烁和短闪烁来分别表示横杠和点。在这个项目中,我们就拼写SOS这三个字母。
通过查阅摩斯码表,我们可以知道,字母“S”的摩斯码是三个点,我们这里用三次短闪烁表示。字母“O”则是三个横杠,用三次长闪烁表示。

硬件连接
Arduino教程02 做一个S.O.S求救信号灯「DFR0100 」图1

图 1 SOS 求救信号器

示例代码

有了前一个项目的基础,不难理解下面样例代码1。但先不要急着输入这段代码,只是看一下。

样例代码1:int ledPin = 10;
void setup() {
pinMode(ledPin, OUTPUT);
}
void loop() {
  // 三个短闪烁来表示字母“S”
digitalWrite(ledPin,HIGH);
delay(150);
digitalWrite(ledPin,LOW);
delay(100);

digitalWrite(ledPin,HIGH);
delay(150);
digitalWrite(ledPin,LOW);
delay(100);
digitalWrite(ledPin,HIGH);
delay(150);
digitalWrite(ledPin,LOW);
delay(100);

delay(1000); //1000毫秒延时产生字母之间的间隙

  //三个长闪烁来表示字母“O”
digitalWrite(ledPin,HIGH);
delay(400);
digitalWrite(ledPin,LOW);
delay(100);
digitalWrite(ledPin,HIGH);
delay(400);
digitalWrite(ledPin,LOW);
delay(100);
digitalWrite(ledPin,HIGH);
delay(400);
digitalWrite(ledPin,LOW);
delay(100);

delay(1000); //1000毫秒延时产生字母之间的间隙

//再用三个短闪烁来表示字母“S”
digitalWrite(ledPin,HIGH);
delay(150);
digitalWrite(ledPin,LOW);
delay(100);

digitalWrite(ledPin,HIGH);
delay(150);
digitalWrite(ledPin,LOW);
delay(100);
digitalWrite(ledPin,HIGH);
delay(150);
digitalWrite(ledPin,LOW);
delay(100);
delay(5000); // 在重复SOS信号前等待5秒
}


上面的写法固然正确,是不是觉得有点繁琐呢?如果有100个字母,难不成还重复100遍吗?有没有更好的编写程序的方法呢?想必发明编程的人也考虑到这个问题了,所以我们有了更好的一种写法。
我们先来看一下样例代码2。

样例代码2:
//项目 -- SOS求救信号器
int ledPin = 10;
void setup() {
pinMode(ledPin, OUTPUT);
}
void loop() {
// 三个短闪烁来表示字母“S”
for(int x=0;x<3;x++){
digitalWrite(ledPin,HIGH);  //设置LED 为开
delay(150);                 //延时150毫秒
digitalWrite(ledPin,LOW);   //设置LED 为关
delay(100);                 //延时100毫秒
}

//1000毫秒延时产生字母之间的间隙
delay(1000);
//三个长闪烁来表示字母“O”
for(int x=0;x<3;x++){
digitalWrite(ledPin,HIGH); //设置LED 为开
delay(400);                 //延时400毫秒
digitalWrite(ledPin,LOW);  //设置LED 为关
delay(100);                 //延时100毫秒
}
//1000毫秒延时产生字母之间的间隙
delay(1000);
// 再用三个短闪烁来表示字母“S”
for(int x=0;x<3;x++){
digitalWrite(ledPin,HIGH); //设置LED 为开
delay(150);                 //延时150毫秒
digitalWrite(ledPin,LOW);  //设置LED 为关
delay(100);                //延时100毫秒
}
//在重复SOS信号前等待5秒
delay(5000);
}
在输入代码的时候,注意保持代码层次的清晰,除了美观外,也便于你日后检查代码。编译通过后,上传代码到Arduino中,如果一切顺利的话,我们将看到LED闪烁出摩斯码SOS信号,等待5秒,重复闪烁。
通过使用Arduino板外接电池,并将整个装置封装在一个防水盒子里,我们就能创建出一个便携式设备,用于在紧急情况下发送国际通用的求救信号SOS。这一信号在航海和登山等户外活动中尤为重要,因为它能够快速有效地传达出求助信息。
我们接着来分析下代码。

代码回顾
代码loop()前的部分与项目【闪烁第一个LED】是完全一样的。也是初始化一个变量,设置数字引脚10的模式为输出模式。在主函数loop()中,你可以看到与项目【闪烁第一个LED】中类似的语句用来控制LED的打开和关闭,并通过延时delay()实现长短闪烁功能。然而,有所不同的是这次主函数包含了三个独立的代码段。

第一段代码段是输出代表字母“S”的三个点:

for(int x=0;x<3;x++){
digitalWrite(ledPin,HIGH);  //设置LED 为开
delay(150);                 //延时150毫秒
digitalWrite(ledPin,LOW);   //设置LED为关
delay(100);                 //延时100毫秒
}

LED开关的控制代码位于一对花括号(也称为大括号)内部,这个区域被定义为一个代码段。花括号都必须成对出现,即开启一个花括号必须有一个相应的闭合花括号,否则编译器在处理代码时会因为语法错误而无法通过编译。有个小技巧大家可以学一下,在开始写花括号的时候,就先把“{”“}”都写上,之后再在两个花括号之间输入代码,这样就不会出现写到最后括号对应不上的情况。

当程序运行后我们可以看到,灯闪了3次而不是只闪了1次。产生这样效果的是因为使用了for循环(用来重复执行循环体中的代码块)。我们来看一下:
for语句格式如下:

Arduino教程02 做一个S.O.S求救信号灯「DFR0100 」图2


来看下我们程序中的for循环:

for(int x=0;x<3;x++){
  ...
}

第一次循环:

· 声明并初始化变量x=0。
· 判断x<3,为真,则执行循环体中的程序。
· x自加,更新x为1。

第二次循环:

· 此时x=1。
· 判断x<3,为真,则执行循环体中的程序。
· x自加,更新x为2。
......
循环结束:
· 在下一次循环开始前,x的值被自加到3。
· 判断3<3,为假,因此循环结束,不再执行循环体。并继续向下执行。

(x++是x=x+1的简写,实现x的迭代(自加)功能。)

我们这里需要它循环3次,所以设置为x<3。从0开始计算,0,1,2,循环了3次。那如果要循环100次的话呢?
答案:
for(int x=0;x<100;x++){
  ...
}

我们在写一些判断语句的时候会经常用到一些比较运算符,比如大于,小于等等。下面就介绍一些常用的比较运算符。

比较运算符
for循环中的“<”称之为比较运算符。比较运算符在代码中是用作判断的,用于比较两个值。我们常用的比较运算符有:

==(等于)           >(大于)
!=(不等于)         <=(小于等于)
<(小于)              >=(大于等于)

特别要说明一下,比较运算中等于必须是两个等号(单等号的作用是赋值)。还有像小于等于和大于等于,<和=之间不能留有空格,否则编译不通过。
当然,除了比较运算符外,程序也可以用的+、-、*、/(加、减、乘、除)这些常用的算术运算符。

现在知道for循环是如何运作的了吧!我们的主函数loop()中有三个for循环,按照下面表格运行,最终完成SOS的输出。

第一个for循环        短闪烁3次,代表输出3个点,也就是字母“S”
第二个for循环        长闪烁3次,代码输出3个横杠,也就是字母“O”
第三个for循环        短闪烁3次,代表输出3个点,也就是字母“S”

局部变量和全局变量
必须要注意的,我们这里要引用一个新的概念:局部变量和全局变量。局部变量,这类变量只在自己的代码块内起作用。像是该程序的for循环中定义的变量x就属于局部变量,这意味着每个for循环都拥有自己独立的x变量。这些x变量之间互不影响,各自在其所属的循环中控制迭代过程,确保了即使在同一程序中存在多个for循环,它们之间的变量也不会产生冲突。还有一种变量叫全局变量,不同之处是,它能在整个程序中起作用,但条件是,必须在setup()、loop()函数外声明。像我们这里的ledPin,就能在整个程序中起作用。

在构建SOS求救信号器项目时,为了确保SOS信号中的每个字母(S、O、S)能够被清晰区分,我们在每个for循环迭代完成(表示一个字母)后,特意插入了1000毫秒的延时。这个延时使得SOS字母之间的停顿变得明显,有助于接收方准确识别每个字母。而在整个SOS信号序列完成后,即三个字母(S、O、S)均通过LED灯的闪烁表示完毕后,我们进一步设置了一个5秒的延时。这个较长的延时是在程序准备重新进入主循环loop()并执行下一轮SOS信号之前的一个等待时间,确保了SOS信号之间有足够的间隔,避免信号间的混淆。

好了,我们SOS求救信号器项目就算告一个段落了。有所收获吗?

课后练习
我们以【闪烁第一个LED】和【SOS求救信号器】两个项目作为基础,现在尝试自己做个交通信号灯吧,下图是交通信号灯的运行过程,虚线框的是程序的循环部分。自己动手试一下吧!

提示:原先我们只控制了一个LED灯,现在要扩展到同时控制三个不同颜色的LED灯。电路连接的基本原理保持不变,但我们需要利用三个不同的数字端口来分别控制这三个LED灯。在编程时,关键在于通过调整这些数字端口的高低电平信号,来独立控制每个LED灯的亮灭状态。

Arduino教程02 做一个S.O.S求救信号灯「DFR0100 」图3


下载附件示例代码.rar


下一篇教程:Arduino教程 03 交通信号灯

DFRobot版权所有,欢迎转载。
转载请务必标注来源: DF创客社区+作者姓名+原文网址。

创作许可协议

本项目采用 None(不开放任何权利,保留所有权利) 进行许可。

评论(25)
Rainiwalk
Rainiwalk
int red = 1;
int yellow = 2;
int green = 3;
void setup() {
pinMode(red, OUTPUT);
pinMode(yellow, OUTPUT);
pinMode(green, OUTPUT);
}
void loop() {
digitalWrite(red,HIGH);
delay(5000);
digitalWrite(yellow,HIGH);
delay(2000);
digitalWrite(red,LOW);
digitalWrite(yellow,LOW);
digitalWrite(green,HIGH);
delay(5000);
digitalWrite(green,LOW);
digitalWrite(yellow,HIGH);
delay(2000);
digitalWrite(yellow,LOW);
}
简单粗暴的代码哈哈
yuzai
yuzai
int redPin = 13;
int yellowPin = 12;
int greenPin = 11;
void setup() {
pinMode(redPin, OUTPUT);
pinMode(yellowPin, OUTPUT);
pinMode(greenPin, OUTPUT);
}
// 灯亮
void lightOn(int pin) {
digitalWrite(pin, HIGH); // 开灯
}
// 灯灭
void lightOff(int pin) {
digitalWrite(pin, LOW); // 关灯
}
void loop() {
// 交通灯逻辑
lightOn(redPin); // 红灯亮 5秒
delay(5000);
lightOn(yellowPin);
delay(2000);
lightOff(redPin);
lightOff(yellowPin);
lightOn(greenPin);
delay(5000);
lightOff(greenPin);
lightOn(yellowPin);
delay(2000);
lightOff(yellowPin);
}
B5oi0T0lyJ7m
B5oi0T0lyJ7m
[code]// 项目 - 交通信号灯
int carRed = 13; // 汽车红灯引脚
int carYellow = 12; // 汽车黄灯引脚
int carGreen = 8; // 汽车绿灯引脚
int button = 2; // 按钮引脚
int pedRed = 7; // 行人红灯引脚
int pedGreen = 4; // 行人绿灯引脚
int crossTime = 5000; // 允许行人通过的时间(毫秒)
unsigned long changeTime; // 按钮按下后的时间
void setup() {
pinMode(carRed, OUTPUT); //灯光设置为输出
pinMode(carYellow, OUTPUT); //灯光设置为输出
pinMode(carGreen, OUTPUT); //灯光设置为输出
pinMode(pedRed, OUTPUT); //灯光设置为输出
pinMode(pedGreen, OUTPUT); //灯光设置为输出
pinMode(button, INPUT); // 按钮设置为输入模式
// 初始状态设置
digitalWrite(carRed, HIGH); // 车行红灯亮
digitalWrite(pedGreen, HIGH); // 人行绿灯亮
}
void loop() {
int state = digitalRead(button); //state状态=digitaLRead函数 读取状态(botton按钮)
// 检测按钮状态及时间间隔
if (state == HIGH && (millis() - changeTime) > 5000) { //if判断(state状态==高电平HIGH 与&& (系统运行时间millis() 减- 按钮按下去的时间chuangeTime) 小于> 5秒 5000
// 调用变灯函数
changeLights();
}
}
void changeLights() { //这里其实我目前还不是很理解.前面那个调用变灯函数和这里的关系.
//给初始化的行人绿灯闪烁
for (int x = 0; x < 3; x++) { //循环指令
digitalWrite(pedGreen, HIGH); //打开行人绿灯
delay(400); //等待0.4秒
digitalWrite(pedGreen, LOW); //关闭行人绿灯
delay(400); //等待0.4秒
} //循环3次结束
digitalWrite(pedGreen,LOW); //关闭行人绿灯
delay(500); //等待0.5秒
digitalWrite(pedRed,HIGH); //开启行人红灯
delay(1000); //等待1秒,显得自然
for (int i = 0; i < 3; i++){ //循环指令
digitalWrite(carRed,LOW); //关闭车辆红灯
delay(400); //等待0.4秒
digitalWrite(carRed,HIGH); //打开车辆红灯
delay(400); //等待0.4秒
} //循环3次结束
digitalWrite(carRed,LOW); //关闭车辆红灯
delay(500); //等待0.5秒
digitalWrite(carYellow,HIGH); //打开车辆黄灯
delay(1000); //等待1秒
for (int o = 0; o < 3; o++){ //循环指令
digitalWrite(carYellow,LOW); //车辆黄灯关闭
delay(400); //等待0.4秒
digitalWrite(carYellow,HIGH); //车辆黄灯打开
delay(400); //等待0.4秒
} //循环3次结束
digitalWrite(carYellow,LOW); //车辆黄灯关闭
delay(500); //等待0.5秒
digitalWrite(carGreen,HIGH); //打开车辆绿灯
delay(10000); //等待10秒
for (int y = 0; y < 3; y++){ //循环指令
digitalWrite(carGreen,LOW); //关闭车辆绿灯
delay(400); //等待0.4秒
digitalWrite(carGreen,HIGH); //打开车辆绿灯
delay(400); //等待0.4秒
} //循环3次结束
digitalWrite(carGreen,LOW); //关闭车辆绿灯
digitalWrite(pedRed,LOW); //关闭行人红灯
delay(500); //等待0.5秒
digitalWrite(carRed,HIGH); //打开车辆红灯,回到初始状态
digitalWrite(pedGreen,HIGH); //打开行人绿灯.回到初始状态
// 更新changeTime
changeTime = millis();
}[/code]根据本章知识做的,有问题欢迎指正.
B5oi0T0lyJ7m
B5oi0T0lyJ7m
[code] int hongdeng =13; //变量hongdeng =13号端口//
int huangdeng =12; //变量huangdeng =12号端口//
int lvdeng =8; //变量lvdeng =8号端口//
void setup(){ //首先调用steuo 查看输出类型 配置串口 只运行一次不会重复运行//
pinMode(hongdeng,OUTPUT); //pinMode就是函数调用 调用红灯 设置为O输出模式//
pinMode(huangdeng,OUTPUT); //pinMode就是函数调用 调用黄灯 设置为O输出模式//
pinMode(lvdeng,OUTPUT); //pinMode就是函数调用 调用绿灯 设置为O输出模式//
}
void loop(){
//下面给绿灯添加长时亮起和循环闪烁//
digitalWrite(lvdeng,HIGH);//引用绿灯 给予5V电压//
delay(5000); //延时4秒//
digitalWrite(lvdeng,LOW); //引用绿灯 给予0V电压//
int o = 0; //设置变量o为0//
for(o=0;o<4;o++){ //设置for循环 每循环一次加一 大于三次结束//
digitalWrite(lvdeng,HIGH);// 引用绿灯 给予5V电压//
delay(400); // 延时0.4秒//
digitalWrite(lvdeng,LOW); //给予绿灯0V电压//
delay(400); //延时0.4秒//
}
//下面给黄灯添加长时亮起和循环闪烁//
digitalWrite(huangdeng,HIGH);//引用黄灯 给予5V电压//
delay(1000); //延时4秒//
digitalWrite(huangdeng,LOW); //引用黄灯 给予0V电压//
int i = 0; //设置变量i为0//
for(i=0;i<4;i++){ //设置for循环 每循环一次加一 大于三次结束//
digitalWrite(huangdeng,HIGH);// 引用黄灯 给予5V电压//
delay(400); // 延时0.4秒//
digitalWrite(huangdeng,LOW); //给予黄0V电压//
delay(400); //延时0.4秒//
}
//下面给红灯添加长时亮起和循环闪烁
digitalWrite(hongdeng,HIGH);//引用红灯 给予5V电压//
delay(5000); //延时4秒//
digitalWrite(hongdeng,LOW); //引用红灯 给予0V电压//
int x = 0; //设置变量X为0//
for(x=0;x<4;x++){ //设置for循环 每循环一次加一 大于三次结束//
digitalWrite(hongdeng,HIGH);// 引用红灯 给予5V电压//
delay(400); // 延时0.4秒//
digitalWrite(hongdeng,LOW); //给予红灯0V电压//
delay(400); //延时0.4秒//
}
//最后给一个小小的延时 告诉我 它在等在重新出发 哈哈哈哈哈//
delay(2000);
}[/code]附件里是完整版的详解内容,不让发太多文字,就剪辑了一部分。只针对本章学习的内容作品。
业余潜水员
业余潜水员
选了一个最简单粗暴的做法实现红绿灯.反正就4个状态嘛,那就直接全局变量状态,然后判断状态值是什么再显示,简单粗暴其实不错,代码不贴了太简单
Cloud-Tifa
Cloud-Tifa
int red = 7, yellow = 3, green = 4;
void setup() { pinMode(red,OUTPUT);
pinMode(yellow,OUTPUT);
pinMode(green,OUTPUT);
}
void loop() {
digitalWrite(red,HIGH);
digitalWrite(yellow,LOW);
digitalWrite(green,LOW);
delay(5000);
digitalWrite(red,HIGH);
digitalWrite(yellow,HIGH);
digitalWrite(green,LOW);
delay(2000);
digitalWrite(red,LOW);
digitalWrite(yellow,LOW);
digitalWrite(green,HIGH);
delay(5000);
digitalWrite(red,LOW);
digitalWrite(yellow,HIGH);
digitalWrite(green,LOW);
delay(2000);
}
Kaiii
Kaiii
红绿灯。。。[code]//手写红绿灯
int yellow = 10;
int red = 3;
int green = 4;
void setup() {
// put your setup code here, to run once:
pinMode(yellow,OUTPUT);
pinMode(red,OUTPUT);
pinMode(green,OUTPUT);
}
void loop() {
// put your main code here, to run repeatedly:
int i = 0;
for (i=0;i<5;i++){
digitalWrite(red,HIGH);
delay(1000);
}
digitalWrite(red,LOW);
for (i=0;i<2;i++){
digitalWrite(yellow,HIGH);
delay(1000);
}
digitalWrite(yellow,LOW);
for (i=0;i<5;i++){
digitalWrite(green,HIGH);
delay(1000);
}
digitalWrite(green,LOW);
for (i=0;i<2;i++){
digitalWrite(yellow,HIGH);
delay(1000);
}
digitalWrite(yellow,LOW);
}
[/code]
LearnArduino
LearnArduino
int ledRed = 2;
int ledYellow = 3;
int ledGreen = 4;
void setup() {
pinMode(ledRed,OUTPUT);
pinMode(ledYellow,OUTPUT);
pinMode(ledGreen,OUTPUT);
}
void loop() {
// put your main code here, to run repeatedly:
digitalWrite(ledRed,HIGH);
delay(5000);
digitalWrite(ledYellow,HIGH);
delay(2000);
digitalWrite(ledRed,LOW);
digitalWrite(ledYellow,LOW);
digitalWrite(ledGreen,HIGH);
delay(5000);
digitalWrite(ledGreen,LOW);
digitalWrite(ledYellow,HIGH);
delay(2000);
digitalWrite(ledYellow,LOW);
}
IdSNilMdFl2A
IdSNilMdFl2A
作者太棒了!怒赞!
IdSNilMdFl2A
IdSNilMdFl2A
红绿灯代码!我是小白!有什么地方可以完善的吗?
int ledpin1 = 8;
int ledpin2 = 10;
int ledpin3 = 12;
void setup() {
pinMode(ledpin1, OUTPUT);
pinMode(ledpin2,OUTPUT);
pinMode(ledpin3,OUTPUT);
}
void loop() {
digitalWrite(ledpin1,HIGH);
digitalWrite(ledpin2,LOW);
delay(5000);
digitalWrite(ledpin1,HIGH);
digitalWrite(ledpin2,HIGH);
delay(2000);
digitalWrite(ledpin1,LOW);
digitalWrite(ledpin2,LOW);
digitalWrite(ledpin3,HIGH);
delay(5000);
digitalWrite(ledpin2,HIGH);
digitalWrite(ledpin3,LOW);
delay(2000);
}
且听风吟丶
且听风吟丶
期待我也能做出来
DFHk-0ykaN8
DFHk-0ykaN8
为什么 这样写效果是很奇怪的抖动,,没有呼吸的效果
我的习惯是这样写的
jzzgb
jzzgb
不错,点赞
云飞
云飞
很好 有代码
绝地智者
绝地智者
厉害了,新手来顶一顶帖子,加油学习~
LeSoleil
LeSoleil
太好了!
1093050170
1093050170
很详细!!
地狱满员
地狱满员
写得很好特别是程序分析过程,这个过程是小白们理解程序执行原理所需要的,猛赞
Peter达
Peter达
谢谢分享
gray6666
gray6666
教程详细,感谢分享