ws2812b сколько можно подключить к ардуино

leks
Offline
Зарегистрирован: 22.10.2017

Добрый день. Планирую сделать тусклую подсветку периметра в помещении на ws2812, есть ардуино уно. Сколько максимум светодиодов может ею управляться, с использованием библиотеки Adafruit_NeoPixel.h?

sadman41
Offline
Зарегистрирован: 19.10.2016

Берете свой скетч с использованием библиотеки Adafruit_NeoPixel.h, ставите кол-во светодиодов равное десяти. Компилируете. Затем ставите двадцать, тридцать, сто штук. Компилируете. Как только получили ошибку - всё, это максимальное значение.

Ну или можете просто интерполировать, исходя из количества свободной памяти. Сами светодиоды и микроконтроллер при этом подключать необходимости нет

Принцип понятен?

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Но если этот принцип сложен. То посмотрите 38 попугаев. https://www.youtube.com/watch?v=p7ZBR2mIG9A . Там тоже есть ваше решение.

leks
Offline
Зарегистрирован: 22.10.2017

То есть, ограничивается 2 Кб памяти для уно? И тогда 650-700 светодиодов это предел? А для заданного скетча ещё меньше? Или ход мыслей неверен?

sadman41
Offline
Зарегистрирован: 19.10.2016

leks пишет:

То есть, ограничивается 2 Кб памяти для уно? И тогда 650-700 светодиодов это предел? А для заданного скетча ещё меньше? Или ход мыслей неверен?

Если у вашего скетча, который мы не видим, затрат по памяти нет вовсе, то все ограничивается 2kb RAM.

leks
Offline
Зарегистрирован: 22.10.2017
// Подключаем библиотеку Adafruit NeoPixel.
#include "Adafruit_NeoPixel.h"

// Указываем, какое количество пикселей у нашей ленты.
#define LED_COUNT1 5

// Указываем, к какому порту подключен вход ленты DIN.
#define LED_PIN1 6

// Создаем переменную strip для управления нашей лентой.
Adafruit_NeoPixel strip1 = Adafruit_NeoPixel(LED_COUNT1, LED_PIN1, NEO_GRB + NEO_KHZ800);

 int r=0;int g=0;int b=0;int k=10;int j=0;

void setup()
{
 
  // Инициализируем ленту.
  strip1.begin();
 
}

void loop()
{
 if (j==1) {r=random(0,2);g=random(0,2);b=random(0,2);j=0;}else{j=1;r=0;g=0;b=0;}
  // Включаем все по очереди светодиоды.
  for (int i = 0; i < LED_COUNT1; i++)
  {
   
    strip1.setPixelColor(i, strip1.Color(k*r,k*g, k*b)); //псевдослучайный цвет
    strip1.show();
   delay(75); 
   
  }
  
 
 
}

Код пока никакой на 5 светодиодов. По очереди включились, выключились, разными цветами.

sadman41
Offline
Зарегистрирован: 19.10.2016

Да, как оказалось энтот неопиксель адафруитовский в рантайме память резервирует. Прекомпиляция в этом деле не поможет.

Тогда берете объём свободной после компиляции скетча RAM и, пользуясь знанием, полученным из этого кода:

