## 三色灯控制
### 1. 硬件平台
- [[STEP-MXO2第二代]]
### 2. 设计要求
- 掌握按键消抖和PWM的实现原理
- 了解LED通过PWM调亮度的方法
- 掌握三基色颜色合成的原理
- 基于[[STEP-MXO2第二代]]平台实现三色灯的基本颜色合成及亮度控制
### 3. 工作原理
这里三色灯是在一个物理封装里面,有R(红)、G(绿)、B(兰)三种颜色的LED灯,这三个灯非常靠近,从远处看可以当作一个三色的发光点。
{{ :三基色合成.jpg |三基色合成}}
根据红、绿、蓝三色的不同组合可以合成不同颜色的光,例如红色和绿色组合可以产生黄色的光,绿色和蓝色组合可以产生青色的光,相同颜色不同亮度组合也会产生不同的光等等,如图。
本实验中我们实现三基色的固定组合,最终输出产生图中的红色、绿色、蓝色、黄色、青色、品红、白色7中颜色,然后根据PWM的原理调节LED灯颜色的亮度,使用PWM,给LED灯上施加数字信号,通过调整数字信号的占空比(调整占空比 = 调整有效值)来控制LED灯的亮度。
{{ :脉冲有效值.jpg |脉冲信号有效值}}
如上图所示,脉冲信号的周期为T,高电平脉冲宽度为t,占空比为t/T。为了实现PWM脉宽调制,我们需要保持周期T不变,调整高电平脉宽t的时间,从而改变占空比。
* 当t = 0时,占空比为0%,因为我们的LED硬件为低电平点亮,所以为最亮的状态。
* 当t = T时,占空比为100%,LED灯为最暗(熄灭)的状态。
我们使用按键控制t的变化,控制RGB合成色的亮度。
### 4. 硬件连接
三色灯是由三种颜色的LED集成的,硬件连接如下:
{{ ::rgb_led.jpg |RGB三色灯硬件连接}}
注意:R、G、B三种颜色的LED的限流电阻的阻值是不同的,主要是因为达到同样的亮度,每种颜色的LED灯所需要的电流是不同的。
小脚丫开发板上有两组RGB三色灯,在本实验中我们采用其中的一组做实验。
### 5. 代码设计
#### 5.1 设计文件
{{ :三色灯程序设计.jpg |三色灯程序设计}}
三色灯设计要求我们输出不同的颜色同时亮度可调,我们使用一个按键循环控制颜色,另外使用两个按键控制灯的亮度,接口定义如下:
input clk_in,
input rst_n_in,
input key_color,
input key_up,
input key_down,
output led_R,
output led_G,
output led_B
有按键输入,需要按键消抖,具体原理请参考[[按键消抖]]实验,调用按键消抖的功能模块
//Debounce for key
wire [2:0] key_pulse;
Debounce1 Debounce_uut
(
.clk(clk_in),
.rst_n(rst_n_in),
.key_n({key_color,key_up,key_down}),
.key_pulse(key_pulse)
);
wire color_pulse = key_pulse[2];
wire up_pulse = key_pulse[1];
wire down_pulse = key_pulse[0];
定义计数器cnt,每当按动按键key_color时,cnt在0~7之间循环计数,然后使用case语句,根据cnt不同的状态控制三色灯输出不同的颜色:
always@(posedge color_pulse or negedge rst_n_in) begin
if(!rst_n_in) begin
cnt <= 3'd0;
color <= 3'd0;
end else begin
cnt <= cnt + 3'd1;
case(cnt)
3'd0: color <= BLACK;
3'd1: color <= RED;
3'd2: color <= GREEN;
3'd3: color <= BLUE;
3'd4: color <= YELLOW;
3'd5: color <= CYAN;
3'd6: color <= MAGENTA;
3'd7: color <= WHITE;
default: color <= BLACK;
endcase
end
end
调用PWM功能模块,实现亮度的调节,具体原理见[[脉冲发生器]]和[[呼吸灯]]实验,为了保证三色灯在单色(红、绿、蓝)、双色合成(黄、青、品红)和三色合成(白)之间切换时亮度相同,单色切换为双色合成色时,需要将双色合成时每种基色的亮度减半,单色切换为三色合成色时需要将三色合成时每种基色亮度降为33%,亮度与占空比相关。例如红色时我们调节控制信号占空比为60%,输出黄色时其中的红色和绿色的控制信号占空比都为30%,输出白色时其中的红绿蓝三色的控制信号占空比都为20%,使用脉宽不变,改变脉冲周期的方法实现
localparam CYCLE_ONE = 5;
localparam CYCLE_TWO = 10;
localparam CYCLE_THREE = 15;
reg [3:0] cycle;
//Control duty cycle
always @(color) begin
case(color)
3'b110: cycle = CYCLE_ONE;
3'b101: cycle = CYCLE_ONE;
3'b011: cycle = CYCLE_ONE;
3'b100: cycle = CYCLE_TWO;
3'b010: cycle = CYCLE_TWO;
3'b001: cycle = CYCLE_TWO;
3'b000: cycle = CYCLE_THREE;
3'b111: cycle = CYCLE_THREE;
default: cycle = CYCLE_ONE;
endcase
end
我们采用产生PWM信号Lightness_out,然后根据PWM控制亮度,如下:
assign led_R = Lightness_out? color[0]:1'b1;
assign led_G = Lightness_out? color[1]:1'b1;
assign led_B = Lightness_out? color[2]:1'b1;
引脚分配如下:
^ 管脚名称 | clk_in| rst_n_in| key_color| key_up| key_down| led_R| led_G| led_B|
^ FPGA管脚 | C1 | N14 | L14 | M13 | M14 | M2 | N2 | P2 |
### 6. 仿真结果
{{:红色.jpg?180 |红色}}
{{:绿色.jpg?180 |绿色}}
{{:蓝色.jpg?180 |蓝色}}
{{:黄色.jpg?180 |黄色}}
{{:青色.jpg?180 |青色}}
{{:品红.jpg?180 |品红}}
{{:白色.jpg?180|白色}}
### 7. 资源报告
^ 资源 | 数量 | 比例 | 说明 |
^ LUTs | 77 | 2% | |
^ 寄存器 | 43 | 1% | |
^ 存储器 | 0 | 0% | |
^ IO管脚 | 8 | | |
^ 时钟频率 | 12MHz | | |
### 8. 知识点
* 颜色合成原理
* PWM脉宽调节
* 脉冲发生原理
### 9. 参考文档
* [[按键消抖]]
* [[脉冲发生器]]
* {{:machxo2familydatasheet.pdf|Lattice MachXO2数据手册}}
### 10. 相关文档
^ **文件名称** | **功能** |
^ **[[Color_led.v]]** | **三色灯,顶层模块** |
^ **[[Debounce1.v]]** | **按键消抖模块** |
^ **[[Lightness.v]]** | **PWM亮度调节模块** |