.NET与树莓派控制彩色灯带WS28XX的实现

彩色灯带,相信不用老周多说,大家都知道,没准你家里的灯墙里面就有。老周的茅屋是早期建造的,所以没有预留的灯槽,明灯的话是不好看的,因此老周家里没使用灯带。不过,像柜子后面,显示器后面,书桌边沿这些地方,可以贴彩色灯带。书架上也贴了一些,因为那个书架是圣诞树形状的,没办法一条灯带贴完,只能把它剪开 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 总线启用。

看看最终效果。

【补充】如果出现程序运行几秒钟就“卡死”的情况,那是SPI被系统降频了所致。若遇到此问题,可以在 config.txt 文件中修改 GPU 超频参数。

sudo nano /boot/config.txt

加上这两行:

core_freq=250
core_freq_min=250

或者

core_freq=500
core_freq_min=250

这样配置后,至少保证了 GPU 内核在空闲时的频率不低于 250 MHz。

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

以上就是.NET与树莓派控制彩色灯带WS28XX的实现的详细内容,更多关于.NET树莓派控制彩色灯带WS28XX的资料请关注我们其它相关文章!

(0)

相关推荐

  • .Net Core使用Socket与树莓派进行通信详解

    前言 去年买的树莓派一直放在抽屉里吃灰,前些阵子Debian 9发布,也不出意外的支持了树莓派. 于是重新拿出读卡器又重新了装上了Debian桌面版系统. 介绍 现在这个东西目前的程度只是了解一下Python和.Net的通信.最佳的版本应该是,可以通过服务器端远程执行树莓派命令. 这样做的原因大家也都知道,很多宽带现在不提供外网IP,这样造成家庭没有公网ip,也没办法远程对树莓派控制,我想做的东西类似内网穿透Ngrok之类的. 效果 Python端 #!/usr/bin/env python2

  • .NET 与树莓派WS28XX 灯带的颜色渐变动画效果的实现

    在上一篇水文中,老周演示了 WS28XX 的基本使用.在文末老周说了本篇介绍颜色渐变动画的简单实现. 在正式开始前,说一下题外话. 第一件事,最近树莓派的价格猛涨,相信有关注的朋友都知道了.所以,如果你不是急着用,可以先别买.或者,可以选择 Raspberry Pi 400,这个配置比 4B 高一点,这个目前价格比较正常.Pi 400 就是那个藏在键盘里的树莓派.其实,官网上面的价格已经调回原来的价格了,只是某宝上的那些 Jian 商,还在涨价. 第二件事,树莓派上的应用是不是可以用 C 来写?

  • .NET与树莓派控制彩色灯带WS28XX的实现

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

  • C语言实现定时器控制LED灯闪烁

    本文实例为大家分享了C语言实现定时器控制LED灯闪烁的具体代码,供大家参考,具体内容如下 实现效果如图: 周期:2s: LED引脚为P2口. #include<reg52.h> void Delay_1s(void) { unsigned char i; for(i=0;i<20;i++) { //2的6次方=655136 TH1=0x3C;//655136-50000=155146==>0x3CB0 TL1=0xB0; TR1=1;//启动定时器,开始计时 while(!TF1)

  • 控制Android LED灯颜色的代码实例

    很多Android手机上都配有LED灯,比如HTC的手机在充电.新来短信等时候都会有响应的指示,其实很简单的这都是NotificationManager的一些参数而已,下面Android123给大家说下如何通过代码控制LED灯的闪烁,因为有些机型没有LED灯或颜色种类较少,发布时需要真机观察. 复制代码 代码如下: final int ID_LED=19871103;         NotificationManager nm=(NotificationManager)getSystemSer

  • 树莓派实现移动拍照

    驱动树莓派gpio的中间层库函数有wiringPi,BCM2835,以及PRi.GPIO,这里我选择使用Python语言开发的PRi.GPIO. 1.安装RPi.GPIO (1)先安装python-dev,输入以下指令. sudo apt-get install python-dev (2)安装RPi.GPIO wget https://pypi.python.org/packages/source/R/RPi.GPIO/RPi.GPIO-0.5.11.tar.gz #解压: tar -zxvf

  • 浅谈带缓冲I/O 和不带缓冲I/O的区别与联系

    这里搜集从网上看到的一些言论,自认为还是比较靠谱的,有些不靠谱的根据自己的理解进行了修正. 首先要明白不带缓冲的概念:所谓不带缓冲,并不是指内核不提供缓冲,而是只单纯的系统调用,不是函数库的调用.系统内核对磁盘的读写都会提供一个块缓冲(在有些地方也被称为内核高速缓存),当用write函数对其写数据时,直接调用系统调用,将数据写入到块缓冲进行排队,当块缓冲达到一定的量时,才会把数据写入磁盘.因此所谓的不带缓冲的I/O是指进程不提供缓冲功能(但内核还是提供缓冲的).每调用一次write或read函数

  • java通过控制鼠标实现屏幕广播的方法

    本文实例讲述了java通过控制鼠标实现屏幕广播的方法.分享给大家供大家参考.具体分析如下: 在前面一篇<java实现屏幕共享功能实例分析>中提到截取屏幕时是没鼠标,为了看到教师端界面上的鼠标,可以在截取屏幕的时候,把鼠标绘制到每一张截图上去,但是由于截图的时候是一张张截取的,所以看到的鼠标难免会有点卡,之前写了java鼠标操控小程序,可以通过这种方式来看到鼠标的演示. 实现的方式也挺简单的,前面两篇文章分别实现了鼠标控制和不带鼠标的屏幕分享功能,把这两个结合一下就ok了,下面简单分析下. 服务

  • 为什么说python更适合树莓派编程

    树莓派是一个非常廉价的.只有手掌大小的完全可编程的计算机.虽然树莓派的体积小,但是它的潜力无限.你可以像使用常规台式计算机一样在树莓派上创建一个非常酷的工程.例如,你可以用树莓派搭建你自己的家用云存储服务器. 树莓派用python来进行编程.树莓派项目的一个核心思想是Python编程语言的使用.Python允许树莓派的拥有者将项目扩展到令人难以置信的规模. Python是一个解释型的面向对象的.跨平台的编程语言.良好的可靠性.清晰的语法和易用性,使它成为最流行的编程语言之一.Python是一个优

  • PHOTOSHOP技巧167条

    工具面板技巧 1. 快速打开文件  双击Photoshop的背景空白处(默认为灰色显示区域)即可打开选择文件的浏览窗口. 2. 随意更换画布颜色  选择油漆桶工具并按住Shift点击画布边缘,即可设置画布底色为当前选择的前景色.如果要还原到默认的颜色,设置前景色为25%灰度(R192,G192,B192)再次按住Shift点击画布边缘. 3. 选择工具的快捷键  可以通过按快捷键来快速选择工具箱中的某一工具,各个工具的字母快捷键如下:  选框-M 移动-V 套索-L 魔棒-W  喷枪-J 画笔-

随机推荐