我用自然语言写完了小车的控制逻辑 | 硬件 Vibe Coding 实战

朋友的工作室在暑期开展了一次科创课的前置课程,我过去一起策划了硬件工程部分的内容和材料。

当时在周末参与讨论了一些方案,难点在于:

  1. 如何能够让大部分同学都在课程上做同一样作品(因为时间有限,实际动手环节相当于只有一个周末的时间),但在课程结束之后能够有不同的成果。
  2. 而且同学们的代码基础基本为零,所以在这样的短时间课程中,描述清楚自己想要实现的功能,并且着手初步实现就已经非常了不起了。

为了让同学能在同样的平台上发挥个性,我们设计了多种扩展方向:

  • 车身结构可自由设计与装饰;
  • 不同传感器组合(颜色识别、超声波、循迹、红外等)形成不同功能满足不同的选题;
  • 采用我的“预制”代码进行编程,而且让功能组合模块化,既可实现基础循迹,也可挑战自主不同的传感器组合实验。

顺便,还把之前做的那块板子用上了。

之前写的一篇文章 大模型 AI 对话+控制实验,又手搓了一块开发板,当时是为了赶上小智 AI 的那股风,把原本需要用面包板才能搭建的所有器件都集成到一块板子上,并且还预留了直流电机和充放电的位置,方便扩展。

不过,后续这块板子将会继续优化,计划拆解成两片,降低单片板子的制作成本(当然这是题外话,后续会列出单独文章详解)。

目前而言,如果只是自己玩玩,没什么特殊要求的话,从购物 app 自行购买相应的基础开发板和元器件就行。

我这边用的平台依然是基于 ESP32 和 Arduino IDE,操作简单、上手容易,详细的教程也会在后续更新。

什么是 Vibe Coding?

“Vibe Coding” 是 2025 年开始流行的新概念,由曾任职于特斯拉和OpenAI、专门研究深度学习和计算机视觉的 Andrej Karpathy 提出。它的核心思想是:

用自然语言(Prompt)表达意图,让 AI 写出实现的代码。

简单来说:传统编程是“告诉电脑怎么做”,而vibe coding 是“告诉 AI 我想要什么样的结果”。

例如:

“我希望让灯光像呼吸一样闪烁。”
“当温度超过 30 ℃ 时,风扇慢慢转起来。”
“检测到人靠近时,播放一段欢迎音效。”

AI 理解你的意图后,会自动生成并解释代码。

当然这些话语并不能直接让 AI 生成实际可用的代码,你还需要让 AI 知道,你把灯接哪儿了、把温度传感器接哪儿了、把直流电机接哪儿了、把人体红外传感器接哪儿了…

给小车注入灵魂,硬件 Vibe Coding

为了 AI 写出高质量代码,关键在于描述清楚你的需求

这类嵌入式项目我通常分三层来写 Prompt:

层级说明示例
硬件层指定板子主模块型号、传感器or执行器模块种类与引脚、使用的硬件平台“ESP32-S3, OLED I2C(41,42), 超声波17/18, 电机L9110S(11,12,14,13)”
功能层描述行为逻辑与控制规则“距离障碍物<15cm后退并左转0.5秒后掉头、否则巡线前进”
表达层约定输出格式与风格“请用结构化函数封装,包含注释与调试输出”

所以,最终的 prompt 可能长这样:

请用 ESP32-S3 开发一辆智能小车,请帮我基于 Arduino IDE ,使用 C++ 写一份完整的控制程序。

功能需求:

  • 使用 SSD1306 通过 I2C 接口显示信息(SDA=41, SCL=42)。OLED 显示当前速度、行驶距离、超声波距离、巡线状态、RGB 值。
  • 使用 TCS34725 颜色传感器,只需要读取 RGB 值(不需要颜色识别)。
  • 使用 HC-SR04 超声波模块测距。
  • 使用 L9110S 驱动电机,4 路 PWM 控制,定义引脚为:
    左电机 IN1=11, IN2=12;右电机 IN1=14, IN2=13。
  • 使用 4 路巡线传感器,输入引脚为 37, 36, 35, 45。
  • 使用 WS2812B 灯(3颗),连接引脚为38。

功能逻辑:

  1. 超声波避障优先:距离 < 15cm 时后退、左转避障再掉头。
  2. 巡线功能:使用 4 路传感器加权算法(-3, -1, 1, 3),PID简化为比例控制。
  3. 若失线 < 200ms,继续用上一次误差纠偏;否则停车。
  4. 同时读取颜色传感器值并在 OLED 显示。
  5. 颜色传感器的 RGB 值请做亮度归一化处理,增强差异度(防止偏白)。
  6. LED 灯条状态:
    • LED0:系统运行状态;
    • LED1:超声波距离反馈(红近、橙中、绿远);
    • LED2:颜色传感器实时 RGB 显示。

其他:

  • 在串口输出调试信息。
  • 循环周期 10ms。
  • 保持结构化、模块化的函数划分(例如 readUltrasonic、lineFollow、updateOLED 等)。

请输出完整 Arduino 代码(包含头文件导入、初始化、主循环、函数定义),并能在 ESP32-S3 上运行。

当你把这段文字输出给 ChatGPT 之后,它会输出代码,但可能并不能完全地符合你的要求。