...
  // Allocate new data -- note: ALL PIXELS ARE CLEARED
  numBytes = n * ((wOffset == rOffset) ? 3 : 4);
  if((pixels = (uint8_t *)malloc(numBytes))) {
...

делите свободный объем на 3 для трехцветного светодиода. Грубо получается 650 шт.

leks
Offline
Зарегистрирован: 22.10.2017

Понял, спасибо.

arduinec
Offline
Зарегистрирован: 01.09.2015

leks пишет:

Планирую сделать тусклую подсветку периметра в помещении на ws2812, есть ардуино уно. Сколько максимум светодиодов может ею управляться, с использованием библиотеки Adafruit_NeoPixel.h?

С использованием библиотеки Adafruit_NeoPixel получится управлять 500 светодиодами.
Более подробный ответ здесь (#17): http://arduino.ru/forum/programmirovanie/upravlenie-ws2812b#comment-313414

leks
Offline
Зарегистрирован: 22.10.2017

Опять попутно возник вопрос наивный - А можно прикрутить к уно микросхему памяти (для резервирования библиотекой большего числа пикселей)? Или проще взять мегу?

sadman41
Offline
Зарегистрирован: 19.10.2016

Дешевого способа "взять модуль и подключить", так, чтобы эта память виделась, как родная, насколько мне известно - нет. Так что берите Мегу. У роботдина а алиэкспрессе есть конструктив Меги для удобного встраивания в девайсы - по подобию Mini/Nano.

Logik
Offline
Зарегистрирован: 05.08.2014

Вобще, если уж задача становится экстремальной, то и методы решения нужны не тривиальные. Зачем нужен буфер в ОЗУ? - для хранения 3-х яркостей цветовых каналов RGB для каждого светодиода. А можна ли без буфера? Например если все светодиоды светятся одинаково - можна. Достаточно 3-х байт и подключай хоть 100500 светодиодов. А если хочется чтоб по разному светились и без буфера? - тоже можно, но нужна функция, которая определяла бы значения яркости от номера светодиода. И так для 3-х цветов. Снова можна хоть 100500 светодиодов. Все будут светится как в функции задано, но постоянно одним и тем же цветом. И последний заход )) А как сделать чтоб еще и менялось со временем, т.е. чтоб "бегущие огни" или  "падающие звезды"? Тоже можна. В нашу функцию надо добавить еще один параметр - время. Тогда свечение каждого светодиода будет зависить от его номера и изменятся во времени. Так можна подключить 2000 светодиодов. Ограничивает уже время на заливку каждого кадра эффекта в ленту светодиодов.

Вывод - Adafruit_NeoPixel  зло. Ограничивает кол-во светодиодов  (кстати не 600-700 шт, а хороше если 500) из за своего принципа буферирования.

ПС. Осознаю что изложеное - не уровень ТС, но может кому и сгодится.

ППС. Еще прийдется прерывания позапрещать, а миллис и др. этого не переживет.

leks
Offline
Зарегистрирован: 22.10.2017

Logik пишет:

 

ПС. Осознаю что изложеное - не уровень ТС, но может кому и сгодится.

ППС. Еще прийдется прерывания позапрещать, а миллис и др. этого не переживет.

Спрашивать как управлять без библиотеки бесполезно? В рамках её нет возможности ограничить кол-во бит на пиксель?

sadman41
Offline
Зарегистрирован: 19.10.2016

Ну, смотрите, как работает ваш WS2812: он сидит спокойно на заднице и слушает DIN. Как только, грубо говоря, туда начинают сыпаться биты, он отсчитывает 24шт (по 8 бит на цвет), выставляет на своих RGB светодиодах  ШИМ и начинает пропускать остальное дальше. Следующий по цепочке WS2812 делает то же самое. Как только передача прекратилась (нет битстрима некоторое малое время) - 2812 переходит в состояние ожидания следующего раунда. Т.е., в сущности, вам нужно тупо битстримить в DIN. 

Кажется просто, так? Вычисляй цвет для следующего леда и кидай в DIN. Однако, битстримить для WS2812 нужно на постоянной скорости и времени на сложную математику у вас не будет, иначе дальше первого пикселя посылка не уйдет . Стало быть - нужна или быстрая математика с предсказуемым временем задержки или буфер в памяти, в котором будет сформирована посылка, а потом выплюнута в DIN. В библиотеках идут по простому пути - используя буфер. Но вы можете, не используя библиотеку, написать алгоритм так, что он по какому-то закону будет описывать повторяющиеся фрагменты на стрипе, пользуясь гораздо меньшим буфером, а потом выкидывать его в DIN несколько раз. Например, если хотите получить один цвет на стрип, то в цикле закидывайте одни и те же 24 бита столько раз, сколько светодиодов у вас в ленте. И памяти вы потратите ровно 3 байта. 

