返回顶部
首页 > 资讯 > 后端开发 > ASP.NET >.NET与树莓派WS28XX灯带的颜色渐变动画效果的实现
  • 686
分享到

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

2024-04-02 19:04:59 686人浏览 薄情痞子
摘要

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

在上一篇水文中,老周演示了 WS28XX 的基本使用。在文末老周说了本篇介绍颜色渐变动画的简单实现。

在正式开始前,说一下题外话。

第一件事,最近树莓派的价格猛涨,相信有关注的朋友都知道了。所以,如果你不是急着用,可以先别买。或者,可以选择 Raspberry Pi 400,这个配置比 4B 高一点,这个目前价格比较正常。Pi 400 就是那个藏在键盘里的树莓派。其实,官网上面的价格已经调回原来的价格了,只是某宝上的那些 Jian 商,还在涨价。

第二件事,树莓派上的应用是不是可以用 C 来写?这是废话了。树莓派上运行的是 linux 系统,当然可以了。有伙伴会说,用.net体验如何?老周可以告诉你:完全没问题,这个库大部分api老周都做过实验。.net iot 库的性能你不用担心,因为最近几年.NET的性能提升很大,更何况.NET只是封装了底层API的调用,当指令传递到系统驱动层,其效率和 C 是一样的。你不妨想想,连 python 这种性能差得没有天敌的编程语言都能玩物联网,.NET 你还怕啥呢。尽管目前开源的库不多,但官方给的 Devices 也基本覆盖各种传感器模块。

-------------------------------------------------------------------------------------

好了,F话就聊到这儿,接下来正片开始。

让WS28XX 控制灯带产生动画,其本质上就是每隔一段时间更新一下每个灯珠的颜色。由于人眼的反应速度和处理能力比不上猫,所以我们会看到动画。咱们看到的是动画,但老周估计喵喵们看到的是PPT。

所以,所谓颜色渐变动画,首先,你要确定两种颜色——起始色和最终色,比如从绿色变成红色,绿色是起始,红色是终点。

然后,我们要算出起始色与终点色之间,R、G、B 各值间的差值。

假设,我们的延时 d = 40 ms(精确到毫秒就够,不用考虑微秒纳秒,反正你眼睛看不到),然后咱们要从红色变成蓝色。

红:R=255, G=0, B=0

蓝:R=0, G=0, B=255

计算差距,终点减去起点,不管正负。

dif_R = 0-255 = -255

dif_G = 0-0 = 0

dif_B = 255-0 = 255

这样我们就看到,从红到蓝,R的值是递减的,G不变,B的值是递增的。我们先不去想算法对不对,不妨继续推算:

第一轮循环,R=255-1=254, G=0,B=0+1=1,Sleep 40;

第二轮循环,R=255-2=253,G=0,B=0+2=2,Sleep 40;

第三轮循环,R=255-3=252,G=0,B=0+3=3,Sleep 40

……

直到把目标值变成 R=0,G=0,B=255。每一轮循环之间,会暂停 40 ms。

可是,算法还真不能这么简单,咱们忽略了一个问题,请看下面的举例:

假设要从 R=120,G=200,B=10 变成 R=255,G=100,B=60

计算差值:difR = 255-120=135,difG=100-200=-100,difB=60-10=50。RGB之间的差值并不相等,如果我们每轮循环都 +1 或 -1,那么会存在一个问题:有的值可能早已到达终值,而有的值还没到达终值。这种情况灯光的渐变过程会看起来不太顺畅。

所以,我们必须解决的问题就是要在 N 轮循环之后,RGB三个值要同时到达终值。这么一来,差值大的要渐变得快一些,差值小的要渐变得慢一些。跑得快的等一下跑得慢的,形成统一战线,同时到达终点。

因此,渐变过程中循环的次数必须统一,但每次循环里面,RGB改变的量不同,但N轮循环过后会同时到达终值。

举例,从 R1=100,G1=0,B1=230 变为 R2=20,G2=72,B2=57

那么,差值:

  dR = 20-100=-80

  dG = 72-0=72

  dB = 57-230=-173

假如循环次数为80次,可以理解为分 80 个步长来完成,设 step = 80。接下来就得算出这80步中,每一步里RGB各值要变化多少(单位步长)。

  pR = dR / 80=-80/80 = -1

  pG = dG / 80 = 72 / 80 = 0.9

  pB = dB / 80 = -173 / 80 = -2.16

再设某一轮循环(某一步)为 i ,于是

for i = 0; i <= 80; i++

  R = R1 + i * -1;

  G = G1 + i * 0.9;

  B = B1 + i * -2.16;

