news 2026/5/25 16:20:06

基于ESP32与MicroPython的便携式记忆游戏机开发全流程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于ESP32与MicroPython的便携式记忆游戏机开发全流程

1. 项目概述:一个父子共创的电子记忆游戏

几年前,我儿子对电脑游戏很着迷,但对屏幕背后的世界一无所知。为了让他理解“魔法”是如何发生的,我决定和他一起动手,做一个看得见、摸得着的电子玩具。我们的目标不是造一个多么复杂的设备,而是创造一个能让他亲手焊接、亲手编程,并且玩得开心的东西。最终,我们选定了一个经典游戏的复刻版——一个需要记忆颜色序列的“记忆游戏机”。

这个项目的核心非常简单:模仿上世纪七八十年代风靡一时的“Simon”游戏。游戏机会亮起一个颜色的LED,玩家需要按下对应颜色的按钮;接着,它会再随机亮起一个LED,玩家则需要按顺序重复整个越来越长的颜色序列。听起来简单,但序列变长后,对记忆力的挑战可不小。

我选择用Python作为编程语言,主要是因为它语法清晰、接近自然语言,对初学者非常友好。硬件上,我们选用了一块ESP32开发板,它功能强大、价格便宜,而且自带Wi-Fi和蓝牙(虽然我们这个项目用不上),更重要的是,它可以用一块锂电池供电,让我们的游戏机摆脱电线,真正“活”起来。整个项目只用了ESP32上的8个GPIO引脚:4个控制LED,4个读取按钮状态。为了增加点趣味性和信息反馈,我们还加了一块小小的128x64像素的OLED屏幕,用来显示分数和关卡。

从一堆散乱的元器件、面包板上的原型,到最后用3D打印外壳封装成一个可以揣在口袋里、带到任何地方玩的完整设备,这个过程充满了乐趣和挑战。这个游戏机陪伴我们度过了整个假期,它不仅是一个玩具,更是一堂生动的物理、电子和编程入门课。下面,我就把我们从零到一搭建这个“记忆大师”游戏机的完整过程、踩过的坑和收获的经验,毫无保留地分享出来。

2. 核心设计思路与方案选型

2.1 为什么选择“记忆游戏”作为入门项目?

对于电子和编程的初学者,尤其是孩子,第一个项目的选择至关重要。它需要满足几个条件:目标明确反馈即时有成就感,并且能拆解成清晰的步骤。记忆游戏完美契合这些要求。

它的游戏逻辑是线性的、可预测的:生成序列 -> 展示序列 -> 等待输入 -> 验证输入。这个循环对应到程序里,就是几个清晰的函数模块。孩子能很容易地理解“这里该写一个让灯闪起来的函数”,“那里该写一个检查按钮的函数”。当代码写完,下载到板子上,灯真的按写的逻辑亮起来,按钮真的能控制游戏时,那种“我创造了它”的成就感是无与伦比的。这比单纯在屏幕上打印“Hello World”要生动和有趣得多。

2.2 硬件平台选型:ESP32为何胜出?

在项目开始时,我们考虑过几种主流微控制器:Arduino Uno、Raspberry Pi Pico和ESP32。

  • Arduino Uno:经典,资料极多。但它核心性能较弱,需要额外的硬件才能实现无线功能,而且原生开发环境(Arduino IDE)对Python支持不直接(需要通过Firmata等协议,增加了复杂度)。
  • Raspberry Pi Pico:性价比高,原生支持MicroPython(一种针对微控制器的Python精简版本),非常不错。但在当时,其生态系统和社区资源相对于ESP32还是稍显年轻。
  • ESP32:这是我们最终的选择。理由如下:
    1. 双核处理器与充足内存:比传统Arduino性能强得多,能轻松处理游戏逻辑、OLED显示,并为未来扩展(比如添加声音)留足余地。
    2. 对MicroPython支持成熟:有一个非常活跃的社区,固件稳定,库丰富。我们可以用纯Python来编程,学习路径一致。
    3. 集成Wi-Fi与蓝牙:虽然本项目未使用,但这意味着未来我们可以轻松升级项目,比如做成联网对战版,或者用手机蓝牙遥控,项目的“可成长性”很好。
    4. 广泛的电源管理特性:它支持从锂电池直接供电,并集成了充电管理电路。这意味着我们只需要一块常见的3.7V锂电池和一个USB口,就能实现充电、供电一体化,非常适合制作便携设备。

