彩色灯带,相信不用老周多说,大家都知道,没准你家里的灯墙里面就有。老周的茅屋是早期建造的,所以没有预留的灯槽,明灯的话是不好看的,因此老周家里没使用灯带。不过,像柜子后面,显示器后面,书桌边沿这些地方,可以贴彩色灯带。书架上也贴了一些,因为那个书架是圣诞树形状的,没办法一条灯带贴完,只能把它剪开 N 段,测算好每一段的距离,再用烙铁加线重新焊接起来(嫌麻烦的话可以直接买连接头,不用焊接)。

买灯带时老周没有买驱动器,毕竟一开始老周就计划自己写个程序来控制灯带的色彩。装饰用的灯带,5V 电压足矣。如果灯较多可以考虑独立供电,5V电源比较方便好弄,手机充电头、锂电池+5V稳压板即可轻松解决。其实,两米长度内直接用开发板供电都没啥问题。要是五米一卷的,用树莓派的5V引脚供电没有问题,但用 ESP32 的话,电压好像有点不够,亮度降低。

老周的卧室里面目前使用的装饰灯是用 ESP 32 做的,两颗18650电池供电(需要稳压模块调到5V电压)。主要是看中 ESP32有 WiFi 功能,上面写个 UDP 服务器,通过接收到的命令来切换灯带颜色。

控制命令比较简单,全用文本格式,客户端只要发送满足格式要求的命令到 ESP32 即可。比如,发送

SET+255 125 127

首先识别出“SET+”,后面三个数值用空格分隔,依次表示 RGB 三个值。例如,让灯变成蓝色

SET+0 0 255

=================================================================================

彩色灯带使用 WS28XX 作为IC,常见的像 WS2812B。每个灯珠都可以单独控制,灯带剪开后只需要串联好就行,灯带末端不需要连接回路,WS28XX 自带回路。

WS28XX 的时序其实很简单,+5V 和 GND 是供电接口,剩下一根数据线来传输信号,所以这货是单数据线控制的。当N个灯珠串联起来后,第一个灯珠的 Din 输入信号,Dout 输出信号;第一个灯珠 Dout 联第二个灯珠的 Din;第二个灯珠的 Dout 联第三个灯珠的 Din ……

我们都知道,RGB三个值,各为一个字节,8位,三个值合起来 24 位,所以每个灯珠的数据为24位,3个 byte。对于每个二进制位,WS28XX 是通过单周期内高电平的持续时间来判断 0 或 1。

请看下面的高清无码美图。

上面这个就是 WS28XX 的时序图。在一个脉冲周期内,如果:

高电平持续时间为 0.4 微秒,低电平持续时间为 0.85 微秒,那么就是0;

高电平持续时间为 0.85 微秒,低电平持续时间为 0.4 微秒,那么就是1。

故一个周期的总时长为 1.25 微秒,即频率为 1000000 / 1.25 = 800 KHz,即 0.8 MHz

请记住这个频率,后面有用。

WS28XX的信号是连续发的,中间不需要停顿;如果出现超过 50 微秒的低电平,那么WS28XX会认为你的信号发送完毕。如果数据线上有数据来就会从第一个灯珠开始进行处理(等于更新整个灯带的数据)。

例如,有四个灯珠串联,每个灯的RGB有24位,那么,你需要向WS28XX连续发送 24 * 4 = 96 位数据,数据发送中不要停顿,所有数据都是连着发的—— 96位连续发,中间不用停顿;全部发完后再输出50微秒左右的低电平表示结束发送。

比如,红色,RGB 是 255,0,0,那么这24位就是:

1111 1111 0000 0000 0000 0000

如果有三个灯珠,第一个灯珠设置为绿色,第二个灯珠为白色,第三个灯珠为蓝色,那么三组RGB为:

【0,255,0】【255,255,255】【0,0,255】。于是,72位二进制为:

0000 0000 1111 1111 0000 0000 1111 1111 1111 1111 1111 1111 0000 0000 0000 0000 1111 1111

在发送的时候,这72位是连续发送的,中间不需要延时,发完后把电平拉低,50 us后WS28XX就会认为你已经发完数据。

正如你所看到的,WS28XX 的通信协议比较简单。但是,问题出在它的时间很短。你如果纯手动写代码来改变电平的高低,要求程序有很高的性能。低配的单片机可能不够快,像树莓派这样的开发板,虽然处理器肯定比单片机快,但是代码传递到系统驱动,再由驱动传到底层硬件。而且每次切换电平需要来回两次通信,花的时间太长,都有可能超出 1.25 us 的周期。

所以,一般不采取直接写GPIO电平的方式通信,而是借助硬件上所支持的协议。能够做这事的硬件协议有俩:

