NeoPixel 灯环做机器人眼睛:16灯接线与眨眼代码

2026-10-30 09:39:09 13阅读

想给桌面机器人做表情,最省事的做法是在眼眶位置塞两个圆形灯环。这类可寻址 RGB 灯(WS2812 系列,Adafruit 给它起的商品名叫 NeoPixel)每颗灯珠里都封了一颗驱动芯片,整串只用一根数据线,想让第几颗亮、亮什么颜色,代码里点一下就行。不用移位寄存器,不用一堆 IO 口,新手照着接完线,跑一遍示例就能看到灯环一圈圈亮起来。

这篇按 Adafruit 官方的 NeoPixel Überguide 走一遍:灯环怎么选、线怎么接、库怎么装、示例代码怎么跑,最后说几个新手最常翻车的点。主控用 Arduino Uno 或 ESP32 都行,代码是同一个。

不同尺寸的 NeoPixel 圆形灯环与灯条实物

为什么眼睛位置要用可寻址灯环

普通 RGB 灯只有共阴共阳四根脚,你只能让它整体亮成一种颜色,想做“眼睛眯一下”“瞳孔转一圈”这种效果,得靠 PWM 分别调三个通道,做出来的还是整片颜色渐变,不是逐颗控制。可寻址灯不一样,每一颗灯珠都有地址,一根线上串 16 颗,你可以让第 1 颗亮红、第 8 颗灭、第 16 颗亮蓝,剩下的随便。

WS2812 的通信协议是固定频率的 800 KHz 数据流,每个 bit 占 1.25 微秒,一颗灯要 24 个 bit(红绿蓝各 8 位),也就是 30 微秒。一帧数据发完,线要停至少 50 微秒,灯珠才会把颜色“锁存”显示出来。这个时序很紧,所以驱动库必须用汇编或者精确延时写,自己拿 digitalWrite 慢慢敲是不行的,直接用官方库最省事。

WS2812 单颗灯珠特写,驱动芯片与 RGB 三色芯片封装在同一个支架里

尺寸和形态怎么挑

官方灯环常见的有 12 颗、16 颗、24 颗、60 颗几种。做眼睛最常用 16 颗:外径差不多一枚硬币大小,装在 3D 打印或亚克力眼眶里刚好,光线也够亮。12 颗的更小,适合小尺寸桌面机器人;24 颗和 60 颗的适合做大面积氛围光或者头环,功耗和体积都上去了,眼睛位置用不着。

灯环的背面有 DIN 和 DOUT 两个焊盘,箭头指向数据流动方向。买来是散件,要自己焊三根线:5V、GND、DIN。DIN 接主控的数字口,DOUT 留着,以后想串第二个灯环就用它接下一个的 DIN。

通电点亮状态的 RGB 圆形灯环

接线:电阻、电容、电平这三样别省

官方在基础接线页里反复强调的三件事,新手最容易全省掉,然后就开始遇到“偶尔闪一下”“颜色乱跳”“烧第一颗灯”。

  • 数据线串一颗 300 到 500 欧的电阻。作用是抑制线上的振铃和过冲,第一颗灯最容易被冲坏,串上就踏实了
  • 电源两端并一颗 1000 微法左右的电解电容。灯环从全灭到全亮是瞬间的大电流跳变,电源来不及补,电压会往下掉一下,表现出来就是闪。电容当个小水库,把这个坑填掉
  • 3.3V 主控要加电平转换。ESP32、树莓派这类板子输出 3.3V,而 5V 供电的灯珠要求数据高电平接近电源电压,按常见的 70% 经验值算就是 3.5V,3.3V 差一点点。官方建议加 74AHCT125 或 74HCT245 这类转换芯片。也有人在 4.5V 供电(三节干电池)下直接 3.3V 驱动,因为 70% 只有 3.15V,就够用了

还有一个物理层面的细节:接线的顺序是 GND 先接,再接 5V,最后接数据线。带电插拔数据线,或者电源没稳就插灯,是烧灯珠的常见原因。用可调电源调试时也一样,先把电压调稳再连灯环。

NeoPixel 与主控的接线示意图,数据线串电阻、电源并电容

装库、跑示例,五分钟看到灯亮

Arduino IDE 里打开“工具→管理库”,搜 Adafruit NeoPixel,装最新版。装完在“文件→示例→Adafruit_NeoPixel”下面能看到 simple 和 strandtest 两个例子。simple 是逐颗点亮的极简版,最适合第一次验证接线对不对;strandtest 是效果合集,跑马灯、彩虹、流水全在里面,拿来当“眼睛动效”的素材库很够用。

下面是官方 simple 示例的完整代码,我把 include 的尖括号换成了引号(站点清洗会吃掉尖括号,这是发布规范里的硬要求,代码本身一个字没改)。NUMPIXELS 这里默认就是 16,正好对应 16 颗灯环;PIN 是 6,接在你实际用的那个数字口上就行。

#include "Adafruit_NeoPixel.h"
#ifdef __AVR__
 #include "avr/power.h" // Required for 16 MHz Adafruit Trinket