比方说,上述的这段 prompt 中,并没有描述清楚 OLED 如何显示数据。AI 生成的代码可能用了别的第三方库文件(如 SSD1306),而不是你想要的 Adafruit_SSD1306 库,前后的一致性不佳。所以,这个时候你需要针对具体的改进点和 AI 进行沟通:

好,那你接下来就按照这样的接线写Arduino代码。

OLED IIC 12832 – 显示速度和路程内容 – 显示避障距离 – 显示颜色传感器数值和颜色 – 显示巡线参数 请用英文简写表示。目前所有传感器均未连接,请先把所有的显示数值做成合理的随机数,并且封装成函数,每当我接入指定的传感器之后,即可轻松显示。

AI 输出的部分内容如下,里面清晰地把需要下载什么库文件、显示屏的显示效果都写了出来,实际测试效果还行(但小车手上已经发完,没找到实拍图),运行时实时显示速度、距离、颜色。

RGB LED 指示灯分别按超声波距离变化和颜色传感器“看到的颜色”进行闪烁;颜色传感器正常工作;循线的 PID 控制部分也有一定的体现。

// === RGB 状态灯 ===
void updateLEDs() {
  // 运行指示
  strip.setPixelColor(0, strip.Color(0, 150, 0));
  // 超声波距离反馈
  if (ultrasonicDist == -1) strip.setPixelColor(1, strip.Color(0, 0, 0));
  else if (ultrasonicDist < 10) strip.setPixelColor(1, strip.Color(255, 0, 0));
  else if (ultrasonicDist < 30) strip.setPixelColor(1, strip.Color(255, 180, 0));
  else strip.setPixelColor(1, strip.Color(0, 255, 0));
  // 颜色传感器(增强对比后的 RGB)
  strip.setPixelColor(2, strip.Color(rVal, gVal, bVal));
  strip.show();
}

AI生成的巡线函数如下所示:

// === 循线函数(基于权重 + 比例修正) ===
bool lineFollow(int baseSpeed = 100, float Kp = 0.9f) {
  int s[4];
  s[0] = digitalRead(LINE1_PIN);
  s[1] = digitalRead(LINE2_PIN);
  s[2] = digitalRead(LINE3_PIN);
  s[3] = digitalRead(LINE4_PIN);

  int active_count = 0;
  int error = 0;
  for (int i = 0; i < 4; i++) {
    if (s[i]) {
      error += weights[i];
      active_count++;
    }
  }

  if (active_count == 0) {
    if (millis() - line_lost_time < 200) {
      int correction = map(last_error, -3, 3, -50, 50);
      setMotorSpeed(baseSpeed + correction, baseSpeed - correction);
      return true;
    } else {
      stopCar();
      return false;
    }
  }

  line_lost_time = millis();
  last_error = error;

  float norm_err = error / 3.0f; // 近似 -1..1
  int correction = (int)(Kp * norm_err * baseSpeed);
  int left_speed = baseSpeed - correction;
  int right_speed = baseSpeed + correction;

  left_speed = constrain(left_speed, -255, 255);
  right_speed = constrain(right_speed, -255, 255);

  setMotorSpeed(left_speed, right_speed);
  return true;
}

小车通过 4 路红外巡线传感器自动判断线路偏差,并实时修正转向,使其稳定沿线行驶。每个传感器被赋予一个“权重”,表示它距离中心线的远近。当某个传感器检测到黑线时,对应的权重会被加到 error 里。

这里用了最基础的比例控制算法(P 控制)。偏差越大,修正值越大。Kp 是比例系数,用来调节转向灵敏度。计算得到的 correction 会被加减到左右轮速度中。

如果 4 个传感器都没检测到线(说明小车完全偏离轨道),程序会暂时使用“上一次误差方向”继续纠偏 200ms,如果仍找不到,就停下来等待我去干预。

于是,这样一份“预制代码”完成了。

即使同学们是零代码基础,这样让大部分同学都在课程上通过“预制代码”做同一样作品并且根据自己不同的选题选择不同的模块(传感器+执行器),在课程结束之后能够有不同的成果。

当然,如果后续需要深入研究的话,代码的学习还是必不可少的。

未完待续

传统编程你得告诉计算机怎么做,建立在他人代码上手动创作(例如库文件、别人的成功案例等等);而硬件 Vibe Coding 作为一个新词,其本质还是需要基于一个需要能够拥有强大代码能力的AI,并且让我告诉 AI 我想要什么最终效果或者产品。

另外,因为时间比较紧,小车结构本身也是由之前的一个项目直接改的。整体来说,在安装过程中,或多或少还是会遇到一些问题。比如:有些孔的位置没打、小车运动起来没有那么稳等等,这些都是需要在后续的版本中需要改进的地方。

这些工作虽说目前而言没有办法直接使用 AI 代替,但是 AI 总能给我们一些思路和启发。希望能够让同学在“拼装-调试-修改”的过程中理解:一个工程作品,不仅仅是拼装+接电路,而是一个从设计、实现到验证的完整思考过程。

AI 写 DIY 硬件代码不是“偷懒”,而是加快想法实现和快速迭代进行原型验证的方法。

在硬件领域,这意味着:

  • 想法到简单原型的距离被压缩到短至分钟级别;
  • 创意门槛被彻底降低,让更多人能把“脑中的装置”变成现实;
  • 产品经理、工程师角色正在转变:从“写代码的人”,变成“描述系统行为的人”。

更多软硬件教程和知识干货,欢迎关注公众号【晓栋XD】,我将持续分享有关 AI + 软硬件产品创作。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