注意:市面上ESP32开发板型号繁多,推荐选择像“ESP32 DevKitC V4”或“NodeMCU-32S”这类引脚引出完善、自带USB转串口芯片的版本,会省去很多调试的麻烦。

2.3 软件与工具链的搭建

编程环境我们选择了Thonny。这是一个对初学者极其友好的Python IDE,特别适合MicroPython开发。

它的优势在于:

  • 无缝连接硬件:安装好驱动后,可以像操作本地文件一样,直接在IDE里选择串口连接ESP32,上传、下载文件,甚至使用交互式命令行(REPL)实时调试,查看变量状态。
  • 简洁直观的界面:没有复杂的配置,孩子可以快速聚焦于写代码本身。
  • 内置包管理器:可以方便地为ESP32安装额外的MicroPython库,比如我们后面用到的OLED驱动库。

开发流程大致是:在Thonny中编写Python代码 -> 通过USB线连接ESP32 -> 将代码作为主脚本上传到ESP32的文件系统中 -> 复位或上电后ESP32自动运行。这种“写-传-跑”的循环非常快速直观。

3. 硬件电路设计与连接详解

3.1 元器件清单与作用

在画电路图之前,我们先明确需要哪些“演员”:

  1. 主角 ESP32开发板:1块,系统大脑。
  2. LED(发光二极管):4个(红、绿、蓝、黄各一)。用于显示颜色序列。注意要选择合适颜色的散光LED,视觉效果更柔和。
  3. 按钮(微动开关):4个。用于玩家输入。建议选用带帽的12x12mm四脚微动开关,手感清晰。
  4. 电阻
    • 限流电阻:4个,每个LED串联一个。阻值计算是关键。ESP32的GPIO输出电压约为3.3V,假设LED工作电流我们设定在10mA(足够亮且安全),不同颜色LED正向压降不同(通常红色约1.8V,蓝/绿/白约3.0V)。以红色LED为例,电阻值 R = (3.3V - 1.8V) / 0.01A = 150Ω。为方便采购,统一使用220Ω电阻,亮度稍减但完全可用,且更安全。
    • 上拉电阻:4个,每个按钮接一个。ESP32的GPIO可以配置内部上拉电阻,但为了电路稳定性和教学直观,我们外部使用了10kΩ的电阻。它的作用是当按钮未按下时,将GPIO引脚稳定地拉到高电平(3.3V);按下时,引脚接地变为低电平。
  5. OLED显示屏(128x64):1块。常用型号是SSD1306驱动的I2C接口屏幕。它只有4个引脚(VCC, GND, SCL, SDA),接线非常简洁。
  6. 锂电池:1块,3.7V,容量建议在500mAh以上。用于便携供电。
  7. 电池充电/升压一体模块:1个(如TP4056+升压)。这是实现便携的关键。TP4056模块负责给锂电池安全充电,升压部分将电池的3.7V稳定升压到5V,供给ESP32。
  8. 面包板、杜邦线(公对公、公对母):用于原型搭建。
  9. 后续封装材料:如3D打印外壳、螺丝、导线等。

3.2 电路连接原理与实操接线图

电路的核心逻辑是“输出控制LED,输入读取按钮”。以下是接线明细表:

元件引脚/端连接到 ESP32 引脚说明
红色LED阳极(长脚)通过220Ω电阻 -> GPIO 23输出高电平时点亮
阴极(短脚)GND
绿色LED阳极通过220Ω电阻 -> GPIO 22输出高电平时点亮
阴极GND
蓝色LED阳极通过220Ω电阻 -> GPIO 21输出高电平时点亮
阴极GND
黄色LED阳极通过220Ω电阻 -> GPIO 19输出高电平时点亮
阴极GND
红色按钮一脚GPIO 15配置为输入,内部/外部上拉
另一脚GND按下时,GPIO15接地
绿色按钮一脚GPIO 2配置为输入,内部/外部上拉
另一脚GND
蓝色按钮一脚GPIO 4配置为输入,内部/外部上拉
另一脚GND
黄色按钮一脚GPIO 18配置为输入,内部/外部上拉
另一脚GND
OLED屏幕VCC3.3V切勿接5V,会烧毁!
GNDGND
SCLGPIO 25 (I2C时钟线)
SDAGPIO 26 (I2C数据线)
电源电池+充电模块B+
电池-充电模块B-
充电模块OUT+ESP32 VIN (或5V引脚)
充电模块OUT-ESP32 GND
充电模块USB口用Micro USB线连接电脑或充电器用于充电和初始编程

重要提示:在将任何元件连接到ESP32之前,务必断开USB或电池供电。接线时,优先完成GND(地线)的连接,建立一个共同的参考点。LED的长脚(阳极)必须通过电阻连接正极,短脚(阴极)接GND,接反了不会亮。按钮的两脚没有正反之分。

接线顺序建议:先在面包板上完成电源部分(ESP32、电池模块)的连接并测试通电正常。然后逐一连接LED及其电阻,每接好一个,就写一段简单的测试代码(如pin.value(1))验证是否能点亮。接着连接按钮,同样写测试代码读取引脚状态。最后连接OLED屏幕。这种“分模块测试”的方法,能让你在问题出现时快速定位,避免所有线都缠在一起后无从下手。

4. 软件编程:从零到一的逻辑实现

4.1 开发环境准备与固件烧录

首先,需要给ESP32“安装操作系统”,也就是MicroPython固件。

  1. 从MicroPython官网下载最新的ESP32通用固件(.bin文件)。
  2. 安装ESP32的刷机工具,如esptool.py(可通过Python的pip安装)。
  3. 将ESP32通过USB连接电脑,进入下载模式:通常需要按住板上的“BOOT”按钮,再按一下“EN”复位按钮,然后松开“EN”,再松开“BOOT”。
  4. 使用命令行擦除原有固件并刷入新固件。命令类似:
    esptool.py --chip esp32 --port COM3 erase_flash esptool.py --chip esp32 --port COM3 --baud 460800 write_flash -z 0x1000 esp32-xxx.bin
    (请将COM3替换为你的实际串口号,esp32-xxx.bin替换为你的固件文件名)。

刷写成功后,打开Thonny,在右下角选择解释器为“MicroPython (ESP32)”,并选择正确的串口端口。连接后,Shell交互窗口会出现>>>提示符,输入print(‘Hello, ESP32!’)测试,成功则环境搭建完成。

4.2 核心游戏逻辑的代码拆解

游戏的主程序可以分解为几个核心函数,我们采用面向过程的方式,让逻辑更清晰。

1. 硬件初始化 (init_hardware)这个函数负责配置所有用到的引脚。

from machine import Pin, I2C import ssd1306 import time # 定义LED和按钮对应的引脚 led_pins = [23, 22, 21, 19] button_pins = [15, 2, 4, 18] # 初始化LED对象列表(设置为输出模式) leds = [Pin(pin, Pin.OUT) for pin in led_pins] # 初始化按钮对象列表(设置为输入模式,并启用内部上拉电阻) buttons = [Pin(pin, Pin.IN, Pin.PULL_UP) for pin in button_pins] # 初始化OLED显示屏 (I2C) i2c = I2C(0, scl=Pin(25), sda=Pin(26), freq=400000) oled = ssd1306.SSD1306_I2C(128, 64, i2c) def init_hardware(): # 确保所有LED初始状态为熄灭(低电平) for led in leds: led.value(0) # 清空OLED屏幕并显示欢迎信息 oled.fill(0) oled.text("Memory Game!", 10, 10) oled.text("Press any key", 15, 30) oled.show()

实操心得Pin.PULL_UP启用了芯片内部的上述电阻,这样我们就不必在外部为每个按钮焊接一个10k电阻了,极大地简化了电路。这是ESP32等现代微控制器的便利之处。

2. 游戏序列生成与展示 (generate_sequence,play_sequence)游戏的核心是生成一个随机序列,并以视觉(LED闪烁)的方式播放给玩家。

import urandom # 用于生成随机数 sequence = [] current_level = 1 MAX_LEVEL = 20 # 游戏最大关卡数 def generate_sequence(length): """生成指定长度的随机序列,每个元素是0-3的数字,对应4种颜色""" return [urandom.getrandbits(2) for _ in range(length)] # getrandbits(2)生成0-3的随机数 def play_sequence(seq, speed=0.5): """播放序列:点亮对应LED,延时,熄灭,间隔""" for color_index in seq: leds[color_index].value(1) # 点亮LED time.sleep(speed) # 保持点亮状态 leds[color_index].value(0) # 熄灭LED time.sleep(0.2) # 序列中每个颜色之间的间隔

3. 玩家输入捕获与验证 (get_player_input,check_sequence)需要持续监听按钮,并对比玩家的输入和游戏序列。

def wait_for_button(): """等待并返回第一个被按下的按钮索引,同时提供视觉反馈""" pressed_index = None while pressed_index is None: for i, btn in enumerate(buttons): if btn.value() == 0: # 按钮按下时为低电平 leds[i].value(1) # 按下时对应LED亮起作为反馈 time.sleep(0.2) # 消抖兼反馈显示 leds[i].value(0) while btn.value() == 0: # 等待按钮释放 time.sleep(0.05) pressed_index = i break # 跳出for循环 time.sleep(0.01) # 短暂延时,防止循环空跑耗电 return pressed_index def check_sequence(seq): """让玩家重复整个序列,并逐项检查""" for i, correct_color in enumerate(seq): player_color = wait_for_button() if player_color != correct_color: return False # 按错,游戏结束 # 按对了,可以给一个简短的成功提示,比如快速闪烁一下对的灯 leds[player_color].value(1) time.sleep(0.1) leds[player_color].value(0) return True # 整个序列输入正确

4. 游戏主循环与状态管理将以上函数串联起来,并管理游戏状态(开始、进行中、结束)。

def game_loop(): global sequence, current_level game_active = True sequence = generate_sequence(current_level) while game_active: # 1. 更新OLED显示当前关卡 oled.fill(0) oled.text("Level: {}".format(current_level), 20, 20) oled.show() # 2. 向玩家播放序列 play_sequence(sequence, speed=max(0.1, 0.6 - current_level*0.02)) # 速度随关卡递增 # 3. 获取并验证玩家输入 oled.text("Your turn!", 25, 40) oled.show() if check_sequence(sequence): # 玩家成功 oled.fill(0) oled.text("Correct!", 30, 25) oled.show() time.sleep(1) current_level += 1 if current_level > MAX_LEVEL: oled.fill(0) oled.text("You WIN!", 30, 25) oled.show() time.sleep(3) game_active = False break sequence = generate_sequence(current_level) # 生成更长的新序列 else: # 玩家失败 oled.fill(0) oled.text("Wrong! Score:{}".format(current_level-1), 10, 25) oled.show() # 失败动画:所有LED快速闪烁几次 for _ in range(5): for led in leds: led.value(1) time.sleep(0.1) for led in leds: led.value(0) time.sleep(0.1) time.sleep(3) game_active = False # 游戏结束,回到初始状态 current_level = 1 oled.fill(0) oled.text("Game Over", 25, 25) oled.text("Press to restart", 5, 45) oled.show() wait_for_button() # 等待任意按钮按下以重启

5. 主程序入口最后,在main.py文件中调用初始化函数并启动游戏循环。确保将主循环代码文件命名为main.py,这样ESP32上电后会自动执行。

# main.py if __name__ == '__main__': init_hardware() while True: game_loop()

main.py和依赖的ssd1306.py库文件通过Thonny上传到ESP32的根目录,然后重启设备,游戏就应该跑起来了!

5. 从原型到产品:外壳设计与制作

当面包板上的电路稳定运行后,我们就开始考虑把它变成一个“产品”。这个过程能让孩子理解工程设计中的另一个重要环节——机械结构与外观设计。

5.1 3D建模与设计考量

我们使用免费的在线3D建模软件(如Tinkercad)进行设计。设计外壳时需要考虑以下几点:

  1. 固定与定位:外壳需要留出精确的孔位来固定ESP32开发板、OLED屏幕、4个按钮和4个LED。LED的孔需要稍微大一点,以便嵌入和扩散光线。
  2. 按钮手感:按钮帽要略高于外壳表面,并且周围留有间隙防止卡住。我们在按钮下方设计了支撑柱,确保按下时受力均匀。
  3. 电池仓与充电口:需要为锂电池设计一个容易放入取出的仓室,并为充电模块的Micro USB口开一个访问孔。
  4. 散热与组装:ESP32在运行时会有轻微发热,外壳顶部和底部我们设计了一些栅格状的通风孔。外壳设计为上下盖结构,用螺丝固定,方便后期维修和更换电池。
  5. 美学:和孩子一起选择颜色,并在外壳上刻上游戏的名字“Memory Master”和他的名字缩写,增加归属感。

5.2 焊接与内部走线

有了外壳,就需要将面包板上的临时连接变为永久性的可靠连接。

  1. 准备万用板:根据外壳内部空间,裁剪一块合适大小的洞洞板(万用板)。
  2. 规划布局:在板上大致摆放ESP32、按钮、LED、电阻等元件,规划一个整洁的布局,确保所有连接线最短,且不会互相干扰。
  3. 焊接:这是锻炼孩子精细操作和耐心的好机会。从低矮的元件(电阻)开始焊起,再到LED、按钮插座,最后是连接排针和飞线。
    • 技巧:使用助焊剂可以让焊接更顺畅。焊锡不要太多,形成一个小圆锥形即可。每个焊点焊接时间不宜过长(2-3秒),以免烫坏元件或焊盘。
  4. 飞线:对于无法通过板子背面走线连接的引脚,使用不同颜色的细导线(如AWG30硅胶线)进行连接。用热熔胶或扎带固定线束,使其整洁牢固。

避坑指南:焊接LED和按钮时,务必再次确认极性(LED)和引脚对应关系(按钮)。最好在焊接前,用万用表的二极管档或通断档测试一下。一旦焊反,拆下来会很麻烦,可能损坏焊盘。

5.3 总装与测试

将所有模块组装进外壳:

  1. 先将焊好元件的万用板用螺丝固定在下壳内。
  2. 将OLED屏幕对准视窗卡好,并用少量热熔胶固定侧面。
  3. 将按钮从外壳内侧装入孔位,确保其能自由活动。
  4. 将LED从内侧插入孔位,可以使用一小段热缩管作为遮光罩,防止LED之间串光。
  5. 连接电池,并妥善放置电池和充电模块,用双面胶或尼龙扎带固定,防止晃动。
  6. 盖上上盖,拧紧螺丝。

总装完成后,不要急于庆祝。进行全面的功能测试

  • 测试每个按钮是否都能正常触发,且手感一致。
  • 测试每个LED是否能正常点亮,亮度是否均匀。
  • 测试充电功能是否正常(充电指示灯会亮)。
  • 长时间运行游戏,检查是否有过热或程序崩溃的情况。

6. 项目总结与扩展思考

经过这个完整的项目,我儿子不仅学会了焊接、读电路图、3D设计基础,更重要的是,他理解了软件和硬件是如何协同工作的。他看到了一行行抽象的代码,如何转化为具体的灯光闪烁和屏幕显示,又如何通过物理按钮被控制。这种“创造-控制-反馈”的闭环体验,是任何理论课程都无法替代的。