leks
Offline
Зарегистрирован: 22.10.2017

А примеров реализации безбиблиотечных для Ардуино нет? Смущает частота в 800 килогерц. 

sadman41
Offline
Зарегистрирован: 19.10.2016

У меня нет, а внутри адафруитовской библиотеки на assembler-e вывод написан. Можете попотрошить ее.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

leks пишет:

А примеров реализации безбиблиотечных для Ардуино нет? Смущает частота в 800 килогерц. 

Не совсем понятно, что Вы хотите.

Можно либо пользоваться библиотекой, либо писать самому. Вы видите еще какой-то третий вариант?

Logik
Offline
Зарегистрирован: 05.08.2014

А чего же не понятно. Либка - не святая корова, лезем в неё и забираем функцию вывода из буфера в ленту. Потом используем её в самописаном коде. Причем можна хитро использовать, так чтоб не лезть в ассемблер. А именно вызывать её для очередного светодиода с указанием длины буфера в 1.

Мне эта фрукта и даром не нужна, у меня есть своя функция, в  http://arduino.ru/forum/proekty/pokhvalimsya-khudozhestvennoi-samodeyatelnostyu-na-ws2812   лежит. С ней и поэкспериментирую. Сетап не меняю, а дальше


COLOR c;

COLOR m[]={{50,  0, 0},
           {200, 0, 0},
           {250, 50, 0},
           {50,  250, 50},
           {0,   50,  250}
         };
         
void GetColor(word n, word t)
{
  if((n>=t) && (n<t+5))
  {
     c.RED=m[n-t].RED;
     c.GREEN=m[n-t].GREEN;
     c.BLUE=m[n-t].BLUE;
     return;
  }
  c.RED=0;
  c.GREEN=0;
  c.BLUE=0;
}

void loop()
{
  for(;;)
  { 
  for(word t=0;t<40;t++)
  {
   for(word n=0;n<40;n++)
   {
     GetColor(n, t);
     OutFrame(&c, 3);
   }
   asm volatile ("sei \n\t");
   delay(200); 
  }
  }
}

В самой OutFrame коментируем разрешение прерівания, это sei \n\t. Получаем https://www.youtube.com/watch?v=mUzARyG3ahw Работает идея вобщем. Только GetColor надо быстрой писать, чтоб небыло разрывов при заливе в ленту.

leks
Offline
Зарегистрирован: 22.10.2017

andriano:

Я человек только начинающий пользоваться микроконтроллерами и программированием, поэтому и наивен. Думал внутри библиотеки есть возможность увеличивать число пикселей в ленте за счёт уменьшения битов данных на пиксель. Под примерами подразумевал разжёваные скетчи где без библиотеки (или с "непрофильной библиотекой") включают, например энный пиксель в ленте.

Logik:

Первая ссылка в сообщении почему то пустая.

Logik
Offline
Зарегистрирован: 05.08.2014

Поправил.

leks
Offline
Зарегистрирован: 22.10.2017

Не знаю зачем, но всё таки провёл опыты с К561КП2 и парой pl9823. Работает. Значит можно про мини и 1000-ю неопикселей управлять.

 
leks
Offline
Зарегистрирован: 22.10.2017
// Подключаем библиотеку Adafruit NeoPixel.
#include "Adafruit_NeoPixel.h"
 
// Указываем, какое количество пикселей у нашей ленты.
#define LED_COUNT1 1
 
 
// Указываем, к какому порту подключен вход ленты DIN.
#define LED_PIN1 6
 
Adafruit_NeoPixel strip1 = Adafruit_NeoPixel(LED_COUNT1, LED_PIN1, NEO_RGB + NEO_KHZ400);// Создаем переменную strip для управления нашей лентой. 
 
long Y=0;
 
