news 2026/9/23 2:48:41

Johnny-Five 驱动 LED 点阵屏(Led.Matrix)实战:从 MAX7219 到 HT16K33 的完整指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Johnny-Five 驱动 LED 点阵屏(Led.Matrix)实战:从 MAX7219 到 HT16K33 的完整指南
  • IoT
  • 机器人
  • 嵌入式

【免费下载链接】johnny-five

JavaScript Robotics and IoT programming framework, developed at Bocoup.

项目地址:https://gitcode.com/gh_mirrors/jo/johnny-five
点击查看免费下载

本指南以 Johnny-Five 官方示例 docs/led-matrix.md 为核心,系统讲解如何使用five.Led.Matrix在 Arduino 上驱动 8×8 LED 点阵屏:从 MAX7219 芯片的 SPI 接线、心形图案与滚动文字绘制,到基于 I2C 的 HT16K33 控制器,再到双屏级联与 REPL 交互调试。读完本文,你将掌握二进制点阵数据格式、核心 API 用法以及底层LedControl的实现原理,可以独立实现自定义图形、字符动画和多屏显示方案。

一、Led.Matrix 是什么

Led.Matrix是 Johnny-Five 提供的高层 LED 点阵控制组件,定义于 lib/led/matrix.js。它继承自 lib/led/ledcontrol.js 中的LedControl类,构造时通过options.isMatrix = true切换到矩阵模式,并挂接字符表LedControl.MATRIX_CHARSLed.Matrix同时被注册为five.Led.Matrix,与five.Ledfive.Led.RGBfive.Led.Digits一起通过 lib/led/index.js 对外导出。

从源码结构看,LedControl内部通过 "Controller" 机制支持两种完全不同的底层驱动:

控制器通信方式典型芯片构造要点
DEFAULT(默认)SPI 类三线(data/clock/cs)MAX7219 / MAX7221必须提供pins
HT16K33I2C宏晶 HT16K33(Adafruit LED Backpack 常见)必须提供controller: "HT16K33"addresses

LedControl的 JSDoc 明确标注:默认控制器的引脚参数只接受{data, clock, cs}对象或[data, clock, cs]数组(见 lib/led/ledcontrol.js L46-L54),而dims(屏幕尺寸)、isBicolor(双色)等选项仅对 HT16K33 生效。

二、硬件准备与接线(MAX7219 默认控制器)

官方示例使用的硬件是 Arduino 板 + 基于 MAX7219 芯片的 8×8 点阵模块。接线如图:

接线要点(MAX7219 采用类似 SPI 的三线串行协议,时钟同步逐位移位输出):

  • data(数据线 DIN)→ Arduino 数字引脚
  • clock(时钟线 CLK)→ Arduino 数字引脚
  • cs(片选线 CS/LOAD)→ Arduino 数字引脚
  • 5VGND为模块供电并与主控共地

官方示例将data: 2, clock: 3, cs: 4接到 Arduino 的 D2/D3/D4。Fritzing 原始接线图见 docs/breadboard/led-matrix.fzz。

在源码层面,DEFAULT 控制器初始化时会把这几个引脚全部设置为OUTPUT,并使用board.shiftOut(pins.data, pins.clock, byte)按设备数量逐字节移位输出(见 lib/led/ledcontrol.js L762-L998 的DEFAULT控制器实现),cs拉低后开始传输、拉高完成锁存。

三、第一个示例:心形图案与滚动文字

从命令行运行官方示例:

node eg/led-matrix.js

完整源码见 eg/led-matrix.js,代码如下:

