Матрица 8*32 ws2812b
- Войдите на сайт для отправки комментариев
Ср, 03/08/2022 - 19:07
Тренируюсь с матрицей, примеры библиотеки "неопиксель матрикс" не заработали - матрица не светит :)
Стал писать функции сам, три нарисовал, фантазия иссякла. Не могу корректно массивы цифр перевести в PROGMEM, пробовал на семёрке, какая то кракозябра рисуется. Как это подправить?
Раз ino.
// Подключаем библиотеку Adafruit NeoPixel.
#include <Adafruit_NeoPixel.h>
// Указываем, какое количество пикселей у нашей ленты.
#define LED_COUNT 256
// Указываем, к какому порту подключен вход ленты DIN.
#define LED_PIN 6
Adafruit_NeoPixel strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);// Создаем переменную strip для управления нашей лентой.
int k=10;//яркость свечения пикселя из 0 до 255 ступеней
int t=75;//единица длительности переключений в мс
void setup()
{
strip.begin();
pusto_ ();
}
/////////////////////////////////////////////////////
void loop()
{
for(int i=0;i<85;i++){
pusto_ ();
zifra_(i,0,1);zifra_(i-5,1,2);zifra_(i-10,2,3);zifra_(i-15,3,4);zifra_(i-20,4,5);zifra_(i-25,5,6);
zifra_(i-30,6,7);zifra_(i-35,7,1); zifra_(i-40,8,2);zifra_(i-45,9,3);
strip.show();
delay(t);
}
}
//////////////////////////////////////////////////////
Два ino.
//////////////////////////////////////////////////////
//пиксель заданного цвета по координатам
void pixel_(byte x,byte y,byte color){
if(x<32&&y<8&&color<8){
if(x%2==0){
strip.setPixelColor(y+x*8, strip.Color(k*(color%2),k*((color%4)/2),k*((color%8)/4))); //
}
else {strip.setPixelColor(7-y+x*8, strip.Color(k*(color%2),k*((color%4)/2),k*((color%8)/4)));}
}
}
/////////////////////////////////////////////////////
//стереть данные в буфере
void pusto_ (){
for(int i=0;i<LED_COUNT;i++){
strip.setPixelColor(i, strip.Color(0,0,0)); //
}
}
/////////////////////////////////////////////////////
//цифра заданного цвета по координате Х ( 5*8 пикселей)
void zifra_(int X,byte zif, byte COLOR){
//
if(zif==0){
byte zifra_0[8]={B01110,
B10001,
B10001,
B10001,
B10001,
B10001,
B10001,
B01110};
for(byte st_1=0;st_1<8;st_1++){
for(byte st_2=0;st_2<5;st_2++){
pixel_(X-st_2,7-st_1,COLOR*bitRead(zifra_0[st_1],4-st_2));
}}}
//
if(zif==1){
byte zifra_1[8]={B00100,
B01100,
B10100,
B00100,
B00100,
B00100,
B00100,
B01110};
for(byte st_1=0;st_1<8;st_1++){
for(byte st_2=0;st_2<5;st_2++){
pixel_(X-st_2,7-st_1,COLOR*bitRead(zifra_1[st_1],4-st_2));
}}}
//
if(zif==2){
byte zifra_2[8]={B01110,
B10001,
B00001,
B00001,
B01110,
B10000,
B10000,
B11111};
for(byte st_1=0;st_1<8;st_1++){
for(byte st_2=0;st_2<5;st_2++){
pixel_(X-st_2,7-st_1,COLOR*bitRead(zifra_2[st_1],4-st_2));
}}}
//
if(zif==3){
byte zifra_3[8]={B11111,
B10010,
B00100,
B01110,
B00001,
B00001,
B10001,
B01110};
for(byte st_1=0;st_1<8;st_1++){
for(byte st_2=0;st_2<5;st_2++){
pixel_(X-st_2,7-st_1,COLOR*bitRead(zifra_3[st_1],4-st_2));
}}}
//
if(zif==4){
byte zifra_4[8]={B00010,
B00110,
B01010,
B10010,
B10010,
B11111,
B00010,
B00010};
for(byte st_1=0;st_1<8;st_1++){
for(byte st_2=0;st_2<5;st_2++){
pixel_(X-st_2,7-st_1,COLOR*bitRead(zifra_4[st_1],4-st_2));
}}}
//
if(zif==5){
byte zifra_5[8]={B11111,
B10000,
B10000,
B11110,
B00001,
B00001,
B10001,
B01110};
for(byte st_1=0;st_1<8;st_1++){
for(byte st_2=0;st_2<5;st_2++){
pixel_(X-st_2,7-st_1,COLOR*bitRead(zifra_5[st_1],4-st_2));
}}}
//
if(zif==6){
byte zifra_6[8]={B01110,
B10001,
B10000,
B01110,
B10001,
B10001,
B10001,
B01110};
for(byte st_1=0;st_1<8;st_1++){
for(byte st_2=0;st_2<5;st_2++){
pixel_(X-st_2,7-st_1,COLOR*bitRead(zifra_6[st_1],4-st_2));
}}}
//
if(zif==7){
byte zifra_7[8]={B11111,
B00001,
B00001,
B00010,
B00100,
B01000,
B10000,
B10000};
for(byte st_1=0;st_1<8;st_1++){
for(byte st_2=0;st_2<5;st_2++){
pixel_(X-st_2,7-st_1,COLOR*bitRead(zifra_7[st_1],4-st_2));
}}}
//
if(zif==8){
byte zifra_8[8]={B01110,
B10001,
B10001,
B01110,
B10001,
B10001,
B10001,
B01110};
for(byte st_1=0;st_1<8;st_1++){
for(byte st_2=0;st_2<5;st_2++){
pixel_(X-st_2,7-st_1,COLOR*bitRead(zifra_8[st_1],4-st_2));
}}}
//
if(zif==9){
byte zifra_9[8]={B01110,
B10001,
B10001,
B10001,
B01110,
B00001,
B10001,
B01110};
for(byte st_1=0;st_1<8;st_1++){
for(byte st_2=0;st_2<5;st_2++){
pixel_(X-st_2,7-st_1,COLOR*bitRead(zifra_9[st_1],4-st_2));
}}}
//
}
/////////////////////////////////////////////////////