R1、G1、B1 指的是起始颜色的值,在一次循环中,让初始值加上 i 与单位步长(pR、pG、pB)的乘积。

这么一搞,就能保证在 N 个循环后,三个值能同时到达终值。

------------------------------------------------------------------------------------------

OK,有了上面的推演过程,我们可以把它翻译成代码。我直接封装为一个类。


public class GradLeds
    {
        Ws28xx _leds;
        public GradLeds(Ws28xx ws) => _leds = ws;

        public void Run(Color start, Color end, int steps = 120, int delay_ms = 30)
        {
            if (steps <= 0)
                throw new Exception("steps 不能小于/等于0");
            if (delay_ms <= 0)
                throw new Exception("延时必须大于0");

            // 计算RGB的差值,不论正负
            float dR = (float)end.R - start.R;
            float dG = (float)end.G - start.G;
            float dB = (float)end.B - start.B;
            // 计算每一个步长(step)要增长的值
            float ir = dR / steps;
            float ig = dG / steps;
            float ib = dB / steps;

            // 通过宽度获取灯珠数
            int ledNum = _leds.Image.Width;
            for (var a = 0; a <= steps; a++)
            {
                // 如果运行状态为false,退出循环
                if(AppContext.TryGetSwitch("running",out bool b) && !b)
                {
                    break;
                }
                Color tc = Color.FromArgb(
                        (int)(start.R + a * ir),
                        (int)(start.G + a * ig),
                        (int)(start.B + a * ib)
                );
                // 填充所有灯珠
                for (var n = 0; n < ledNum; n++)
                {
                    _leds.Image.SetPixel(n, 0, tc);
                }
                _leds.Update();
                // 延时
                Thread.Sleep(delay_ms);
            }
        }
    }

在这个类中,我用到了 AppContext,如果你看过老周在几千年前写的博文,应该会记得这个 AppContext类,它可以用来设置一些全局开关,开关名是字符串,值是布尔值。直接用这个类,我们不需要刻意去写个类,再弄个静态字段来当全局变量了,更何况静态成员是不能跨 AppDomain 共享值的,如果多线程还得考虑同步。

在 AppContext 中老周会设置一个开关,名为 running,如果是 true,说明程序在运行;若为 false,则说明程序要退出了,就不会再渐变了。

因为这个渐变过程会持续几秒时间甚至更长,如果程序要退出,就不要再循环了,而是赶紧终止操作。

start 和 end 表示起始颜色和终点颜色,steps 表示要进行多少步(循环数),delay_ms 参数表示每一轮循环之间的延时。

回到主程序,调用测试


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

// 初始化SPI总线
SpiConnectionSettings settings = new(0)
{
    Mode = SpiMode.Mode0,
    DataBitLength = 8,
    ClockFrequency = 2400_000
};
using SpiDevice device = SpiDevice.Create(settings);

// WS28XX,30个灯珠
Ws28xx ws = new Ws2812b(device, 30);
GradLeds grdled = new(ws);

int steps = 90; //90个循环
int delay = 25; //延时(毫秒)
// 设置运行状态
AppContext.SetSwitch("running", true);

// 按Ctrl+C时程序要退出,处理一下
Console.CancelkeyPress += async (_, e) =>
{
    e.Cancel = true;    //阻上程序马上退出
    // 关闭开关,表示程序不再运行了
    AppContext.SetSwitch("running", false);
    await Task.Delay(150);  //保险一点,等一会儿
    e.Cancel = false;   //告诉系统,可以退出了
};

// 主循环
while (AppContext.TryGetSwitch("running", out bool b) && b)
{
    // 从红变蓝
    grdled.Run(Color.Red, Color.Blue, steps, delay);
    // 从蓝变黄
    grdled.Run(Color.Blue, Color.Yellow, steps, delay);
    // 从黄变深粉色
    grdled.Run(Color.Yellow, Color.DeepPink, steps, delay);
    // 从深粉色变白色
    grdled.Run(Color.DeepPink, Color.White, steps, delay);
    // 从白变回红
    grdled.Run(Color.White, Color.Red, steps, delay);
}

// 黑灯收工
ws.Image.Clear(Color.Black);
ws.Update();

最后这两句是当退出 while 循环后,让所有灯珠熄灯(黑色表示灯灭)。


ws.Image.Clear(Color.Black);
ws.Update();

好了,咱们来看看效果,这个效果应该能接受。

其他动画算法,大伙伴们不妨自己动手去试试。算法不一定要从网上抄,可以根据自己的理解去设计。可以做出自己的创意,你爱咋玩就咋玩。

--结束END--

本文标题: .NET与树莓派WS28XX灯带的颜色渐变动画效果的实现