#endif

// Which pin on the Arduino is connected to the NeoPixels?
#define PIN        6 // On Trinket or Gemma, suggest changing this to 1

// How many NeoPixels are attached to the Arduino?
#define NUMPIXELS 16 // Popular NeoPixel ring size

// When setting up the NeoPixel library, we tell it how many pixels,
// and which pin to use to send signals. Note that for older NeoPixel
// strips you might need to change the third parameter -- see the
// strandtest example for more information on possible values.
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

#define DELAYVAL 500 // Time (in milliseconds) to pause between pixels

void setup() {
  // These lines are specifically to support the Adafruit Trinket 5V 16 MHz.
  // Any other board, you can remove this part (but no harm leaving it):
#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
  clock_prescale_set(clock_div_1);
#endif
  // END of Trinket-specific code.

  pixels.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
}

void loop() {
  pixels.clear(); // Set all pixel colors to 'off'

  // The first NeoPixel in a strand is #0, second is 1, all the way up
  // to the count of pixels minus one.
  for(int i=0; i < NUMPIXELS; i++) { // For each pixel...

    // pixels.Color() takes RGB values, from 0,0,0 up to 255,255,255
    // Here we're using a moderately bright green color:
    pixels.setPixelColor(i, pixels.Color(0, 150, 0));

    pixels.show();   // Send the updated pixel colors to the hardware.

    delay(DELAYVAL); // Pause before next pass through loop
  }
}

烧进去以后应该看到:绿灯从第 0 颗开始,每半秒往下一颗走,一圈走完再从头来。如果一颗都不亮,先查三件事——5V 有没有接、GND 有没有和主控共地、DIN 有没有接反(DIN 接的是主控输出,不是 DOUT)。如果颜色不对,比如你要红色它亮绿色,那不是坏了,是灯珠内部顺序是 GRB 不是 RGB,库里的 NEO_GRB 参数已经处理了,你自己拼颜色值时记得按 GRB 的顺序填。

供电算笔账,别拿 Arduino 的 5V 硬扛

单颗灯珠满亮白光时最大能吃 60 毫安,16 颗就是 960 毫安。Arduino Uno 的 5V 引脚从 USB 取电,总共只能稳定给 500 毫安左右,直接带 16 颗满亮会顶到板子的极限,轻则灯变暗、板子重启,重则烧稳压。官方给的经验值是按每颗 20 毫安估算(混色和动画时实际远低于满白),16 颗大约 320 毫安,这个量级 Uno 还能扛。要做“眼睛眨一下满亮”的效果,就老老实实外接一个 5V 2A 的电源,灯环的 5V 接电源正极,GND 同时接电源负极和主控 GND,共地这一步不能省。

用可调电源给灯环供电,先把电压调稳再连灯

做眼睛动画的思路其实很简单:把 16 颗当成一个圆环,用亮度做“眨眼”——正常状态整体亮度调到 40 左右,眨眼时把亮度在 100 毫秒内压到 0 再拉回来;想做“瞳孔”就用中间几颗亮、外圈暗。库里有 setBrightness 和 ColorHSV 两个函数,前者整体调光、后者用色相角度挑颜色,两行代码就能做出挺像样的表情。新手先把 simple 跑通,再改这两处,不容易乱。

最后提醒一句:灯环不是给机器人“看见世界”用的,它只负责表情和状态提示。真要做视觉,得另配摄像头。但就“让一台铁疙瘩看起来活着”这件事来说,两个灯环的性价比,比加一块屏幕高得多。


作者:隔壁老王的教程
链接:https://www.aiddithome.com/p/80cd83e12bfe2.html
本作版权归作者所有,未经允许请勿转载。若存在违规行为,您可以点击 “举报”。


登录 后发表评论
5条评论
第三次终于亮了
1楼 · 7小时前

想问下,ESP32 用 3.3V 的数据线直驱 5V 灯环到底稳不稳?我这么跑了一周多没出问题,但心里一直没底,看完这篇才知道官方是按 70% 电压算的,4.5V 供电才刚好卡过去。

拆开看看再说
2楼 · 7小时前

供电那段太真实了。我一开始直接拿 Uno 的 5V 口带 24 颗,一开满白板子就重启,还以为是程序写错了,折腾一晚上。后来外接电源就好了。

修啥都行二哥
3楼 · 7小时前

拿灯环做眼睛确实比小屏幕便宜,但亮度太高晚上看着有点吓人,我加了一层磨砂亚克力当扩散片,效果立刻柔和很多。

默默点赞的路人
4楼 · 7小时前

代码里 include 换引号那段解释得清楚。之前一直不明白为什么别人的代码贴到网站上尖括号就没了,现在知道是清洗机制吃掉的。

触底反弹的Tony
5楼 · 7小时前

我用 16 灯环做过桌面小机器人的眼睛,第一个坑就在第一颗灯上——数据线忘了串电阻,亮了几次就灭了。后来补了个 300 欧的,一直稳到现在。这篇把电阻电容那几条讲明白了,省不少试错。