obsidian-notes/DIY/LED灯环.md
2024-06-20 08:45:57 +08:00

5.8 KiB
Raw Blame History

title updated tags
led ring 2024-06-08
led
编码器
源码

目的

实现一个独立的多色led灯环与电位器或编码器配合使用同步显示当前状态。

设计

采用WS2812B1010小封装最小连线和IO消耗下实现对每个LED的独立、多色控制。

协议1

动态配置HEX格式每次显示前发送显示指令当前值,[区间下限,区间上限],[下限颜色,上限颜色]

当前值 区间下限 区间上限 下限颜色 上限颜色
2字节 2字节 2字节 3字节 3字节
2字节取值范围为[-32768,32768]
  1. 参数只有当前值时,其它参数使用缺省值[区间下限,区间上限]=[0,1],[下限颜色,上限颜色]=[#FF0001,#00FF7F]
  2. 参数只有当前值区间下限区间上限时,其它参数使用缺省值[下限颜色,上限颜色]=[#FFA500,#FFA500]
  3. 缺省为静态显示,支持动态显示,如海浪

协议2

静态配置HEX格式。需初始化显示参数索引值,[区间下限,区间上限],[下限颜色,上限颜色],每次显示前发送指令:索引值,当前值

00,0000,0001,#FF0001,#00FF7F //双色显示布尔量
01,0001,0064,#FFA500,#FFA500 //单色显示0~100范围
02,FD2E,02D2,#00FF7F,#FF00FF //双色渐变显示-722~722范围

渐变色转换算法

使用色相环实现颜色渐变具有更好的显示效果 参考aardio代码实现

    rgb2hsb = function(r,g,b) {
        if( 0 > r || r > 255 ) error("R值范围0~255",2) 
        if( 0 > g || g > 255 ) error("G值范围0~255",2)  
        if( 0 > b || b > 255 ) error("B值范围0~255",2) 

        var rgb =  { r;g;b };  
        ..table.sort(rgb);  

        var max = rgb[3];  
        var min = rgb[1];  
          var d = (max - min);

          var s;
        var v = max / 255;
        if(max == 0) s = 0 else s =  d /  max;

        var h = 0;
        if(d){
            if (max == r ){
                h =  (g - b) * 60 / d;
                if (g < b) h = h + 360;
            }
            elseif (max == g) {  
                h = (b - r) * 60 / d + 120;  
            } 
            else{  
                h = (r - g) * 60 / d + 240;  
            } 
        } 

        return ..math.round(h,2)%360, ..math.round(s,2), ..math.round(v,2);  
    }

    hsb2rgb = function(h,s,v) {  
        h = h % 360;
        if( h <0 || h >360 ) error("h值范围0~360",2)
        if( s <0 || s >1 ) error("s值范围0~1",2)
          if( v <0 || v >1 ) error("v值范围0~1",2)

        var r,g,b = 0,0,0;  
        var i = ..math.floor( (h / 60) % 6 );  
        var f = (h / 60) - i;  
        var p = v * (1 - s);  
        var q = v * (1 - f * s);  
        var t = v * (1 - (1 - f) * s);  

        select (i) {  
            case 0{ 
                r = v;  
                g = t;  
                b = p;  
            }
            case 1{  
                r = q;  
                g = v;  
                b = p;  
            }
            case 2{  
                r = p;  
                g = v;  
                b = t;  
            }
            case 3{  
                r = p;  
                g = q;  
                b = v;  
            } 
            case 4{   
                r = t;  
                g = p;  
                b = v;  
            }
            case 5{   
                r = v;  
                g = p;  
                b = q;   
            }
        }  
        return ..math.round(r * 255),..math.round(g * 255), ..math.round(b * 255);  
    }

在色相h、纯度s、明度l三个维度作线性差值假如共20个led其中16个led作范围显示区间划分为16等份则为渐变色

静态存储

静态初始化的优点是响应速度快,因为更新颜色时没有计算耗时,缺点是耗内存 三维数组uint color[N][16][3]

{
    {//索引0
        {0x01,0x00,0xFF},//#FF0001
        {0x7F,0xFF,0x00}//#00FF7F
    },
    {//索引1
        {r0,g0,b0},
        {r1,g1,b1},
        {r2,g2,b2},
        //...Unknown encodingUnknown encoding1024/3/16=21组。

优化后

可改用统一颜色计算uint8 colormap[N][3]待用N为总LED个数占用N*3字节。

协议为:

[索引值] 区间下限/当前值 [区间上限] [下限颜色] [上限颜色]
1字节 2字节 2字节 3字节 3字节
可选 可选 可选 可选
四种模式:
  1. 索引值,[区间下限,区间上限],[下限颜色,上限颜色]总11字节
  2. 索引值,[区间下限,区间上限]总5字节
  3. 索引值,当前值总3字节
  4. 当前值总2字节 即
  5. 0x00,0x0000,0x0000,r,g,b配置颜色。总11字节且前5字节全为0。
  6. index,min,max更新索引配置。总5字节。
  7. index,value动态更新颜色。总3字节。
  8. 仅value则沿用上次的index。总2字节。

存储过程:

直接分配4*M字节内存支持M个索引按需扩展按index进行索引存储即uint8 cfg[index]=[min,max]

优势是简洁高效,去重容易,直接引用,不用遍历搜索。

  • ==去重==指后发送的索引配置会覆盖之前的配置
  • ==直接引用==指以索引配置支持无序输入,程序以此作为数组的位置编号,取出时直接取出,无需在数组中搜索。

颜色值映射过程:

  1. 计算渐变色并分为N个
  2. 计算index=round((value-min)/((max-min)/N)),四舍五入
  3. 发送colormap[0]至colormap[index]

主控:

华大MCU/华大/选型#[HC32L110C6](https //www.hdsc.com.cn/Category82-1389)系列及沁恒CH32V003系列,优选后者,便宜够用。