Для одноцветной матрицы примерно так:
// цифры 6x8 const uint8_t PROGMEM font_digit[] = { 0x7E, 0x85, 0x89, 0x91, 0xA1, 0x7E, // 0 0x00, 0x00, 0x41, 0xFF, 0x01, 0x00, // 1 0x43, 0x85, 0x89, 0x89, 0x89, 0x73, // 2 0x42, 0x81, 0x91, 0x91, 0x91, 0x6E, // 3 0x0C, 0x14, 0x24, 0x44, 0x84, 0xFF, // 4 0xF2, 0xA1, 0xA1, 0xA1, 0xA1, 0x9E, // 5 0x7E, 0x91, 0x91, 0x91, 0x91, 0x4E, // 6 0xC0, 0x80, 0x87, 0x88, 0x90, 0xE0, // 7 0x6E, 0x91, 0x91, 0x91, 0x91, 0x6E, // 8 0x72, 0x89, 0x89, 0x89, 0x89, 0x7E, // 9 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // space };Вывод примерно так
for (byte j = 0; j < 6; j++) { setColumn(i, pgm_read_byte(&font_digit[data[i] * 6 + j])); }setColumn - это условно, у меня метод другой, но суть такая, цифры рисуются по столбцам битовой маской: 0 - пиксель отключен, 1 - пиксель светится.
Вот как тут еще цвет пикселя задать - тут думать нужно )))
UPD: хотя чего там думать, в массиве вместо байта - массив CRGB
Стал писать функции сам
Это самое лучшее, что Вы могли сделать. Продолжайте и через некоторое время у Вас будут проблемы "что сделать", а проблем "как сделать" не будет.
Продолжайте и через некоторое время у Вас будут проблемы "что сделать", а проблем "как сделать" не будет.
и это грустно... наоборот - веселее
Вывод примерно так...
Вот и я в том же духе пробовал, так фрагмент работает и 7 рисуется:
// if(zif==7){ byte zifra_7[8]={B11111, B00001, B00001, B00010, B00100, B01000, B10000, B10000}; for(byte st_1=0;st_1<8;st_1++){ for(byte st_2=0;st_2<5;st_2++){ pixel_(X-st_2,7-st_1,COLOR*bitRead(zifra_7[st_1],4-st_2)); }}} //а так выходит китайский иероглиф и 7 "отсиметриченная" тоже проглядывается в нём:
// if(zif==7){ byte zifra_7[8] PROGMEM ={B11111, B00001, B00001, B00010, B00100, B01000, B10000, B10000}; for(byte st_1=0;st_1<8;st_1++){ for(byte st_2=0;st_2<5;st_2++){ pixel_(X-st_2,7-st_1,COLOR*bitRead(pgm_read_byte(&zifra_7[st_1]),4-st_2)); }}} //Непонятно где я обманываюсь.
Непонятно где я обманываюсь.
const byte zifra_7[8] PROGMEM ={Если PROGMEM, то константа ))
Продолжайте и через некоторое время у Вас будут проблемы "что сделать", а проблем "как сделать" не будет.
и это грустно... наоборот - веселее
Нет, это скучно, когда понимаешь что практически любая алгоритмическачкая задача решаема.
Мне кажется сам PROGMEM в таком расположении массива не работает.
Потому что такой вариант 7 рисовать не должен, а он её рисует.
// if(zif==7){ const byte PROGMEM zifra_7[8]={B11111, B00001, B00001, B00010, B00100, B01000, B10000, B10000}; for(byte st_1=0;st_1<8;st_1++){ for(byte st_2=0;st_2<5;st_2++){ pixel_(X-st_2,7-st_1,COLOR*bitRead(zifra_7[st_1],4-st_2)); }}} //Да, не работает.
Пришлось переделать к более привычному виду:
//массив цифр const byte zifra_0_9[10][8]PROGMEM ={ {B01110,//0 B10001, B10001, B10001, B10001, B10001, B10001, B01110}, {B00100,//1 B01100, B10100, B00100, B00100, B00100, B00100, B01110}, {B01110,//2 B10001, B00001, B00001, B01110, B10000, B10000, B11111}, {B11111,//3 B10010, B00100, B01110, B00001, B00001, B10001, B01110}, {B00010,//4 B00110, B01010, B10010, B10010, B11111, B00010, B00010}, {B11111,//5 B10000, B10000, B11110, B00001, B00001, B10001, B01110}, {B01110,//6 B10001, B10000, B01110, B10001, B10001, B10001, B01110}, {B11111,//7 B00001, B00001, B00010, B00100, B01000, B10000, B10000}, {B01110,//8 B10001, B10001, B01110, B10001, B10001, B10001, B01110}, {B01110,//9 B10001, B10001, B10001, B01110, B00001, B10001, B01110}}; ////////////////////////////////////////////////////// //пиксель заданного цвета по координатам void pixel_(byte x,byte y,byte color){ if(x<32&&y<8&&color<8){ if(x%2==0){ strip.setPixelColor(y+x*8, strip.Color(k*(color%2),k*((color%4)/2),k*((color%8)/4))); // } else {strip.setPixelColor(7-y+x*8, strip.Color(k*(color%2),k*((color%4)/2),k*((color%8)/4)));} } } ///////////////////////////////////////////////////// //стереть данные в буфере void pusto_ (){ for(int i=0;i<LED_COUNT;i++){ strip.setPixelColor(i, strip.Color(0,0,0)); // } } ///////////////////////////////////////////////////// //цифра заданного цвета по координатам вершины нижнего левого угла Х,Y ( 5*8 пикселей) void zifra_(int X,int Y,byte zif, byte COLOR){ if(zif>=0&&zif<10){ for(byte st_1=0;st_1<8;st_1++){ for(byte st_2=0;st_2<5;st_2++){ pixel_(X-st_2,Y+7-st_1,COLOR*bitRead(pgm_read_byte(&zifra_0_9[zif][st_1]),4-st_2)); }}} } /////////////////////////////////////////////////////А если
Не может такого быть, чтобы у всех работало, а у тебя нет ))
Да, вот в таком написании заработало.
#include <Adafruit_NeoMatrix.h> #include <Adafruit_GFX.h> #define PIN 6 Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(32, 8, PIN, NEO_MATRIX_BOTTOM + NEO_MATRIX_RIGHT + NEO_MATRIX_COLUMNS + NEO_MATRIX_ZIGZAG, NEO_GRB + NEO_KHZ800); int N=1000; void setup() { matrix.begin(); matrix.setTextWrap(false); matrix.setBrightness(10); matrix.setTextColor(matrix.Color(255, 110, 0)); } int x = matrix.width(); void loop() { matrix.fillScreen(0); matrix.setCursor(x, 0); // Отступ сверху matrix.setTextColor(matrix.Color(0, 255, 0)); matrix.print(utf8rus("С Наступающим")); matrix.setTextColor(matrix.Color(0, 255, 255)); matrix.print(utf8rus(" НОВЫМ ")); matrix.setTextColor(matrix.Color(255, 255, 255)); matrix.print(utf8rus("2023")); matrix.setTextColor(matrix.Color(255, 110, 0)); matrix.print(utf8rus(" Годом!")); if(--x < -300) { // Если показывается не весь текст, то увеличить число x = matrix.width(); } matrix.show(); // Функция показа текста delay(25); // Скорость прокрутки } /* Функция перекодировки русских букв из UTF-8 в Win-1251 */ String utf8rus(String source) { int i,k; String target; unsigned char n; char m[2] = { '0', '\0' }; k = source.length(); i = 0; while (i < k) { n = source[i]; i++; if (n >= 0xC0) { switch (n) { case 0xD0: { n = source[i]; i++; if (n == 0x81) { n = 0xA8; break; } if (n >= 0x90 && n <= 0xBF) n = n + 0x30; break; } case 0xD1: { n = source[i]; i++; if (n == 0x91) { n = 0xB8; break; } if (n >= 0x80 && n <= 0x8F) n = n + 0x70; break; } } } m[0] = n; target = target + String(m); } return target; }Запустилась таки "матрица-неопиксель". И голову теперь можно не напрягать :)
Здесь как мне кажется наиболее простое и удобное решение:
http://arduino-kid.ru/blog/adresnaya-lenta-ws2812b-beguschaya-stroka-upr...
Круто!:)
Нашёл интересный авторский алгоритм огня:
https://labdata.ru/article/algoritm-ognja-dlja-adresnyh-svetodiodnyh-matric
Имитация очень правдоподобная и имеет много настроек - можно исходный скетч развить в тему пламени, например, камина. Но я попробовал сделать его фоновым для бегущей строки. Если матовый экран от пикселей удалить на 5-10 мм вообще блеск.
// Алгоритм огня для светодиодной адресной матрицы // // Автор: Роман Исаков, 2020 // (с) LabData.ru // Параметры подключения #define PIN 6 #define x_size 32 #define y_size 8 // Параметры алгоритма #define fire_dT 20 // задержка обрабобтки модели огня в мс #define fire_loss 0.7 // коэффициент потери энергии #define fire_smooth 1.0 // Коэффициент сглаженности распределения энергии частиц #define sig 0.9 // ширина пламени #define dlt 90 // общая мощность пламени #define mlt 200 // усиление возгорания #define Hue 5 // Цвет пламени (0- красный) #define H0 0 #define H255 60 #define S0 200 #define S255 255 #define V0 0 #define V255 255 #include <Adafruit_GFX.h> #include <Adafruit_NeoMatrix.h> Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix( x_size,y_size , PIN, NEO_MATRIX_BOTTOM + NEO_MATRIX_RIGHT + NEO_MATRIX_COLUMNS + NEO_MATRIX_ZIGZAG, NEO_RGB + NEO_KHZ800); int x = matrix.width(); //Картина возгорания byte fire_frame[y_size][x_size]; //Распределение вероятностей возгорания byte fire_prob[x_size]; void setup (){ SetupMatrix(); } void loop(){ LDfire(); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Функция настройки матрицы. Поместить в setup void SetupMatrix(){ matrix.begin(); matrix.clear(); matrix.show(); Generate_Prob(sig, mlt); // Создать распределение вероятностей (форма огня) } // Сгенерировать распределение вероятностей void Generate_Prob(float sigma, int mult) { for(int i=0; i<x_size; i++){ fire_prob[i] = round(mult*(1/(sigma*2.5))*exp(-sq(i-(x_size/2))/(2*sq(sigma)))); } } // Функция реализации алгоритма огня. Поместить в loop void LDfire() { static uint32_t old_T = 0; if (millis() - old_T > fire_dT) { // отслеживание срабатывания old_T = millis(); // Цикл огня // 1. Сдвиг матрицы for (uint8_t y = y_size - 1; y >0; y--) { for (uint8_t x = 0; x < x_size; x++) { fire_frame[y][x] = fire_frame[y - 1][x]*fire_loss; } } // 2. Заполнение нижней строки псевдослучайными числами for (uint8_t x = 0; x < x_size; x++) { byte fire_old = fire_frame[0][x]; fire_frame[0][x] = round(fire_old + (random(fire_prob[x], fire_prob[x]+dlt)-fire_old)*fire_smooth); } // 3. Визуализация матрицы for (uint8_t y = 0 ; y <= y_size-1 ; y++) {//тут автор досадно допустил < , а надо <= for (uint8_t x = 0; x < x_size; x++) { matrix.drawPixel(x, y, E2Color(fire_frame[y_size-1-y][x])); } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //вставка бегущей строки matrix.setCursor(x, 0); matrix.setTextColor(matrix.Color(25, 0, 25)); matrix.print(utf8rus("В огне брода нет")); if(--x <-200) {x = matrix.width();} ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// matrix.show(); } } // Функция расчета цвета из энергии частицы uint16_t E2Color(byte E) { byte H = Hue + map(E, 0, 255, H0, H255); byte S = constrain(map(E, 0, 255, S255, S0), 0, 255); byte V = constrain(map(E, 0, 255, V0, V255), 0, 255); return HSV2Color(H,S,V); } // Функция перевода из модели HSV в код цвета. uint16_t HSV2Color(uint8_t hue, uint8_t sat, uint8_t val) { uint8_t red, green, blue; byte h = ((24 * hue / 17) / 60) % 6; byte vmin = (long)val - val * sat / 255; byte a = (long)val * sat / 255 * (hue * 24 / 17 % 60) / 60; byte vinc = vmin + a; byte vdec = val - a; switch (h) { case 0: red = val; green = vinc; blue = vmin; break; case 1: red = vdec; green = val; blue = vmin; break; case 2: red = vmin; green = val; blue = vinc; break; case 3: red = vmin; green = vdec; blue = val; break; case 4: red = vinc; green = vmin; blue = val; break; case 5: red = val; green = vmin; blue = vdec; break; } return matrix.Color(green,red,blue); } ////////////////////////////////////////////////////////////////////////////////// // Функция перекодировки русских букв из UTF-8 в Win-1251 String utf8rus(String source) { int i,k; String target; unsigned char n; char m[2] = { '0', '\0' }; k = source.length(); i = 0; while (i < k) { n = source[i]; i++; if (n >= 0xC0) { switch (n) { case 0xD0: { n = source[i]; i++; if (n == 0x81) { n = 0xA8; break; } if (n >= 0x90 && n <= 0xBF) n = n + 0x30; break; } case 0xD1: { n = source[i]; i++; if (n == 0x91) { n = 0xB8; break; } if (n >= 0x80 && n <= 0x8F) n = n + 0x70; break; } } } m[0] = n; target = target + String(m); } return target; } //////////////////////////////////////////////////////////////////////////////////PS Почему теперь нельзя вставить гифку больше 1 Мб?
Нет случайно ни у кого подобных алгоритмов водопада, восхода или заката :)
:)
Долго думал чего у Гайвера, а соответственно и у остального мира нет, и понял - генератора пиксельного орнамента на симметрии четверти:
Если с генерацией всё ясно, то с анимацией не очень. Орнамент можно двигать влево-вправо (что я и сделал), калейдоскопить - вращая четверть (думаю, что сделаю). А ещё что можно изобрести?
солярные знаки можно вращать (посолонь и противосолонь)
ЗЫ я застал время когда такие пиротехнические эффекты еще строили
:)
Долго думал чего у Гайвера, а соответственно и у остального мира нет, и понял - генератора пиксельного орнамента
у гайвера есть все
:)
Эпично!, красиво.
Это около 16 матриц 8*32. Уно, нано не смогёт. Но явно не генератор орнамента, а картинки. А у Гайвера... я с этим сравнивал:
https://alexgyver.ru/gyvermatrixos-guide/
раздел "эффекты и режимы"
красота то какая...
Это около 16 матриц 8*32.
это одна 64х64
А что за тип?, уно-нано-(библиотеки) тянут (есть)? :)
А что за тип?, уно-нано-(библиотеки) тянут (есть)? :)
так это те же матрицы, что я вам показывал когда вы разные шкалы рисовали на ОЛЕД дисплее, помните?
https://arduino.ru/forum/proekty/imitatsiya-razlichnykh-shkal-na-displee...
Библиотека (поддерживает стм32 блюпилы и блекпилы)
А про орнаменты найдите мою статейку на гайверофоруме (ник такой же как тут) - я там рассказываю как рисовал эту заставку с птицами для часов (сообщение 18). Дал бы ссылку, да у меня с работы Гайвер закрыт
... когда вы разные шкалы рисовали на ОЛЕД дисплее, помните?
Вспомнил, там же у меня было 128*64 :)
Вспомнил, там же у меня было 128*64 :)
у меня их много разных, от 32х16 до 128х64
Библиотека (поддерживает стм32 блюпилы и блекпилы)
Не понял, а чё ... за коней топим?
Не понял, а чё ... за коней топим?
ой ее.... попал :)
теперь поздно оправдываться что картинко не мое :)
Узорю дальше, сделал зеркальные отражения, ещё в природе есть поворот на 90гр., вопрос: а ещё что то есть?
Не понял, а чё ... за коней топим?
Последняя игра чемпионата СССР, которую смотрел на стадионе.
Холодные сырые деревянные лавки, польский плащ болотного цвета на тощем студенте, на голове дурацкая "тирольская" шляпа. В заднем кармане джинсов 20 чеков Внашпосылторга и 7р. с мелочью, а в карманчике рубашки повестка в армию, которую только-что вручили. Домой только завтра, предкам сообщать. Настроение прескверное, а тут еще мясо запыленщиков ипет.
В армию осенью не взяли, перебор, ушел весной 1984. А вернулся - под "Шахтером" радиорынок, синклеры, память, логика 155ая на разлив..