1、PWM。这个估计大家能理解,前面老周说要记住那个通信频率,现在用上了。把PWM频率设为 800 KHz,然后一个周期的时长就是 1.25 us。最后你一定猜到了,发送1时,高电平持续0.85 us,占空比 68%;发送0时,高电平持续0.4 us,占空比 32%。于是呢,不断地改变占空比,就能给WS28XX发信号。许多方案是和DMA一起使用的,就是为了提高速度。.NET Iot 封装的 PWM 不支持 DMA 方式,因此这个方案跳过。

2、SPI,这个方案是目前最优秀方案。.NET Iot 封装的库也是采用 SPI 协议。这是个巧妙利用,将SPI的 MOSI 口与灯带的 Din 连接,让 SPI 时序来控制灯珠。

为啥不用 IIC (I2C)呢?因为 IIC 要从机地址啊,我们又不是真的使用 IIC 设备,所以这里不适合。根据官方的示例,使用SPI时要设置以下几个参数:

a、速率 2400 KHz,正好是 800 K 的三倍。于是乎,SPI 中 3 个二进制位对应WS28XX中 1 个二进制位。要发送 1 ,SPI 写入二进制 110;要发送 0 ,SPI 写入二进制 100。一个灯珠的数据是3字节24位,那么 SPI 就得写入72位(9个字节)。

b、SPI 模式选择 Mode0。

c、数据长度为8位。

因为树莓派是支持硬件 SPI 的,所以 SPI 方案是没有问题的。若开发板没有硬件 SPI(靠软件模拟),就不能使用SPI方案了,速度跟不上。

=======================================================================

知道原理后,咱们可以动手做了。

第1步,引用 Iot.Device.Bindings 包(Nuget),依赖包 System.Device.Gpio 会自动引入,所以不用管它。

第2步,using 以下命名空间:

using System.Device.Spi;
using System.Drawing;
using Iot.Device.Graphics;
using Iot.Device.Ws28xx;

第3步,初始化 SpiDevice 对象。

SpiConnectionSettings setting = new(0)
{
Mode = SpiMode.Mode0,
ClockFrequency = 2400_000, //注意速率
DataBitLength = 8
}; using SpiDevice spidev = SpiDevice.Create(setting);

把 ClockFrequency 设置为 2400,000 hz,原因前面解释过。

第4步,老周买的灯带是 WS2812B 芯片的,所以,实例化 WS28XX 时用 Ws2812b 类,大部分灯带都是这个。

// 30表示使用30个灯珠,这个按实际来传值,要用到50个灯珠,就传50
const int LED_NUM = 30;
Ws28xx leds = new Ws2812b(spidev, LED_NUM);

老周现用来测试的灯带是五米长的,150 个灯,但为了省电,只选择了 30 个灯做实验,你可以根据实际情况改代码。咱们这里用的灯带,所以只考虑宽度,高度忽略;如果用的是点阵屏,则要考虑高度,即几行几列。

第5步,准备七种常用颜色,待会咱们做色彩轮换效果。

Color[] colors =
{
Color.Blue, // 蓝色
Color.Yellow, // 黄色
Color.White, // 白色
Color.Red, // 红色
Color.Green, // 绿色
Color.Pink, // 粉色
Color.Orange // 橙色
};

第6步,色彩轮换,七种颜色轮着显示。

// Color数组中正在使用的索引
int theIndex = 0; // 进入循环,开始溜灯
while (true)
{
// 当表示索引的值超出数组范围后,重回0
if (theIndex > colors.Length - 1)
{
theIndex = 0;
}
// 获取位图对象
BitmapImage image = leds.Image;
// 循环修改每个灯珠的颜色
for (int x = 0; x < LED_NUM; x++)
{
// 更新像素点(对应一个灯珠)
image.SetPixel(x, 0, colors[theIndex]);
// 调用更新,才会刷新灯带显示
leds.Update();
Thread.Sleep(10);
}
theIndex++;
Thread.Sleep(1000);
}

可以把一个灯珠视为一个像素,先从 Image 属性中获得对 BitmapImage 对象的引用,然后用 SetPixel 方法来设置每个灯的颜色。这里因为用的是灯带,所以 y 坐标都是 0,仅改变 x 坐标上的值。

修改完颜色后,如果想灯珠马上更新,请调用 Update 方法。

最后,强调一下:接线时,树莓派的 MOSI 接灯带的数据接口(Din 或 Di)。

如果SPI不能用,请执行 sudo raspi-config,然后进入“Interface Options”,确认 SPI 总线启用。

看看最终效果。

除了变色、流水,还有比较常用的特效是颜色渐变。颜色渐变算法我们可以自己写,老周会在下一篇水文中演示颜色渐变效果。

