炫酷 RGB 之.NET nanoFramework 点灯大师

news2024/9/25 17:17:15

前面介绍了 .NET nanoFramework 入门,本文继续以微雪的 ESP32-S2-Pico 为例介绍 .NET nanoFramework 的开发:控制 ESP32 板载 RGB 灯 和 外接 RGB 灯。内容包含 状态灯的意义、WS2812 、HSV、PWM 等相关知识。

文章目录

  • 1. 背景
  • 2. 状态灯的意义
  • 3. 板载 LED
  • 4. WS2812
    • 4.1 简介
    • 4.2 控制原理
  • 5. 板载 RGB 控制
    • 5.1 简单颜色测试
    • 5.2 HSV 颜色模型
    • 5.3 呼吸灯效果
    • 5.4 整体颜色测试
  • 6. 官方驱动库 Ws28xx.Esp32
  • 7. 全彩 RGB
  • 8. 最后

1. 背景

ESP32 开发第一步,基本是先点灯吧?点灯,点灯,点灯,没想到我这个点灯,点了 2 周。一是工作比较忙,只有闲暇时间搞搞这个,再者也是需要查找学习各种资料,因为这个板载的灯没有那么好点,一时疏忽,找错了方向。

2. 状态灯的意义

我不清楚是不是有 ESP32 开发第一步要先点灯这个说法,但是设备的状态指示灯的作用还是非常大的,通过它可以向用户提供设备的工作状态信息。设备状态灯通常用不同颜色或闪烁频率来表示设备的不同工作状态。例如:

  • 绿色:设备正常工作。
  • 红色:设备出现故障。
  • 黄色:设备正在进行某项操作,如升级。
  • 闪烁:设备正在进行某项操作,如数据传输。

设备状态灯是一种非常简单易懂的人机交互手段,使用户能够快速了解设备的工作状态,并能够及时采取措施。

通常设备状态灯在设备外部或者是设备前面,方便用户查看,比如说一个路由器上面有个红绿灯,绿灯就是网络正常,红灯就是网络有问题。再比如一些简单的小家电,红灯表示正在充电,灯灭则表示充满。

3. 板载 LED

ESP32-S2-Pico 这款板载的 LED 硬件有过版本修改,通过简单的 GPIO 拉高并不能点亮。

硬件变化

查找原理图我们可以发现,LED 接的是 GPIO9 ,LED 这一块的电路是 WS2812B-0807,这一部分的原理图如下图所示,仅有一个灯珠:

WS2812

4. WS2812

4.1 简介

WS2812 是一种高性能、低成本的全彩 LED 灯带。它是一种串联控制的灯,可以将多个 LED 灯连接在一起,通过串行信号控制各个 LED 灯的颜色和亮度。

WS2812 的主要特点是具有色彩丰富、高亮度、高动态范围、高精度的色温调节能力,可以实现 256 级灰度调节。

WS2812 的控制方式是通过一种称为单总线控制的方式。这种控制方式是通过单线控制所有 LED 灯,并且每个 LED 灯都有一个内置的控制器,可以接收单线信号并解码。这样可以使得控制器只需要通过单线发送信号,就可以控制所有 LED 灯的颜色和亮度。

WS2812 在很多领域都有广泛的应用,如:LED灯带、LED点阵屏幕、LED灯管、LED灯环等。

4.2 控制原理

WS2812 每个 LED 灯都有一个内置的控制器,它可以接收单线信号并解码。控制器通过接收单线信号来控制 LED 灯的颜色和亮度。

控制器解码信号的方式是通过高电平和低电平的时间来区分不同的数据位。

通常每个 LED 灯的颜色都由三个数据位(红、绿、蓝)组成,每个数据位可以表示 8 级亮度。

当控制器接收到单线信号时,首先会检测到一个高电平脉冲,这个脉冲用来同步数据。接下来是 24 位数据,其中 8 位红色数据、8 位绿色数据和 8 位蓝色数据。控制器按照这样的数据格式解码信号,并设置 LED 灯的颜色和亮度。

毕竟文章重点不同,在这里只是做了简单的介绍,知道了原理是可以自己写出驱动的,当然要查阅相关硬件的手册文档,更详细的了解相关数据发送的方式,不同灯珠通讯时序的具体时间要求会不大相同。感兴趣的同学可以自行查找资料,进行尝试。

