Потенциометр + RGB светодиод

Тема в разделе "Arduino & Shields", создана пользователем inspirer, 3 фев 2016.

  1. inspirer

    inspirer Нуб

    Доброго времени ) сам только начинаю изучать arduino, поэтому вопрос самый, что ни на есть нубский, не ржите короче)

    хочу через подключить RGB светодиод и потенциометром изменять цветовую палитру. вот тут и вопрос, как правильнее или грамотнее реализовать подобную затею? Например, с помощью map обозначить пороги, для потенциометра будет 0, 1023, а светодиоды могут работать в диапазоне 0, 255.

    А дальше как лучше сделать? я думал, что создать цикл или конструкцию if из 3 частей. примерно разделить 1023 на 3 части, где доминирует определённый цвет и дальше меняются значения двух других в зависимости от изменения сопротивления на потенциометра.



    Код (C++):
    const int BLED=9;    //синий светодиод pin 9
    const int GLED=10;   //зелёный светодиод pin 10
    const int RLED=11;   // красный светодиод pin 11
    const int POT=0;    //потенциометр pin 0
    int val =0;



    void setup()
    {
      pinMode (BLED, OUTPUT);   //синий светодиод назначен на выход
      pinMode (GLED, OUTPUT);   //зелёный светодиод назначен на выход
      pinMode (RLED, OUTPUT);   //красный светодиод назначен на выход
      pinMode (POT, INPUT);  //потенциометр назначен на вход
    }




    void loop()
    {
     
      val = analogRead(POT); // чтение аналогового сигнала
      val = map(val, 0, 1023, 255, 0); //установка промежуточных значений
      analogWrite()

     
    }
    вот примерно как бы это выглядело на мой взгляд, но только тут 7 цветов в зависимости от того сколько раз нанималась кнопка, а у меня бы было 3 блока.
    например значения от 0 до 341 - идёт преобладание красного цвета, 0 - красный (255,0,0) и так до 341 будут смешиваться другие цвета (но наверное диапазон двух остальных цветов не до 255, а тоже может разделить на части,)

    затем от 341 до 682 - идёт преобладание зелёного цвета, 341 - зелёный (0,255,0) и так до 682
    затем от 682 до 1023 - идёт преобладание синего цвета, 682 - синий (0,255,255)

    Код (C++):
    {
      //RED
      if (mode == 1)
      {
        digitalWrite(RLED, HIGH);
        digitalWrite(GLED, LOW);
        digitalWrite(BLED, LOW);
      }
      //GREEN
      else if (mode == 2)
      {
        digitalWrite(RLED, LOW);
        digitalWrite(GLED, HIGH);
        digitalWrite(BLED, LOW);
      }
      //BLUE
      else if (mode == 3)
      {
        digitalWrite(RLED, LOW);
        digitalWrite(GLED, LOW);
        digitalWrite(BLED, HIGH);
      }
      //PURPLE (RED+BLUE)
      else if (mode == 4)
      {
        analogWrite(RLED, 127);
        analogWrite(GLED, 0);
        analogWrite(BLED, 127);
      }
      //TEAL (BLUE+GREEN)
      else if (mode == 5)
      {
        analogWrite(RLED, 0);
        analogWrite(GLED, 127);
        analogWrite(BLED, 127);
      }
      //ORANGE (GREEN+RED)
      else if (mode == 6)
      {
        analogWrite(RLED, 127);
        analogWrite(GLED, 127);
        analogWrite(BLED, 0);
      }
      //WHITE (GREEN+RED+BLUE)
      else if (mode == 7)
      {
        analogWrite(RLED, 85);
        analogWrite(GLED, 85);
        analogWrite(BLED, 85);
      }
    Кто, что думает по этому поводу? как лучше реализовать? Если по тупому написал, поправьте пожалуйста, я только начинаю изучать, от программирования далёк ваще
     
  2. Onkel

    Onkel Гуру

    я делал двойным for , чтобы яркость была постоянной нужно первый цикл R от 0 до 255, второй цикл по G от 0 до sqrt(255**2-R**2), потом вычисляем B чтобы сумма квадратов была равна 255*255. Можно и линейно, чтобы сумма всегда была 255, но с квадратным корнем еще и немного подмигивает.
     
  3. Sindbad

    Sindbad Гик

    Вот тут что-то не то. Если крутим потенциометр от 0 до 1023 и должны видеть переход красный - зеленый - синий, логично предположить эти цвета в крайних точках, т.е.
    0 - красный (255,0,0)
    512 - зеленый (0,255,0)
    1023 - синий (0,0,255)
    Или что-то другое подразумевалось?

    Тогда промежуточные точки можно определить так
    после красного постепенно наращиваем зеленый
    256 - (255, 255, 0)
    А затем постепенно уменьшаем красный
    512 - зеленый (0,255,0)
    Затем постепенно наращиваем синий
    768 - (0,255,255)
    И до конца постепенно уменьшаем зеленый
    1023 - синий (0,0,255)

    Каждый переход направления - новая формула, т.е. новая ветка в условии if - else if - ....

    Можно как-то по другому представить себе цвета на отрезке 0-1023, тогда и формулы будут другие. В любом случае, цвета RGB, даже на плоскости корректно не отобразить, только в пространстве https://ru.wikipedia.org/wiki/RGB#/media/File:RGBCube_b.svg , а отрезок это даже не плоскость, в нем всего одно измерение из необходимых трех.
     
  4. inspirer

    inspirer Нуб

    а можешь пример кода привести? и зачем яркость делать постоянной? я же не напряжение буду менять? Напряжение всегда либо HIGH либо LOW. Или я не догоняю просто?-)
     
  5. inspirer

    inspirer Нуб

    возможно ты и прав на счёт RGB. Может мне имеет смысл просто выбрать цветов 15, например, и при переводе потенциометра в определённый диапазон значений зажигать определённый цвет? Так наверное ещё реализуемо, по-крайней мере своими силами и на данном этапе)) Хотя идея с полноценным RGB всё равно интересная)) и если существует решение от форумчан интересно на него посмотреть
     
  6. Onkel

    Onkel Гуру

    отнюдь. У нас есть функция analogWrite(x) c 256 значениями.

    чтобы глаза не уставали и не появлялась раздражительность
    если мы поставим условием постоянство яркости, то плоскость для r и g (например), а b выбираем из постоянства мощности (или яркости, или с учетом разной чувствительности глаза на разные длины волн). Тогда плоскость самое то. Мы же спектр цветов хотим пройти, а не спектр 3 цвета/яркость
     
    inspirer нравится это.
  7. Onkel

    Onkel Гуру

    существует только один спосов разложить в растр rgb при 1024 точках - взять 32 отсчета r , 32 отсчета b и g вычислить исходя из постоянства яркости (или физиологического эквивалента). Я же про это как раз и написал
     
    inspirer нравится это.
  8. inspirer

    inspirer Нуб

    подумаю, как написать это в коде, но пока представление очень далёкое... в любом случае спасибо тебе. Буду сюда свои мысли с кодом скидывать, подсказывай там по возможности
     
  9. lerik2703

    lerik2703 Гик

    если вам не принципиально при каком положении потенциометра, какой цвет будет гореть тогда за основу возьмите пример от амперки http://wiki.amperka.ru/projects:christmastree точнее функцию

    Код (C++):
    // функция перевода цвета из шкалы «HSV» в «RGB»
    void f_HSV_to_RGB(int hue, int sat, int val)
    {
      int base;
      if (sat == 0) {
        r = val;
        g = val;
        b = val;
      } else {
        base = ((255 - sat) * val) >> 8;
        switch (hue / 60) {
          case 0: {
            r = val;
            g = (((val - base) * hue) / 60) + base;
            b = base;
            break;
          }
          case 1: {
            r = (((val - base) * (60 - (hue % 60))) / 60) + base;
            g = val;
            b = base;
            break;
          }
          case 2: {
            r = base;
            g = val;
            b = (((val - base) * (hue % 60)) / 60) + base;
            break;
          }
          case 3: {
            r = base;
            g = (((val - base) * (60 - (hue % 60))) / 60) + base;
            b = val;
            break;
          }
          case 4: {
            r = (((val - base) * (hue % 60)) / 60) + base;
            g = base;
            b = val;
            break;
          }
          case 5: {
            r = val;
            g = base;
            b = (((val - base) * (60 - (hue % 60))) / 60) + base;
            break;
          }
          case 6: {
            r = val;
            g = 0;
            b = base;
            break;
          }
        }
      }
    }
    вызываем так
    Код (C++):

    val = analogRead(POT);
    value = map( val, 0, 1023, 360, 0); //псевдо HSV
    f_HSV_to_RGB(value, 255, 255);
    диодиками светим так
    Код (C++):
    analogWrite(ledPinR, r);
    analogWrite(ledPinG, g);
    analogWrite(ledPinB, b);
    переменные r, g, b глобальные тип int
     
    Последнее редактирование: 3 фев 2016
    inspirer нравится это.
  10. Onkel

    Onkel Гуру

    тут тоже три переменные, val я так понимаю яркость? Я же предложил val сделать постоянной, чтобы сумма или корень из суммы квадратов rgb было константой. Тогда у нас получается 2 переменные, а две переменные растрировать в одну проще - корень из 2^10 будет 2^5, вот и преобразуем нашу линейную координату l в дискретное множестов точек {rg}
    r=l/32;
    g=l%32;
    потом проверяем на яркость и отбрасываем если сумма (или корень из суммы квадратов) больше 255 и добавляем b исходя из равенства суммы (или корня...) постоянной нашей яркости.
    Если тупо делать по 3 переменным, то 1024^1/3~10, то мы получим очень сильные мигания- при повороте поетнциометра леды нас 100 раз мигнут и 10 раз мигнут сильно (на всю). вы рукой сможете повернуть потенциометр ровнехонько на 3°? Не думаю ©.
     
    inspirer нравится это.
  11. inspirer

    inspirer Нуб

    наверное не принципиально, но интересно попробовать вариант, который предложил Onkel, только с кодом нужно разобраться. Спасибо за помощь, в любом случае какой-то из вариантов доведу до реализации
     
  12. lerik2703

    lerik2703 Гик

    да
    и сколько цветов получиться?
    и мне :)
     
  13. Onkel

    Onkel Гуру

    1024, столько же сколько точек получится при оцифровке сигнала с потенциометра
     
  14. olegoriy

    olegoriy Гик

    Очень часто сталкиваюсь по работе с оборудованием которое имеет три цвета светодиодов и управляется в двух режимах:
    первый - регулировка всей гаммы с шагом от 0 до 255 по одному каналу
    второй - регулировка яркости каждого цвета от 0 до 255 по трем каналам.

    Как показала практика производители разного оборудования используют разные алгоритмы для вывода определенного цвета по первому режиму. И добиться определенного цвета очень сложно.

    По второму режиму все достаточно проще.

    Предлагаю вам использовать три потенциометра на каждый цвет)
     
    inspirer нравится это.
  15. inspirer

    inspirer Нуб

    тоже вариант, не сразу подумал об этом, но потенциометр пока один есть, когда в радиомагазин вырвусь неизвестно) но спасибо за идею, оставлю на крайний случай ;))
     
  16. Onkel

    Onkel Гуру

    на самом деле ДВА потенциометра (две координаты) охватят ВСЮ палитру цветов при постоянной яркости.
     
  17. olegoriy

    olegoriy Гик

    не хочу спорить но двумя координатами будет немного сложно быстро перейти от фиолетового к биризовому
    хотя тремя я думаю будет еще дольше)))
     
  18. inspirer

    inspirer Нуб

    оба потенциометра будут отвечать за сочетания цветов? при условии, что есть цикл с постоянной яркостью?
     
  19. Onkel

    Onkel Гуру

    вы поймите, что тремя потенциометрами вы не получите большего к-ва цветов, просто они у вас будут повторяться, например белый свет в системе с двумя потенциометрами будет иметь цв. координаты (к примеру, не совсем точно) - {80,80,80}, и все , а с тремя потенциометрами у вас будет 255 белых цветов - {1,1,1}, {2,2,2}.... {255,255,255} - это одни и те же цвета, отличающиеся только яркостью.
     
  20. inspirer

    inspirer Нуб

    цикл начал писать, вот, что получилось

    Код (C++):
    for (int i=0; i<=255; i++ )
       {
          analogWrite (RLED, i);
          delay (100);
       }

       for (int i=0; sqrt(255*2-RLED*2); i++)
       {
        analogWrite (GLED, i);
        delay (100);
        }
    с BLED я пока не понял, как правильно нужно записать.

    И ещё вопрос, я скетч залил, но и цикл выполняется сам без изменения вращения потенциометра? как мне записать, чтобы цикл выполнялся при наличии изменения значений потенциометра, если правильно выражаюсь?