|
通过精确控制红色、绿色和蓝色LED灯的强度来显示颜色。
白色光 本篇文章旨在制作一种可以测量光线“颜色”的设备。您可能知道,日照光实际上是无数不同波长的电磁辐射的混合物。可见光谱中的每个波长(从约400nm延伸到700nm)对应于特定颜色,并且我们的眼睛将这种颜色混合解释为“白色”光。
然而,毫无疑问,你会注意到生活看起来有点不同,这取决于主要的照明来源。荧光灯和强烈的阳光看起来特别白,而白炽灯泡和蜡烛营造出更温暖的“淡黄”的氛围。出现这些变化是因为不同的“白色”光源产生了截然不同的颜色混合。强度和波长之间的这种关系被称为光谱成分,这是用图像比用文字更容易解释的概念之一。看一下Popular Mechanics的这张图。
我强烈推荐以下文章,名为Ultimate Light Bulb Test:Incandescent vs. Compact Fluorescent vs.LED。它提供了有关不同灯泡光谱特性的有趣和详细信息,包括人们可能用来描述每个灯泡产生的光质量的一些词。
红色、绿色和蓝色 “RGB”这个词现在很常见,它本身几乎就是一个词。标准的附加显示系统(如计算机显示器)使用红色、绿色和蓝色光的组合来产生各种不同的颜色。因此,我们可以使用红色、绿色和蓝色光电探测器的组合来“测量”颜色。在白光的背景下,以这种方式思考它可能更有帮助:通过使用对红光、绿光和蓝光敏感的独立探测器,我们可以基于光能量来估计光谱成分。可见光谱的下三分之一(对应于蓝色探测器)、中间三分之一(对应于绿色)、上三分之一(对应于红色)。在您仔细考虑下面的图像后,这应该更加清晰,该图像传达了用于该项目的RGB传感器中红色、绿色、蓝色和透明光电探测器的相对光谱灵敏度(Rohm的BH1745NUC)。
单像素RGB显示器 除非我们有某种方式报告结果,否则我们的颜色测量将不会非常有用。我们将使用RGB LED模块实现这一目标:我们可以根据RGB光电探测器的输出调整每个LED的强度(也就是亮度),因此模块的整体颜色将类似于照亮BH1745NUC传感器IC的颜色。在本文中,我们将讨论LED控制器,在下文中,我们将此功能与BH1745NUC的读取数据相结合。
该项目利用定制设计的PCB,包括EFM8 Universal Bee微控制器、四通道DAC(德州仪器的DAC084S085)、四通道运算放大器(德州仪器的LMV614)、RGB LED(Avago的ASMT-YTB7-0AA02)和BH1745NUC。
至关重要的是要理解LED强度和正向电流之间的关系比LED强度和正向电压之间的关系简单得多。请考虑本项目中使用的LED模块数据表中的以下图表。
强度和电流之间的关系是线性的;电流和电压之间的关系是高度非线性的,这意味着强度和电压之间的关系也是高度非线性的。因此,如果我们想以可预测和直接的方式控制强度,我们需要调整电流而不是电压。
从电压源到电流源 DAC是一个4通道、8位、电压输出器件,通过SPI控制。 EFM8提供2.4 V参考电压。因此,DAC输出电压在0V至2.4V之间变化,步长为(2.4V)/(28)= 9.4mV。我们希望将此电压转换为将LED从零强度变为最大强度的电流。要做到这一点,我们需要一个运算放大器和一些负反馈;通用方法如下:
这里的基本原理是运算放大器将调整其输出,以使负输入端的电压等于正输入端的电压。反馈电阻器(RFB)将通过LED的电流转换为电压,使得施加到正输入的控制电压确定LED的正向电流并因此确定其强度。以下是该项目中使用的电路的设计过程: 1. 选择最大正向电流。我们将使用20 mA,这对于绿色和蓝色LED轻松低于25 mA的指定最大值(红色LED的最大值为50 mA)。请记住选择能够安全地获取这么大电流的运算放大器。 2. 使用电阻分压器将控制电压降低10倍。这使我们可以使用更小的反馈电阻,从而增加可用于LED正向压降的输出电压比例。 3. 调整反馈电阻的大小,使最大电流下的反馈电压等于最大10分频控制电压: (2.4 V÷10)= RFB×20mA⇒RFB= 240 mV20 mA =12Ω 这是实际电路的原理图:
固件代码 固件中包含用于测试RGB LED电路的所有源文件和项目文件。将项目加载到Simplicity Studio时,可以双击“hwconf”文件以访问端口引脚和外设的配置详细信息。另请注意,这些源文件包含一些此演示项目不需要的代码。
该项目的功能如下:DAC通道A控制红色LED,通道B控制绿色LED,通道C控制蓝色LED。 EFM8首先将通道A从0增加到255,然后将通道B从0增加到255,然后将通道C从0增加到255。 RGB例程实现如下: - while (1)
- {
- /*It is an 8-bit DAC, so the full range is 0 to 255. First channel A
- * (corresponding to the red LED) is incremented, then channel
- * B (corresponding to green), then channel C (corresponding to blue).*/
-
- /*The unused colors are set to zero to ensure that
- * we display pure red, green, and blue.*/
- UpdateDAC(DAC_RGB_G, 0);
- UpdateDAC(DAC_RGB_B, 0);
- UpdateDAC(DAC_RGB_R, 0);
- Delay_10ms(100);
- for(n=1; n>0; n++)
- {
- UpdateDAC(DAC_RGB_R, n);
- Delay_us(10000);
- }
- UpdateDAC(DAC_RGB_R, 0);
- UpdateDAC(DAC_RGB_B, 0);
- UpdateDAC(DAC_RGB_G, 0);
- Delay_10ms(100);
- for(n=1; n>0; n++)
- {
- UpdateDAC(DAC_RGB_G, n);
- Delay_us(10000);
- }
- UpdateDAC(DAC_RGB_R, 0);
- UpdateDAC(DAC_RGB_G, 0);
- UpdateDAC(DAC_RGB_B, 0);
- Delay_10ms(100);
- for(n=1; n>0; n++)
- {
- UpdateDAC(DAC_RGB_B, n);
- Delay_us(10000);
- }
- }
复制代码
UpdateDAC()函数中的代码和注释描述了将新数据加载到DAC芯片的过程: - void UpdateDAC(unsigned char ChannelABCorD, unsigned char DACcode)
- {
- //ensure that we are not interrupting an ongoing transmission
- while(SPI_State != IDLE);
- /*This switch statement sets the two most significant bits of the 16-bit DAC word
- * according to which channel is being updated. It also sets the two "operation mode"
- * bits to binary 01, which corresponds to "write to specified register and
- * update outputs."*/
- switch(ChannelABCorD)
- {
- case DAC_CH_A:
- UpdateDAC_FirstByte = 0x10;
- break;
- case DAC_CH_B:
- UpdateDAC_FirstByte = 0x50;
- break;
- case DAC_CH_C:
- UpdateDAC_FirstByte = 0x90;
- break;
- case DAC_CH_D:
- UpdateDAC_FirstByte = 0xD0;
- break;
- }
- /*The upper four bits of the DAC code are the lower four bits
- * of the first byte, and the lower four bits of the DAC code are
- * the upper four bits of the second byte.*/
- UpdateDAC_FirstByte = UpdateDAC_FirstByte | (DACcode >> 4);
- UpdateDAC_SecondByte = DACcode << 4;
- SPI0CFG |= BIT4; //this sets the proper clock polarity for the DAC interface
- DAC_NSS = LOW; //activate DAC slave select
- SPI0DAT = UpdateDAC_FirstByte;
- SPI_State = FIRST_DAC_BYTE_SENT;
- }
复制代码
SPI传输从UpdateDAC()中的最后四个语句开始,并在SPI状态机中继续,SPI状态机包含在SPI中断服务程序中。 - SI_INTERRUPT (SPI0_ISR, SPI0_IRQn)
- {
- //SPI registers are on all SFR pages, so need need to modify SFRPAGE
- SPI0CN0 &= ~BIT7; //clear interrupt flag
- switch(SPI_State)
- {
- //SPI communications with DAC=====================================
- case FIRST_DAC_BYTE_SENT:
- SPI0DAT = UpdateDAC_SecondByte;
- SPI_State = SECOND_DAC_BYTE_SENT;
- break;
- case SECOND_DAC_BYTE_SENT:
- DAC_NSS = HIGH; //disable slave select
- SPI_State = IDLE;
- break;
- }
- }
复制代码
总结 我们现在已经设计完成了电路和固件,它们将RGB LED组合成一个8位深度的单像素彩色显示屏。 在下一篇文章中,我们将使用此像素直观地传达照亮RGB传感器的光的颜色特征。 |