void setup()
{
 strip1.begin(); 
pinMode(3, OUTPUT);//выводы для управления-пересчёта каналов подключения входа ленты
digitalWrite(3,LOW);
pinMode(4, OUTPUT);//
digitalWrite(4,LOW);
pinMode(5, OUTPUT);//
digitalWrite(5,LOW);
 }
 
void loop()
{
if (millis()-Y>5000){Y=millis();digitalWrite(3,! digitalRead (3));}//перебрасываем канал каждые 5 сек. (перебираем Х0 и Х1 выход К561КП2)
 
strip1.setPixelColor(0, strip1.Color(15,0,0));//включение пикселя
strip1.show();
delay(200);
strip1.setPixelColor(0, strip1.Color(0,0,0));//выключение пикселя
strip1.show();
delay(200);
} 

 

Buldakov
Offline
Зарегистрирован: 17.01.2016

Вопрос по светодиодной ленте WS2812

Есть лента из 8 светодиодов.

Нужно изменять цвет и яркость каждого светодиода. При помощи какой библиотеки это можно сделать?

При использовании библиотеки "Adafruit_NeoPixel.h" могу изменять цвет каждого светодиода, но яркость только всей линейки одновременно.

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015

Buldakov пишет:

Вопрос по светодиодной ленте WS2812

Есть лента из 8 светодиодов.

Нужно изменять цвет и яркость каждого светодиода. При помощи какой библиотеки это можно сделать?

При использовании библиотеки "Adafruit_NeoPixel.h" могу изменять цвет каждого светодиода, но яркость только всей линейки одновременно.

код где?

bwn
Offline
Зарегистрирован: 25.08.2014

Хм, а 0-255, это разве не яркость конкретного светодиода?

Buldakov
Offline
Зарегистрирован: 17.01.2016

0-255 это цвет светодиода в 8 и 9 строках. Яркость в 10 строке.

Например цвет GreenYellow код 173 255 47. Как яркость поменять?

#include <Adafruit_NeoPixel.h>
#define PIN 4 // номер порта к которому подключен модуль
#define count_led 8 // количество светодиодов
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(count_led, PIN, NEO_GRB + NEO_KHZ800); 
void setup() {
pixels.begin();pixels.show();} // Устанавливаем все светодиоды в состояние "Выключено"
void loop() {
pixels.setPixelColor(0, pixels.Color(255,255,0));//1 led 
pixels.setPixelColor(1, pixels.Color(255,255,0));//2 led 
pixels.setBrightness( 64); //общую яркость светодиодной ленты
pixels.show();}

 

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015

надо понимать что такое яркость и что такое цвет

наглядно в винде можно посмотреть

leks
Offline
Зарегистрирован: 22.10.2017

Числа (255,255,0) задают максимум красного и зелёного - жёлтый самый яркий. Пропорционально снижая или увеличивая меняем яркость при сохранности цвета. 10 строка лишняя при таком раскладе.

leks
Offline
Зарегистрирован: 22.10.2017

Все мыслимые теоритически сочетания цвето-яркости для пикселей укладываются в произведение 256*256*256.

Buldakov
Offline
Зарегистрирован: 17.01.2016

Хорошо. при раскладе RGB(173.255.47) Как мне поменять яркость желтозеленого цвета от 1 до 100 % яркости и при этом не поменять цвет?

Например 1 светодиод яркость =100%. 2 светодиод =40%. 3 светодиод = 1%.

#include <Adafruit_NeoPixel.h>
#define PIN 4 // номер порта к которому подключен модуль
#define count_led 8 // количество светодиодов
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(count_led, PIN, NEO_GRB + NEO_KHZ800); 
void setup() {
pixels.begin();pixels.show();} // Устанавливаем все светодиоды в состояние "Выключено"
void loop() {
pixels.setPixelColor(0, pixels.Color(173,255,47));//1 led 
pixels.setPixelColor(1, pixels.Color(173,255,47));//2 led 
pixels.setPixelColor(2, pixels.Color(173,255,47));//3 led 
pixels.show();}

 