原理介绍:https://cdn-shop.adafruit.com/datasheets/WS2812B.pdf

这里我们只需要使用写好的驱动就可以了,比如 MicroPython 的 neopixel 类库。当然 .NET nanoFramework 也有相关的类库: Ws28xx.Esp32。

5. 板载 RGB 控制

这里我们采用 ESP32 WS2812 Driver ,代码仓库:https://github.com/nanoframework/nf-Community-Contributions/tree/master/drivers/ESP32-WS2812,提供了 PixelController 控制的帮助类,可以让我们轻松的实现 WS2812 的控制,你也可以通过源代码了解驱动的实现。

5.1 简单颜色测试

PixelController 构造函数提供三个参数,分别是 GPIO ,像素数,可选参数是否为 RGBW 灯带控制,默认 false

PixelController controller = new PixelController(9, 1);
// 简单测试颜色
controller.SetColor(0,255,0,0);//红
controller.UpdatePixels();
Thread.Sleep(1000);
controller.SetColor(0, 0, 255, 0);//绿
controller.UpdatePixels();
Thread.Sleep(1000);
controller.SetColor(0, 0, 0, 255);//蓝
controller.UpdatePixels();
Thread.Sleep(1000);
controller.SetColor(0, 255, 255, 255);//白
controller.UpdatePixels();
Thread.Sleep(1000);

效果:

效果

5.2 HSV 颜色模型

上一节简单测试了灯光的红、绿、蓝、白几种颜色,使用的 SetColor ,这个方法是设置灯光的 RGB 颜色。另外一个设置颜色的方式是使用 SetHSVColor,这个方式使用的 HSV 颜色模型。

HSV (Hue, Saturation, Value) 和 RGB (Red, Green, Blue) 是两种不同的颜色空间。在 HSV 颜色模型中:

  • Hue(色调),表示颜色的类型,如红色、黄色、蓝色等。Hue 的值用角度度量,取值范围为0°~360°,从红色开始按逆时针方向计算,红色为0°,绿色为120°,蓝色为240°。它们的补色是:黄色为60°,青色为180°,紫色为300°;
  • Saturation(饱和度),表示颜色接近光谱色的程度,值越大颜色越饱和,值越小颜色越灰暗。Saturation 的值范围为 0 到 1。
  • Value(明度),表示颜色的明亮程度,值越大颜色越亮,值越小颜色越暗。Value 的值范围为 0 到 1。

HSV

与传统的 RGB 相比 HSV 可以非常方便的通过调整明度来平滑的显示颜色亮度变化。

5.3 呼吸灯效果

要想实现呼吸灯的效果,我们只需要通过 SetHSVColor 来设置不同明度的色彩即可平滑的实现呼吸灯的亮度变化效果。

// 呼吸灯效果
PixelController controller = new PixelController(9, 1);
var ts = 0;
for (; ; )
{
    var add = true;
    var v = 0f;
    for (; ; )
    {
        controller.SetHSVColor(0, 240, 50, v);
        controller.UpdatePixels();
        if (add)
        {
            v += 0.05f;
        }
        else
        {
            v -= 0.05f;
        }
        if (v >= 1) add = false;
        if (v <= 0) break;
        Thread.Sleep(50);
    }
    if (ts > 5) break;
    ts++;
}

效果:

在这里插入图片描述

5.4 整体颜色测试

色彩 RGB 我们可以通过随机三个 255 以内的数字来生成随机的颜色。了解了 HSV 后,我们也可以通过 Hue(色调)的取值,直接在圆环中均匀的截取颜色。

 // 生成多少种颜色 或是 灯带的灯珠数量
uint ledCount = 25;
PixelController controller = new PixelController(9, ledCount);

// 添加开始时设置的 ledCount 种颜色
// step 是步长
int step = (int)(360 / ledCount);
var hue = 0;
for (uint i = 0; i < ledCount; i++)
{
    // HSV
    // 色调H 取值范围为0°~360°
    // 饱和度S 取值范围为0%~100%,值越大,颜色越饱和
    // 明度V 表示颜色明亮的程度,通常取值范围为0%(黑)到100%(白)
    // V 这个取值挺好的,设置为1 差点亮瞎
    controller.SetHSVColor((short)i, (short)hue, 1, 0.05f);
    hue = hue + step;
    controller.UpdatePixels();
}