项目过程中几个关键的收获点:

  1. 调试是常态:代码第一次就完美运行的概率极低。学会使用print()输出变量状态,或者用LED闪烁不同次数来指示程序运行到哪一步,是嵌入式开发最基本的调试技能。
  2. 电源管理的重要性:当我们第一次用电池供电时,发现屏幕偶尔会闪烁。后来意识到是电池电量不足时,电压下降导致ESP32和屏幕工作不稳定。这引出了关于电压、电流和电池容量的一堂生动物理课。
  3. 用户体验(UX)细节:比如按钮按下时对应的LED要亮起给予反馈,游戏失败或成功要有明确的声光提示(我们后来加了一个有源蜂鸣器),关卡提升时序列播放速度可以适当加快以增加难度。这些细节让游戏变得“好玩”。

这个项目还有巨大的扩展潜力,可以作为一个持续学习的平台:

  • 增加声音:加入一个无源蜂鸣器,为每种颜色分配一个不同的音调,实现真正的“Simon”游戏体验。
  • 难度与模式:在OLED菜单上增加选择项,比如调整速度、开启“残酷模式”(错一次即结束)、或者改变序列生成规则(如禁止连续同色)。
  • 数据记录:利用ESP32的Flash存储,保存最高分记录。
  • 无线化:利用ESP32的Wi-Fi,将得分上传到简单的网络服务器,或者实现双人对战模式。

这个小小的记忆游戏机,最终远远超出了一个玩具的范畴。它是一把钥匙,打开了一扇通往创造世界的大门。看到孩子从“消费者”转变为“创造者”时眼中的光芒,我觉得所有投入的时间都无比值得。如果你也想为孩子或为自己开启这样一段旅程,不妨就从这样一个具体而微的项目开始吧。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/25 16:20:03

使用Python和Taotoken SDK快速构建一个多轮对话聊天机器人原型

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 使用Python和Taotoken SDK快速构建一个多轮对话聊天机器人原型 本文面向希望快速体验大模型对话能力的开发者,介绍如何…

作者头像 李华
网站建设 2026/5/25 16:17:18

5分钟免费搞定HS2汉化:Honey Select 2完整中文补丁终极教程

5分钟免费搞定HS2汉化:Honey Select 2完整中文补丁终极教程 【免费下载链接】HS2-HF_Patch Automatically translate, uncensor and update HoneySelect2! 项目地址: https://gitcode.com/gh_mirrors/hs/HS2-HF_Patch 还在为Honey Select 2的日文界面而烦恼吗…

作者头像 李华
网站建设 2026/5/25 16:16:15

KMS智能激活工具:Windows和Office一键永久激活的终极解决方案

KMS智能激活工具:Windows和Office一键永久激活的终极解决方案 【免费下载链接】KMS_VL_ALL_AIO Smart Activation Script 项目地址: https://gitcode.com/gh_mirrors/km/KMS_VL_ALL_AIO 还在为系统激活问题而烦恼吗?KMS_VL_ALL_AIO智能激活脚本为…

作者头像 李华
网站建设 2026/5/25 16:10:43

【IF-SAFE-02】功能安全入门:基础设施安全 - 电源/时钟/SCU的守护

IF-SAFE-02_基础设施安全 【IF-SAFE-02】基础设施安全 - 电源/时钟/SCU的守护 本文深入解析AURIX™ TC3xx芯片的基础设施安全机制,涵盖PMS电源监控、时钟冗余备份、SCU看门狗及温度传感器的安全设计原理,揭示芯片如何通过多层防护机制应对共因失效&…

作者头像 李华
网站建设 2026/5/25 16:10:09

AI语音转换完全指南:从零开始掌握AICoverGen的3个关键步骤

AI语音转换完全指南:从零开始掌握AICoverGen的3个关键步骤 【免费下载链接】AICoverGen A WebUI to create song covers with any RVC v2 trained AI voice from YouTube videos or audio files. 项目地址: https://gitcode.com/gh_mirrors/ai/AICoverGen AI…

作者头像 李华