RGB色彩模式是工业界的一种颜色标准,是通过对红(R)、绿(G)、蓝(B)三个颜色通道的变化以及它们相互之间的叠加来得到各式各样的颜色的,RGB即是代表红、绿、蓝三个通道的颜色,这个标准几乎包括了人类视力所能感知的所有颜色,是目前运用最广的颜色系统之一。三个值的范围一般用0~255或者0~100来表示。
HSV是一种将RGB色彩空间中的点在倒圆锥体中的表示方法。HSV即色相(Hue)、饱和度(Saturation)、明度(Value),又称HSB(B即Brightness)。色相是色彩的基本属性,就是平常说的颜色的名称,如红色、黄色等,范围0~360。饱和度(S)是指色彩的纯度,越高色彩越纯,低则逐渐变灰,取0-100%的数值。明度(V),取0-max(计算机中HSV取值范围和存储的长度有关),一般取0-100%的数值。HSV颜色空间可以用一个圆锥空间模型来描述。圆锥的顶点处,V=0,H和S无定义,代表黑色。圆锥的顶面中心处V=max,S=0,H无定义,代表白色。
之所以需要了解这两个颜色空间,是因为市面上大多数的RGB灯都是使用这两种颜色来表示颜色的。例如智能家居的灯产品中常常将HSV值面向用户,而将RGB值用于控制PWM占空比。用户通过HSV了解灯的状态,芯片接收新的HSV值后转化为RGB后调节PWM占空比。
了解了两个颜色空间,就可以设计一个简单的RGB灯了。使用上一次的工程即可。
RGB LED灯模块淘宝上有很多,要注意PWM的频率和LED的频率相符,一般使用1KHz左右的频率。STM32CubeMX生成初始化代码后,需要另外使用HAL_TIM_PWM_Start函数开启PWM,然后就可以使用__HAL_TIM_SET_COMPARE宏设置想要的占空比比较值了。
这里给出几个颜色的色相值。红色0,黄色60,橙色30,绿色120,蓝色240,紫色300。饱和度和亮度默认100。设置颜色时,需要将HSB值转换成RGB值,然后根据RGB值设置3个PWM通道的占空比,灯就会显示相应的颜色了。
关于HSV和RGB之间的转化算法,可以参考百度百科。百度上也有很多转换的相关文章可以参考。以下的算法是我自己用的。
//! hsb结构体 typedef struct { //! h(色相) float h; //! s(饱和度) float s; //! b(亮度) float b; }hsb_t; //! rgb结构体 typedef struct { //! r(红色)百分比 float r; //! g(绿色)百分比 float g; //! b(蓝色)百分比 float b; }rgb_t; static void hsb_to_rgb(hsb_t * hsb, rgb_t * rgb) { int i; float f, p, q, t, r, g, b; float h = hsb->h, s = hsb->s / 100, v = hsb->b / 100; if( s == 0 ) { rgb->r = rgb->g = rgb->b = hsb->b; return; } h /= 60; // sector 0 to 5 i = (int)h; f = h - i; // factorial part of h p = v * ( 1 - s ); q = v * ( 1 - s * f ); t = v * ( 1 - s * ( 1 - f ) ); switch( i ) { case 0: r = v; g = t; b = p; break; case 1: r = q; g = v; b = p; break; case 2: r = p; g = v; b = t; break; case 3: r = p; g = q; b = v; break; case 4: r = t; g = p; b = v; break; default: // case 5: r = v; g = p; b = q; break; } rgb->r = r * 100; rgb->g = g * 100; rgb->b = b * 100; } void set_rgb_color(rgb_t * rgb) { __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, (uint32_t)(rgb->r * 10)); __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_2, (uint32_t)(rgb->g * 10)); __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_3, (uint32_t)(rgb->b * 10)); } void set_hsb_color(hsb_t * hsb) { rgb_t rgb; hsb_to_rgb(hsb, &rgb); set_rgb_color(&rgb); }