xiaobai 头像xiaobai

xiaobai 项目文档 · 更新于 2026-09-11

ESP8266 后驱遥控车(初版 2026-08-25 · 最后更新 2026-09-11 01:25)

拆开后按本文原样接。固件:Documents/Mac管家/wifi_boat/
刷写:arduino-cli compile --fqbn esp8266:esp8266:nodemcuv2 --upload -p /dev/cu.usbserial-110 /Users/xiaobai/Documents/Mac管家/wifi_boat

串口号每次可能变,先 ls /dev/cu.usbserial-* 看实际是几,再填进 -p

手机连热点 wifi-boat / 密码 12345678 → http://192.168.4.1/
左侧竖滑=速度,右侧竖滑=转向急缓,中间九宫格方向,前灯后灯夹在前进两边。
倒车后灯自动亮,前进/停/转弯后灯灭。无语音。

硬件:NodeMCU ESP8266(CP2102)、L298N、两只后驱 N20 6V 150rpm12V 电池、前后小 LED。


更新日志

时间 做了什么
2026-08-25 初版。数字开关全速,网页 8 个按钮,转向靠「一侧轮子停死」
2026-09-10 20:35 确认板子端口为 /dev/cu.usbserial-110(旧笔记里的 -10 已失效)
2026-09-10 20:45 加 PWM 调速:ENA/ENB 改 analogWrite,网页加速度滑块 1~100%,新增 /api/cmd?c=speed&v=N。另加 150ms 启动斜坡,换向时先清零占空比防 L298N 上下桥对冲
2026-09-10 21:00 重写差速转向:内轮 35% / 外轮 100%(原来内轮 0% 会蹭地顿挫),掉头 ±70%,倒车 80%。加串口测试指令,用 pyserial 实测全部占空比通过
2026-09-11 00:50 网页 v5 改版:速度/转向改两侧竖滑,方向居中九宫格,前灯后灯移到前进左右;新增 /api/state 实时轮速条与转弯半径显示;转向急缓可在网页上调(c=turn&v=20~55),不用重新刷机
2026-09-11 01:05 修方向键无响应:方向键改表单 + 隐藏 iframe 提交(不依赖 JS),所有响应加 Connection: close 防 ESP8266 socket 被轮询占满,轮询 400ms→1000ms 且页面隐藏时暂停,页面加 JS 错误显示
2026-09-11 01:15 加跑偏修正:网页「跑偏修正」滑块 -20~+20(负补左轮、正补右轮),串口 trim N;同时加 turn Nwifi 诊断指令
2026-09-11 01:20 热点改 802.11g:ESP8266 默认 11n 广播,部分 iPhone 连不上;测试脚本移入 Mac管家/wifi_boat/tools/,项目里新增 CHANGELOG.md
2026-09-11 01:25 修强制门户不弹窗:补齐各家系统的探测地址(iOS library/test/success.html、Android mobile/status.php、Win11 redirect 等 10 个),并撤掉网页响应上的 Connection: close(只保留在 /api/*

强制门户(连上自动弹界面)怎么工作

手机连上 Wi-Fi 后会自动访问一个固定地址探测网络。只要返回的内容不是它预期的,系统就判定「这个网需要登录」,把我们的控制页弹出来:

系统 探测地址 它期待的
iOS /hotspot-detect.html/library/test/success.html 正文 Success
Android / Chrome /generate_204/mobile/status.php HTTP 204
Windows /ncsi.txt/connecttest.txt/redirect Microsoft NCSI

代码里这些地址一律返回控制页(WebControl.cpp 里那个 portal lambda),所以一定判成"需要登录"。
另外 DNS 开了通配(dns_.start(53,"*",apIp_)),任何域名都指到 192.168.4.1,探测必然落到我们这儿。

不弹窗时怎么办(iOS 会缓存"这个网不用弹"的判断):

  1. 设置 → Wi-Fi → 点 wifi-boat 的 ⓘ → 忽略此网络,重新输密码连一次 ← 这招最灵
  2. 还是不弹就直接在 Safari 打开 http://192.168.4.1/ ,加到主屏幕后跟 App 一样
  3. 确认连没连上:串口发 wifi,看 已连设备 是不是 ≥1

排查:手机连不上 wifi-boat

热点本身起没起来,用串口查(115200 发 wifi):

[WIFI] 模式=AP  SSID=wifi-boat  IP=192.168.4.1  已连设备=0  广播=2

已连设备 是 0 就说明手机没连上来。按顺序试:

  1. 关掉蜂窝数据再连。iOS 发现这个网没有互联网,会自动切回 4G,表现就是"连不上"
  2. 连的时候会弹「此网络无互联网连接」,要点「仍要使用」,别点取消
  3. 设置 → Wi-Fi → 点 wifi-boat 右边的 ⓘ → 忽略此网络,再重新输密码连一次
  4. 还不行就关掉私有无线局域网地址(同一个 ⓘ 页面里)
  5. 密码是 12345678必须 8 位以上,短了 ESP8266 直接拒绝
  6. 固件已经把无线模式从 11n 降到 11gWebControl.cppWiFi.setPhyMode

排查:按了没反应

按顺序查,90% 停在第 1 步:

  1. L298N 有没有接 12V 电池?
    板子只插 USB 时,ESP8266 照常输出 PWM、网页轮速条照常动,但马达一根线都不会转——L298N 的电机电源是独立的,不吃 USB 的电。
  2. L298N 上那个红色/绿色 LED 亮不亮? 不亮就是 12V 没进来。
  3. +5V 跳帽插了吗? 中间那个。拔了逻辑 5V 不起,L298N 不工作。
  4. ENA / ENB 跳帽拔了吗? 没拔就一直全速,8266 控不了。
  5. 上面都正常 → 看网页:按「前进」按钮会不会变蓝、轮速条动不动
  6. 会变蓝 = 指令到了,问题在电机那侧(12V / 接线 / 跳帽)
  7. 不变蓝 = 网页没发到,看页面底部有没有红色「离线」

电源(先接这个)

12V 电池:

线 接到
红 + L298N 螺丝孔 +12V
黑 − L298N 螺丝孔 GND
充电 NTC,空着

L298N 跳帽:

给 8266 供电(二选一,12V 不准进 8266):

  1. L298N +5V → NodeMCU VIN,GND 已共地 → 可拔 USB
  2. 或 USB 充电宝 / 电脑,只供电不控车

8266 ↔ L298N(信号 + 共地)

NodeMCU 丝印 → L298N:

ESP GPIO L298N 作用
GND GND 必须共地
D5 14 ENA 左使能(全速 HIGH)
D1 5 IN1 左方向
D2 4 IN2 左方向
D6 12 ENB 右使能
D7 13 IN3 右方向
D8 15 IN4 右方向

不要用 D3/D4/D0 当电机脚(烧录/LED/拉高不稳)。D8=GPIO15 启动时要保持低,接 IN4 可以。


电机 ↔ L298N

位置 线色(装车时) L298N
左后 白 + 灰 OUT1 / OUT2
右后 黄/蓝(或紫) OUT3 / OUT4

转反了:只对调那一侧两根 OUT,不要改 8266 脚。

直连电池能转、过 298 不转:逻辑 5V 没起来或 ENA/ENB 没打开。12V 已接时插上 +5V 跳帽,ENA/ENB 可先插跳帽测电机,再拔掉改接 8266。


灯光(小 LED,禁止 12V 直插 GPIO)

ESP 接法
前灯 D0 (GPIO16) D0 → 220Ω → LED 正极,负极 → GND
后灯 D3 (GPIO0) D3 → 220Ω → LED 正极,负极 → GND

网页「前灯/后灯」开关。后退自动开后灯。D3 是烧录脚,下次刷机失败先拔后灯再刷。


不要接


调速(2026-09-10 加)

ENA/ENB 改走 PWMconfig.h 里调):

参数 说明
PWM_FREQ_HZ 1000 L298N 是双极型,别超 5kHz
PWM_MAX_DUTY 1023 8266 analogWrite 满量程 = 全速
PWM_MIN_DUTY 300 低于此值减速电机只嗡嗡不转,滑块 1% 也保底 300
RAMP_MS 150 占空比 0→满的爬升时间,抑制起步打滑和电流冲击

转向(2026-09-10 重写)

只有两个后轮 = 差速转向,转弯半径由两轮速度差决定:

R = (轮距 / 2) × (v外 + v内) / (v外 − v内)
动作 内轮 外轮 实测占空比 转弯半径 说明
左转 左 35% 右 100% 358 / 1023 ≈1.04×轮距 平滑弧线,保住 68% 推力
右转 右 35% 左 100% 1023 / 358 ≈1.04×轮距 同上
掉头 左反 70% 右正 70% −716 / 716 ≈0 原地自旋,只用于掉头
后退 80% 80% 818 / 818 倒车限速

旧做法是内轮 0%(停死)——车被停住那只轮子拖着蹭地,顿挫、掉一半推力、还磨胎。
改成 35% 后内侧继续滚,转向依然很急,但顺滑得多。

想更急 → TURN_INNER_PCT 往 20 调;想更飘 → 往 50 调。
SPIN_PCT 不给 100%,双轮反向满速电流翻倍,L298N 和电池都扛不住。

低速时转向会变宽:滑块 50% 时内外比约 46%,30% 时约 59%。
因为 PWM_MIN_DUTY 兜底生效了(内轮算下来低于 300 会被抬到 300)。这是有意保留的——不然内轮直接停转。

串口测试指令(115200)

不用连网页也能测:

f 前进   b 后退   l 左转   r 右转   u 掉头   s 停止
speed 70   设速度     turn 35  转向急缓
trim -8    跑偏修正(负=补左轮 正=补右轮)
stat       看每侧 dir / 目标占空比 / 实际占空比
wifi       看热点状态和已连设备数

测试脚本在项目里:Mac管家/wifi_boat/tools/

python3 tools/test_motor.py     # 自动跑完全部动作,打印实测占空比
python3 tools/demo_drive.py     # 接 12V 电池后跑真车演示序列
python3 tools/demo_drive.py 50  # 50% 速度演示

提速边界(重要)

6V 电机吃的是 12V 电池经 L298N 后的 ~9.5V(L298N 压降约 2.5V),已超速 58%。
所以软件层面 100% 占空比就是天花板,再想快只有硬件:

方案 提升 备注
换 MOSFET 驱动(TB6612 / DRV8871) +15~25% 抢回 2V 压降
换高转速 N20(150→300rpm) +100% 扭矩减半,小车载得动
换更大轮子 线速度 ∝ 轮径 扭矩需求上升
加电池电压 ❌ 别做 6V 电机会烧

网页按钮

速度滑块 + 前进 / 左转 / 右转 / 后退 / 掉头 / 停止 / 前灯 / 后灯

转弯代码(src/motor/Motor.cpp):

void Motor::left() {
  /* 左转:左轮是内侧,慢;右轮外侧,快 */
  setSides(1, TURN_INNER_PCT, 1, TURN_OUTER_PCT);
}

void Motor::right() {
  setSides(1, TURN_OUTER_PCT, 1, TURN_INNER_PCT);
}

void Motor::uturn() {
  setSides(-1, SPIN_PCT, 1, SPIN_PCT);
}