本文链接: https://lsjlt.com/news/160035.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • .NET与树莓派WS28XX灯带的颜色渐变动画效果的实现
    在上一篇水文中,老周演示了 WS28XX 的基本使用。在文末老周说了本篇介绍颜色渐变动画的简单实现。 在正式开始前,说一下题外话。 第一件事,最近树莓派的价格猛涨,相信有关注的朋友都...
    99+
    2024-04-02
  • .NET与树莓派控制彩色灯带WS28XX的实现
    彩色灯带,相信不用老周多说,大家都知道,没准你家里的灯墙里面就有。老周的茅屋是早期建造的,所以没有预留的灯槽,明灯的话是不好看的,因此老周家里没使用灯带。不过,像柜子后面,显示器后面...
    99+
    2024-04-02
  • .NET与树莓派控制彩色灯带WS28XX怎么实现
    本篇内容介绍了“.NET与树莓派控制彩色灯带WS28XX怎么实现”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!彩色灯带,相信不用老周多说,大...
    99+
    2023-06-29
  • Android实现颜色渐变动画效果
    目录前言一、Android中插值器TypeEvaluator二、案例效果实现1.利用Android自带的颜色插值器ArgbEvaluator2.看看Android自带颜色插值器Arg...
    99+
    2024-04-02
  • android颜色渐变动画效果怎么实现
    在Android中,你可以使用ValueAnimator和ArgbEvaluator类来实现颜色渐变动画效果。下面是一个简单的示例代...
    99+
    2023-08-18
    android
  • Android怎么实现颜色渐变动画效果
    本篇内容主要讲解“Android怎么实现颜色渐变动画效果”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Android怎么实现颜色渐变动画效果”吧!效果图:一、Android中插值器TypeEva...
    99+
    2023-06-30
  • iOS SwiftUI 颜色渐变填充效果的实现
    SwiftUI 为我们提供了各种梯度选项,所有这些选项都可以通过多种方式使用。 Gradient 渐变器 A color gradient represented as an arr...
    99+
    2022-05-15
    SwiftUI 颜色渐变
  • Android实现背景颜色滑动渐变效果的全过程
    目录前言一、介绍一下GradientDrawable二、实现三、源码:总结前言 今天和朋友聊到这个功能,刚开始的想法是自定义view,如何进行滑动监听,经过一列操作完成效果后,发现...
    99+
    2024-04-02
  • Android TextView渐变颜色和方向及动画效果的设置详解
    GradientTextView Github点我 一个非常好用的库,使用kotlin实现,用于设置TexView的字体 渐变颜色、渐变方向 和 动画效果 添加依赖 之前仓库发布在...
    99+
    2024-04-02
  • Css3中如何实现hover动画的颜色动画效果
    这篇文章主要为大家展示了“Css3中如何实现hover动画的颜色动画效果”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Css3中如何实现hover动画的颜色动画...
    99+
    2024-04-02
  • Android实现流动的渐变色边框效果
    目录前言实现思路总结前言 记得在介绍 motion_toast 一篇的时候,开篇有一张动图,边框是渐变色而且感觉是流动的。这个动效挺有趣的,当时也有人问怎么实现,经过上一篇《让你的聊...
    99+
    2024-04-02
  • css3中怎么使用animation属性实现背景颜色动态渐变的效果
    本篇内容主要讲解“css3中怎么使用animation属性实现背景颜色动态渐变的效果”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“css3中怎么使用animat...
    99+
    2024-04-02
  • Android直播软件搭建之实现背景颜色滑动渐变效果的详细代码
    Android直播软件搭建实现背景颜色滑动渐变效果的相关代码 一、介绍一下GradientDrawable GradientDrawable 支持渐变色的Drawable,与sha...
    99+
    2024-04-02
  • CSS3点击按钮实现背景渐变动画效果的示例分析
    这篇文章主要介绍了CSS3点击按钮实现背景渐变动画效果的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。效果图如下:实例代码如下:&l...
    99+
    2024-04-02
  • CSS如何实现动态渐变色边框围绕内容区域旋转的效果
    这篇文章将为大家详细讲解有关CSS如何实现动态渐变色边框围绕内容区域旋转的效果,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。效果图&emsp;&emsp;...
    99+
    2024-04-02
  • CSS3怎么实现歌词进度文字颜色填充变化动态效果的思路
    这篇文章将为大家详细讲解有关CSS3怎么实现歌词进度文字颜色填充变化动态效果的思路,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。播放音乐时,歌词会随歌曲的进度逐渐填充颜色,不是逐字改变颜色,而是从左向右横...
    99+
    2023-06-08
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作