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 引脚图


代码实现
# 导入必要的库
import time
import machine
# 定义 LED 和蜂鸣器连接的引脚
LED_PIN = 7 # LED
BUZZER_PIN = 8 # 蜂鸣器
# 将引脚号配置为输出模式
led = machine.Pin(LED_PIN, machine.Pin.OUT)
buzzer = machine.Pin(BUZZER_PIN, machine.Pin.OUT)
# --- 摩尔斯电码时间定义 ---
DOT_DURATION = 0.2 # "点"的持续时间(秒),作为基本时间单位
DASH_DURATION = 3 * DOT_DURATION # 划 = 3个点
INTER_ELEMENT_GAP = DOT_DURATION # 符号间间隔 = 1个点
INTER_LETTER_GAP = 3 * DOT_DURATION # 字母间间隔 = 3个点
INTER_WORD_GAP = 7 * DOT_DURATION # 单词间间隔 = 7个点
# --- 核心功能函数 ---
def signal_on():
"""同时打开 LED 和蜂鸣器"""
led.on()
buzzer.on()
def signal_off():
"""同时关闭 LED 和蜂鸣器"""
led.off()
buzzer.off()
def dot():
"""发送一个"点"信号"""
signal_on()
time.sleep(DOT_DURATION)
signal_off()
def dash():
"""发送一个"划"信号"""
signal_on()
time.sleep(DASH_DURATION)
signal_off()
def letter_s():
"""发送字母 'S' (...): 三个点"""
print('.', end='')
dot()
time.sleep(INTER_ELEMENT_GAP)
print('.', end='')
dot()
time.sleep(INTER_ELEMENT_GAP)
print('.', end='')
dot()
def letter_o():
"""发送字母 'O' (---): 三个划"""
print('-', end='')
dash()
time.sleep(INTER_ELEMENT_GAP)
print('-', end='')
dash()
time.sleep(INTER_ELEMENT_GAP)
print('-', end='')
dash()
def play_sos():
"""播放一次完整的 SOS 信号序列"""
print("发送 S: ", end='')
letter_s()
print(" | ", end='')
time.sleep(INTER_LETTER_GAP)
print("发送 O: ", end='')
letter_o()
print(" | ", end='')
time.sleep(INTER_LETTER_GAP)
print("发送 S: ", end='')
letter_s()
print()
print("SOS 序列发送完毕。")
# --- 主程序 ---
try:
print("程序启动,准备发送 SOS 信号。按下 Ctrl+C 停止。")
# 初始状态确保设备关闭
signal_off()
time.sleep(2) # 等待 2 秒后开始
# 无限循环,持续发送 SOS 信号
while True:
play_sos()
# 一次完整的 SOS 序列结束后,等待间隔
print(f"等待 {INTER_WORD_GAP} 秒后重复。..\n")
time.sleep(INTER_WORD_GAP)
except KeyboardInterrupt:
# 当用户按下 Ctrl+C 时,会捕获到 KeyboardInterrupt 异常
print("\n 程序被用户中断。")
finally:
# 无论程序是正常结束还是异常中断,都执行这部分代码
print("正在关闭 LED 和蜂鸣器。..")
signal_off()
print("设备已安全关闭。")
代码解释
-
导入库:
machine库用于控制硬件(GPIO),time库用于实现延时。 -
引脚定义:程序开头定义了 LED 和蜂鸣器的 GPIO 引脚号。
# 定义 LED 和蜂鸣器连接的引脚
LED_PIN = 7 # LED
BUZZER_PIN = 8 # 蜂鸣器 -
GPIO 初始化:使用
machine.Pin类创建对象,并将引脚配置为machine.Pin.OUT(输出模式),以便控制高低电平。有源蜂鸣器内部集成了振荡源,具有“一通电就响”的特性(只要 GPIO 输出高电平即发声),可以用数字信号输出控制。
# 将引脚号配置为输出模式
led = machine.Pin(LED_PIN, machine.Pin.OUT)
buzzer = machine.Pin(BUZZER_PIN, machine.Pin.OUT) -
摩尔斯电码时间定义:定义了基础时间单位
dot_duration(点),其他时间间隔(划、间隔)均基于此计算。这种参数化设计使得调整播放速度变得非常容易,只需修改一个变量即可。# --- 摩尔斯电码时间定义 ---
DOT_DURATION = 0.2 # "点"的持续时间(秒),作为基本时间单位
DASH_DURATION = 3 * DOT_DURATION # 划 = 3个点
INTER_ELEMENT_GAP = DOT_DURATION # 符号间间隔 = 1个点
INTER_LETTER_GAP = 3 * DOT_DURATION # 字母间间隔 = 3个点
INTER_WORD_GAP = 7 * DOT_DURATION # 单词间间隔 = 7个点 -
基础控制函数:
signal_on()和signal_off()封装了 LED 和蜂鸣器的同步控制。signal_on():同时点亮 LED 并让蜂鸣器发声。signal_off():同时关闭 LED 和蜂鸣器。
-
摩尔斯电码元素:
dot()和dash()函数分别实现了“点”和“划”的信号发送。它们在发送信号后都会自动调用signal_off(),确保下一个信号开始前状态是干净的。 -
字母函数:
letter_s()和letter_o()通过组合点和划来表示字母 S (...) 和 O (---),并严格遵守摩尔斯电码的间隔标准。 -
主循环逻辑:
play_sos()函数按 S-O-S 的顺序播放完整求救信号。while True循环确保信号不断重复发送,每次发送后等待inter_word_gap秒。
-
异常处理:使用
try...except...finally结构增强程序稳定性。except KeyboardInterrupt:捕获用户中断(Ctrl+C),允许程序优雅退出。finally:无论程序如何结束,都强制调用signal_off()关闭设备,防止蜂鸣器一直长鸣或 LED 长亮。