Плавное изменение цвета трехцветного светодиода. Управление RGB-светодиодом с помощью Arduino. Подключение RGB светодиода с общим анодом к Arduino

Недавно я купил 2 рулона rgb светодиодной ленты по 5 метров, и сразу решил поэкспериментировать с ней. В комплекте шёл блок для управления лентой, но мне показались программы малоинтересными, а под рукой был Tinyos Uno (полный китайский аналог Arduino UNO ). Учитывая то, что ардуино работает максимум с 5в на выход, а чаще 3.3в то нужно было найти решение. В этой статье рассмотрено как подключить 12 вольтовую светодиодную ленту к ардуино с отдельным питанием для ленты и управлением с ардуинки с использованием МОСФЕТов (MOSFETs) для управления каналами RGB ленты .

Начнём со стандартной спецификации аналоговой светодиодной ленты, которая, как мне кажется, наиболее распространена.

  • 10.5mm (0.41") ширина, 3mm (0.12") толщина, 100mm (3.95") длина на каждый сегмент
  • Бывает влагозащищённые (waterproof ) и без защиты (non-waterproof )
  • Имеет клейкую ленту с обратной стороны для крепления ленты
  • Максимальное напряжение 12V и 60mA на каждый сегмент
  • 3 светодиода с общим анодом на каждом сегменте
  • Длина волн светодиодов: 630nm/530nm/475nm
  • Нет микроконтроллера или чип контроллера (чисто аналоговое управление)

Прежде чем начинать работу с Arduino и напряжением выше, чем 5 вольт очень советую прочитать про , чтобы не сжечь вашу Arduino . В ней хорошо описано использование МОСФЕТов с Ардуино . Если вы уже прочитали эту статью, то давайте двигаться дальше.
Для работы со светодиодной лентой нам понадобятся:

  1. MOSFET транзисторы, которые можно найти на том же EBay
  2. Резисторы на 10k?
  3. Макетная беспаечная плата (breadboard )
  4. Проводки для соединения ардуино с макетной платой (папа-папа)
  5. Светодиодная лента (Я брал на aliexpress вот эту ленту , и планирую заказать ещё пару у этого же продавца)

Теперь перейдём к схеме подключения, из неё станет понятно основная часть данной статьи:

Теперь обратимся к Arduino IDE , в которой напишем скетч для управления нашей лентой:

// Note that there"s some legacy code left in here which seems to do nothing // but should do no harm ... // don"t futz with these, illicit sums later #define RED 9// pin for red LED #define GREEN 10 // pin for green - never explicitly referenced #define BLUE 11 // pin for blue - never explicitly referenced #define SIZE 255 #define DELAY 20 #define HUE_MAX 6.0 #define HUE_DELTA 0.01 //long deltas = { 5, 6, 7 }; long rgb; long rgbval; // for reasons unknown, if value !=0, the LED doesn"t light. Hmm ... // and saturation seems to be inverted float hue=0.0, saturation=1, value=1; /* chosen LED SparkFun sku: COM-09264 has Max Luminosity (RGB): (2800, 6500, 1200)mcd so we normalize them all to 1200 mcd - R 250/600 = 107/256 G 250/950 = 67/256 B 250/250 = 256/256 */ long bright = { 107, 67, 256}; //long bright = { 256, 256, 256}; long k, temp_value; void setup () { randomSeed(analogRead(4)); for (k=0; k<3; k++) { pinMode(RED + k, OUTPUT); rgb[k]=0; analogWrite(RED + k, rgb[k] * bright[k]/256); } } void loop() { hue += HUE_DELTA; if (hue > HUE_MAX) { hue=0.0; } rgbval=HSV_to_RGB(hue, saturation, value); rgb = (rgbval & 0x00FF0000) >> 16; // there must be better ways rgb = (rgbval & 0x0000FF00) >> <3; k++) { // for all three colours analogWrite(RED + k, rgb[k] * bright[k]/256); } delay(DELAY); } long HSV_to_RGB(float h, float s, float v) { // H is given on . S and V are given on . // RGB is returned as a 24-bit long #rrggbb int i; float m, n, f; // not very elegant way of dealing with out of range: return black if ((s<0.0) || (s>1.0) || (v<1.0) || (v> < 0.0) || (h > 6.0)) { return long(v * 255) + long(v * 255) * 256 + long(v * 255) * 65536; } i = floor(h); f = h - i; if (!(i&1)) { f = 1 - f; // if i is even } m = v * (1 - s); n = v * (1 - s * f); switch (i) { case 6: case 0: return long(v * 255) * 65536 + long(n * 255) * 256 + long(m * 255); case 1: return long(n * 255) * 65536 + long(v * 255) * 256 + long(m * 255); case 2: return long(m * 255) * 65536 + long(v * 255) * 256 + long(n * 255); case 3: return long(m * 255) * 65536 + long(n * 255) * 256 + long(v * 255); case 4: return long(n * 255) * 65536 + long(m * 255) * 256 + long(v * 255); case 5: return long(v * 255) * 65536 + long(m * 255) * 256 + long(n * 255); } }

Заливаем скетч на ардуино и радуемся.
Есть так же вариант с использованием температурного сенсора DS18B20 , который работает по протоколу 1-Wire .

Идея состоит в том, что "холодная температура", как правило, синего цвета, а "горячая температура " получит красный цвет. Если вы взгляните на колесо HSV, которое мы использовали в первом скетче (цветовое колесо см. wiki), цвет будет составлять от 240 °, когда холодно и до 0 °, если горячая, двигаясь по часовой стрелке (проходя голубой, зеленый и желтый).

Холодная температура в данном случае имеется ввиду 18 ° C, а горячая подразумевает 30 ° C. Температура ниже холодного порога будет считаться холодной, выше горячего порога - горячей. Окончательный код на самом деле довольно прост, когда у вас есть уже готовый код HSV:

// HSV fade/bounce for Arduino // Note that there"s some legacy code left in here which seems to do nothing // but should do no harm ... #include "OneWire.h" //#include "Streaming.h" const int DS18S20_Pin = 2; //DS18S20 Signal pin on digital 2 #define MIN_TEMP 18 #define MAX_TEMP 30 //Temperature chip i/o OneWire ds(DS18S20_Pin); // on digital pin 2 // don"t futz with these, illicit sums later #define RED 9// pin for red LED #define GREEN 10 // pin for green - never explicitly referenced #define BLUE 11 // pin for blue - never explicitly referenced #define SIZE 255 #define DELAY 0 #define HUE_MAX 6.0 #define HUE_DELTA 0.01 //long deltas = { 5, 6, 7 }; long rgb; long rgbval; // for reasons unknown, if value !=0, the LED doesn"t light. Hmm ... // and saturation seems to be inverted float hue=0.0, saturation=1, value=1; /* chosen LED SparkFun sku: COM-09264 has Max Luminosity (RGB): (2800, 6500, 1200)mcd so we normalize them all to 1200 mcd - R 250/600 = 107/256 G 250/950 = 67/256 B 250/250 = 256/256 */ long bright = { 107, 67, 256}; //long bright = { 256, 256, 256}; long k, temp_value; void setup () { randomSeed(analogRead(4)); Serial.begin(57600); for (k=0; k<3; k++) { pinMode(RED + k, OUTPUT); rgb[k]=0; analogWrite(RED + k, rgb[k] * bright[k]/256); } } void loop() { float temperature = constrain(getTemp(), MIN_TEMP, MAX_TEMP); float deltaTemp = (MAX_TEMP - MIN_TEMP); float deltaHue = 4 - 0; hue = map((temperature - MIN_TEMP) * 100, 0, deltaTemp * 100, deltaHue * 100, 0) / 100.0; //Serial << "Temperature: " << temperature << endl; //Serial << "HUE: " << hue << endl; rgbval=HSV_to_RGB(hue, saturation, value); rgb = (rgbval & 0x00FF0000) >> 16; // there must be better ways rgb = (rgbval & 0x0000FF00) >> 8; rgb = rgbval & 0x000000FF; for (k=0; k<3; k++) { // for all three colours analogWrite(RED + k, rgb[k] * bright[k]/256); } //delay(DELAY); } float getTemp(){ //returns the temperature from one DS18S20 in DEG Celsius byte data; byte addr; if (!ds.search(addr)) { //no more sensors on chain, reset search ds.reset_search(); return -1000; } if (OneWire::crc8(addr, 7) != addr) { Serial.println("CRC is not valid!"); return -1000; } if (addr != 0x10 && addr != 0x28) { Serial.print("Device is not recognized"); return -1000; } ds.reset(); ds.select(addr); ds.write(0x44,1); // start conversion, with parasite power on at the end byte present = ds.reset(); ds.select(addr); ds.write(0xBE); // Read Scratchpad for (int i = 0; i < 9; i++) { // we need 9 bytes data[i] = ds.read(); } ds.reset_search(); byte MSB = data; byte LSB = data; float tempRead = ((MSB << 8) | LSB); //using two"s compliment float TemperatureSum = tempRead / 16; return TemperatureSum; } long HSV_to_RGB(float h, float s, float v) { // H is given on . S and V are given on . // RGB is returned as a 24-bit long #rrggbb int i; float m, n, f; // not very elegant way of dealing with out of range: return black if ((s<0.0) || (s>1.0) || (v<1.0) || (v>1.0)) { return 0L; } if ((h < 0.0) || (h > 6.0)) { return long(v * 255) + long(v * 255) * 256 + long(v * 255) * 65536; } i = floor(h); f = h - i; if (!(i&1)) { f = 1 - f; // if i is even } m = v * (1 - s); n = v * (1 - s * f); switch (i) { case 6: case 0: return long(v * 255) * 65536 + long(n * 255) * 256 + long(m * 255); case 1: return long(n * 255) * 65536 + long(v * 255) * 256 + long(m * 255); case 2: return long(m * 255) * 65536 + long(v * 255) * 256 + long(n * 255); case 3: return long(m * 255) * 65536 + long(n * 255) * 256 + long(v * 255); case 4: return long(n * 255) * 65536 + long(m * 255) * 256 + long(v * 255); case 5: return long(v * 255) * 65536 + long(m * 255) * 256 + long(n * 255); } }

серии «Дерзай».

RGB расшифровывается как аббревиатура Red, Green, Blue, при помощи этих цветов можно получить любой цвет путем смешения. Светодиод RGB содержит 3 небольших кристалла R, G, B, с помощью которых мы сможем синтезировать любой цвет или оттенок. В этом уроке мы подключим RGB-светодиод к плате Arduino и заставим его переливаться всеми цветами радуги.
Для данного проекта Вам понадобятся детали, которые имеются в наборах «Базовый» и «Изучаем Arduino»:

  1. Arduino Uno;
  2. Кабель USB;
  3. Плата прототипирования;
  4. Провода «папа-папа» — 7 шт;
  5. Резисторы 220 Ом – 3 шт;
  6. RGB-светодиод – 1 шт;
  7. Потенциометр.

Собираем схему, показанную на рисунке 1.

Рисунок 1. Схема соединений

Теперь приступим к написанию скетча.
RGB-светодиод должен переливаться всеми цветами радуги от красного до фиолетового, затем переходим к красному и так по кругу. Скорость перехода цветов регулируем потенциометром. В таблице 1 приведены данные значений R, G, B для 7 основных цветов радуги.

Таблица 1. Данные значений R, G, B для 7 основных цветов радуги

Для смешения цветов необходимо с выводов Arduino на R, G, B входы светодиода подавать полный спектр напряжений. Но Arduino не может на цифровой вывод выдавать произвольное напряжение. Выдается либо +5В (HIGH), либо 0 В (LOW). Для симуляции неполного напряжения используется ШИМ (Широтно-Импульсная Модуляция, или PWM).

Я надеюсь, Вы уже изучили главу 2.6 книги Джереми Блюма «Изучаем Arduino: инструменты и методы технического волшебства», где подробно рассказывается о механизме широтно-импульсной модуляции.
Алгоритм выполнения программы:

  • Увеличиваем значение зеленой составляющей G, пока не достигнем значения оранжевого (255,125,0),
  • Увеличиваем значение зеленой составляющей G, пока не достигнем желтого цвета (255,255,0).
  • Уменьшаем значение красной составляющей R до значения зеленого цвета (0,255,0).
  • Начальную точка — красный цвет (255,0,0).
  • Увеличиваем значение синей составляющей B до значения голубого цвета (0,255,255).
  • Уменьшаем значение зеленой составляющей G до значения синего цвета (0,0,255).
  • Постепенно увеличим значение красной составляющей R до значения фиолетового цвета (255,0,255).
  • Уменьшаем значение синей составляющей B до значения красного цвета (255,0,0).

Переходим к шагу 1.

После каждого шага делаем паузу для фиксации показа цвета,

Delay(VIEW_PAUSE);

проверяем значение потенциометра и изменяем значение скорости изменения цвета.

Void setpause() { pause=map(analogRead(POT),0,1024,MIN_PAUSE,MAX_PAUSE); Serial.print("pause=");Serial.println(pause); }

Создадим в Arduino IDE новый скетч , занесем в него код из листинга 1 и загрузим скетч на на плату Arduino. Напоминаем, что в настройках Arduino IDE необходимо выбрать тип платы (Arduino UNO) и порт подключения платы.
Листинг 1

Const int RED=11; // вывод R RGB-светодиода const int GREEN=10; // вывод G RGB-светодиода const int BLUE=9; // вывод B RGB-светодиода int red; // переменная для хранения R-составляющей цвета int green; // переменная для хранения G-составляющей цвета int blue; // переменная для хранения B-составляющей цвета const int POT=A0; // вывод подключения потенциометра const int MIN_PAUSE=10; // минимальная задержка смены цвета, мс const int MAX_PAUSE=100; // максимальная задержка смены цвета, мс int pause; // переменная для хранения текущей задержки const int VIEW_PAUSE=2000; // время фиксации основного цвета, мс void setup() { Serial.begin(9600); } void loop() { // от красного к желтому Serial.println("red - yellow"); red=255;green=0;blue=0; for(green=0;green<=255;green++) setRGB(red,green,blue); setpause(); delay(VIEW_PAUSE); // от желтому к зеленому Serial.println("yellow - green"); red=255;green=255;blue=0; for(red=255;red>=0;red--) setRGB(red,green,blue); setpause(); delay(VIEW_PAUSE); // от зеленого к голубому Serial.println("green - blue"); red=0;green=255;blue=0; for(blue=0;blue<=255;blue++) setRGB(red,green,blue); setpause(); delay(VIEW_PAUSE); // от голубого к синему Serial.println("blue - blue"); red=0;green=255;blue=255; for(green=255;green>=0;green--) setRGB(red,green,blue); setpause(); delay(VIEW_PAUSE); // от синего к фиолетовому Serial.println("blue - purple"); red=0;green=0;blue=255; for(red=0;red<=255;red++) setRGB(red,green,blue); setpause(); delay(VIEW_PAUSE); // от фиолетового к красному Serial.println("purple - red"); red=255;green=0;blue=255; for(blue=0;blue>=0;blue--) setRGB(red,green,blue); setpause(); delay(VIEW_PAUSE); } // функция установки цвета RGB-светодиода void setRGB(int r,int g,int b) { analogWrite(RED,r); analogWrite(GREEN,g); analogWrite(BLUE,b); delay(pause); } // функция установки текущей задержки void setpause() { pause=map(analogRead(POT),0,1024,MIN_PAUSE,MAX_PAUSE); Serial.print("pause=");Serial.println(pause); }

После загрузки скетча наблюдаем изменение цвета RGB-светодиода цветами радуги, потенциометром меняем скорость смены цвета (см. рисунок 2,3).


Рисунок 2,3. RGB-светодиод – всеми цветами радуги

В прошлый раз был рассмотрен способ подключения светодиодной ленты к ардуино через драйвер L298. Управление цветом осуществлялось программно - функция Random. Теперь пришла пора разобраться, как управлять цветом светодиодной ленты на основании показаний датчика температуры и влажности DHT 11.

За основу взят пример подключения светодиодной ленты через драйвер L298. Плюсом ко всему в пример добавлен дисплей LCD 1602, который будет отображать показания датчика DHT 11.

Для проекта понадобятся следующие элементы Ардуино:

  1. Плата Ардуино УНО.
  2. Дисплей LCD 1602 + I2C.
  3. Датчик температуры и влажности DHT
  4. Светодиодная лента.
  5. Драйвер L298.
  6. Блок питания 9-12В.
  7. Корпус для ардуино и дисплея (по желанию).

Первым делом посмотрим на принципиальную схему (рис. 1). На ней можно увидеть, как нужно подключить все вышеперечисленные элементы. В сборке схемы и подключении ничего сложного нет, однако стоит упомянуть об одном нюансе, о котором большинство людей забывают, и в итоге получают неправильные результаты работы LED – ленты с Ардуино.

Рисунок 1. Принципиальная схема подключения Arduino и светодиодной ленты с датчиком DHT 11

Во избежание некорректной работы светодиодной ленты (мерцание, несоответствие цветов, неполное свечение и т.д.), питание всей схемы необходимо сделать общим, т.е. объединить контакты GND (земля) контроллера Ардуино и драйвера L298 (светодиодной ленты). Как это сделать, можно посмотреть на схеме.

Пару слов о подключении датчика влажности. Если покупать голый DHT 11, без обвязки, то между первым и вторым контактами, 5В и Data, соответственно, нужно впаять резистор номиналом 5-10 кОм. Диапазон измерения температуры и влажности написан на обратной стороне корпуса датчика DHT 11. Температура: 0-50 градусов по Цельсию. Влажность: 0-80%.


Рисунок 2. Правильное подключение датчика влажности DHT 11

После сборки всех элементов проекта по схеме, необходимо написать программный код, который заставит все это работать так, как нам нужно. А нужно нам, чтобы светодиодная лента изменяла цвет в зависимости от показаний датчика DHT 11 (влажности).

Для программирования датчика DHT 11 понадобится дополнительная библиотека.

Код программы Arduino и RGB – лента. Изменение цвета ленты в зависимости от влажности.

#include #include //библиотека для работы с дисплеем LCD 1602 #include //библиотека для работы с датчиком влажности и температуры DHT 11 int chk; //переменная будет хранить все данные с датчика DHT11 int hum; //переменная будет хранить показания влажности с датчика DHT11 dht11 DHT; //объект типа DHT #define DHT11_PIN 4 //контакт Data датчика DHT11 подключен на вход 4 #define LED_R 9 // пин для канала R #define LED_G 10 // пин для канала G #define LED_B 11 // пин для канала B //переменные будут хранить значения цветов //при смешивании всех трех цветов будет получаться необходимый цвет int led_r=0, led_g=0, led_b=0; //объявление объекта дисплея с адресом 0х27 //не забываем использовать в проекте дисплей через плату I2C LiquidCrystal_I2C lcd(0x27,16,2); void setup() { //создание дисплея lcd.init(); lcd.backlight(); // объявляем пины выходами pinMode(LED_R, OUTPUT); pinMode(LED_G, OUTPUT); pinMode(LED_B, OUTPUT); } void loop() { chk = DHT.read(DHT11_PIN);//читаем данные с датчика DHT11 //вывод данных на дисплей lcd.print("Temp: "); lcd.print(DHT.temperature, 1); lcd.print(" C"); lcd.setCursor(0,1); lcd.print("Hum: "); lcd.print(DHT.humidity, 1); lcd.print(" %"); delay(1500); //для корректной работы датчика нужна задержка на опрос lcd.clear(); hum = DHT.humidity; //берем показания влажности //в диапозоне от 19 до 30% влажности выдать зеленый цвет if ((hum >= 19) && (hum <= 30)) { led_r = 1; led_g = 255; led_b = 1; } //в диапозоне от 31 до 40% влажности выдать красный цвет if ((hum >= 31) && (hum <= 40)) { led_r = 255; led_g = 1; led_b = 1; } //в диапозоне от 41 до 49% влажности выдать синий цвет if ((hum >= 41) && (hum <= 49)) { led_r = 1; led_g = 1; led_b = 255; } // подача сигналов цвета на выхода analogWrite(LED_R, led_r); analogWrite(LED_G, led_g); analogWrite(LED_B, led_b); }

Метки: Метки

Широтно-импульсная модуляция (ШИМ, PWM) - веселая штука, и особенно прикольно с ее помощью управлять сервомоторами, однако сегодня мы применим ее к трехцветному светодиоду. Это позволит нам управлять его цветом и получить некое подобие красоты.

ШИМ

Гениально определение ШИМ сформулировано в Википедии , поэтому я просто скопипащу его оттуда: "ШИМ - приближение желаемого сигнала (многоуровневого или непрерывного) к действительным бинарным сигналам (с двумя уровнями - вкл / выкл ), так, что, в среднем, за некоторый отрезок времени, их значения равны. <...> ШИМ есть импульсный сигнал постоянной частоты и переменной скважности, то есть отношения периода следования импульса к его длительности. С помощью задания скважности (длительности импульсов) можно менять среднее напряжение на выходе ШИМ . "


Теперь разберемся, что это значит. Пусть есть обычный такой прямоугольный сигнал:




Он имеет фиксированную частоту и скважность 50%. Это означает, что половину периода напряжение максимально, а другую половину оно равно нулю. Проинтегрировав этот сигнал за период, мы увидим, что его энергия равна половине максимальной. Это будет эквивалентно тому, как если бы мы все время подавали половину напряжения.


Если у нас максимальное напряжение равно 5 В, то напряжение, получаемое на выходе ШИМ равно скважность умножить на 5 В (и делить на 100% чтобы формал-nazi не привязывались):


Arduino позволяет записать на ШИМ-выход значение от 0 до 255, а это значит, что мы можем получить напряжение с дискретностью примерно 20 мВ.


Трехцветный светодиод

Вот он, четырехногий красавец:


Самая длинная нога - это общий анод, а все остальные - это катоды, каждый отвечает за свой цвет: (смотрим на рисунок) самая нижняя - красный, вторая сверху - зеленый, самая верхняя - синий.

Если подать на длинную ногу +5В, а на все остальные 0В, то получится белый свет (умоляю, предохраняйтесь - ставьте ограничивающие резисторы!). Насколько он белый, можно судить по следующему видео:


Но получать белый цвет на нем как раз-таки неинтересно. Посмотрим, как заставить его переливаться разными цветами.

ШИМ на Arduino

Частота ШИМ на Arduino - примерно 490 Гц. На плате Arduino UNO выводы, которые могут быть использованы для ШИМ - 3,5,6, 9, 10 и 11. На плате к этому есть подсказка - шелкографией перед номерами ШИМ-выводов есть тильда или диез.

Нет ничего проще, чем управлять ШИМ на Arduino! Для этого используется одна единственная функция analogWrite(pin, value) , где pin - номер вывода, а value - значение от 0 до 255. При этом ничего не надо писать в void setup() !

Подробнее про это на английском языке можно почитать и .

Совсем немного работаем

Сделаем так, чтобы светодиод переливался разными цветами. Пусть один цвет плавно гаснет, в то время как другой разгорается. Поочередно будем менять пару цветов, и цвет будет переходить по кругу из красного в зеленый, из зеленого в синий, из синего в красный.

Соберем незамысловатую схему:


И напишем незамысловатый код:

//обзываем выводы соответственно цвету
int REDpin = 9;
int GREENpin = 10;
int BLUEpin = 11;

void setup (){}

void loop (){
for (int value = 0 ; value <= 255; value +=1) {
//яркость красного уменьшается
analogWrite (REDpin, value);
//яркость зеленого увеличивается
analogWrite (GREENpin, 255-value);
//синий не горит
analogWrite (BLUEpin, 255);
//пауза
delay (30);
}

for (int value = 0 ; value <= 255; value +=1) {
//красный не горит
analogWrite (REDpin, 255);
//яркость зеленого уменьшается
analogWrite (GREENpin, value);
//яркость синего увеличивается
analogWrite (BLUEpin, 255-value);
//пауза
delay (30);
}

for (int value = 0 ; value <= 255; value +=1) {
//яркость красного увеличивается
analogWrite (REDpin, 255-value);
//зеленый не горит
analogWrite (GREENpin, 255);
//яркость синего уменьшается
analogWrite (BLUEpin, value);
//пауза
delay (30);
}
}

На предыдущем уроке мы уже попробовали . Теперь же разберемся с многоцветным светодиодом, который часто называют сокращенно: RGB-светодиод .

RGB — это аббревиатура, которая расшифровывается как: Red — красный, Green — зеленый, Blue — синий. То есть внутри этого устройства размещается сразу три отдельных светодиода. В зависимости от типа, RGB-светодиод может иметь общий катод или общий анод.

Смешение цветов

Чем RGB-светодиод, лучше трех обычных? Всё дело в свойстве нашего зрения смешивать свет от разных источников, размещенных близко друг к другу. Например, если мы поставим рядом синий и красный светодиоды, то на расстоянии несколько метров их свечение сольется, и глаз увидит одну фиолетовую точку. А если добавим еще и зеленый, то точка покажется нам белой. Именно так работают мониторы компьютеров, телевизоры и уличные экраны.

Матрица телевизора состоит из отдельно стоящих точек разных цветов. Если взять лупу и посмотреть через нее на включенный монитор, то эти точки можно легко увидеть. А вот на уличном экране точки размещаются не очень плотно, так что их можно различить невооруженным глазом. Но с расстояния несколько десятков метров эти точки неразличимы.

Получается, что чем плотнее друг к другу стоят разноцветные точки, тем меньшее расстояние требуется глазу чтобы смешивать эти цвета. Отсюда вывод: в отличие от трех отдельностоящих светодиодов, смешение цветов RGB-светодиода заметно уже на расстоянии 30-70 см. Кстати, еще лучше себя показывает RGB-светодиод с матовой линзой.