157 lines
5.6 KiB
Markdown
157 lines
5.6 KiB
Markdown
|
---
|
|||
|
title: led ring
|
|||
|
updated: 2024-06-08
|
|||
|
tags:
|
|||
|
- led
|
|||
|
- 编码器
|
|||
|
- 源码
|
|||
|
---
|
|||
|
# 目的
|
|||
|
实现一个独立的多色led灯环,与电位器或编码器配合使用,同步显示当前状态。
|
|||
|
# 设计
|
|||
|
采用WS2812B,1010小封装,最小连线和IO消耗下实现对每个LED的独立、多色控制。
|
|||
|
## ~~协议1~~
|
|||
|
动态配置,HEX格式,每次显示前发送显示指令:`当前值,[区间下限,区间上限],[下限颜色,上限颜色]`
|
|||
|
|
|||
|
| 当前值 | 区间下限 | 区间上限 | 下限颜色 | 上限颜色 | |
|
|||
|
|:-----------------------:|:----:|:----:|:----:|:----:| --- |
|
|||
|
| 2字节 | 2字节 | 2字节 | 3字节 | 3字节 | |
|
|||
|
| 2字节取值范围为:[-32768,32768] | | | | | |
|
|||
|
1. 参数只有`当前值`时,其它参数使用缺省值`[区间下限,区间上限]=[0,1],[下限颜色,上限颜色]=[#FF0001,#00FF7F]`
|
|||
|
2. 参数只有`当前值`、`区间下限`、`区间上限`时,其它参数使用缺省值`[下限颜色,上限颜色]=[#FFA500,#FFA500]`
|
|||
|
3. 缺省为静态显示,支持动态显示,如`海浪`
|
|||
|
|
|||
|
## ~~协议2~~
|
|||
|
静态配置,HEX格式。需初始化显示参数`索引值,[区间下限,区间上限],[下限颜色,上限颜色]`,每次显示前发送指令:`索引值,当前值`
|
|||
|
```c
|
|||
|
00,0000,0001,#FF0001,#00FF7F //双色显示布尔量
|
|||
|
01,0001,0064,#FFA500,#FFA500 //单色显示0~100范围
|
|||
|
02,FD2E,02D2,#00FF7F,#FF00FF //双色渐变显示-722~722范围
|
|||
|
```
|
|||
|
## 渐变色转换算法
|
|||
|
使用色相环实现颜色渐变具有更好的显示效果
|
|||
|
参考aardio代码实现
|
|||
|
```javascript
|
|||
|
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\]
|
|||
|
```c
|
|||
|
{
|
|||
|
{//索引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字节
|
|||
|
即
|
|||
|
1. 0x00,0x0000,0x0000,r,g,b配置颜色。总11字节,且前5字节全为0。
|
|||
|
2. index,min,max更新索引配置。总5字节。
|
|||
|
3. index,value动态更新颜色。总3字节。
|
|||
|
4. 仅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]
|