第一次打开,只做这五步
- 打开 押题工程选择器,按任务书关键词选择最接近的工程。
- 在 VS Code 中直接打开
D:\AI开发\ceping\arduino_pio\工程名,必须看得到platformio.ini。 - 先看
include/contest_user_config.h改引脚,再看src/task_logic.cpp改题目规则。 - 先点击 PlatformIO 的勾号编译,成功后再接线、烧录并打开 115200 串口。
- 输入
SELFTEST、PINOUT、STATUS,然后按评分点逐项修改和验收。
比赛只走 Arduino 路线。不要新增 lib_deps,不要临时切换框架。每个代码文件顶部已经用中文说明文件作用、调用关系和现场修改位置。
30 秒选择工程
| 题目最难的部分 | 首选工程 | 任务书 |
|---|---|---|
| 分级报警、静音、闪烁 | mock_01_alarm | 押题 01 |
| Touch、ADC 阈值、保持 | mock_02_touch_adc | 押题 02 |
| ASCII 文本命令、查询上报 | mock_03_uart_controller | 押题 03 |
| 倒计时、阶段、顺序控制 | mock_04_traffic_timer | 押题 04 |
| 计数、秒表、反应时间 | mock_05_button_stopwatch | 押题 05 |
| 帧头、LEN、CMD、SUM/CRC | mock_06_binary_uart | 押题 06 |
| 模拟量、PWM、亮度、频率 | mock_07_adc_pwm | 押题 07 |
| 密码、序列输入、三错锁定 | mock_08_touch_access | 押题 08 |
| 多个模块混合,无法归类 | universal_console | 万能速查 |
打开详细选择器可查看每种题通常改哪个函数。
整个离线工具包的结构
下面是你会在磁盘看到的完整逻辑结构。带“历史备份”或“自动生成”的目录比赛时不用打开。
D:\AI开发\ceping\
├─ README_FIRST.html ← 总入口,就是本页
├─ arduino_pio\ ← 比赛真正使用的 9 个完整工程
│ ├─ universal_console\ ← 无法归类时的万能兜底
│ ├─ mock_01_alarm\ ← 声光报警
│ ├─ mock_02_touch_adc\ ← Touch + ADC
│ ├─ mock_03_uart_controller\ ← UART 文本命令
│ ├─ mock_04_traffic_timer\ ← 倒计时/顺序状态机
│ ├─ mock_05_button_stopwatch\ ← 秒表/反应测试
│ ├─ mock_06_binary_uart\ ← UART 二进制帧
│ ├─ mock_07_adc_pwm\ ← ADC/PWM 联动
│ └─ mock_08_touch_access\ ← Touch 密码门禁
├─ docs\ ← 全部离线 HTML 教程
│ ├─ index.html ← 文档目录
│ ├─ question_router.html ← 题目关键词选工程
│ ├─ mock_01...mock_08.html ← 八份任务书与评分表
│ ├─ arduino_quickstart.html ← VS Code / PlatformIO 操作
│ ├─ quick_reference.html ← 引脚、API、改题速查
│ ├─ special_drills.html ← 八道专项训练
│ ├─ troubleshooting.html ← 编译、烧录、硬件排障
│ ├─ build_verification.html ← 九个固件大小和 SHA-256
│ ├─ idf_quickstart.html ← 历史备份说明,不用打开
│ └─ style.css ← 所有 HTML 共用样式
├─ modules\ ← 可复制的最小代码片段
│ ├─ arduino\ ← 比赛可用,8 个中文注释片段
│ └─ esp_idf\ ← 历史备份,不用打开
├─ tools\ ← PowerShell/CMD 离线工具
│ ├─ build_arduino.ps1 ← 编译一个 Arduino 工程
│ ├─ build_all_arduino.ps1 ← 编译全部 9 个工程
│ ├─ verify_arduino_offline.ps1 ← 本地依赖扫描 + 全量编译
│ ├─ flash_arduino.ps1 ← 编译并烧录指定 COM 口
│ ├─ monitor.ps1 ← 打开 115200 串口
│ ├─ detect_ports.ps1 ← 查找开发板 COM 口
│ ├─ open_docs.ps1 ← 打开本页
│ ├─ *.cmd ← 可双击运行的脚本入口
│ └─ *idf*.ps1 / build_all.ps1 ← 历史双框架脚本,不用打开
├─ shared\arduino\ContestToolkit\ ← 公共库的中文注释母版
├─ esp_idf\ ← 早期 ESP-IDF 四工程,历史备份
├─ .openteams\specs\ ← 工具包设计稿,不参与编译
└─ .playwright-mcp\ ← 文档检查生成目录,不参与比赛
每个 Arduino 工程编译后还会出现:
└─ .pio\build\esp32s3_n8r8\ ← PlatformIO 自动生成,不要手改
├─ firmware.bin ← 最终固件
└─ firmware.elf / 中间文件
一个押题工程里面有什么
arduino_pio\mock_XX_xxx\
├─ platformio.ini
├─ include\
│ └─ contest_user_config.h
├─ src\
│ ├─ main.cpp
│ ├─ task_logic.h
│ └─ task_logic.cpp
└─ lib\ContestToolkit\
├─ library.json
└─ src\
├─ ContestToolkit.h / .cpp
└─ Ws2812Rmt.h / .cpp
| 文件 | 它是干什么的 | 现场是否修改 |
|---|---|---|
platformio.ini | 选择 ESP32-S3、Arduino、N8R8 内存和 115200 串口 | 通常不改 |
contest_user_config.h | 集中放 RGB、Touch、ADC、按键、蜂鸣器、UART 和普通输出引脚 | 先改这里 |
main.cpp | 程序起点,只负责创建应用并调用 begin/loop | 通常不改 |
task_logic.h | 把当前题型的回调注册函数告诉 main.cpp | 通常不改 |
task_logic.cpp | 状态、按键动作、Touch 动作、ADC 规则、定时输出和专属命令 | 主要改这里 |
ContestToolkit.h/.cpp | 消抖、定时器、Touch、ADC、通用命令、NVS、输出的稳定底层 | 不要先改 |
Ws2812Rmt.h/.cpp | 把 RGB 数值转换成板载 WS2812 需要的精准波形 | 通常不改 |
library.json | 告诉 PlatformIO 这是本地库;JSON 格式不能写注释 | 不要改 |
程序从哪里开始,到哪里结束
| 顺序 | 函数 | 通俗解释 |
|---|---|---|
| 1 | setup() | 上电后只执行一次,是整个程序起点。 |
| 2 | app.begin() | 初始化串口、默认参数、NVS、GPIO、定时器、Touch 和当前题型。 |
| 3 | loop() | setup 结束后无限重复,程序正常运行没有传统意义上的“结束”。 |
| 4 | app.loop() | 每 10 ms 检查串口、按键、Touch、ADC 和蜂鸣器超时。 |
| 5 | shortPress / touchChanged / adcSample | 公共底层确认输入可靠后,通知当前题型发生了什么。 |
| 6 | tick() | 根据当前状态决定 RGB、蜂鸣器、GPIO 或 PWM 应该怎样输出。 |
| 7 | 回到 loop() | 继续下一轮,直到断电或复位。 |
一句话:公共库负责“看见输入”,task_logic.cpp负责“决定怎么办”,输出函数负责“让硬件表现出来”。
task_logic.cpp 常用函数翻译
| 函数 | 什么时候调用 | 题目变化时通常改什么 |
|---|---|---|
beginTask(app) | 硬件初始化完成后调用一次 | 默认状态、题型专属默认参数 |
printHelp(app) | 输入 HELP 时 | 新增专属命令后补帮助文案 |
shortPress(app) | 按键消抖后确认一次短按 | 短按切换哪个状态或增加什么数值 |
longPress(app) | 按住至少约 1.2 秒再松开 | 复位、确认、清零、紧急模式 |
touchChanged(app, active) | Touch 稳定触发或松开 | 通常只在 active=true时执行一次动作 |
adcSample(app, millivolts) | 完成一轮 ADC 去极值平均 | 阈值、分档、映射和传感器触发规则 |
tick(app, now_ms) | 约每 10 ms | 状态转换、倒计时、灯、声音和 GPIO 输出 |
command(app, command, arguments) | 公共命令不认识时 | 增加题目专属串口命令和参数校验 |
status(app) | 输入 STATUS 时 | 打印本题最关键的内部变量 |
createTaskHooks() | main.cpp 创建 app 时 | 通常不改;它把上面函数注册给底层 |
题目不完全一样时怎样改
- 先选最难模块作为底座。二进制协议选 06,复杂倒计时选 04,ADC/PWM 选 07。
- 先只改引脚。修改
contest_user_config.h后立即编译,确认工程基础没有坏。 - 把题目写成状态。例如待机、运行、报警就是 mode 0、1、2。
- 把输入规则放进事件函数。短按做什么写
shortPress,ADC 超限做什么写adcSample。 - 把状态对应输出放进 tick。不要用长
delay()等待。 - 需要另一题的能力时只复制相关函数思路。九个工程的
ContestApp接口相同,不要复制整份公共库。 - 每拿一个评分点就编译和测试。先输入输出,再状态机,再串口/NVS,最后做错误处理。
| 例子 | 选择底座 | 怎样组合 |
|---|---|---|
| “温度分档报警风扇” | 07 ADC/PWM | 保留 ADC/PWM,从 01 参考静音和报警闪烁规则 |
| “串口协议控制交通灯” | 06 二进制 UART | 保留帧解析,把 04 的阶段状态机写进 06 的 tick |
| “密码门禁并定时上报” | 08 Touch 门禁 | 保留密码状态机,参考 03 的 report_ms 周期上报 |
哪些能改,哪些不要先改
| 级别 | 内容 | 规则 |
|---|---|---|
| 优先修改 | contest_user_config.h、task_logic.cpp | 引脚、阈值、时间、状态、输出、专属命令都在这里。 |
| 按需参考 | modules/arduino | 只复制你理解并需要的片段,先看文件顶部依赖说明。 |
| 通常不改 | main.cpp、task_logic.h、platformio.ini | 除非题目或环境明确要求,否则保持原样。 |
| 不要先改 | lib/ContestToolkit、shared | 它们是九套工程共同验证过的稳定底层。 |
| 绝对不手改 | .pio、firmware.bin、中间文件 | 每次编译自动生成,改了也会被覆盖。 |
默认接线
| 功能 | 引脚 | 接法 |
|---|---|---|
| 板载 RGB | GPIO38 | v1.1;若不亮改为 GPIO48 |
| Touch | GPIO4 | 接导电片,校准时不要触碰 |
| ADC | GPIO1 | 电位器中间脚;两端接 3V3 和 GND |
| 按键 | GPIO15 | 按钮接 GPIO15 与 GND,使用内部上拉 |
| 蜂鸣器 | GPIO16 | 无源蜂鸣器;大电流器件增加三极管 |
| UART1 | TX17 / RX18 | 交叉连接 USB-TTL,电平必须为 3.3 V并共地 |
| 普通 LED/PWM | GPIO21 | GPIO21 → 220 Ω → LED → GND |
禁止把 5 V 直接输入 GPIO 或 ADC。ESP32-S3 GPIO 不是 5 V 耐受,ADC 输入不得超过 3.3 V。N8R8 默认避开 GPIO35–37。
公共串口命令
HELP # 显示公共命令和本题专属命令
PINOUT # 显示固件实际使用的引脚
SELFTEST # RGB、蜂鸣器、ADC、Touch、按键、NVS 快速检查
STATUS # 显示公共状态和本题内部状态
LED 255 0 0 # 手动设置 RGB
BEEP 2000 300 # 2000 Hz 鸣叫 300 ms
ADC READ # 立即读取一次 ADC
ADC AUTO 500 # 每 500 ms 采样
TOUCH READ # 查看 Touch 原始值和基线
TOUCH CAL # 重新校准 Touch
MODE 2 # 切换本题 mode
SET ADC_LOW 1000 # 设置低阈值,单位 mV
SET ADC_HIGH 2200 # 设置高阈值,单位 mV
SET BLINK 300 # 设置闪烁半周期,单位 ms
SET REPORT 1000 # 设置自动上报周期,单位 ms
SAVE / LOAD / FACTORY # 保存、读取、恢复默认值
串口固定为 115200 8N1。文本命令不区分大小写,以回车或换行结束。06 二进制协议使用 UART1,USB 串口只看调试日志。
构建、烧录和串口
VS Code / PlatformIO
- “文件 → 打开文件夹”,选择一个含
platformio.ini的押题工程。 - 状态栏勾号:编译;箭头:烧录;插头:串口监视器。
- 烧录失败时关闭串口监视器;必要时按住 BOOT、点 RESET、松开 BOOT 后重试。
PowerShell 备用
# 查 COM 口
.\tools\detect_ports.ps1
# 编译一套工程
.\tools\build_arduino.ps1 mock_04_traffic_timer
# 烧录,COM5 换成实际端口
.\tools\flash_arduino.ps1 mock_04_traffic_timer COM5
# 打开串口
.\tools\monitor.ps1 COM5
# 断网检查并编译全部 9 个工程
.\tools\verify_arduino_offline.ps1
比赛前检查清单
- 关闭 Wi-Fi 后运行
tools\verify_arduino_offline.ps1,看到ALL 9 ARDUINO PROJECTS BUILD OK。 - 连接开发板运行
tools\detect_ports.ps1,记下 COM 号。 - 烧录万能工程,依次执行
SELFTEST、PINOUT、STATUS。 - 确认板载 RGB 使用 GPIO38 还是 GPIO48,并固定配置。
- 实测按键、Touch、ADC、蜂鸣器、普通 LED 和 UART1。
- 给 USB 数据线、杜邦线、按键、蜂鸣器、电位器准备备件。
- 把本页、选题页、八份任务书和排障页加入浏览器书签。
九个工程的最新固件大小与校验值见 构建验收记录。没有连接开发板时,“编译成功”不能代替“硬件已验证”。