var five = require("johnny-five"); var board = new five.Board(); board.on("ready", function() { var heart = [ "01100110", "10011001", "10000001", "10000001", "01000010", "00100100", "00011000", "00000000" ]; var matrix = new five.Led.Matrix({ pins: { data: 2, clock: 3, cs: 4 } }); matrix.on(); var msg = "johnny-five".split(""); // Display each letter for 1 second function next() { var c; if (c = msg.shift()) { matrix.draw(c); setTimeout(next, 1000); } } next(); this.repl.inject({ matrix: matrix, // Type "heart()" in the REPL to // display a heart! heart: function() { matrix.draw(heart); } }); });

这段代码覆盖了Led.Matrix最核心的四个操作:

  1. 构造:通过pins声明三根控制线,缺省控制器即 MAX7219;
  2. 开机matrix.on()写入 SHUTDOWN 操作码使屏幕点亮(详见下文 API 章节);
  3. 逐字绘制matrix.draw(c)接受单个字符,内部查字符表渲染;
  4. REPL 注入:把matrix和自定义的heart()注入交互终端,运行时可直接输入heart()显示心形。

注意:five.Led.Matrixdraw()一次只接受"单个字符"或"完整行数据数组",因此官方示例用msg.shift()逐个取出字符、配合setTimeout(next, 1000)实现每秒滚动一个字符的轮播效果。

四、深入理解二进制点阵数据格式

示例中的heart数组是点阵绘制的核心数据格式:8 个字符串,每行 8 个字符,1表示该像素点亮,0表示熄灭。把数组逐行读出来,正好拼出一颗心:

01100110 10011001 10000001 10000001 01000010 00100100 00011000 00000000

draw()的实现中(lib/led/ledcontrol.js L364-L409),如果传入的是数组,则直接作为逐行数据使用;如果传入的是单个字符,则从ledCharacters.MATRIX_CHARS字符表查找对应字形,然后逐行调用row(addr, idx, rowData)下发。字符表定义于 lib/led/led-chars.js,覆盖:

  • 标点符号与符号:空格、!"#$%&'()*+,-./[\]^_`:;<=>?@{|}~
  • 数字0-9
  • 大写字母A-Z(每个字形 8 行,采用 5×7 风格点阵,行值最高0x1F即 5 位有效)

另外 lib/led/ledcontrol.js L1067-L1092 会在加载时动态生成双位数"00"-"99"的字形(左数字占 3 位、右数字移位合并),因此matrix.draw("42")这类双字符也被原生支持。

draw()还会校验字符行数与屏幕行数的一致性:当传入数组长度与rows不匹配时会抛出Invalid character错误;若字符表字形长度小于屏幕行数,会自动补齐 0(见 L385-L394)。

五、Led.Matrix 核心 API 详解

MatrixLedControl继承的公开方法,在 lib/led/ledcontrol.js L156-L426 中有完整定义,逐一说明:

5.1 开关与亮度

  • on([addr])/off([addr]):不带参数作用于所有级联设备,带addr只作用于第addr块。实现上通过send(addr, OP.SHUTDOWN, 1|0)写入 MAX7219 的关断寄存器(0x0C)。
  • brightness(addr, val):亮度val取值 0-100,内部经Board.map(val, 0, 100, 0, 15)映射为 0-15 级后写入OP.INTENSITY(0x0A)。不传addr则作用于全部设备。

5.2 绘制方法

  • draw(chr)/draw(addr, chr):绘制单个字符或自定义行数据数组(上文已述)。
  • clear([addr]):清屏。DEFAULT 控制器实现为向每行写入 0。
  • led(addr, row, col, state):点亮/熄灭单个像素点,statetrue/false1/0;MAX7219 模式按0x80 >> col计算列位并写入行寄存器。
  • row(addr, row, val):写入一整行,val可为 0-255 的数字或"01100110"这样的二进制字符串(内部parseInt(val, 2))。仅矩阵设备支持,否则抛出异常。
  • column(addr, col, value):写入一整列,value在 8×8 或 16×8 屏上为 8 位值(0-0xFF),在 8×16 屏上为 16 位值(0-0xFFFF);实现上逐行调用led()
  • digit(addr, position, chr):矩阵模式下会转调draw()(七段数码管模式下才按位段寻址,见 L224-L229)。

5.3 多设备辅助

  • each(callbackfn):遍历所有级联设备,回调callbackfn(deviceIndex)on/off/clear/draw/brightness等方法的无参调用都基于它广播。
  • device(addr):返回一个以addr预绑定、可链式调用的方法集对象,方便对指定设备做局部操作。

5.4 尺寸与方向

LedControl.MATRIX_DIMENSIONS(L1094-L1107)支持三种矩阵规格:8x816x8(16 行 8 列)、8x16(8 行 16 列),默认8x8。构造时若行列组合非法(如16x16),会直接抛出Invalid matrix dimensions specified: must be 8x8, 16x8 or 8x16

LedControl.DIRECTIONS(L1047-L1058)定义UP/RIGHT/DOWN/LEFT四向常量,供 HT16K33 旋转逻辑与上层动画使用。

六、级联多屏:双 MAX7219 点阵实战

Led.Matrix天然支持 MAX7219 级联(多个模块的DOUT → DIN串接)。官方进阶示例 docs/led-matrix-tutorial.md(源码 eg/led-matrix-tutorial.js)演示了双屏用法:

var temporal = require("temporal"); var readline = require("readline"); var five = require("johnny-five"); var board = new five.Board({ repl: false }); var CHARS = five.LedControl.MATRIX_CHARS; board.on("ready", function() { var display = new five.Led.Matrix({ pins: { data: 2, cs: 3, clock: 4, }, devices: 2 // 级联了两块 MAX7219 点阵 }); display.on(0); display.on(1); // 第二块屏画"眨眼"动画:两帧交替 function winker() { var a = [0, 102, 102, 102, 0, 129, 66, 60]; var b = [0, 96, 96, 102, 0, 129, 66, 60]; display.draw(1, a); temporal.queue([{ delay: 50, task: ... }, ...]); } winker(); // 第一块屏通过 readline 读取终端输入逐字显示 rl.on("line", function(text) { output = text; draw(); }); });

这个示例体现了三个实战技巧:

  1. devices: 2声明级联数量,display.on(0)/display.on(1)分别点亮两块屏;
  2. 每块屏独立绘制display.draw(0, char)在 0 号屏显示字符,display.draw(1, 帧数据数组)在 1 号屏播放动画帧;
  3. 动画帧复用同一数据格式a/b两个长度为 8 的数字数组就是两帧"眼睛",配合temporal库做 50ms 间隔的帧切换实现眨眼效果。

由此可推断,draw(addr, data)的第二参数既可以是字符(查表),也可以是直接的行数据数组,这让自定义动画与"从终端打字上屏"都非常直接。

七、HT16K33:走 I2C 总线的 Adafruit 点阵

如果使用 Adafruit LED Backpack 系列点阵(内置 HT16K33 驱动芯片),改用 I2C 控制器,无需三根 SPI 线,只需 SDA/SCL 两根数据线和电源。官方文档 docs/led-matrix-HT16K33.md 给出了完整示例(源码 eg/led-matrix-HT16K33.js):

node eg/led-matrix-HT16K33.js
var five = require("johnny-five"); var board = new five.Board(); board.on("ready", function() { var heart = [ "01100110", "10011001", "10000001", "10000001", "01000010", "00100100", "00011000", "00000000" ]; var matrix = new five.Led.Matrix({ addresses: [0x70], controller: "HT16K33", rotation: 3, }); matrix.clear(); matrix.draw(heart); });

HT16K33 控制器的底层实现(lib/led/ledcontrol.js L429-L754)有几个关键行为:

  • 地址管理:合法的 I2C 地址集合为0x70-0x77(Set 类型维护,L429),每个地址被占用后从集合中移除,避免与 I2C 总线上的其他 HT16K33 冲突;非法地址抛出Invalid HT16K33 controller address
  • rotation旋转:构造时可指定1/2/3,用于匹配不同封装(如 Adafruit 16×8 双屏的物理方向);led()内部按旋转值做行列坐标变换(L592-L613),并对 8×8 单色屏做列环绕(L617-L619)。
  • 操作码SHUTDOWN: 0x20BRIGHTNESS: 0xE0BLINK: 0x80。初始化时自动执行on、关闭闪烁blink(device, false)、亮度 100 并清屏。
  • blink(addr, val):支持"slow"(每 2 秒)、"normal"(每 1 秒)、"fast"(每 500ms)三种闪烁频率,或false关闭,对应数据手册中的 6/4/2/0。
  • 双色支持isBicolor: trueled()state可传LedControl.COLORS.RED / YELLOW / GREEN(定义于 L1041-L1045),分别控制红/绿/黄三色 LED 的位操作。
  • writeDisplay:每次修改后通过io.i2cWrite(address, bytes)一次性把 8 行的低 8 位与高 8 位写入显示缓冲。

另外注意:scanLimit方法在 HT16K33 控制器下未实现,会抛出提示错误(L698-L703);print()方法在矩阵模式下同样抛出Led.Matrix does not yet support the print method(L278-L281),因此矩阵场景统一使用draw()

八、运行、调试与 REPL 交互

8.1 运行前提

  • 需要 Arduino 开发板并烧录 Johnny-Five 依赖的 Firmata 固件;
  • 在项目根目录安装依赖后运行示例:node eg/led-matrix.js(示例使用../lib/johnny-five本地引用,见 eg/led-matrix.js L1);
  • 对 HT16K33 示例同理:node eg/led-matrix-HT16K33.js

8.2 REPL 实时调试

five.Board()默认会开启 REPL(docs/repl.md 有专门说明)。官方示例用this.repl.inject(...)把运行时对象注入交互终端,启动后可以直接输入:

heart() // 显示心形 matrix.off() // 关屏 matrix.on() // 开屏 matrix.draw("A") // 显示字母 A matrix.clear() // 清屏

这种"脚本绘制 + 终端即时调试"的组合,非常适合在不动代码的情况下快速验证图形与动画帧,是点阵项目开发调试的推荐姿势。

8.3 源码与测试参考

想深入了解实现细节,可继续阅读:

  • 组件入口:lib/led/matrix.js(Matrix extends LedControlisMatrix = true
  • 核心实现:lib/led/ledcontrol.js(两种控制器、操作码、绘制方法、MATRIX_DIMENSIONSCOLORSDIRECTIONS
  • 字形字符表:lib/led/led-chars.js(MATRIX_CHARSDIGIT_CHARS
  • 示例程序:eg/led-matrix.js、eg/led-matrix-tutorial.js、eg/led-matrix-HT16K33.js
  • 官方文档:docs/led-matrix.md、docs/led-matrix-tutorial.md、docs/led-matrix-HT16K33.md

九、总结

Led.Matrix把 MAX7219 的 SPI 时序与 HT16K33 的 I2C 寄存器操作全部封装成统一的draw/clear/on/off/led/row/columnAPI,上层只需关心"8 行二进制数据"这一种图形描述格式。无论是官方的心形图案、滚动字母,还是双屏眨眼动画、Adafruit 背板点阵,都遵循同一套数据模型——这正是 Johnny-Five 矩阵驱动最值得掌握的设计思路:把硬件差异收敛到 Controller 层,把创造力留给数据数组。

  • IoT
  • 机器人
  • 嵌入式

【免费下载链接】johnny-five

JavaScript Robotics and IoT programming framework, developed at Bocoup.

项目地址:https://gitcode.com/gh_mirrors/jo/johnny-five
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

蓝色星空BBS避坑指南:3个坑让新手少走弯路

蓝色星空BBS避坑指南:3个坑让新手少走弯路 官方文档翻了三遍还是记不住重点?别慌,这正是我写这篇蓝色星空BBS避坑指南的原因。很多刚接触这块的运维开发同学,一上来就被长篇大论的配置说明劝退。其实核心逻辑就那几件事,只是没人帮你把废话过滤掉。今天咱们不背文档,只聊真问题。 概念速懂:这到底是个啥…

作者头像 李华
网站建设 2026/9/23 2:47:55

猎天使魔女pc性能优化实战面试突击指南

猎天使魔女pc性能优化实战面试突击指南 面试被问到猎天使魔女pc在PC端的渲染瓶颈时,你愣了五秒,脑子里一片空白。这种场景太熟悉了,简历上写着“熟悉大型3D项目优化”,结果面试官只问了一句“魔女2 PC版怎么解决高帧率下的Draw…

作者头像 李华
网站建设 2026/9/23 2:47:33

天堂2sf源码解析一文搞懂转岗实战

天堂2sf源码解析一文搞懂转岗实战 刚学完 Python 语法,打开 IDE 却盯着空白编辑器发呆?这是很多转行新人的真实困境。代码会写,项目不会搭,这是典型的“技能孤岛”现象。 在掘金技术社区的技术分享中,资深工程师常强调: 脱离业务场景的语法学习,只是机械记忆。…

作者头像 李华
网站建设 2026/9/23 2:47:13

发offer前必看的5个新手避坑指南

发offer前必看的5个新手避坑指南 凌晨两点,你盯着屏幕上的红色报错信息,心里只剩一个念头:这代码到底怎么就挂了?Stack Trace 长得像天书,从最底层的 NullPointerException 到最外层的 ServiceException…

作者头像 李华