Поиск сообщества
Показаны результаты для тегов 'WS2812'.
Найдено: 7 результатов
-
Arduino HC-06 (Serial.available() внутри условия Serial.available)
Гость опубликовал тема в Arduino, ESP32, ESP8266, Raspberry Pi
Доброго времени суток. Не смог реализовать повторный Serial.available() внутри условия Serial.available. Может кто-то уже сталкивался с этим. Задача состоит в том, что нужно зажечь светодиодные ленты WS2812b. Алгоритм действий: 1) Ожидаем появления данных на входе serial с помощью if (Serial.available()){} 2) Принимаем значения int val=Serial.paresInt(); 3)Условие сравнивания if(val>123){chess=val;} esle if(val<124){color=val;} т.е номер светодиода это chess, цвет это color 4) На смартфон отправляем 'n', для разрешения отправки следующих данных 5)Ждем уже цвет светодиода на входе serial далее по предыдущему алгоритму 6)Зажигаем указанный светодиод на указанный цвет. #include <FastLED.h> #define LED_PIN 6 #define NUM_LEDS 123 CRGB leds[NUM_LEDS]; const unsigned int DIM1 = 123; const unsigned int DIM2 = 1; const unsigned int DIM3 = 3; int ary[DIM1][DIM2][DIM3]; void setup() { Serial.begin(9600); FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS); } void loop() { if(Serial.available()){ int val=Serial.parseInt(); int chess=val; Serial.println(chess); delay(1); Serial.println('n'); clear_serail(); if(Serial.available()){int color=Serial.parseInt(); Serial.println(color); if(color>0){ if(color==124){ ary[chess][1][1]=0; ary[chess][1][2]=255; ary[chess][1][3]=0; Serial.println(ary[chess][1][1]); Serial.println(ary[chess][1][2]); Serial.println(ary[chess][1][3]); leds[chess]=CRGB(ary[chess][1][1],ary[chess][1][2],ary[chess][1][3]); FastLED.show(); Serial.println('l'); clear_serail(); } if(color==125){ ary[chess][1][1]=255; ary[chess][1][2]=0; ary[chess][1][3]=0; leds[chess]=CRGB(ary[chess][1][1],ary[chess][1][2],ary[chess][1][3]); FastLED.show(); Serial.println('l'); clear_serail(); }}} } } void clear_serail(){ Serial.end(); Serial.begin(9600); } -
WS2812 или поморгаем ещё разок
parovoZZ опубликовал запись в блоге в Attiny 0-ой и 1-ой серии (Attiny817, 1614 и прочие)
Всем привет! В этом топике я покажу, как с помощью новейшей Attiny от Atmel/Microchip управлять светодиодами WS2812. Для начала давайте вспомним, а лучше подсмотрим в даташите на временные интервалы нуля и единицы. Где видим, что для передачи нуля нам необходим импульс длительностью от 200 и до 500 наносекунд, для передачи единицы - от 550 и до 850 наносекунд. Период же так и вообще может изменяться в широких пределах. Управлять светодиодами мы будем с помощью SPI. Но не напрямую, а через CCL. Почему? Всё просто - SPI содержит 8-ми битный регистр и как его не крути, целочисленная передача не получится - исходный бит надо будет "разбавлять" нулями либо единицами. А что если поступить наоборот - длительность исходного бита будет задавать период сигнала, а разбивать бит будем тактовой частотой SCK того же интерфейса SPI. Так мы сформируем "1", которую поймет драйвер светодиода. Да, T1H и T1L по длительности будут равны, но в параметры даташита мы укладываемся. Как же быть с нулем? Для этого мы воспользуемся помощью зрительного зала таймера TCA0. Пусть он нам разобьет тактовую частоту SCK ещё раз напополам и мы получим длительность T0H в четыре раза меньшую, чем период. Но всё равно укладываемся в даташит)) В результате манипуляций мы получим такую картину: Звиняюсь, но диаграммы отображают (не то, что там подписано....) желтая диаграмма - это RGB код для светодиодов, зеленая диаграмма - тактовая частота SCK, синий - меандр с таймера TCA0, фиолетовый - подготовленные импульсы для подачи на WS2812. Работать мы будем на тактовой частоте в 20 МГц, поэтому первое, что сделаем, отключим прескалер: CCP = CCP_IOREG_gc; CLKCTRL.MCLKCTRLB = 0; Затем подготовим блок SPI: //... Инициализация SPI inline void SPI_Init(void) { SPI_PORT.DIR |= (1<<MOSI_PIN) | (1<<SCK_PIN) | (0<<MISO_PIN) | (1<< PIN4_bp); // Все выводы, кроме MISO, выходы SPI0.CTRLA = (0<<SPI_DORD_bp) // Старший бит вперёд | (1<<SPI_MASTER_bp) // SPI мастер | (1<<SPI_CLK2X_bp) // Удвоенная скорость тактирования | SPI_PRESC_DIV64_gc // Делитель = 64 | (1<<SPI_ENABLE_bp); // Разрешаем работу SPI SPI0.CTRLB = (0<<SPI_BUFEN_bp) | (0<<SPI_BUFWR_bp) | (1<<SPI_SSD_bp) | SPI_MODE_0_gc; SPI0.DATA = 0; } //... Передать байт данных inline void SPI_WriteByte(uint8_t data) { SPI0.DATA = data; while(!(SPI0.INTFLAGS & SPI_IF_bm)); } Выставляем прескалер на 64 такта и взводим бит SPI_CLK2X, что в итоге нам даст частоту тактирования 625 кГц. Период тактирования при такой частоте будет равен 1.6 мкс - в даташит укладываемся. Далее настроим таймер: void TCA_Init(void) { TCA0.SINGLE.CTRLB = 1<<TCA_SINGLE_ALUPD_bp | // Установим бит автоматической блокировки обновления регистров компаратора (0 << TCA_SINGLE_CMP0EN_bp) | (0 << TCA_SINGLE_CMP1EN_bp) | (0 << TCA_SINGLE_CMP2EN_bp) | // пины выводов компараторов не включаем TCA_SINGLE_WGMODE_SINGLESLOPE_gc; // Режим работы таймера - односкатный ШИМ с прерыванием OVF в вершине счета } Режим работы таймера следующий - счетчик таймера считает от нуля и до значения в регистре PER, после чего самостоятельно обнуляется и цикл повторяется. Значение прескалера таймера и его режим работы я определю в отдельной функции: inline void TCA0_Mode(uint8_t mode) { TCA0.SINGLE.CTRLA = TCA_SINGLE_CLKSEL_DIV1_gc | // Определяем значение прескалера - 1 mode << TCA_SINGLE_ENABLE_bp; // mode = 1 - таймер включен, mode = 0 - таймер выключен } Уже в основной функции настрою регистры: TCA_Init(); TCA0.SINGLE.PER = TCA_period; TCA0.SINGLE.CMP2 = TCA_cmp2; Компаратор использую CMP2 - далее будет понятно почему. Выход компаратора устанавливается в "1" при сбросе счетчика, а сбрасывается при равенстве значений в счетном регистре и регистре компаратора. Для того, чтобы получить частоту 625 * 2 = 1250 кГц, я определю следующие значений регистров: #define TCA_period 15 #define TCA_cmp2 8 Давайте подключать таблицу LUT CCL. Для этого открываем даташит и внимательно читаем, на какой вход что можно подключить. Напомню, что нам надо завести сигналы от: -MOSI SPI -SCK SPI -WO2 Смотрим - на нулевой канал LUT мы можем подключить от SPI только сигнал SCK (скопирую из файла определений iotn817.h): /* LUT Input 0 Source Selection select */ typedef enum CCL_INSEL0_enum { CCL_INSEL0_MASK_gc = (0x00<<0), /* Masked input */ CCL_INSEL0_FEEDBACK_gc = (0x01<<0), /* Feedback input source */ CCL_INSEL0_LINK_gc = (0x02<<0), /* Linked LUT input source */ CCL_INSEL0_EVENT0_gc = (0x03<<0), /* Event input source 0 */ CCL_INSEL0_EVENT1_gc = (0x04<<0), /* Event input source 1 */ CCL_INSEL0_IO_gc = (0x05<<0), /* IO pin LUTn-IN0 input source */ CCL_INSEL0_AC0_gc = (0x06<<0), /* AC0 OUT input source */ CCL_INSEL0_TCB0_gc = (0x07<<0), /* TCB0 WO input source */ CCL_INSEL0_TCA0_gc = (0x08<<0), /* TCA0 WO0 input source */ CCL_INSEL0_TCD0_gc = (0x09<<0), /* TCD0 WOA input source */ CCL_INSEL0_USART0_gc = (0x0A<<0), /* USART0 XCK input source */ CCL_INSEL0_SPI0_gc = (0x0B<<0), /* SPI0 SCK source */ } CCL_INSEL0_t; На первый канал подключается только MOSI: /* LUT Input 1 Source Selection select */ typedef enum CCL_INSEL1_enum { CCL_INSEL1_MASK_gc = (0x00<<4), /* Masked input */ CCL_INSEL1_FEEDBACK_gc = (0x01<<4), /* Feedback input source */ CCL_INSEL1_LINK_gc = (0x02<<4), /* Linked LUT input source */ CCL_INSEL1_EVENT0_gc = (0x03<<4), /* Event input source 0 */ CCL_INSEL1_EVENT1_gc = (0x04<<4), /* Event input source 1 */ CCL_INSEL1_IO_gc = (0x05<<4), /* IO pin LUTn-N1 input source */ CCL_INSEL1_AC0_gc = (0x06<<4), /* AC0 OUT input source */ CCL_INSEL1_TCB0_gc = (0x07<<4), /* TCB0 WO input source */ CCL_INSEL1_TCA0_gc = (0x08<<4), /* TCA0 WO1 input source */ CCL_INSEL1_TCD0_gc = (0x09<<4), /* TCD0 WOB input source */ CCL_INSEL1_USART0_gc = (0x0A<<4), /* USART0 TXD input source */ CCL_INSEL1_SPI0_gc = (0x0B<<4), /* SPI0 MOSI input source */ } CCL_INSEL1_t; И на третьем канале от таймера TCA0 возможно подключить только WO2: /* LUT Input 2 Source Selection select */ typedef enum CCL_INSEL2_enum { CCL_INSEL2_MASK_gc = (0x00<<0), /* Masked input */ CCL_INSEL2_FEEDBACK_gc = (0x01<<0), /* Feedback input source */ CCL_INSEL2_LINK_gc = (0x02<<0), /* Linked LUT input source */ CCL_INSEL2_EVENT0_gc = (0x03<<0), /* Event input source 0 */ CCL_INSEL2_EVENT1_gc = (0x04<<0), /* Event input source 1 */ CCL_INSEL2_IO_gc = (0x05<<0), /* IO pin LUTn-IN2 input source */ CCL_INSEL2_AC0_gc = (0x06<<0), /* AC0 OUT input source */ CCL_INSEL2_TCB0_gc = (0x07<<0), /* TCB0 WO input source */ CCL_INSEL2_TCA0_gc = (0x08<<0), /* TCA0 WO2 input source */ CCL_INSEL2_TCD0_gc = (0x09<<0), /* TCD0 WOA input source */ CCL_INSEL2_SPI0_gc = (0x0B<<0), /* SPI0 MISO source */ } CCL_INSEL2_t; Пишем: CCL.LUT0CTRLB = CCL_INSEL0_SPI0_gc // Выбор канала SPI SCK | CCL_INSEL1_SPI0_gc; // Выбор канала SPI MOSI CCL.LUT0CTRLC = CCL_INSEL2_TCA0_gc; // Выбор канала W02 таймера TCA Ну и общие настройки, про которые уже писал: CCL.LUT0CTRLA = 0 << CCL_CLKSRC_bp // Блок CCL не тактируем | 1 << CCL_ENABLE_bp // Разрешение работы LUT0 | 1 << CCL_OUTEN_bp; // Разрешение выхода LUT0 CCL.CTRLA = 1 << CCL_ENABLE_bp // Разрешение работы CCL | 0 << CCL_RUNSTDBY_bp; // В стендбае не работаем Теперь необходимо запрограммировать таблицу истинности. Для этого смотрим на диаграмму выше и отмечаем входные состояния, при которых на выходе "1". В остальных случаях "0". У меня получилось следующее: CCL.TRUTH0 = 0xA8; // Таблица истинности Теперь запишем функцию трансляции байта на выход MOSI модуля SPI. Также не забываем, что нам необходимо останавливать таймер TCA0 по окончании пересылки байта и запускать его (со сбросом) в начале посылки, иначе он нам тут натикает совсем не то))) void SPI_out8bit(uint8_t data) { TCA0.SINGLE.CNT = 0; TCA0_Mode(start); SPI_WriteByte(data); TCA0_Mode(stop); } Всё, что нам осталось - это заслать байты в порядке очереди: SPI_out8bit(green[0]); SPI_out8bit(red[0]); SPI_out8bit(blue[0]); Где: uint8_t blue[1]; uint8_t red[1]; uint8_t green[1]; Как видите - никакого ассемблера, куча времени для расчета эффектов. Если подключить буферы в SPI (а мы это обязательно сделаем), ну или высший пилотаж - работать на прерываниях, то формировать узоры можно параллельно с пересылкой байтов в линию Также ещё можно поработать и с внешними интерфейсами. Но это уже совсем другая история. ENJOY! -
Написать скетч Attiny13 для управления WS2812
Ilgam Talipov опубликовал тема в Вакансии и разовая работа
Задача: Написать скетч управления 9 светодиодами аналог WS2812 (из библиотек FastLed и NeoPixel рулятся ). Режим работы - стробы, длительность вспышки 0.1 - 0,2 сек, после того как каждый светодиод моргнул 1 раз, цикл повторяется, длительность цикла 4,5 сек (время примерное, точность не важна). Помочь настроить Arduino IDE для прошивки тинек. Если у вас железа нет, не проблема - мы можем тестить ваш код на нашем железе. Стоимость 5 000 руб мой скайп ilgamt почта talipov@me.com Спасибо -
Приветствую всех! Уважаемые, подскажите пожалуйста, в даташите по светодиодам ws2812b написано что ток потребления светодиодов при белом цвете 60 миллиампер, я подключил их к блоку питания и выставил ток на 3 Ампера, зажег 30 светодиодов белым цветом, ток потребления 1 Ампера , потом отключил кроме 6 светодиодов другие, и эти 6 начали гореть чрезмерно ярко и спустя минуту нагреваются и перестают реагировать на команды с МК. Вопрос такой, если я их подключаю к автомобилю нужно ли стабилизировать ток для этих светодиодов на указанный в даташите 60 миллиампер, или ток стабилизируется для каждого светодиода, встроенным контроллером светодиода? Вопрос возник из за того что они все соединены на ленте параллельно, если бы они были без встроенного контроллера я знаю что нужно стабилизировать ток, но так как в эти встроен контроллер то немного запутался с ними. WS2812B_datasheet_EN.pdf
-
Друзья помогите разобраться. Приобрел управляемые диоды WS2812 многим уже известные. Поиски доступных для новичка исходников результатов не дали. Сталкивался с скечами для Ардуино, библиотеками NeoPixel. Во первых не забрался, во-вторых принципиально хочу сообразить всё это на на своей плате на Attiny или Atmege. Сам по себе принци понять логику. Из даташита понятно что диды управляются 24битами, таймаутами и т.п., но никак не соображу как послать биты в контроллер. Только начал разбираться с ШИМом. Думал тут чтото подобное. Помогите новичку с самого простого.
-
В общем в чем суть, имеется raspberry pi и планируется подключить к нему 4 светодиодные ленты на ws2812. Я тут быстренько нарисовал как оно будет выглядеть, но в силу моего полного профанства в электрике прошу совета, а именно, что нужно и куда добавить. Особенно меня смущает 40 ампер на БП, один светодиод потребляет 60 мА, светодиодов в ленте 30 на метр, лента 5 метров и их 4 штуки. Итого на ленту надо 36 А. Я думаю 4 ампера там погоды не сделают при условии, что под нагрузкой будут все 4 ленты, но что если одна лента вдруг сломается, не повлечет ли увеличившаяся сила тока поломку и остальных лент. В общем как-то так... Прошу подсказать...
-
Здравствуйте! Столкнулся с проблемой при прокладке светодиодной ленты на RGB-светодиодах WS2812. Для тех, кто не знает, это светодиод с индивидуальным цифровым управлением яркостью и цветом свечения. Управляющий сигнал частотой 800кГц, передается по одному проводу и кодируется отношением длительности наличия и отсутствия импульса. Так вот, лента у меня должна находиться в алюминиевом профиле как на картинке, и в этом же профиле проложен сетевой провод 220V. Проблема заключается в том, что когда на сетевом проводе присутствует напряжение, при подаче управляющего сигнала, лента начинает беспорядочно мигать. При этом управление осуществляется, но с явными искажениями, т.е. в целом каждый светодиод работает правильно, но моментами вспыхивает произвольным цветом. Сразу оговорюсь, что длина линии связи между диодами всего 11мм, и сам чип WS2812 устроен так, что он отрезает свой "кусок" входящих данных, а на выходе генерирует новый усиленый, что подсказывает, что помехи от силового провода влияют не на линию передачи данных, а на сами микросхемы. Объясните, пожалуйста, если я в чем-то не прав. И есть ли выход из данной ситуации.