【问题标题】:Smooth animation for rgb led arduinorgb led arduino 的平滑动画
【发布时间】:2015-12-01 01:13:39
【问题描述】:

我正在尝试使用 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 是一个结构体,包含三个字节值,名为 red、green 和 blue

这是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 子句并且当前颜色在不同的值之间波动,有谁知道错误在哪里? 提前感谢大家的帮助

【问题讨论】:

  • 好的。很高兴知道。这里有问题吗?
  • 你说得对,我不清楚,我正在编辑主帖
  • 可能是因为您正在阅读而不确定缓冲区中有数据...记住典型结构是if(Serial.available()){/*READ SERIAL AND PROCESS IT*/}
  • 谢谢,现在代码肯定更正确,但问题仍然存在,我尝试在串行监视器上打印接收到的串行 rgb 值及其 hsv 转换,并且都是正确的。我认为我的错误在算法reach_color

标签: c arduino rgb hsv


【解决方案1】:

我认为我的错误在于算法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);
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-03
    • 2012-09-17
    • 1970-01-01
    相关资源
    最近更新 更多