发作品签到
专业版

自调光屏幕挂灯

工程标签

3.4k
0
0
1

简介

基于STM32制作的一款调光屏幕挂灯,具有照明和调节RGB氛围的效果。主控芯片输出驱动信号驱动LED灯带实现桌面照明效果,采用WS2812B灯带作桌面电脑的背景氛围灯。

简介:基于STM32制作的一款调光屏幕挂灯,具有照明和调节RGB氛围的效果。主控芯片输出驱动信号驱动LED灯带实现桌面照明效果,采用WS2812B灯带作桌面电脑的背景氛围灯。
星火计划2023

开源协议

BSD License

创建时间:2023-03-26 11:46:30更新时间:2023-08-26 01:43:07

描述

1.硬件选型

LED灯带:该设计采用的是这种COB灯带,可以分别对白暖2个灯带分别调光,2种混合即可调节亮度与色温,只有亮度要求的话可以选用普通LED灯带,单纯调整亮度即可(这款灯带实测下来还是有点差强人意,主要是色温不太符合我的预期)

功率:14w/m 608灯,10mm3线 dc24v

0

0

0

电源:

220V转24v电源为市面上LED电源适配器

d2sppHQKndBg8UzRGIA2k1E3a1tLlgB0WNtm4wQg.jpeg

24v-5v采用最常用的DC-DC降压稳压芯片LM2596S-5V,其特点如下:

1.在特定的输入电压和输出负载的条件下,输出电压的误差可以保证在±4%的范围内,振荡频率误差在±15%的范围内;

2.可以用仅80μA的待机电流,实现外部断电;

3.具有自我保护电路(一个两级降频限流保护和一个在异常情况下断电的过温完全保护电路)。

6ZPg0IecTxcamo4KSqitaoyD9xYNEHpX8trY2DAD.png

0

主控:这里用到的是STM32F103CBT6,与C8T6相比内存容量更多,存储更多WS2812B数据内容。

RGB灯:该设计用到的RGB灯为WS2812B,每个LED灯珠为一个像素点,支持RGB无极调色,同时每颗灯珠内部集成有智能数字接口数据锁存信号整形放大驱动电路,还包含有高精度的内部振荡器和可编程定电流控制部分,有效保证了像素点光的颜色高度一致。 

ZbG6lVHNBwULhng4YzkLULCMpL5TjfLCv5RmIU2B.png

2.设计原理

通信数据包格式

帧头 1 2 3 4 5 帧尾 备注
0xff 0xfe 亮度1 亮度2 色温1 色温2 0xfe 挂灯数据
0xff 0x90 序号(0-x个RGB灯) G R B  0xfe 屏幕采集RGB
0xff 0xca - - 亮度 速率 0xfe 跑马灯
0xff 0x66 - - - - 0xfe 静态显示

挂灯调光原理

调节白灯和暖灯的发光强度混合到一起就能得到不同色温的效果,同时调整亮度和色温都用到光照强度的变化,所以定义PWM宽度就是光照总亮度,白光和暖光PWM的占比调整色温。

LED调光

主动调光:电脑上位机发送挂灯亮度、色温发送到单片机,再根据色温与亮度的关系,单片机根据数据内容配置定时器的PWM宽度驱动功率MOS管的开关导通来调节灯带。

/*RxState 是存放串口1字节的buff*/
/*--------数据帧头----------*/
if (RxState == 0){
if(RxData == 0xFF)RxState = 1;
}
/*--------控制信息----------*/
else if (RxState == 1){ 
.........
else if(RxData==0xfe){//挂灯模式的控制信息
RxState=50;
USART1_light_RxPacket[0] = RxData;//存放到一个数组
}
.........
else RxState=0;//接收错误 
return;
}
//接收挂灯信息
else if(RxState==50){
USART1_light_RxPacket[pRxPacket_light+1] = RxData;//存放到一个数组
pRxPacket_light ++;
if (pRxPacket_light >= 4){RxState = 3;pRxPacket_light=0;}//挂灯模式接收完成了,位数够了的话
}
/*---------判断数据包尾部---------*/
else if (RxState == 3){
            
            //如果接收到帧尾就没问题,现在要解决的问题就是怎么在帧尾加入复位信息,因为屏幕采光是最可能出错的地方,6.7
            if (RxData == 0xFE){
                RxState = 0;
            }
}

然后就可以在主程序里设置亮度了

//初始化里面
Light_Init(500,71); //2000hz,网上说这样子不会有频闪
//挂灯控制
if(USART1_light_RxPacket[0]==0xfe){
//这里就是将亮度,色温适配到pwm的脉宽调制,因为亮度和色温都是2字节的数据,PWM是2000hz的频率,所以这里调整一下
Light_data.led0pwmval_warm=((float)(USART1_light_RxPacket[3]*256+USART1_light_RxPacket[4]) / 65536)*(USART1_light_RxPacket[1]*256+USART1_light_RxPacket[2])*0.0076;//=(色温参数/色温总值)*亮度当前值      
Light_data.led0pwmval_while=((float)(65536-(USART1_light_RxPacket[3]*256+USART1_light_RxPacket[4])) / 65536)*(USART1_light_RxPacket[1]*256+USART1_light_RxPacket[2])*0.0076;
 
//写入定时器
TIM_SetCompare2(TIM2,Light_data.led0pwmval_warm);//暖
TIM_SetCompare3(TIM2,Light_data.led0pwmval_while);//白
//清0,避免反复进入这里改变挂灯
USART1_light_RxPacket[0]=0xed;
 
//oled的显示,测试用
Light_data.luminance=((float)(USART1_light_RxPacket[1]*256+USART1_light_RxPacket[2])/65521)*100;//亮度指数
Light_data.temperature=((float)(USART1_light_RxPacket[3]*256+USART1_light_RxPacket[4]) / 65536)*100;//色温指数,暖光占比
 
//oled监测
OLED_ShowString(1,1,"W:");//色温数值-串口接收显示
OLED_ShowString(2,1,"L:");//亮度数值-串口接收显示
 
OLED_ShowNum(1,3,Light_data.led0pwmval_warm,5);
OLED_ShowNum(2,3,Light_data.led0pwmval_while,5);
OLED_ShowNum(1,9,Light_data.temperature,2);OLED_ShowChar(1,11,'%');//显示色温占比
OLED_ShowNum(2,9,Light_data.luminance,2);OLED_ShowChar(2,11,'%');//显示亮度占比
}

 

RGB屏幕背光(有待完善)

WS2812B的协议

0

STM32驱动驱动方法可参考该博文

【STM32】WS2812B灯珠的PWM+DMA控制(库函数)_绘漾的博客-CSDN博客

STM32驱动ws2812b可以有3种方法:1、手动改变PWM脉宽来控制"0"、"1"码,事实是不停的花费时间在这上面是很低效的一种方法,所以out;

2、模拟spi时序,这种就比较方便,将ws2812b的协议衍生成了常用的通信协议;

3、利用PWM+DMA数据搬运的方法,这种就减轻cpu的负担,精度也很ok。

 

void WS2812_DMA_Init(){
DMA_InitTypeDef DMA_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);
//源外设
DMA_InitStructure.DMA_MemoryBaseAddr=(uint32_t)RGB_Singel_buff;//存放数组的,就是哦,1码对应的脉宽值(ccr值)
DMA_InitStructure.DMA_MemoryDataSize=DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryInc=DMA_MemoryInc_Enable;
//目的外设
DMA_InitStructure.DMA_PeripheralBaseAddr=(uint32_t)&TIM3->CCR4;//转运到这里
DMA_InitStructure.DMA_PeripheralDataSize=DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_PeripheralInc=DMA_PeripheralInc_Disable;
 
DMA_InitStructure.DMA_BufferSize=2624;//转运次数
DMA_InitStructure.DMA_DIR=DMA_DIR_PeripheralDST;//传输方向 M->P
 
 
DMA_InitStructure.DMA_M2M=DMA_M2M_Disable;//软件or硬件触发,这里是软件触发
DMA_InitStructure.DMA_Mode=DMA_Mode_Circular;//是否自动重装,单次
 
DMA_InitStructure.DMA_Priority=DMA_Priority_Medium;//通道优先级
DMA_Init(DMA1_Channel3,&DMA_InitStructure);//DMA结构体初始化
 
DMA_Cmd(DMA1_Channel3,DISABLE);//先失能,防止第一个脉冲出问题
 
}

 

//RGBData[],RGB原始数据,size:数量,RGB灯的数量x3(R,G,B)
void RGBShow(uint8_t RGBData[],uint16_t size){
TIM_Cmd(TIM3,DISABLE);
TIM_ForcedOC4Config(TIM3, TIM_ForcedAction_InActive);//先失能,防止第一个脉冲出问题
DMA_Cmd(DMA1_Channel3,DISABLE);
 
//转码
for(u16 i=0;i
    for(uint8_t j=0;j<8;j++){
       RGB_Singel_buff[j+8*i]=((RGBData[i]<
    }
}
   //开启DMA
    DMA_SetCurrDataCounter(DMA1_Channel3,size*8);//长度
    DMA_Cmd(DMA1_Channel3,ENABLE);
    //开启定时器
    TIM_SelectOCxM(TIM3, TIM_Channel_4, TIM_OCMode_PWM1);
    TIM_CCxCmd(TIM3, TIM_Channel_4, TIM_CCx_Enable);
    TIM_Cmd(TIM3,ENABLE);
    //检查传输完成标志位
    while(DMA_GetFlagStatus(DMA1_FLAG_TC3)!=SET&&TIM_GetFlagStatus(TIM3,TIM_FLAG_CC4)==SET);
    //停止
    DMA_ClearFlag(DMA1_FLAG_TC3);
    DMA_Cmd(DMA1_Channel3,DISABLE);
    TIM_Cmd(TIM3,DISABLE);
}

 

 

mJEe9lzuNLWTeMJDt7PH4YF9AE52HiS3Zk4Hyw1p.jpeg

 

非对称光源

0

屏幕挂灯的非对称光源设计作为光源的补充,能在眼睛和屏幕插入柔和的光线且不舍在屏幕上,覆盖屏幕不均匀的光线。能让我们在晚上使用电脑时减少屏幕的反光,减少对眼睛的伤害,减少近视发生或者加重的概率。

我的设计就借鉴屏幕挂灯天花板明基的设计方案,用反光条发射光线获得非对称光源。

这一部分基本没什么技术含量,重点是找好尺寸和折射角度,让LED灯不会发射到屏幕上,引起屏幕反光。我的方案就是用常见的PVC水管作灯管,家里有一个砂轮,就用砂轮竖向割开,用灯槽作灯带和发射带的支撑,找好角度放好。

0

9hhEb1CjTTtwigL4xkP3QULgNCYp46Me1CrljQmm.jpeg

mTaQ7M6jwH2ibVanHXLsjwhGba539FGKRMrlDQjH.jpeg

 

 

设计图

未生成预览图,请在编辑器重新保存一次

BOM

暂无BOM

附件

序号文件名称下载次数
1
色温、亮度调节.mp4
13
2
屏幕挂灯效果.mp4
8
克隆工程
添加到专辑
0
0
分享
侵权投诉

工程成员

评论

全部评论(1)
按时间排序|按热度排序
粉丝0|获赞0
相关工程
暂无相关工程

底部导航