rgb led arduino 的平滑动画
Smooth animation for rgb led arduino
我正在尝试使用 arduino 进行平滑过渡,它正确地从串行接收 rgb 值,但它似乎没有达到目标颜色,因为它在不同的值之间振荡。我正在使用这个库在 hsv RGBConverter 中进行转换。我试图在 hsv 中转换 rgb 值并逐渐更改 hsv 值。这是我的代码:
RGBConverter converter = RGBConverter();
my_color cur_color;
void setup() {
pinMode(RED_LED, OUTPUT);
pinMode(GREEN_LED, OUTPUT);
pinMode(BLUE_LED, OUTPUT);
Serial.begin(BAUD_RATE);
cur_color={0,0,0};
}
void loop() {
my_color final={Serial.read(),Serial.read(),Serial.read()};
double hsv[3];
converter.rgbToHsv(final.red,final.green,final.blue,hsv);
reach_color(&cur_color,hsv);
}
Color 是一个包含三个字节值的结构体,名称为红色、绿色和蓝色
这是reach_color方法
void reach_color(struct color *start, double hsv_final[]){
double hsv[3];
byte rgb[3];
while(true){
converter.rgbToHsv(start->red,start->green,start->blue,hsv);
if ( hsv[0] >hsv_final[0]&&hsv[0]>0 ) hsv[0] -= 0.01;
else if(hsv[0]<hsv_final[0]&&hsv[0]<1) hsv[0]+= 0.01;
else if(hsv[1]>hsv_final[1]&&hsv[1]>0) hsv[1]-= 0.01;
else if(hsv[1]<hsv_final[1]&&hsv[1]<1) hsv[1]+= 0.01;
else if(hsv[2]>hsv_final[2]&&hsv[2]>0) hsv[2]-= 0.01;
else if(hsv[2]<hsv_final[2]&&hsv[2]<1) hsv[2]+= 0.01;
else return;
converter.hsvToRgb(hsv[0],hsv[1], hsv[2], rgb);
start->red=rgb[0];
start->green=rgb[1];
start->blue=rgb[2];
display_color(*start);
delay(30);
}
}
这是显示方式
void display_color(struct color c){
analogWrite(GREEN_LED, c.green);
analogWrite(BLUE_LED, c.blue);
analogWrite(RED_LED, c.red);
}
我需要逐渐从当前颜色移动到最终颜色,但是虽然从不进入 else 子句并且当前颜色在不同值之间振荡,但有人知道错误在哪里吗?
预先感谢大家的帮助
I think that my error is inside the algorithm reach_color
没错。考虑e。 G。 hsv[0]
为0.005,hsv_final[0]
为0;这条线
if ( hsv[0] >hsv_final[0]&&hsv[0]>0 ) hsv[0] -= 0.01;
会将 hsv[0]
设置为 −0.005(这超出了 hsvToRgb()
假定的范围 [0, 1],无论它如何处理)。在下一个循环周期中,行
else if(hsv[0]<hsv_final[0]&&hsv[0]<1) hsv[0]+= 0.01;
将 hsv[0]
重新设置为 +0.005 - 因此它会继续振荡。一般来说,重复加减 0.01 不太可能产生与 rgbToHsv()
返回的值完全相同的值。
您还应该知道,像大多数小数一样,0.01 不能在 double
中准确表示(它的结果约为 0.01000000000000000021)。
而且,在循环中重复调用rgbToHsv()
,根据之前的rgb[]
值重新计算hsv[]
值,使得算法的行为更难预测。
因此,我们必须允许对 HSV 值进行比较,最好只使用 hsv[]
值进行迭代:
void reach_color(struct color *start, double hsv_final[])
{
double hsv[3];
byte rgb[3];
converter.rgbToHsv(start->red, start->green, start->blue, hsv);
while (true)
{
if (hsv[0] - 0.01 >= hsv_final[0]) hsv[0] -= 0.01;
else if (hsv[0] + 0.01 <= hsv_final[0]) hsv[0] += 0.01;
else if (hsv[1] - 0.01 >= hsv_final[1]) hsv[1] -= 0.01;
else if (hsv[1] + 0.01 <= hsv_final[1]) hsv[1] += 0.01;
else if (hsv[2] - 0.01 >= hsv_final[2]) hsv[2] -= 0.01;
else if (hsv[2] + 0.01 <= hsv_final[2]) hsv[2] += 0.01;
else return;
converter.hsvToRgb(hsv[0], hsv[1], hsv[2], rgb);
start->red = rgb[0];
start->green = rgb[1];
start->blue = rgb[2];
display_color(*start);
delay(30);
}
}
我正在尝试使用 arduino 进行平滑过渡,它正确地从串行接收 rgb 值,但它似乎没有达到目标颜色,因为它在不同的值之间振荡。我正在使用这个库在 hsv RGBConverter 中进行转换。我试图在 hsv 中转换 rgb 值并逐渐更改 hsv 值。这是我的代码:
RGBConverter converter = RGBConverter();
my_color cur_color;
void setup() {
pinMode(RED_LED, OUTPUT);
pinMode(GREEN_LED, OUTPUT);
pinMode(BLUE_LED, OUTPUT);
Serial.begin(BAUD_RATE);
cur_color={0,0,0};
}
void loop() {
my_color final={Serial.read(),Serial.read(),Serial.read()};
double hsv[3];
converter.rgbToHsv(final.red,final.green,final.blue,hsv);
reach_color(&cur_color,hsv);
}
Color 是一个包含三个字节值的结构体,名称为红色、绿色和蓝色
这是reach_color方法
void reach_color(struct color *start, double hsv_final[]){
double hsv[3];
byte rgb[3];
while(true){
converter.rgbToHsv(start->red,start->green,start->blue,hsv);
if ( hsv[0] >hsv_final[0]&&hsv[0]>0 ) hsv[0] -= 0.01;
else if(hsv[0]<hsv_final[0]&&hsv[0]<1) hsv[0]+= 0.01;
else if(hsv[1]>hsv_final[1]&&hsv[1]>0) hsv[1]-= 0.01;
else if(hsv[1]<hsv_final[1]&&hsv[1]<1) hsv[1]+= 0.01;
else if(hsv[2]>hsv_final[2]&&hsv[2]>0) hsv[2]-= 0.01;
else if(hsv[2]<hsv_final[2]&&hsv[2]<1) hsv[2]+= 0.01;
else return;
converter.hsvToRgb(hsv[0],hsv[1], hsv[2], rgb);
start->red=rgb[0];
start->green=rgb[1];
start->blue=rgb[2];
display_color(*start);
delay(30);
}
}
这是显示方式
void display_color(struct color c){
analogWrite(GREEN_LED, c.green);
analogWrite(BLUE_LED, c.blue);
analogWrite(RED_LED, c.red);
}
我需要逐渐从当前颜色移动到最终颜色,但是虽然从不进入 else 子句并且当前颜色在不同值之间振荡,但有人知道错误在哪里吗? 预先感谢大家的帮助
I think that my error is inside the algorithm reach_color
没错。考虑e。 G。 hsv[0]
为0.005,hsv_final[0]
为0;这条线
if ( hsv[0] >hsv_final[0]&&hsv[0]>0 ) hsv[0] -= 0.01;
会将 hsv[0]
设置为 −0.005(这超出了 hsvToRgb()
假定的范围 [0, 1],无论它如何处理)。在下一个循环周期中,行
else if(hsv[0]<hsv_final[0]&&hsv[0]<1) hsv[0]+= 0.01;
将 hsv[0]
重新设置为 +0.005 - 因此它会继续振荡。一般来说,重复加减 0.01 不太可能产生与 rgbToHsv()
返回的值完全相同的值。
您还应该知道,像大多数小数一样,0.01 不能在 double
中准确表示(它的结果约为 0.01000000000000000021)。
而且,在循环中重复调用rgbToHsv()
,根据之前的rgb[]
值重新计算hsv[]
值,使得算法的行为更难预测。
因此,我们必须允许对 HSV 值进行比较,最好只使用 hsv[]
值进行迭代:
void reach_color(struct color *start, double hsv_final[])
{
double hsv[3];
byte rgb[3];
converter.rgbToHsv(start->red, start->green, start->blue, hsv);
while (true)
{
if (hsv[0] - 0.01 >= hsv_final[0]) hsv[0] -= 0.01;
else if (hsv[0] + 0.01 <= hsv_final[0]) hsv[0] += 0.01;
else if (hsv[1] - 0.01 >= hsv_final[1]) hsv[1] -= 0.01;
else if (hsv[1] + 0.01 <= hsv_final[1]) hsv[1] += 0.01;
else if (hsv[2] - 0.01 >= hsv_final[2]) hsv[2] -= 0.01;
else if (hsv[2] + 0.01 <= hsv_final[2]) hsv[2] += 0.01;
else return;
converter.hsvToRgb(hsv[0], hsv[1], hsv[2], rgb);
start->red = rgb[0];
start->green = rgb[1];
start->blue = rgb[2];
display_color(*start);
delay(30);
}
}