bwn
Offline
Зарегистрирован: 25.08.2014

Buldakov пишет:

Команда яркости просто масштабирует диапазон. Попробуйте поставить яркость 5-10% и запустить радугу. Массу цветов, Вы просто не увидите. Они к 0 отмасштабировались.

leks
Offline
Зарегистрирован: 22.10.2017

С шагом в 1 процент весьма сомнительно. При 5 ещё как то... так : (173,255,47) ;(173*0.4,255*0.4,47*0.4);(173*0.05,255*0.05,47*0.05)

leks
Offline
Зарегистрирован: 22.10.2017

А вооще я тренировался всего на 7 цветах. Меня поправят, если ошибаюсь, но чем больше цветов задействовано в скетче, тем меньше шагов в их регулировке яркости.

Buldakov
Offline
Зарегистрирован: 17.01.2016

Ну вы же сами пишете что 1% сомнительно. И я знаю, что таким способом это не получить. Поэтому в данную библиотеку и встроили функцию изменения яркости и задания цвета как отдельные функции. Но изменение яркости  работает только для всех светодиодов вместе. Поэтому я и спрашиваю название библиотеки где есть функция яркости для каждого светодиода. Даже если взять цвета Windows то там есть RGB и уровень яркости отдельно.

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015

по уму, надо перевести RGB в какой нибудь HLS там изменить яркость и вернуть в RGB.

leks
Offline
Зарегистрирован: 22.10.2017

Buldakov пишет:

Ну вы же сами пишете что 1% сомнительно. И я знаю, что таким способом это не получить. Поэтому в данную библиотеку и встроили функцию изменения яркости и задания цвета как отдельные функции. Но изменение яркости  работает только для всех светодиодов вместе. Поэтому я и спрашиваю название библиотеки где есть функция яркости для каждого светодиода. Даже если взять цвета Windows то там есть RGB и уровень яркости отдельно.

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

Надеяться, что есть волшебная, которая скажем на сочетании (127,255,11) даст больше 11 ступеней регулировки яркости при сохранении цвета - это маловероятно. 

sadman41
Offline
Зарегистрирован: 19.10.2016

Adafruit's Neopixel умеет только с RGB работать, ибо это нативное представление цвета для пикселей. FastLed HSL-ом немножко балуется, однако из RGB обратно в HSL не конвертит, только HSL->RGB. Так что придется или держать параллельный массив в HSL или писать конвертилку. Brightness(), как верно подмечено, только масштабирует заданные цвета и превращает (254, 128, 32) внутри себя в (128, 64, 16), что потом на страйп и стримится.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Buldakov пишет:
Поэтому я и спрашиваю название библиотеки где есть функция яркости для каждого светодиода.
Вот и я прикидываю что где-то есть библитека с функциями как стать богатым,как стать счастливым, как получить себе большой свой дом.
ПС: Верной дорогой идешь товарищ господин

Buldakov
Offline
Зарегистрирован: 17.01.2016

Мы все едем верной дорогой. Вопрос только в том, что мы хотим куда-то попасть быстро и легко. Для этого надо поспрашать прямую дорогу. Вдруг кто нибудь по ней ходил. Если никто не ходил, есть вариант пойти через лес, либо пойти по другой дороге, где легко и просто.

А по поводу функции, как стать богатым - это все уже давно есть. Вы просто наверное никого не спрашивали про это.

leks
Offline
Зарегистрирован: 22.10.2017

Buldakov пишет:

Мы все едем верной дорогой. Вопрос только в том, что мы хотим куда-то попасть быстро и легко. Для этого надо поспрашать прямую дорогу. Вдруг кто нибудь по ней ходил. Если никто не ходил, есть вариант пойти через лес, либо пойти по другой дороге, где легко и просто.

