简体   繁体   English

rgb led arduino 的平滑动画

[英]Smooth animation for rgb led arduino

I'm trying to make a smooth transition with arduino, it receives rgb values from serial correctly, but it seems to don't reach the target color because it oscillates between different values.我正在尝试使用 arduino 进行平滑过渡,它从串行正确接收 rgb 值,但它似乎没有达到目标颜色,因为它在不同的值之间振荡。 I'm using this library to convert in hsv RGBConverter .我正在使用这个库在 hsv RGBConverter 中进行转换。 I tried to convert rgb value in hsv and to change gradually hsv values.我试图在 hsv 中转换 rgb 值并逐渐改变 hsv 值。 This is my code:这是我的代码:

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 is a struct that contains three byte values named red, green and blue Color 是一个结构体,它包含三个字节值,分别命名为 red、green 和 blue

This is the reach_color method这是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);
    }
}

and this is display method这是显示方法

void display_color(struct color c){
analogWrite(GREEN_LED, c.green);  
analogWrite(BLUE_LED, c.blue);  
analogWrite(RED_LED, c.red); 
}

I need to gradually move from current color to final color, but while never goes in the else clause and current color oscillates between different values, does anyone know where is the error?我需要逐渐从当前颜色移动到最终颜色,但是虽然从来没有进入 else 子句并且当前颜色在不同值之间波动,但有谁知道错误在哪里? Thank you all in advance for the help预先感谢大家的帮助

I think that my error is inside the algorithm reach_color我认为我的错误在于算法reach_color

Right.对。 Consider eg hsv[0] is 0.005 and hsv_final[0] is 0;考虑例如hsv[0]是 0.005 并且hsv_final[0]是 0; the line线

    if ( hsv[0] >hsv_final[0]&&hsv[0]>0 ) hsv[0] -= 0.01;

will set hsv[0] to −0.005 (which is outside the range [0, 1] assumed by hsvToRgb() , whatever that does with it).hsv[0]设置为 -0.005(这超出了hsvToRgb()假定的范围 [0, 1] ,无论它有什么作用)。 In the next loop cycle, the line在下一个循环循环中,该行

    else if(hsv[0]<hsv_final[0]&&hsv[0]<1) hsv[0]+= 0.01;

will set hsv[0] to +0.005 anew - and so it goes on oscillating.将重新设置hsv[0]为 +0.005 - 所以它继续振荡。 In general, the repeated addition or subtraction of 0.01 is unlikely to yield exactly the same value that rgbToHsv() returned.一般来说,重复加减 0.01 不太可能产生与rgbToHsv()返回的完全相同的值。
Also you should be aware that 0.01 like most decimal fractions cannot be exactly represented in a double (it results in approximately 0.01000000000000000021).此外,您应该知道 0.01 像大多数小数一样不能用double精度精确表示(它导致大约 0.01000000000000000021)。
Moreover, the repeated calling of rgbToHsv() in the loop, recalculating hsv[] values based on the previous rgb[] values, makes the algorithm's behavior more difficult to predict.此外,在循环中重复调用rgbToHsv() ,根据之前的rgb[]值重新计算hsv[] rgb[]值,使得算法的行为更难以预测。

So, we have to allow for a tolerance of the HSV values for the comparisons, and better use only the hsv[] values for the iteration:因此,我们必须允许比较的 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);
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM