2015-12-01 4 views
2

Я пытаюсь сделать плавный переход с arduino, он получает правильные значения rgb из серийного номера, но, похоже, не достигает целевого цвета, потому что он колеблется между разными значениями. Я использую эту библиотеку для преобразования в hsv RGBConverter. Я попытался преобразовать значение rgb в hsv и изменить значения hsv постепенно. Это мой код:Плавная анимация для rgb led arduino

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);     
    } 

Цвет является структурой, которая содержит три значения байта имени красного, зеленого и синего цветов

Это метод 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 и текущий цвет колеблются между разными значениями, кто-нибудь знает, где ошибка? Спасибо всем заранее за помощь

+0

Хорошо. Это хорошо знать. Здесь есть вопрос? – immibis

+0

Вы правы, я не понял, я редактирую главный пост –

+0

Возможно, он oscilates, потому что вы читаете, не будучи уверенным, что есть данные в буфере ... Помните, что типичная структура 'if (Serial.available ()) {/ * ПРОЧИТАЙТЕ СЕРИЙ И ПРОЦЕСС ЭТО * /} ' – jabujavi

ответ

1

Я думаю, что моя ошибка в алгоритме reach_color

Right. Рассмотрим е. г. 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 (который находится вне диапазона [0, 1], взятых на себя hsvToRgb(), независимо, что делает с ней). В следующем цикле петли, линии

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() в цикле, пересчет значений hsv[] на основе предыдущих значений rgb[], затрудняет прогнозирование поведения алгоритма.

Таким образом, мы должны обеспечить допуск значений 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); 
    } 
} 
Смежные вопросы