// 循环变换颜色
for (; ; )
{
    controller.MovePixelsByStep(1);
    controller.UpdatePixels();
    Thread.Sleep(500);
}

这段代码比较适合灯带,因为微雪的 ESP32-S2-Pico 只有一个灯珠,MovePixelsByStep 变换后位置后使用 UpdatePixels 也是可以看到颜色变化的。

许多玩家都是喜欢 RBG 光效这种“光污染”的,用这个控制灯带也是可以大有玩头的。

6. 官方驱动库 Ws28xx.Esp32

当然,最好是使用官方的 nanoFramework.Iot.Device.Ws28xx.Esp32 包,通过 Nuget 安装即可,需要注意的是,选对版本,其依赖的其他 nanoFramework 包需要和刷写的固件对应。

使用的方法也很简单,如下是简单的 RGB 颜色控制示例:

// 1 个灯珠,1像素
const int Count = 1;
// 微雪的 ESP32-S2-Pico 的 LED Pin
const int Pin = 9;
public static void Main()
{
    Ws28xx neo = new Ws2812c(Pin, Count);
    BitmapImage img = neo.Image;
    for (; ; )
    {
        img.SetPixel(0, 0, Color.Red);
        neo.Update();
        Thread.Sleep(500);
        img.SetPixel(0, 0, 0, 255, 0);
        neo.Update();
        Thread.Sleep(500);
        img.SetPixel(0, 0, 0, 0, 255);
        neo.Update();
        Thread.Sleep(500);
    }
}

但是,这里需要注意的是:Ws28xx 这里需要使用 Ws2812c 来实例化,不然颜色控制会不对。

7. 全彩 RGB

这一节演示通过 PWM 端口控制全彩红绿蓝三基色 LED 灯。

LED

可以看到该模块有4 Pin,其电压为 5V,接 VBUS 引脚即可,其他三个引脚为 RBG 控制引脚接 GP2-4。

接线

接好设备后面就是写代码了,首先编写初始化功能,定义 R_Pin、 B_Pin、 G_Pin,对应的 GPIO 使用 PWM 需要先进行设置,使用 Configuration.SetPinFunction 将对应 Pin 进行配置。然后使用 PwmChannel.CreateFromPin 从三个引脚创建 PWM 通道,接着启动控制。

/// <summary>
/// 定义 RBG 的 PWM 通道
/// </summary>
private static PwmChannel R_Pin, B_Pin, G_Pin;

/// <summary>
/// 初始化 配置PWM 信息
/// </summary>
public static void Init() {
    // 先设置引脚 , RBG 分别接的 GP2-4
    Configuration.SetPinFunction(2, DeviceFunction.PWM2);
    Configuration.SetPinFunction(3, DeviceFunction.PWM3);
    Configuration.SetPinFunction(4, DeviceFunction.PWM4);

    // 从三个引脚创建 PWM 通道
    R_Pin = PwmChannel.CreateFromPin(2, 40000, 0);
    B_Pin = PwmChannel.CreateFromPin(3, 40000, 0);
    G_Pin = PwmChannel.CreateFromPin(4, 40000, 0);

    // 启动 PWM
    R_Pin.Start();
    B_Pin.Start();
    G_Pin.Start();
}

核心的控制代码也很简单,这里随机生成 255 以内的数然后映射到百分比,PwmChannel 的占空比是个百分比,double 类型,取值 0-1 。

public static void Main()
{
    Init();

    Random random = new Random();

    while (true)
    {
        R_Pin.DutyCycle = random.Next(255) / 255.0;
        B_Pin.DutyCycle = random.Next(255) / 255.0;
        G_Pin.DutyCycle = random.Next(255) / 255.0;
        Thread.Sleep(500);
    }

}

8. 最后

本文相关代码和之前相关系列文章的代码均已在 Github 开源,感兴趣的同学可以查阅:
https://github.com/sangyuxiaowu/ESP32_S2_PICO。

如有错漏之处,敬请指正。

声明:本文来自“桑榆肖物”,仅允许规范转载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/170664.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

萌新如何使用printf函数?

&#x1f40e;作者的话 如果你搜索输入输出函数&#xff0c;那么你会看到输入输出流、Turbo标准库、标准输出端、stdout什么什么乱七八糟的&#xff0c;作为一个萌新&#xff0c;哪懂这些&#xff1f; 本文介绍萌新在前期的学习中&#xff0c;常用的输入输出函数及其功能~ 跳跃…

ROS2机器人编程简述humble-第二章-Controlling the Iterative Execution .3.1

2.3 ANALYZING THE BR2 BASICS PACKAGE 这一节内容有些多……前一篇&#xff1a;ROS2机器人编程简述humble-第二章-DEVELOPING THE FIRST NODE .2里面只有节点&#xff0c;没有任何实际功能。logger.cpp代码如下所示&#xff1a;#include "rclcpp/rclcpp.hpp"using n…

微信小程序分享的图片被裁切了。怎么让他不裁剪正常比例5:4显示

现在的效果 希望的效果 最主要的是下面的这个函数。把图片转成了5:4的临时图片 cutShareImg(doctorImg:string ){let thatthis;return new Promise((resolve) > {wx.getImageInfo({src: doctorImg, // 这里填写网络图片路径 success: (res) > {var data resconsole.l…

使用 LibreOffice 将 word 转化为 pdf 并解决中文乱码问题

目录 一、安装 LibreOffice 二、解决乱码问题 2.1 查看是否安装中文字体 2.2 准备字体 2.3 导入字体 2.4 验证 项目中有一个在线上传 word 并预览 pdf 报告的需求&#xff0c;因为项目部署在 ubuntu 上面&#xff0c;所以借助libreoffice 实现 word 转 pdf&#xff0c;然…

详细实例说明+典型案例实现 对枚举法进行全面分析 | C++

第五章 枚举法 目录 ●第五章 枚举法 ●前言 1.简要介绍 2.代码及结果示例&#xff08;简单理解&#xff09; 3.生活实例 ●二、枚举法的典型案例——鸡兔同笼&质数求解 1.鸡兔同笼 2.质数求解&#xff08;枚举法&#xff09; ●总结 前言 简单的来说…

最新 vue-cli 构建项目

vue-cli 构建项目 当前使用最新版本构建一个vue node项目 插件 vue-clivueelement-plusroutervuex 安装vue-cli npm install -g vue-cli安装完后 vue --version 查看版本 vue --version创建一个项目 vue create demo这里要选择版本&#xff0c;不同版本要相组合配置的插件…

反射的基本使用

文章目录1. 一个需求引出反射2. 反射机制2.1 Java Reflection2.2 Java 反射机制可以完成2.3 反射相关的主要类2.4 反射优点和缺点2.5 反射调用优化-关闭访问检查3. Class类3.1 基本介绍3.2 Class类的常用方法3.3 获取Class类对象3.4 哪些类型有Class对象3.5 类加载3.6 类加载流…

aws imagebuilder 理解并使用imagebuilder构建pcluster自定义ami

参考资料 ec2-image-builder-workshop Troubleshoot EC2 Image Builder 理解imagebuilder imagebuilder 使用 cinc-client 进行客户端统一配置&#xff0c;CINC is not Chef&#xff0c;而是chef的免费分发版本。 https://cinc.sh/about/ imagebuilder管道的整体逻辑如下 核…

OpenHarmony如何切换横竖屏?

前言在日常开发中&#xff0c;大多APP可能根据实际情况直接将APP的界面方向固定&#xff0c;或竖屏或横屏。但在使用过程中&#xff0c;我们还是会遇到横竖屏切换的功能需求&#xff0c;可能是通过物理重力感应触发&#xff0c;也有可能是用户手动触发。所以本文主要带大家了解…

Git 代码版本管理工具详解 进厂必备

目录前言Git 概述什么是版本控制&#xff1f;为什么需要版本控制&#xff1f;版本控制工具集中式分布式Git 工作机制Git安装Git 常用命令(部分)初始化本地库设置用户签名初始化本地库查看本地库状态***工作区代码编写***添加暂存区撤销工作区的修改***提交本地库***工作区修改代…

选择排序算法的实现和优化

初识选择排序&#xff1a; 算法思想[以升序为例]&#xff1a; 第一趟选择排序时&#xff0c;从第一个记录开始&#xff0c;通过n-1次关键字的比较&#xff0c;从第n个记录中选出关键字最小的记录&#xff0c;并和第一个记录进行交换 第二趟选择排序时&#xff0c;从第二个记…

Linux学习笔记【part1】目录结构与VIM文本编辑器

Linux基础篇学习笔记 1.CentOS 7 64位安装 第一步&#xff0c;在软件选择中可以设置图形界面。 第二步&#xff0c;手动分区中设置挂载点&#xff0c;分别为引导分区、通用分区和交换区。 第三步&#xff0c;设置内核崩溃转储机制&#xff0c;这对服务器来说非常有用。 第四步…

传输层协议:TCP与UDP协议的区别

TCP和UDP有哪些区别&#xff1f; 关于TCP与UDP协议两个协议的区别&#xff0c;大部分人会回答&#xff0c;TCP是面向连接的&#xff0c;UDP是面向无连接的。 什么叫面向连接&#xff0c;什么叫无连接呢&#xff1f;在互通之前&#xff0c;面向连接的协议会先建立连接。例如&a…

网络工程师备考7章

考点分布: 注:考点不多,这个重点记住即可; 7.1 IPV4的问题与改进 7.2 IPV6的报文格式 注:版本0110表示IPV6,源地址和目的地址都是128位(bit),整个头部固定40个B(字节) 注:通信类型和流标记实际上是没有用的。负载长度是实际的报文长度,下一个头部:IPV6是可以作…

297. 二叉树的序列化与反序列化

297. 二叉树的序列化与反序列化 难度困难 序列化是将一个数据结构或者对象转换为连续的比特位的操作&#xff0c;进而可以将转换后的数据存储在一个文件或者内存中&#xff0c;同时也可以通过网络传输到另一个计算机环境&#xff0c;采取相反方式重构得到原数据。 请设计一个…

Linux:查看服务器信息,CPU、内存、系统版本、内核版本等

还是最近工作的总结&#xff0c;性能验证要根据服务器的配置才能做进一步的结论论证&#xff0c;废话不多说 目录查看Linux内核版本查看Linux系统版本CPU查看CPU信息&#xff08;型号&#xff09;物理CPU个数每个物理CPU中core的个数(即核数)查看逻辑CPU的个数内存查看内存信息…

【C语言航路】第十三站:动态内存管理

目录 一、为什么存在动态内存分配 二、动态内存函数 1.内存的分区 2.malloc和free &#xff08;1&#xff09;malloc和free库函数文档 &#xff08;2&#xff09;malloc和free的使用 2.calloc &#xff08;1&#xff09;calloc的库函数文档 &#xff08;2&#xff09;c…

模糊图像检测(c++)

Opencv-模糊检测 - 知乎图像清晰度&#xff0c;是指影像上各细部影纹及其边界的清晰程度。 解决问题&#xff1a;由于前端摄像机视频中聚焦不当&#xff0c;异物遮挡等原因&#xff0c;所引起的画面视野图像模糊的现象。 算法原理&#xff1a;将彩色图像转化为灰度图像&#xf…

Python深度学习基础(九)——深入浅析卷积核

深入浅析卷积核引言单通道卷积简单图像边缘检测锐化高斯滤波引言 提到卷积&#xff0c;应该多数人都会想到类似上图的这种示例&#xff0c;可以简单的理解成卷积核与图像中和卷积核相同大小的一块区域与卷积核相乘再求和&#xff0c;通过移动区域产生一个有和组成的新的图像&am…

黑马学ElasticSearch(十二)

目录&#xff1a; &#xff08;1&#xff09;ES集群-集群结构介绍 &#xff08;2&#xff09;es集群-搭建集群 &#xff08;3&#xff09;es集群-集群职责及脑裂 &#xff08;4&#xff09;es集群-分布式新增和查询流程 &#xff08;5&#xff09; es集群-故障转移 &#…