一个用于 WS281x/NeoPixel (WS2811, WS2812, WS2812B, WS2813) RGB LED 灯条、灯环、灯棍、灯矩阵等的 Swift 库
此库简化了 WS281x LED 系列 (WS2811, WS2812, WS281x) 的配置,这些 LED 有时以 NeoPixels(或 LED 矩阵的 NeoMatrix)的名义销售,无论它们的销售形式如何:灯条、矩阵、灯环等...
您将能够设置单个像素的颜色(使用顺序和矩阵坐标),或者通过单个调用批量设置它们(速度更快,建议用于更流畅的动画)。点击这里 或 这里 查看两个实时 GIF 动画,展示了您可以使用此库做什么。
首先,硬件方面需要注意,WS281x LED 是 3 引脚 5V 设备(Vcc、DataIN、GND),但大多数时候可以容忍 3.3V 的 DataIN 信号,例如 RaspberryPi 的 GPIO 引脚(和其他 ARM 板的 GPIO)产生的信号。
如果您注意到将 LED 直接连接到 GPIO 时,LED 闪烁或亮度不足,则可能需要一个电平转换器/转换器/翻译器用于您的数据引脚。有很多不同的方法(具有不同的性能)可以将 3.3V 信号转换为 5V 信号,但解决此特定问题最具成本效益的方法可能只是购买一个简单的电平转换器,例如 SparkFun 上的这个。它工作完美,您只需要焊接一个排针,就可以使用了。
有关 WS281x/NeoPixel LED 的更多硬件信息,请查看 Adafruit 的 Überguide。
现在,对于软件方面,假设我们使用一个带有 60 个 WS2812B LED 的灯条,我们需要做的第一件事是从 SwiftyGPIO 获取一个 PWMOutput
的实例,并使用它来初始化 WS281x
对象。
import SwiftyGPIO
import WS281x
let pwms = SwiftyGPIO.hardwarePWMs(for:.RaspberryPi2)!
let pwm = (pwms[0]?[.P18])!
let numberOfLeds = 60
let w = WS281x(pwm,
type: .WS2812B,
numElements: numberOfLeds)
然后,我们需要指定 LED 的数量以及我们正在使用的 LED 类型(.WS2811
、.WS2812
或 .WS2812B
),该库将使用该类型来确定这些 LED 的正确信令时序。
让我们首先清除灯条中的所有 LED,将它们设置为 rgb 颜色 #000000
var initial = [UInt32](repeating:0x0, count: numberOfLeds)
w.setLeds(initial)
w.start()
w.wait()
使用 setLeds
,我们将灯条配置为包含 60 个 32 位元素的数组,这些元素包含格式为 0x00RRGGBB
的像素 24 位颜色。 完成后,我们调用 start()
发送信号,然后调用 wait()
以完成灯条的配置。
然后,我们可以设置灯条上的单个像素
w.setLed(10, r: 0xF0, g: 0, b: 0)
或者,如果我们有一个矩阵,我们也可以使用两个特定的附加方法,它们使用两种不同的 2D 坐标方案。
您的矩阵的连接方式可能与这两种方式不同,通过使用 setLed() 设置单个像素来进行一些测试,以了解 LED 的连接方式,或者使用蛇形效果,该效果从头到尾滚动显示序列。
让我们为矩阵设置 (4,4) 处的 LED,其中每行以序列中 (row-1)*width 元素开始(例如,Nulsom Rainbow Matrix),如下所示
0 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15
在这种情况下,我们将使用 setLedAsMatrix
w.setLedAsMatrix(x: 4, y: 4, width: matrixWidth, r: 0, g: 0, b: 0xF0)
现在,让我们为矩阵设置 (5,2) 处的 LED,其中每行都连接到上一行的最后一个元素(例如,Pimoroni UnicornHat),如下所示
3 2 1 0
4 5 6 7
11 10 9 8
12 13 14 15
在这种情况下,我们将使用 setLedAsSequentialMatrix
w.setLedAsSequentialMatrix(x: 5, y: 2, width: matrixWidth, r: 0, g: 0, b: 0xF0)
如果这两种方法都没有将矩阵的像素设置在正确的位置,请使用 setLed
来实现您自己的实现或执行批量 setLeds
(如您将在示例中看到的那样,这也是我通常做的事情)
请记住,一旦您调用了其中一个 setLed*
方法,始终调用 start()
以发送将配置 WS2812 LED 序列的信号,并使用 wait()
等待配置的执行完成(仅当您要确保配置将完整应用时才需要,例如,在新的效果之前清除 LED,或者在退出之前干净地关闭 LED 灯条时)。
像往常一样,Adafruit 有一个非常详细的帖子 介绍 NeoPixel 矩阵中的 LED 排列。
完成后(甚至在 defer
块中),请记住使用以下命令清除此库所需的所有临时 PWM 设置
w.cleanup()
所有 SwiftyGPIO 支持的,带有基于模式的 PWM 信号发生器的板,目前只有 RaspberryPi。
要使用此库,您需要 Swift 3.x/4.x。
下面的示例将使用 RaspberryPi 2 板,但您可以轻松地修改该示例以使用其他支持的板之一,RaspberryPi2 的完整工作演示项目可在 Examples
目录中找到。
请参阅 SwiftyGPIO readme 以获取 Swift 安装说明。
一旦您的板运行 Swift,如果您的版本支持 Swift Package Manager,您可以简单地将此库添加为项目的依赖项,并使用 swift build
进行编译
let package = Package(
name: "MyProject",
dependencies: [
.Package(url: "https://github.com/uraimo/WS281x.swift.git", majorVersion: 2),
...
]
...
)
目录 Examples
包含使用 SPM 的示例项目,编译它并使用 ./.build/debug/TestWS2812B
运行该示例。
如果不支持 SPM,您需要手动下载该库及其依赖项
wget https://raw.githubusercontent.com/uraimo/WS281x.swift/master/Sources/WS281x.swift https://raw.githubusercontent.com/uraimo/SwiftyGPIO/master/Sources/SwiftyGPIO.swift https://raw.githubusercontent.com/uraimo/SwiftyGPIO/master/Sources/Presets.swift https://raw.githubusercontent.com/uraimo/SwiftyGPIO/master/Sources/PWM.swift https://raw.githubusercontent.com/uraimo/SwiftyGPIO/master/Sources/Mailbox.swift https://raw.githubusercontent.com/uraimo/SwiftyGPIO/master/Sources/SunXi.swift
下载所有文件后,创建一个额外的文件,其中将包含您的应用程序的代码(例如,main.swift)。 准备好代码后,使用以下命令进行编译
swiftc *.swift
编译器将创建一个 main 可执行文件。
1. 我可以控制多少个 LED?
更新频率和功耗是限制因素。 随着 LED 数量的增加,配置所有连接的 LED 需要越来越多的时间,并且功耗也会增加。 虽然您可以通过将灯条连接到外部 5V 电源适配器而不是使用板的 5V/GND 引脚来解决电源问题,但更新频率问题与 WS281x 协议的时序特性有关。
您可以使用大约 400-500 个 LED 的灯条而不会出现问题,但随后您将开始看到逐渐减少的刷新时间,这可能不适合快速动画。 该库可以驱动多少个 LED? 这取决于 VideoCore 子系统能够分配多少连续内存,有人报告说使用类似的库能够从 RaspberryPi1 控制超过 3000 个 LED。
2. 当我使用 RaspberryPI 音频输出时,为什么该库似乎无法工作?
此库使用的 PWM 硬件与音频输出共享,您不能同时使用它们,并且某些操作系统可能会默认启用音频端口。
您可能需要(ATM,Raspbian 和 Ubuntu 不需要)通过添加到 /etc/modprobe.d/snd-blacklist.conf
来将音频模块列入黑名单
blacklist snd_bcm2835
3. 这是否适用于 APA102/DotStar LED?
否,因为 APA102 LED 使用标准 SPI 连接。
4. 为什么 WS2812B 有两个枚举值
WorldSemi 在 2017 年初发布了 WS2812B 的更新版本,该版本需要更长的复位延迟,有关更多信息,请阅读此内容。 如果您的 WS2812 LED 似乎无法工作,请尝试选择较新型号的枚举值。