跳到主要内容

SOS 信号

重要提示:关于开发板的兼容性

本教程的核心逻辑适用于所有 ESP32 开发板,但所有操作步骤均以 微雪 ESP32-S3-Zero 迷你开发板 为例进行讲解。如果您使用其他型号的开发板,请根据实际情况修改相应设置。

项目介绍

这个项目展示了一个 SOS 信号的模拟程序,通过 ESP32 的 GPIO 引脚控制 LED 和蜂鸣器,模拟摩尔斯电码中的 SOS 信号。

摩尔斯电码

我们先了解 摩尔斯电码(Morse Code) 的构成规则。摩尔斯电码通过不同的排列顺序来表达不同的英文字母、数字和标点符号,它主要由两种基本信号组成:

  • 点(Dot): 短信号,记作 .
  • 划(Dash): 长信号,记作 -

摩尔斯电码表

本项目模拟的是国际通用的求救信号 SOS,其编码规则如下:

  • S:由 3 个点组成,即 ...
  • O:由 3 个划组成,即 ---

因此,整个 SOS 信号的发送序列就是:... --- ...

时间间隔定义

了解了字符构成后,还需要严格遵守国际标准的时间比例,这决定了我们代码中变量的数值关系:

  • 基础单位:我们将“点”的持续时间记为 1 个时间单位(1t)。
  • 划的长度:是点的 3 倍(3t)。
  • 间隔时间
    • 符号间:同一字母内,点与划之间的间隔为 1t。
    • 字母间:字母与字母之间的间隔为 3t。
    • 单词间:单词(或 SOS 序列)之间的间隔为 7t。

硬件连接

需要使用的器件有:

  • LED * 1
  • 330Ω 电阻 * 3
  • 有源蜂鸣器 * 1
  • 面包板 * 1
  • 导线
  • ESP32 开发板

按照下面接线图连接电路:

ESP32-S3-Zero 引脚图

ESP32-S3-Zero-Pinout

接线图

代码实现

/*
SOS 信号

使用 LED 和蜂鸣器模拟 SOS 信号。

硬件:
- LED 连接到引脚 7
- 蜂鸣器连接到引脚 8

Wulu (Waveshare Team)
*/

// 定义 LED 和蜂鸣器连接的引脚
const int ledPin = 7;
const int buzzerPin = 8;

// --- 摩尔斯电码时间定义 (单位:毫秒) ---
const int dotDuration = 200; // "点"的持续时间 (1t)
const int dashDuration = dotDuration * 3; // "划"的持续时间 (3t)
const int interElementGap = dotDuration; // 同一字母内,信号间的间隔 (1t)
const int interLetterGap = dotDuration * 3; // 字母间的间隔 (3t)
const int interWordGap = dotDuration * 7; // SOS 序列间的间隔 (7t)

// 函数声明
void signalOn();
void signalOff();
void dot();
void dash();
void letterS();
void letterO();
void playSOS();

void setup() {
// 初始化串口通信
Serial.begin(115200);
Serial.println("程序启动,准备发送 SOS 信号。..");

// 将引脚配置为输出模式
pinMode(ledPin, OUTPUT);
pinMode(buzzerPin, OUTPUT);

// 确保设备初始状态为关闭
signalOff();
delay(2000); // 等待 2 秒后开始
}

void loop() {
playSOS();

// 一次完整的 SOS 序列结束后,等待间隔
Serial.print("等待 ");
Serial.print(interWordGap);
Serial.println(" 毫秒后重复。..\n");
delay(interWordGap);
}

// --- 核心功能函数 ---

// 同时打开 LED 和蜂鸣器
void signalOn() {
digitalWrite(ledPin, HIGH);
digitalWrite(buzzerPin, HIGH);
}

// 同时关闭 LED 和蜂鸣器
void signalOff() {
digitalWrite(ledPin, LOW);
digitalWrite(buzzerPin, LOW);
}

// 发送一个"点"信号
void dot() {
signalOn();
delay(dotDuration);
signalOff();
}

// 发送一个"划"信号
void dash() {
signalOn();
delay(dashDuration);
signalOff();
}

// 发送字母 'S' (...): 三个点
void letterS() {
Serial.print(".");
dot();
delay(interElementGap);
Serial.print(".");
dot();
delay(interElementGap);
Serial.print(".");
dot();
}

// 发送字母 'O' (---): 三个划
void letterO() {
Serial.print("-");
dash();
delay(interElementGap);
Serial.print("-");
dash();
delay(interElementGap);
Serial.print("-");
dash();
}

// 播放一次完整的 SOS 信号序列
void playSOS() {
Serial.print("发送 S: ");
letterS();
Serial.print(" | ");
delay(interLetterGap);

Serial.print("发送 O: ");
letterO();
Serial.print(" | ");
delay(interLetterGap);

Serial.print("发送 S: ");
letterS();
Serial.println();
Serial.println("SOS 序列发送完毕。");
}

代码解释

  • 引脚定义:使用 const int 定义 LED 和蜂鸣器的引脚号,方便管理和修改。

    const int ledPin = 7;
    const int buzzerPin = 8;
  • 摩尔斯电码时间定义:定义了基础时间单位 dotDuration(点),其他时间间隔(划、间隔)均基于此计算。注意 Arduino 中 delay() 函数的单位是毫秒,所以这里的时间单位都是毫秒。

    const int dotDuration = 200;                 // "点"的持续时间 (1t)
    const int dashDuration = dotDuration * 3; // "划"的持续时间 (3t)
    const int interElementGap = dotDuration; // 同一字母内,信号间的间隔 (1t)
    const int interLetterGap = dotDuration * 3; // 字母间的间隔 (3t)
    const int interWordGap = dotDuration * 7; // SOS 序列间的间隔 (7t)
  • 初始化 (setup)

    • Serial.begin(115200):初始化串口通信,用于在串口监视器中打印调试信息。
    • pinMode(pin, OUTPUT):将 LED 和蜂鸣器引脚配置为输出模式。
    • signalOff():确保程序启动时设备处于关闭状态。
  • 主循环 (loop)

    • playSOS():调用函数播放完整的 SOS 信号。
    • delay(interWordGap):在每次 SOS 序列结束后等待一段时间,然后重复。
  • 基础控制函数

    • signalOn() / signalOff():封装了 digitalWrite 操作,同时控制 LED 和蜂鸣器的高低电平。

      本项目使用的有源蜂鸣器,它的特点是只要通电(GPIO 输出高电平)就会响,断电(GPIO 输出低电平)就停止。

    • dot() / dash():分别实现“点”和“划”的信号逻辑,控制亮/响的持续时间。

  • 字母函数letterS()letterO() 通过调用 dot()dash() 组合出对应的字母,并处理信号之间的微小间隔 (interElementGap)。

  • 播放函数playSOS() 按照 S-O-S 的顺序调用字母函数,并在字母之间插入较长的间隔 (interLetterGap)。

参考链接