STM Урок 142. WS2812B. Подключаем ленты количеством 150-300 светодиодов. Часть 2
В предыдущей части урока мы познакомились с лентами на 150 светодиодов, подготовили блок питания для них, соединили нашу схему и произвели её первоначальную проверку.
Перейдём в файл ws2812.h и изменим в макросе количество светодиодов
#define LED_COUNT 150
Только это ещё далеко не всё.
Перейдём в файл ws2812.c и также добавим размер временного буфера
uint8_t rgb_temp[15][3];
Теперь у нас в каждой группе будет не по 12, а по 15 светодиодов. В каждой ленте таких будет по 10 групп, так как на 12 число 150 не делится.
Функцию ws2812_prepareValue мы также перепишем, так как количество в цикле и количество циклов у нас изменилось
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
void ws2812_prepareValue (uint8_t r00, uint8_t g00, uint8_t b00, uint8_t r01, uint8_t g01, uint8_t b01, uint8_t r02, uint8_t g02, uint8_t b02, uint8_t r03, uint8_t g03, uint8_t b03, uint8_t r04, uint8_t g04, uint8_t b04, uint8_t r05, uint8_t g05, uint8_t b05, uint8_t r06, uint8_t g06, uint8_t b06, uint8_t r07, uint8_t g07, uint8_t b07, uint8_t r08, uint8_t g08, uint8_t b08, uint8_t r09, uint8_t g09, uint8_t b09, uint8_t r10, uint8_t g10, uint8_t b10, uint8_t r11, uint8_t g11, uint8_t b11, uint8_t r12, uint8_t g12, uint8_t b12, uint8_t r13, uint8_t g13, uint8_t b13, uint8_t r14, uint8_t g14, uint8_t b14 ) { rgb_temp[0][0]=r00; rgb_temp[0][1]=g00; rgb_temp[0][2]=b00; rgb_temp[1][0]=r01; rgb_temp[1][1]=g01; rgb_temp[1][2]=b01; rgb_temp[2][0]=r02; rgb_temp[2][1]=g02; rgb_temp[2][2]=b02; rgb_temp[3][0]=r03; rgb_temp[3][1]=g03; rgb_temp[3][2]=b03; rgb_temp[4][0]=r04; rgb_temp[4][1]=g04; rgb_temp[4][2]=b04; rgb_temp[5][0]=r05; rgb_temp[5][1]=g05; rgb_temp[5][2]=b05; rgb_temp[6][0]=r06; rgb_temp[6][1]=g06; rgb_temp[6][2]=b06; rgb_temp[7][0]=r07; rgb_temp[7][1]=g07; rgb_temp[7][2]=b07; rgb_temp[8][0]=r08; rgb_temp[8][1]=g08; rgb_temp[8][2]=b08; rgb_temp[9][0]=r09; rgb_temp[9][1]=g09; rgb_temp[9][2]=b09; rgb_temp[10][0]=r10;rgb_temp[10][1]=g10;rgb_temp[10][2]=b10; rgb_temp[11][0]=r11;rgb_temp[11][1]=g11;rgb_temp[11][2]=b11; rgb_temp[12][0]=r12;rgb_temp[12][1]=g12;rgb_temp[12][2]=b12; rgb_temp[13][0]=r13;rgb_temp[13][1]=g13;rgb_temp[13][2]=b13; rgb_temp[14][0]=r14;rgb_temp[14][1]=g14;rgb_temp[14][2]=b14; } |
Перепишем также и прототип в заголовочном файле
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
void ws2812_prepareValue (uint8_t r00, uint8_t g00, uint8_t b00, uint8_t r01, uint8_t g01, uint8_t b01, uint8_t r02, uint8_t g02, uint8_t b02, uint8_t r03, uint8_t g03, uint8_t b03, uint8_t r04, uint8_t g04, uint8_t b04, uint8_t r05, uint8_t g05, uint8_t b05, uint8_t r06, uint8_t g06, uint8_t b06, uint8_t r07, uint8_t g07, uint8_t b07, uint8_t r08, uint8_t g08, uint8_t b08, uint8_t r09, uint8_t g09, uint8_t b09, uint8_t r10, uint8_t g10, uint8_t b10, uint8_t r11, uint8_t g11, uint8_t b11, uint8_t r12, uint8_t g12, uint8_t b12, uint8_t r13, uint8_t g13, uint8_t b13, uint8_t r14, uint8_t g14, uint8_t b14 ); |
Соответственно, в файле main.c в вызове данной функции добавим аргументов с другими цветами, а также заодно увеличим яркость засчёт удвоения остальных аргументов
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
ws2812_prepareValue(255, 0, 0, 0, 255, 0, 0, 0, 255, 128, 128, 0, 0, 128, 128, 128, 0, 128, 192, 64, 0, 192, 0, 64, 64, 192, 0, 0, 192, 64, 0, 64, 192, 64, 0, 192, 192, 32, 32, 32, 32, 192, 32, 192, 32 ); |
К такому же виду приведём вызов данной функции и в функции ws2812_test01 в файле ws2812.c.
И все равно, если сейчас прошить контроллер, то светодиоды последние также не будут светиться.
Чтобы они засветились, исправим функцию ws2812_setValue, добавив в неё несколько строк, а также исправив существующие под схему 10×15
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
void ws2812_setValue(void) { uint8_t n=0; for(n=0;n<10;n++) { ws2812_pixel_rgb_to_buf_dma( rgb_temp[0][0], rgb_temp[0][1], rgb_temp[0][2], n*15); ws2812_pixel_rgb_to_buf_dma( rgb_temp[1][0], rgb_temp[1][1], rgb_temp[1][2], n*15+1); ws2812_pixel_rgb_to_buf_dma( rgb_temp[2][0], rgb_temp[2][1], rgb_temp[2][2], n*15+2); ws2812_pixel_rgb_to_buf_dma( rgb_temp[3][0], rgb_temp[3][1], rgb_temp[3][2], n*15+3); ws2812_pixel_rgb_to_buf_dma( rgb_temp[4][0], rgb_temp[4][1], rgb_temp[4][2], n*15+4); ws2812_pixel_rgb_to_buf_dma( rgb_temp[5][0], rgb_temp[5][1], rgb_temp[5][2], n*15+5); ws2812_pixel_rgb_to_buf_dma( rgb_temp[6][0], rgb_temp[6][1], rgb_temp[6][2], n*15+6); ws2812_pixel_rgb_to_buf_dma( rgb_temp[7][0], rgb_temp[7][1], rgb_temp[7][2], n*15+7); ws2812_pixel_rgb_to_buf_dma( rgb_temp[8][0], rgb_temp[8][1], rgb_temp[8][2], n*15+8); ws2812_pixel_rgb_to_buf_dma( rgb_temp[9][0], rgb_temp[9][1], rgb_temp[9][2], n*15+9); ws2812_pixel_rgb_to_buf_dma(rgb_temp[10][0],rgb_temp[10][1],rgb_temp[10][2],n*15+10); ws2812_pixel_rgb_to_buf_dma(rgb_temp[11][0],rgb_temp[11][1],rgb_temp[11][2],n*15+11); ws2812_pixel_rgb_to_buf_dma(rgb_temp[12][0],rgb_temp[12][1],rgb_temp[12][2],n*15+12); ws2812_pixel_rgb_to_buf_dma(rgb_temp[13][0],rgb_temp[13][1],rgb_temp[13][2],n*15+13); ws2812_pixel_rgb_to_buf_dma(rgb_temp[14][0],rgb_temp[14][1],rgb_temp[14][2],n*15+14); } } |
Вот теперь мы наконец-то соберём код и прошьём контроллер.
Теперь у нас светятся все светодиоды
Теперь перейдём к тестам.
В файле main.c удалим наш добавленный бесконечный цикл, а в основном бесконечном цикле закомментируем все тесты, кроме первого. Займёмся пока им
|
1 2 3 4 5 6 7 8 9 10 |
ws2812_test01(); //ws2812_test02(); //ws2812_test03(); //ws2812_test04(1); //ws2812_test04(2); //ws2812_test04(3); //ws2812_test04(4); //ws2812_test04(5); //ws2812_test04(6); //ws2812_test05(); |
Если мы сейчас запустим наш код, то светодиоды будут светиться все, так как мы их зажгли с помощью уже исправленной функции, но последние 6 светодиодов бежать не будут, поэтому перейдём в функцию ws2812_test01 в файле ws2812.c.
Первым делом в цикле добавим количество итераций
for(i=0;i<149;i++)
Также цифру с количеством устанавливаемых битов доже прибавим
memcpy((void*)(BUF_DMA+48+3576),(void*)DMA_BUF_TEMP,48);
Соберём код, прошьём контроллер и посмотрим результат.
К сожалению, я не могу в рамках статьи показать красоту бегущих огней, поэтому смотрите видео. А здесь картина получится практически как и предыдущая, единственное, я попробую поймать другой момент, то есть такой, чтобы цвет светодиодов был хотя бы сдвинут
Перейдём в файл main.c, закомментируем первый тест и раскомментируем второй
|
1 2 |
//ws2812_test01(); ws2812_test02(); |
В дальнейшем мы будем поступать таким образом со всем тестами и я повторяться не буду в том, какой тест мы будем раскоментировать, а какой комментировать. Вернёмся в файл ws2812.c и перейдём в тело функции ws2812_test02.
Здесь изменений будет немного побольше.
Во-первых инициализацию коэффициента в обоих местах мы перенесём на уровень выше, так как переменная i в расчёте коэффициента не используется
|
1 2 3 4 |
for(j=0;j<32;j++) { k=1000*(32-j)/32; for(i=0;i<144;i++) |
Также в обоих циклах самого нижнего уровня добавим количество итераций
for(i=0;i<150;i++)
Соберём код, прошьём контроллер.
Тест работает, все 150 светодиодов плавно и одновременно мигают
Переходим к следующему тесту — ws2812_test03.
Первым делом прибавим количество итераций также в обоих циклах
for(i=0;i<150;i++)
В обоих условиях меняем интервалы
if((i<15)||((i>=30)&&(i<45))||((i>=60)&&(i<75))||((i>=90)&&(i<105))||((i>=120)&&(i<135)))
И внутри в обоих циклах меняем делители в делениях по модулю
ws2812_pixel_rgb_to_buf_dma(rgb_temp[i%15][0]*k/1000,rgb_temp[i%15][1]*k/1000,rgb_temp[i%15][2]*k/1000,i);
Прошиваем, смотрим
Переходим к тесту ws2812_test04.
Раскомментируем пока только с единичкой
ws2812_test04(1);
Первым делом в начале теста изменим количество итераций в циклах обоих вложенностей
for(j=0;j<10;j++)
{
for(i=0;i<15;i++)
Ближе к окончанию тела тоже изменим количество итераций в двух циклах
for(jj=0;jj<150;jj++)
{
memcpy((void*)DMA_BUF_TEMP,(void*)(BUF_DMA+48),48);
for(i=0;i<149;i++)
Также изменим ниже количество обрабатываемых битов
memcpy((void*)(BUF_DMA+48+3576),(void*)DMA_BUF_TEMP,48);
Дальше поднимемся выше и займёмся оператором вариантов, а вернее его первым кейсом.
Сначала увеличим порог (можно его увеличить сразу во всех кейсах)
if(i<8)
А затем далее меняем 12 на 15, а 128 на 255
if(i<8)
{rgb_temp[j*15+i][0]=255/((i+1)*2); rgb_temp[j*15+i][1]=0; rgb_temp[j*15+i][2]=0;}
else
{rgb_temp[j*15+i][0]=255/((15-i)*2); rgb_temp[j*15+i][1]=0; rgb_temp[j*15+i][2]=0;}
Попробуем собрать код и прошить контроллер.
Тест отлично работает
В остальных кейсах аналогично 12 заменим на 15, 128 — на 255, 64 — на 128, раскомментируем в main.c вызов 4 теста со всеми аргументами, соберём код, прошьём контроллер и посмотрим результат
Остался ещё один тест — ws2812_test05.
В теле данной функции первым делом добавим количество итераций в цикле
for(i=0;i<150;i++)
В цикле удалим 2 последних условия
if(i%12==10) ws2812_pixel_rgb_to_buf_dma(128*k/3000,128*(1000-k)/667,128*(1000-k)/1000,i);
if(i%12==11) ws2812_pixel_rgb_to_buf_dma(128*(1000-k)/3000,128*k/667,128*(1000-k)/3000,i);
А число 128 везде в цикле заменим на 255, 12 — на 10, а 667 — на 1333
if(i%10==0) ws2812_pixel_rgb_to_buf_dma(255*k/1000,255*(1000-k)/1000,0,i);
if(i%10==1) ws2812_pixel_rgb_to_buf_dma(0,255*k/1000,255*(1000-k)/1000,i);
if(i%10==2) ws2812_pixel_rgb_to_buf_dma(255*k/1000,0,255*(1000-k)/1000,i);
if(i%10==3) ws2812_pixel_rgb_to_buf_dma(255*(1000-k)/1000,255*k/2000,255*k/2000,i);
if(i%10==4) ws2812_pixel_rgb_to_buf_dma(255*k/2000,255*k/2000,255*(1000-k)/1000,i);
if(i%10==5) ws2812_pixel_rgb_to_buf_dma(255*k/2000,255*(1000-k)/1000,255*k/2000,i);
if(i%10==6) ws2812_pixel_rgb_to_buf_dma(255*(1000-k)/2000,255*(1000-k)/2000,255*k/1000,i);
if(i%10==7) ws2812_pixel_rgb_to_buf_dma(255*k/1000,255*(1000-k)/2000,255*(1000-k)/2000,i);
if(i%10==8) ws2812_pixel_rgb_to_buf_dma(255*(1000-k)/2000,255*k/1000,255*(1000-k)/2000,i);
if(i%10==9) ws2812_pixel_rgb_to_buf_dma(255*(1000-k)/3000,255*(1000-k)/1333,255*k/1000,i);
Соберём проект, прошьём контроллер и посмотрим, как красиво теперь переливаются цвета светодиодов
Раскомментируем вызов функций всех тестов и посмотрим ещё раз на все тесты.
Если всё нормально, то пока отключим блок питания от розетки, также отключим программатор от ПК.
В следующей части урока мы изменим код проекта под использование ленты на 300 светодиодов и проверим его на практике.
Исходный код для ленты на 150 светодиодов
Отладочную плату STM32F103C8T6 можно приобрести здесь STM32F103C8T6
Программатор недорогой можно купить здесь ST-Link V2
Ленты светодиодные WS2812B разные можно приобрести здесь WS2812B
Импульсный источник питания 5 В в 40A 200 Вт можно приобрести здесь 5 В в 40A 200 Вт
Логический анализатор 16 каналов можно приобрести здесь
Смотреть ВИДЕОУРОК в RuTube (нажмите на картинку)
Смотреть ВИДЕОУРОК в YouTube (нажмите на картинку)














Добавить комментарий