我目前正在设法通过我选择八种颜色,让我的LED循环。 一切正常,只是我想要去一个更自然的感觉,并且想从一个褪色/过渡到下一个,而不是让它们只是取代彼此。
这里是我到目前为止的代码:
int redPin = 11;
int greenPin = 10;
int bluePin = 9;
void setup()
{
pinMode(redPin, OUTPUT);
pinMode(greenPin, OUTPUT);
pinMode(bluePin, OUTPUT);
}
void loop()
{
setColor(250, 105, 0); // Yellow
delay(1000);
setColor(250, 40, 0); // Orange
delay(1000);
setColor(255, 0, 0); // Red
delay(1000);
setColor(10, 10, 255); // Blue
delay(1000);
setColor(255, 0, 100); // Pink
delay(1000);
setColor(200, 0, 255); // Purple
delay(1000);
setColor(0, 255, 0); // Green
delay(1000);
setColor(255, 255, 255); // White
delay(1000);
}
void setColor(int red, int green, int blue)
{
analogWrite(redPin, 255-red);
analogWrite(greenPin, 255-green);
analogWrite(bluePin, 255-blue);
}
Answer 1:
有什么其他的答案中省略有关这个话题的是,光强度的人类感知是对数,不是线性的 。 所述analogWrite()
例程设置输出销的PWM占空比,并且是直链。 因此,通过采取最小占空比(比如0
)和最大占空比(比如,便于数学这是着想10
),并把它分成相等的块,你会控制intensitiy 线性 ,不会给满意的结果。
什么,你需要做的,而不是被成倍设置你的强度。 比方说,你的最大强度为255
。 您可以产生这个结果的处理你的强度为动力,以提高一些号码。 在我们的例子,因为我们正在处理的电脑,像二进制,二的幂都方便。 所以,
2^0 =1
2^8=256
所以我们可以有8个强度等级。 实际上,注意了最低目前不是完全关闭(这是1
不是0
),我们的最大超出范围( 256
不是255
)。 因此,我们修改公式为
output = 2 ^ intensity - 1
或代码
int output = 1<<intensity - 1;
这产生了从值从0到255的亮度等级0
到8
(含),所以我们实际上得到九个级别的强度。 如果你想更平滑的过渡(即多级亮度),并仍然使用对数强度则需要浮点数学。
如果你申请的强度计算每个通道的这种方法(R,G,B),那么你的看法会与你的代码说它应该是一致的。
作为法尔斯如何顺利各种颜色之间转换,答案取决于你要如何定位的色彩空间。 做最简单的事情就是想想你的颜色空间为三角形,与R,G和B,作为verteces:
接下来的问题是如何定位这个三角形:你可以沿着两边走,从R,到G,到B.这样,你永远不会看到白色(完全开启所有通道)或“黑”(完全全部关闭)。 你可以把你的颜色空间为六边形,具有额外的紫色(R + B),黄色(G + B)和布朗(R + G)的颜色,也是导航周边(再次,没有白色或黑色)。 有因为有这些导航内部,我们可能会想到其他数字的方式尽可能多径衰落的可能性。
当我建立褪色这样的色彩空间和我喜欢的是如下的穿越方案:每想通道作为一个二进制位的,所以现在你有三个(R,G和B)。 如果你觉得每种颜色具有这些渠道是完全对的某种组合,你会得到总共7种颜色(不包括黑色,但包括白色)。 先取这些颜色,从黑色渐变为它和背部为黑色,然后再进入下一个颜色。 下面是一些代码,做这样的事情:
int targetColor = 1;
int nIntensity = 0;
int nDirection = 1; // When direction is 1 we fade towards the color (fade IN)
// when 0 we fade towards black (fade OUT)
#define MAX_INTENSITY 8
#define MIN_INTENSITY 0
#define MAX_TARGETCOLOR 7
void loop() {
for (;;) {
// Update the intensity value
if (nDirection) {
// Direction is positive, fading towards the color
if (++nIntensity >= MAX_INTENSITY) {
// Maximum intensity reached
nIntensity = MAX_INTENSITY; // Just in case
nDirection = 0; // Now going to fade OUT
} // else : nothing to do
} else {
if (--nIntensity <= MIN_INTENSITY) {
nIntensity = MIN_INTENSITY; // Just in case
// When we get back to black, find the next target color
if (++targetColor>MAX_TARGETCOLOR)
targetColor=1; // We'll skip fading in and out of black
nDirection = 1; // Now going to fade IN
} // else: nothing to do
}
// Compute the colors
int colors[3];
for (int i=0;i<3;i++) {
// If the corresponding bit in targetColor is set, it's part of the target color
colors[i] = (targetColor & (1<<i)) ? (1<<nIntensity) -1 : 0;
}
// Set the color
setColor(colors[0], colors[1], colors[2]);
// Wait
delay(100);
}
}
Answer 2:
这的确是可能的不同颜色之间褪色。 什么我也常常在Arduino的书籍和网络上的代码所缺少的,它可以编写C ++类中的Arduino IDE。 因此,我将示出使用C ++类的颜色之间变淡的例子。
应该解决的问题是在其引脚的analogWrite应该做的,因为不是所有的引脚能够脉宽调制(的PWM )。 上的Arduino的设备支持PWM销标注波形符“〜”。 Arduino的UNO具有数字引脚〜3,〜5,-6,-9,〜10和〜11。 而大多数的Arduino使用PWM这些引脚,但检查你的设备以确保万无一失。 您可以通过开启LED的领导对1毫秒和1毫秒这个模仿50%的功率建立定期数字引脚PWM。 或开启3毫秒,1毫秒这个模仿75%的电力。
为了褪色LED,你将不得不减少/增加PWM值,并稍等一会。 Youl'll不得不等待一小会儿,因为否则的Arduino试图淡化/暗淡的LED每秒数千次,你不会看到一个淡入淡出效果,尽管它可能在那里。 所以,你正在寻找一种方法,以逐步减少/增加的第二个参数analogWrite( )
的三个LED; 有关更详尽的解释见的例如第7章Arduino的食谱 。 这本书是为Arduino的球迷反正很好看的!
所以我适应代码从OP到包含“RGB_COLOR”类,它是或多或少只是红色,绿色和蓝色值的容器。 但更重要的是推子类。 当构建推子的实例适当的引脚应是在构造函数中的红色,绿色和蓝色分别。 比推子包含一个成员函数void fade( const rgb_color& const rgb_color&)
其将执行在之间进出的颜色褪色。 默认情况下,该功能将采取256级的10ms的从输入颜色输出颜色。 (这里需要注意,由于整数除法这并不真正意味着每一步1/256,但perceputally你不会注意到它)。
/*
* LedBrightness sketch
* controls the brightness of LEDs on "analog" (PWM) output ports.
*/
class rgb_color {
private:
int my_r;
int my_g;
int my_b;
public:
rgb_color (int red, int green, int blue)
:
my_r(red),
my_g(green),
my_b(blue)
{
}
int r() const {return my_r;}
int b() const {return my_b;}
int g() const {return my_g;}
};
/*instances of fader can fade between two colors*/
class fader {
private:
int r_pin;
int g_pin;
int b_pin;
public:
/* construct the fader for the pins to manipulate.
* make sure these are pins that support Pulse
* width modulation (PWM), these are the digital pins
* denoted with a tilde(~) common are ~3, ~5, ~6, ~9, ~10
* and ~11 but check this on your type of arduino.
*/
fader( int red_pin, int green_pin, int blue_pin)
:
r_pin(red_pin),
g_pin(green_pin),
b_pin(blue_pin)
{
}
/*fade from rgb_in to rgb_out*/
void fade( const rgb_color& in,
const rgb_color& out,
unsigned n_steps = 256, //default take 256 steps
unsigned time = 10) //wait 10 ms per step
{
int red_diff = out.r() - in.r();
int green_diff = out.g() - in.g();
int blue_diff = out.b() - in.b();
for ( unsigned i = 0; i < n_steps; ++i){
/* output is the color that is actually written to the pins
* and output nicely fades from in to out.
*/
rgb_color output ( in.r() + i * red_diff / n_steps,
in.g() + i * green_diff / n_steps,
in.b() + i * blue_diff/ n_steps);
/*put the analog pins to the proper output.*/
analogWrite( r_pin, output.r() );
analogWrite( g_pin, output.g() );
analogWrite( b_pin, output.b() );
delay(time);
}
}
};
void setup()
{
//pins driven by analogWrite do not need to be declared as outputs
}
void loop()
{
fader f (3, 5, 6); //note OP uses 9 10 and 11
/*colors*/
rgb_color yellow( 250, 105, 0 );
rgb_color orange( 250, 40, 0 );
rgb_color red ( 255, 0, 0 );
rgb_color blue ( 10, 10, 255 );
rgb_color pink ( 255, 0, 100 );
rgb_color purple( 200, 0, 255 );
rgb_color green ( 0, 255, 0 );
rgb_color white ( 255, 255, 255 );
/*fade colors*/
f.fade( white, yellow);
f.fade( yellow, orange);
f.fade( orange, red);
f.fade( red, blue);
f.fade( blue, pink);
f.fade( pink, purple);
f.fade( purple, green);
f.fade( green, white);
}
Answer 3:
如果你想要的颜色之间褪色,在色彩空间的工作,这使得它很容易,然后再转换回RGB结尾。
例如,在工作HSL色彩空间 ,保持S和L保持恒定(比如说完全饱和,鲜艳的颜色),然后在“淡出” H绕了一圈-你会从红色经历绿,蓝和回冲。 转换回RGB,然后使用这些值你的LED驱动器。 我用这种技术对于“情绪灯”的应用程序 ,以及其它用于颜色空间转换的代码可以在SO找到。
Answer 4:
这可能是你在找什么。 每当我们想在光谱中的圆形和平滑的运动移位的色彩和变迁理论的颜色,我们真正做的是在HSI / HSV(色调,饱和度,亮度/值)颜色空间使用HUE移光。
就拿如果你将这个数字:
我们将从0-360附加价值的色调,因为颜色具有360度的颜色。 值0.00 - 1.00饱和,和0.00 -1.00为强度/值的值
这里是我的MEGA 2560电路:
下面是该代码运行的视频:
<iframe width="560" height="315" src="https://www.youtube.com/embed/gGG-GndSKi0" frameborder="0" allowfullscreen></iframe>
所以让我们建立一个我们可以通过我们的循环功能,在for循环中的色调值和调用该值360次以上颜色的彩虹完全转移功能。
//Define the pins we will use with our rgb led
int redPin = 9;
int greenPin = 10;
int bluePin = 11;
//define that we are using common anode leds
#define COMMON_ANODE
void setup()
{
pinMode(redPin, OUTPUT);
pinMode(greenPin, OUTPUT);
pinMode(bluePin, OUTPUT);
}
int rgb[3];
//Arduino has no prebuilt function for hsi to rgb so we make one:
void hsi_to_rgb(float H, float S, float I) {
int r, g, b;
if (H > 360) {
H = H - 360;
}
// Serial.println("H: "+String(H));
H = fmod(H, 360); // cycle H around to 0-360 degrees
H = 3.14159 * H / (float)180; // Convert to radians.
S = S > 0 ? (S < 1 ? S : 1) : 0; // clamp S and I to interval [0,1]
I = I > 0 ? (I < 1 ? I : 1) : 0;
if (H < 2.09439) {
r = 255 * I / 3 * (1 + S * cos(H) / cos(1.047196667 - H));
g = 255 * I / 3 * (1 + S * (1 - cos(H) / cos(1.047196667 - H)));
b = 255 * I / 3 * (1 - S);
} else if (H < 4.188787) {
H = H - 2.09439;
g = 255 * I / 3 * (1 + S * cos(H) / cos(1.047196667 - H));
b = 255 * I / 3 * (1 + S * (1 - cos(H) / cos(1.047196667 - H)));
r = 255 * I / 3 * (1 - S);
} else {
H = H - 4.188787;
b = 255 * I / 3 * (1 + S * cos(H) / cos(1.047196667 - H));
r = 255 * I / 3 * (1 + S * (1 - cos(H) / cos(1.047196667 - H)));
g = 255 * I / 3 * (1 - S);
}
rgb[0] = r;
rgb[1] = g;
rgb[2] = b;
}
void setColor(int red, int green, int blue)
{
#ifdef COMMON_ANODE
red = 255 - red;
green = 255 - green;
blue = 255 - blue;
#endif
analogWrite(redPin, red);
analogWrite(greenPin, green);
analogWrite(bluePin, blue);
}
///here we have our main loop and the for loop to shift color
void loop()
{
//the for loop counts to 360 and because its in our control loop it will run forever
// We will use int i to increment the actual desired color
for (int i=0; i<=360;i++){
hsi_to_rgb(i,1,1);
setColor(rgb[0],rgb[1],rgb[2]);
//Changing the delay() value in milliseconds will change how fast the
//the light moves over the hue values
delay(5);
}
}
Answer 5:
您可以通过使用一个结构为你的颜色简化代码。
struct Color
{
unsigned char r;
unsigned char g;
unsigned char b;
};
于是,很容易有一个衰减功能
// the old color will be modified, hence it is not given as reference
void fade(Color old, const Color& newColor)
{
// get the direction of increment first (count up or down)
// each of the inc_x will be either 1 or -1
char inc_r = (newColor.r - old.r)/abs(newColor.r-old.r); // note, that the right hand side will be sign extended to int according to the standard.
char inc_g = (newColor.g - old.g)/abs(newColor.g-old.g);
char inc_b = (newColor.g - old.g)/abs(newColor.g-old.g);
fadeOneColor(old.r, newColor.r, inc_r, old);
fadeOneColor(old.g, newColor.g, inc_g, old);
fadeOneColor(old.b, newColor.b, inc_b, old);
}
void fadeOneColor( unsigned char& col_old,
const unsigned char& col_new,
const char inc,
Color& col)
{
while(col_old != col_new)
{
col_old += inc;
SetColor(col);
delay(20);
}
}
Answer 6:
下面是存储在两个RGB值之间的快速线性衰落uint32_t
如0x00RRGGBB
在许多可寻址的RGB像素带被用于诸如在NeoPixel(并且由一些在NeoPixel Arduino的库中的代码的启发)。
它并不需要色彩空间考虑,但看起来还是在实践中又顺畅。
uint32_t fadeColor(uint32_t const x, uint32_t const y, uint8_t const fade)
{
// boundary cases don't work with bitwise stuff below
if (fade == 0)
{
return x;
}
else if (fade == 255)
{
return y;
}
uint16_t const invFadeMod = (255 - fade) + 1;
uint16_t const fadeMod = fade + 1;
// overflows below to give right result in significant byte
uint8_t const xx[3] // r g b
{
static_cast<uint8_t>((uint8_t(x >> 16) * invFadeMod) >> 8),
static_cast<uint8_t>((uint8_t(x >> 8) * invFadeMod) >> 8),
static_cast<uint8_t>((uint8_t(x >> 0) * invFadeMod) >> 8),
};
uint8_t const yy[3] // r g b
{
static_cast<uint8_t>((uint8_t(y >> 16) * fadeMod) >> 8),
static_cast<uint8_t>((uint8_t(y >> 8)* fadeMod) >> 8),
static_cast<uint8_t>((uint8_t(y >> 0)* fadeMod) >> 8),
};
return ((uint32_t)(xx[0] + yy[0]) << 16) | ((uint32_t)(xx[1] + yy[1]) << 8) | (xx[2] + yy[2]);
}
文章来源: Fading Arduino RGB LED from one color to the other?