【.NET 与树莓派】控制彩色灯带(WS28XX)的更多相关文章

  1. 【.NET 与树莓派】WS28XX 灯带的颜色渐变动画

    在上一篇水文中,老周演示了 WS28XX 的基本使用.在文末老周说了本篇介绍颜色渐变动画的简单实现. 在正式开始前,说一下题外话. 第一件事,最近树莓派的价格猛涨,相信有关注的朋友都知道了.所以,如果 ...

  2. 云中树莓派(4):利用声音传感器控制Led灯

    云中树莓派(1):环境准备 云中树莓派(2):将传感器数据上传到AWS IoT 并利用Kibana进行展示 云中树莓派(3):通过 AWS IoT 控制树莓派上的Led 云中树莓派(4):利用声音传感 ...

  3. 树莓派开机运行Python脚本 控制LED灯闪烁

    一.新建一个开机运行文件 在 /home/pi/.config 下创建一个文件夹,名称为 autostart,并在该文件夹下创建一个led.desktop文件(文件名以.desktop结尾) 编辑le ...

  4. arduino入门学习实现语音控制LED灯

    需要的准备的硬件arduino+PC+麦克风实现语音命令控制LED灯的亮灭. 首先需要将写好的arduino程序烧录到arduino uno主板中,下面是代码如下: int val;//定义变量val ...

  5. C#与Arduino通过串口通信来控制LED灯的状态

    一.引言 最近摆弄了一段时间的Arduino,发现Arduino做一些电子类项目.监控.机器人.电子玩具比较容易,并且Arduino与.NET程序集成也不难.接下来介绍一个简单的小程序,C#做的一个W ...

  6. Homekit_Dohome_智能灯带

    简介:本款产品支持音乐律动控制,可以随音乐改换颜色及频率,可以使用Homekit或者Dohome或者遥控器进行有效控制,同时Dohome App已经对接了各大智能音箱,下载Dohome App后就可以 ...

  7. 嵌入式Linux学习入门:控制LED灯

    记录自己linux学习过程,让自己能够一直坚持下去 1.原理图分析: nLED_1, nLED_2, nLED_4, 给低电平则对应LED灯亮,高电平则对应LED灯灭, S3C2440芯片GPF4-G ...

  8. arduino 红外遥控器控制LED灯

    /* 日期:2016.9.1 功能:红外遥控器控制LED灯 开,关,闪烁,呼吸 元件: 跳线公公头 * 5 led 220欧电阻 红外接收管,红外遥控 接线: 红外灯面向自己从左到右分别接 IO3 , ...

  9. BLE 安卓APP控制LED灯的实现(转)

    源:BLE 安卓APP控制LED灯的实现 //注:参考AmoMcu源代码修改. 打开APP,检查蓝牙是否打开 BluetoothAdapter mBluetoothAdapter; final Blu ...

随机推荐

  1. 8大原则带你秒懂Happens-Before原则

    摘要:在并发编程中,Happens-Before原则是我们必须要掌握的,今天我们就一起来详细聊聊并发编程中的Happens-Before原则. 本文分享自华为云社区<[高并发]一文秒懂Happe ...

  2. 新技能GET!在前端表格中花式使用异步函数的奥义

    背景 60年代时,操作系统中独立运行的单元通常是进程.但随着计算机技术的发展,人们发现在进程运行过程中,创建.撤销与切换都要花费较大的时空开销. 到了80年代为了解决这一问题,出现了更小的独立运行基本 ...

  3. [bzoj1101]Zap

    1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 50001 4 int t,n,m,k,ans,mu[N],vis ...

  4. [atARC094D]Worst Case

    首先,容易证明满足条件的$ip_{i}$必然是一个前缀 将其看成一张二分图,$i$向满足$ip_{i}<xy$的$p_{i}$连边,即找到一个前缀满足其有完美匹配 二分枚举前缀长度$k$,根据h ...

  5. 十行HTML实现增强现实--思途青岛

    你想通过网络实现增强现实吗?现在你只需要 10 行 HTML 代码!真的!让我带你看一看代码,非常简单.我们最近发布了AR.js.你不需要安装任何应用,用你的手机通过网络就能体验到强大的增强现实.但让 ...

  6. 洛谷 P4463 - [集训队互测 2012] calc(多项式)

    题面传送门 & 加强版题面传送门 竟然能独立做出 jxd 互测的题(及其加强版),震撼震撼(((故写题解以祭之 首先由于 \(a_1,a_2,\cdots,a_n\) 互不相同,故可以考虑求出 ...

  7. 平衡树 & LCT

    1. 非旋 Treap(FHQ Treap) 1.1. 算法简介 FHQ Treap 的功能非常强大.它涵盖了 Treap 几乎所有的功能 所以我非常后悔学了 Treap,浪费时间. FHQ 的核心思 ...

  8. R语言与医学统计图形【7】低级绘图函数

    R语言基础绘图系统 基础绘图包之低级绘图函数--气泡图.一页多图.背景网格.添加线条和散点.数学表达式 4.气泡图 symbols是高级绘图函数,可在图上添加标记,标记的形状包括:circles,sq ...

  9. jumpserver——脚本安装

    CentOS Linux release 7.7.1908 (Core) 3.10.0-1062.4.1.el7.x86_64 Initialize(){ yum update -y systemct ...

  10. 36-Same Tree

    Same Tree My Submissions QuestionEditorial Solution Total Accepted: 126116 Total Submissions: 291884 ...