跳到主要内容

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

接线图

代码实现

# 导入必要的库
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 长亮。

参考链接