А по поводу функции, как стать богатым - это все уже давно есть. Вы просто наверное никого не спрашивали про это.

Тогда надо искать.., ведь если быстро переключать между (127,255,11) и (127,255,10), чередуя разные длительности, то можно и любую яркость для синего между 10 и 11 выставить...

То есть чисто гипотетически обетованнная библиотека должна быть.

sadman41
Offline
Зарегистрирован: 19.10.2016

лекс, к чему такие извращения - шимить шим?

leks
Offline
Зарегистрирован: 22.10.2017

sadman41 пишет:

лекс, к чему такие извращения - шимить шим?

Согласен, затея безнадёжная, разве для нескольких пикселей, чисто для эксперимента.

sadman41
Offline
Зарегистрирован: 19.10.2016

Вот, поискал вам функцию: https://www.rapidtables.com/convert/color/rgb-to-hsv.html

Но мне кажется, что при конвертации туда-сюда цвет всё равно может поменять оттенок в связи с тем, что потеряется точность на делении.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Цвет будет менятся,даже если сохранять пропорции яркости красного, желтого, синего , так это сцука человеческие глаза. Ну там колбочки, трубочки. Да и вообще в сумерках все кошки серы, даже если это тигры . 

sadman41
Offline
Зарегистрирован: 19.10.2016

Поэтому в при разных L в HSL при переводе получаются разные пропорции R, G, B.

Но, вообще, я вспомнил - в FastLed можно поиграться с Dimming and brightening functions

AlexanderNO
Offline
Зарегистрирован: 08.11.2018

Изменению яркости (V или B) пространства HSV (HSB) соответствует пропорциональное изменение значений каждого цвета пространства RGB относительно исходных. Введя коэффициенты исходных значений цветов (float kX = float(X)/255.0) можно менять цветовую яркость каждого светодиода:  int NewX = int (float(X)-kX).  

 

 

b707
Offline
Зарегистрирован: 26.05.2017

Buldakov пишет:

Ну вы же сами пишете что 1% сомнительно. И я знаю, что таким способом это не получить. Поэтому в данную библиотеку и встроили функцию изменения яркости и задания цвета как отдельные функции.

Я вижу, что Вы продолжаете не понимать сути. Отдельная функция яркости просто умножает каждый компонент цвета RGB на коефициент. Так эта функция работает "для всех светодиодов".

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

Buldakov
Offline
Зарегистрирован: 17.01.2016

Да мне понятно, что яркость светодиода формируется путем яркости отдельных цветов RGB. напрмер для цвета (173,255,47)  для изменения яркости надо писать (173*0.4,255*0.4,47*0.4); А для 8 светодиодов надо (173,255,47) делить на 8 разных коэффициентов. Я понимаю, что при 1 % яркости у меня вместо (173,255,47) будет что то типа(2,3,0) и цвет будет не тот.

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

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Buldakov пишет:

Вопрос только в том, что мы хотим куда-то попасть быстро и легко. Для этого надо поспрашать прямую дорогу.

Очень хорошо, что Вы это понимаете.

Непонятно только, раз Вы понимаете, что прямая дорога лучше, зачем ищете библиотеку?

b707
Offline
Зарегистрирован: 26.05.2017

Buldakov пишет:

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

библиотека Неопиксель. А функцию написать самостоятельно.

Buldakov
Offline
Зарегистрирован: 17.01.2016

Всем спасибо. Без яркости получился такой код.

 

if (Delta_r< w1) pixels.setPixelColor(2, pixels.Color(  0,  0,  0)); 
if (Delta_r>=w2) pixels.setPixelColor(2, pixels.Color(255,255,  0));
if (Delta_r>=w1 && Delta_r<w2) 
 { 
 U_out=(Delta_r-w1)*(255.0/(w2-w1));U_out=pow((U_out+15),2)/256;if (U_out>=255) U_out=255;
pixels.setPixelColor(2, pixels.Color(U_out,U_out,  0));
 }