Мини матрица 16х16 ws2812b

может и так будет работать, но в моей библии по ардуино я почему то такой пример оставил…

#include <FastLED.h>
#define NUM_LEDS 50
#define PIN 6
#define COLOR_ORDER RGB
CRGB leds[NUM_LEDS];

void setup() {
FastLED.addLeds<WS2811, PIN>(leds, NUM_LEDS);
FastLED.setBrightness(255);
}

void loop() {
leds[0] = CRGB(0, 255, 0);
leds[0].fadeLightBy(250);
FastLED.show();
delay(1000);
leds[0] = CRGB(0, 255, 0);
leds[0].fadeLightBy(25);
FastLED.show();
delay(1000);
}

может пригодится…

Ну, дык, у вас про яркость и скучно :slightly_smiling_face: Вот веселее:

#include "FastLED.h" // подключаем библиотеку фастлед

#define PIN A0
#define Width  8
#define Height  8
#define NUM_LEDS (Width * Height)
CRGB leds[NUM_LEDS];

void setup() {
  FastLED.addLeds <WS2812, PIN, GRB>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
}

void loop() {
  fadeToBlackBy(leds, NUM_LEDS, 40);
  int pos = random(NUM_LEDS);
  leds[pos] += CHSV(random(), 255, random());
  FastLED.show();
  delay(200);
}
1 лайк

lilik а у вас много времени свободного ?)))

https://vk.com/wall-104993817_739

вроде повторить реально, на ардуино, а может и нет…
если заинтересует, может сделаете…
инструкция как картинки такие как делать через фотошоп вроде есть в сети…

возможно… сейчас не могу проверить)))

Оно и без ардуино интересно…для детей, но дети выросли, а до внуков дело не дошло ещё.

ооо работает, и тоже прикольно))) а не подскажите как сию магию применить на скетче лелика ?))) или на похожем если там не отслеживается каждый диод…

а в качестве какой то анимации для дисплея из за долго обновления потом не получится задействовать ? будет еще один инструмент, в который надо будет вникать)))

так там же рандом задает яркость…

byte M=255;//мощность свечения
//if(millis()%5==0){massiv_kolzo[0]=random(0,8);}
//if(millis()%5==1){massiv_kolzo[0]=0;}
и будут все светиться на полную просто... или я не понял о чем вы)))
if(millis()%5==0){massiv_kolzo[0]=random(0,8);}
//if(millis()%5==1){massiv_kolzo[0]=0;}
возможно так...

Об этом:

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

Получил матрицу 8х8, попробовал вариант скетча без библиотеки. Теперь всё нормально показывает с динамической памятью, при попытке включения 1000 пикселей пишет ошибку, как и надо. В случае узоров конечно можно попробовать сделать без буфера. В общем случае это очень трудно, иначе уже бы сделали в мире.

Спойлер
/////////////////////////////////////
/// примеры для ws2812b матрица
////////////////////////////////////
#define line_ 64 //число пикселей в ленте
uint8_t dataPin = 6;// вывод для подключения
byte buffer_[3 * line_]; //массив данных по цветам пикселей матрицы-ленты



///RGB
void setup() {
  WS2812bOut(dataPin, 0 , 0 , 0 ); //строка не нужная, но без неё не компилируется
  pusto_buf();
  buf_ris();
}
void loop() {
  for (int i = 0; i < line_; i++) { //бегущий огонёк жёлтый
    cvet_pixel(i, 5, 5, 0);
    buf_ris();
    delay(50);
    pusto_buf();
  }

}
//////////////////////////////////////
void cvet_pixel(int N, byte R, byte G, byte B) {
  buffer_[3 * N] = R; buffer_[3 * N + 1] = G; buffer_[3 * N + 2] = B;
}
//////////////////////////////////////
void pusto_buf() { //очистка матрицы-ленты
  for (int ni = 0; ni < 3 * line_; ni++) {
    buffer_[ni] = 0;
  }

}
//////////////////////////////////////
void buf_ris() { // вывод данных по цветам пикселей на матрицу-ленту
  for (int ni = 0; ni < 3 * line_; ni = ni + 3) { //перебор номеров пикселей в ленте
    WS2812bOut(dataPin, buffer_[ni] , buffer_[ni + 1] , buffer_[ni + 2] ); //функция вывода данных цвета для текущего номера пикселя
  }
}
//////////////////////////////////////
//функция вывода цвета пикселя
/////////////////////////////////////////////////////////////////////////////////////////////////
static void WS2812bOut(const uint8_t _dataPin, uint8_t R, uint8_t G, uint8_t B )  {
  uint8_t _data[] = {G, R, B}; uint16_t _dataSize = 3;
  volatile uint8_t hi, lo, next, currentByte, currentBit = 0x08, *port, *ptrData = _data;
  uint8_t pinMask;

  digitalWrite(_dataPin, LOW);
  pinMode(_dataPin, OUTPUT);

  port    = portOutputRegister(digitalPinToPort(_dataPin));
  pinMask = digitalPinToBitMask(_dataPin);

  currentByte = *ptrData++;


  hi = *port |  pinMask;
  lo = *port & ~pinMask;
  next = lo;

  noInterrupts();
  asm volatile (
    "head20:"                   "\n\t" // Clk  Pseudocode    (T =  0)
    "st   %a[port],  %[hi]"    "\n\t" // 2    PORT = hi     (T =  2)
    "sbrc %[byte],  7"         "\n\t" // 1-2  if(b & 128)
    "mov  %[next], %[hi]"     "\n\t" // 0-1   next = hi    (T =  4)
    "dec  %[bit]"              "\n\t" // 1    bit--         (T =  5)
    "st   %a[port],  %[next]"  "\n\t" // 2    PORT = next   (T =  7)
    "mov  %[next] ,  %[lo]"    "\n\t" // 1    next = lo     (T =  8)
    "breq nextbyte20"          "\n\t" // 1-2  if(bit == 0) (from dec above)
    "rol  %[byte]"             "\n\t" // 1    b <<= 1       (T = 10)
    "rjmp .+0"                 "\n\t" // 2    nop nop       (T = 12)
    "nop"                      "\n\t" // 1    nop           (T = 13)
    "st   %a[port],  %[lo]"    "\n\t" // 2    PORT = lo     (T = 15)
    "nop"                      "\n\t" // 1    nop           (T = 16)
    "rjmp .+0"                 "\n\t" // 2    nop nop       (T = 18)
    "rjmp head20"              "\n\t" // 2    -> head20 (next bit out)
    "nextbyte20:"               "\n\t" //                    (T = 10)
    "ldi  %[bit]  ,  8"        "\n\t" // 1    bit = 8       (T = 11)
    "ld   %[byte] ,  %a[ptr]+" "\n\t" // 2    b = *ptr++    (T = 13)
    "st   %a[port], %[lo]"     "\n\t" // 2    PORT = lo     (T = 15)
    "nop"                      "\n\t" // 1    nop           (T = 16)
    "sbiw %[count], 1"         "\n\t" // 2    i--           (T = 18)
    "brne head20"             "\n"   // 2    if(i != 0) -> (next byte)
    : [port]  "+e" (port),
    [byte]  "+r" (currentByte),
    [bit]   "+r" (currentBit),
    [next]  "+r" (next),
    [count] "+w" (_dataSize)
    : [ptr]    "e" (ptrData),
    [hi]     "r" (hi),
    [lo]     "r" (lo)
  );
  interrupts();
}
///////////////////////////////////////////////////////


1 лайк

Вот вариант генератора узоров без библиотеки, но с буфером.
…теперь генерация гораздо приятнее.

Спойлер
/////////////////////////////////////
// примеры для ws2812b
//Arduino UNO

#define line_ 256 //число пикселей в ленте
uint8_t dataPin = 6;// вывод для подключения
byte buffer_[3 * line_]; //массив данных по цветам пикселей матрицы-ленты
byte M = 2; //мощность свечения


const byte massiv_per3[32][8] PROGMEM = { {204, 187, 195, 180, 68, 51, 75, 60}, //1
  {203, 188, 196, 179, 67, 52, 76, 59}, //2
  {202, 189, 197, 178, 66, 53, 77, 58}, //3
  {205, 186, 194, 181, 69, 50, 74, 61}, //4
  {221, 170, 165, 210, 85, 34, 45, 90}, //5
  {171, 220, 164, 211, 84, 35, 44, 91}, //6
  {172, 219, 163, 212, 83, 36, 43, 92}, //7
  {218, 173, 213, 162, 82, 37, 93, 42}, //8
  {217, 174, 214, 161, 81, 38, 41, 94}, //9
  {190, 201, 198, 177, 65, 54, 57, 78}, //10
  {206, 185, 182, 193, 70, 49, 73, 62}, //11
  {222, 169, 166, 209, 86, 33, 89, 46}, //12
  {238, 153, 150, 225, 102, 17, 105, 30}, //13
  {237, 154, 149, 226, 101, 18, 29, 106}, //14
  {236, 155, 148, 227, 100, 19, 28, 107}, //15
  {235, 156, 147, 228, 99, 20, 27, 108}, //16
  {234, 157, 229, 146, 98, 21, 26, 109}, //17
  {233, 158, 230, 145, 97, 22, 25, 110}, //18
  {232, 159, 231, 144, 96, 23, 24, 111}, //19
  {216, 175, 215, 160, 80, 39, 40, 95}, //20
  {200, 191, 199, 176, 64, 55, 56, 79}, //21
  {184, 207, 183, 192, 48, 71, 72, 63}, //22
  {168, 223, 167, 208, 32, 87, 88, 47}, //23
  {239, 152, 151, 224, 16, 103, 104, 31}, //24
  {255, 136, 135, 240, 119, 0, 15, 120}, //25
  {254, 137, 241, 134, 1, 118, 121, 14}, //26
  {253, 138, 242, 133, 117, 2, 13, 122}, //27
  {252, 139, 243, 132, 116, 3, 12, 123}, //28
  {251, 140, 244, 131, 115, 4, 11, 124}, //29
  {250, 141, 245, 130, 114, 5, 10, 125}, //30
  {249, 142, 246, 129, 113, 6, 9, 126}, //31
  {248, 143, 247, 128, 112, 7, 8, 127} //32
};
byte massiv_kolzo3[32] = {1, 2, 2, 2, 0, 0, 0, 0, 6, 6, 5, 6, 0, 0, 0, 4, 5, 6, 7, 2, 0, 0, 0, 0, 6, 6, 5, 6, 0, 7, 7, 6}; // начальный набор цветов
const byte massiv_per[28][8]PROGMEM = { {248, 247, 128, 112, 7, 8, 127, 143}, //1
  {249, 246, 144, 96, 6, 9, 111, 159}, //2
  {250, 245, 160, 80, 5, 10, 95, 175}, //3
  {251, 244, 176, 64, 4, 11, 79, 191}, //4
  {252, 243, 192, 48, 3, 12, 63, 207}, //5
  {253, 242, 208, 32, 2, 13, 47, 223}, //6
  {254, 241, 224, 16, 1, 14, 31, 239}, //7
  {237, 226, 209, 33, 18, 29, 46, 222}, //8
  {236, 227, 193, 49, 19, 28, 62, 206}, //9
  {235, 228, 177, 65, 20, 27, 78, 190}, //10
  {234, 229, 161, 81, 21, 26, 94, 174}, //11
  {233, 230, 145, 97, 22, 25, 110, 158}, //12
  {232, 231, 129, 113, 23, 24, 126, 142}, //13
  {216, 215, 130, 114, 39, 40, 125, 141}, //14
  {217, 214, 146, 98, 38, 41, 109, 157}, //15
  {218, 213, 162, 82, 37, 42, 93, 173}, //16
  {219, 212, 178, 66, 36, 43, 77, 189}, //17
  {220, 211, 194, 50, 35, 44, 61, 205}, //18
  {203, 196, 179, 67, 52, 59, 76, 188}, //19
  {202, 197, 163, 83, 53, 58, 92, 172}, //20
  {201, 198, 147, 99, 54, 57, 108, 156}, //21
  {200, 199, 131, 115, 55, 56, 124, 140}, //22
  {184, 183, 132, 116, 71, 72, 123, 139}, //23
  {185, 182, 148, 100, 70, 73, 107, 155}, //24
  {186, 181, 164, 84, 69, 74, 91, 171}, //25
  {169, 166, 149, 101, 86, 89, 106, 154}, //26
  {168, 167, 133, 117, 87, 88, 122, 138}, //27
  {152, 151, 134, 118, 103, 104, 121, 137} //28
};
byte massiv_kolzo[28] = {1, 2, 2, 2, 0, 0, 0, 0, 6, 6, 5, 6, 0, 0, 0, 4, 5, 6, 7, 2, 0, 0, 0, 0, 6, 6, 5, 6}; // начальный набор цветов
const byte massiv_per2[4][64]PROGMEM = {{120, 121, 137, 153, 169, 168, 167, 166, 165, 164, 148, 132, 116, 100, 84, 68, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 77, 93, 109, 125, 141, 157, 173, 189, 205, 221, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 208, 192, 176, 160, 144, 128, 112, 96, 80, 64, 48, 32, 16, 0}, //1
  {135, 134, 118, 102, 86, 87, 88, 89, 90, 91, 107, 123, 139, 155, 171, 187, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, 178, 162, 146, 130, 114, 98, 82, 66, 50, 34, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 47, 63, 79, 95, 111, 127, 143, 159, 175, 191, 207, 223, 239, 255}, //2
  {136, 152, 151, 150, 149, 133, 117, 101, 85, 69, 70, 71, 72, 73, 74, 75, 76, 92, 108, 124, 140, 156, 172, 188, 204, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, 193, 177, 161, 145, 129, 113, 97, 81, 65, 49, 33, 17, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, //3
  {119, 103, 104, 105, 106, 122, 138, 154, 170, 186, 185, 184, 183, 182, 181, 180, 179, 163, 147, 131, 115, 99, 83, 67, 51, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 62, 78, 94, 110, 126, 142, 158, 174, 190, 206, 222, 238, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240}, //4

};
byte massiv_kolzo2[64] = {0, 0, 0, 0, 1, 1, 1, 1, 3, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 5, 5, 5, 5, 7, 7, 7, 7, 0, 0, 0, 0, 6, 6, 6, 6, 4, 4, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 5, 5, 5, 5, 0, 0, 0, 0}; // начальный набор цветов фрагмента
const byte massiv_per1[16][16]PROGMEM = {{207, 199, 71, 79, 251, 243, 115, 123, 184, 176, 48, 56, 140, 132, 4, 12}, //1
  {223, 215, 87, 95, 250, 242, 114, 122, 168, 160, 32, 40, 141, 133, 5, 13}, //2
  {206, 198, 70, 78, 235, 227, 99, 107, 185, 177, 49, 57, 156, 148, 20, 28}, //3
  {205, 197, 69, 77, 219, 211, 83, 91, 186, 178, 50, 58, 172, 164, 36, 44}, //4
  {222, 214, 86, 94, 234, 226, 98, 106, 169, 161, 33, 41, 157, 149, 21, 29}, //5
  {239, 231, 103, 111, 249, 241, 113, 121, 152, 144, 16, 24, 142, 134, 6, 14}, //6
  {255, 248, 119, 127, 247, 240, 112, 120, 136, 128, 0, 8, 143, 135, 7, 15}, //7
  {238, 230, 102, 110, 233, 225, 97, 105, 153, 145, 17, 25, 158, 150, 22, 30}, //8
  {221, 213, 85, 93, 218, 210, 82, 90, 170, 162, 34, 42, 173, 165, 37, 45}, //9
  {204, 196, 68, 76, 203, 195, 67, 75, 187, 179, 51, 59, 188, 180, 52, 60}, //10
  {220, 212, 84, 92, 202, 194, 66, 74, 171, 163, 35, 43, 189, 181, 53, 61}, //11
  {237, 229, 101, 109, 217, 209, 81, 89, 154, 146, 18, 26, 174, 166, 38, 46}, //12
  {254, 246, 118, 126, 232, 224, 96, 104, 137, 129, 1, 9, 159, 151, 23, 31}, //13
  {253, 245, 117, 125, 216, 208, 80, 88, 138, 130, 2, 10, 175, 167, 39, 47}, //14
  {236, 228, 100, 108, 201, 193, 65, 73, 155, 147, 19, 27, 190, 182, 54, 62}, //15
  {252, 244, 116, 124, 200, 192, 64, 72, 139, 131, 3, 11, 191, 183, 55, 63}, //16
};
byte massiv_kolzo1[16] = {2, 2, 2, 2, 0, 0, 0, 0, 6, 6, 5, 6, 0, 0, 0, 0}; // начальный набор цветов
long Y = 0; //
byte FL = 0; //
///RGB
void setup() {
  WS2812bOut(dataPin, 0 , 0 , 0 ); //строка не нужная, но без неё не компилируется
  pusto_buf();
  buf_ris();

}
void loop() {

  if (millis() - Y > 10000) {
    Y = millis();
    FL++;
    if (FL > 3) {
      FL = 0;
    }
  }
  if (FL == 0) {
    fun_1();
  }
  if (FL == 1) {
    fun_2();
  }
  if (FL == 2) {
    fun_3();
  }
  if (FL == 3) {
    fun_4();
  }

}
/////////////////////////////////////
void gruppa3(byte n, byte cv) {
  for (int in = 0; in < 8; in++) {
    cvet_pixel(pgm_read_byte(*massiv_per3 + 8 * n + in), (cv % 2)*M, ((cv / 2) % 2)*M , ((cv / 4) % 2)*M );
  }

}
/////////////////////////////////////
void kolzo3() {
  byte V = 0;
  for (int in = 0; in < 32; in++) {
    if (in != 0 && in != 31) {
      massiv_kolzo3[in] = massiv_kolzo3[in + 1];
    }
    if (in == 0) {
      V = massiv_kolzo3[in];
      massiv_kolzo3[0] = massiv_kolzo3[1];
    }
    if (in == 31) {
      massiv_kolzo3[in] = V;
    }
  }
}
/////////////////////////////////////
void fun_4() {
  for (int i = 0; i < 32; i++) {
    gruppa3(i, massiv_kolzo3[i]);
  }
  buf_ris();
  delay(100);//быстрота смены узора
  kolzo3();
  if (millis() % 5 == 0) {
    massiv_kolzo3[0] = random(0, 8);
  }
  if (millis() % 5 == 1) {
    massiv_kolzo3[0] = 0;
  }
}
/////////////////////////////////////
void gruppa(byte n, byte cv) {
  for (int in = 0; in < 8; in++) {
    cvet_pixel(pgm_read_byte(*massiv_per + 8 * n + in), (cv % 2)*M, ((cv / 2) % 2)*M , ((cv / 4) % 2)*M);
  }

}
/////////////////////////////////////
void kolzo() {
  byte V = 0;
  for (int in = 0; in < 28; in++) {
    if (in != 0 && in != 27) {
      massiv_kolzo[in] = massiv_kolzo[in + 1];
    }
    if (in == 0) {
      V = massiv_kolzo[in];
      massiv_kolzo[0] = massiv_kolzo[1];
    }
    if (in == 27) {
      massiv_kolzo[in] = V;
    }
  }
}
/////////////////////////////////////
void fun_2() {
  for (int i = 0; i < 28; i++) {
    gruppa(i, massiv_kolzo[i]);
  }
  buf_ris();
  delay(200);//быстрота смены узора
  kolzo();
  if (millis() % 5 == 0) {
    massiv_kolzo[0] = random(0, 8);
  }
  if (millis() % 5 == 1) {
    massiv_kolzo[0] = 0;
  }
}
////////////////////////////////////
void gruppa2(byte n, byte cv) {
  for (int in = 0; in < 4; in++) {
    cvet_pixel(pgm_read_byte(*massiv_per2 + 64 * in + n), (cv % 2)*M, ((cv / 2) % 2)*M , ((cv / 4) % 2)*M );
  }

}
/////////////////////////////////////
void kolzo2() {
  byte V = 0;
  for (int in = 0; in < 64; in++) {
    if (in != 0 && in != 63) {
      massiv_kolzo2[in] = massiv_kolzo2[in + 1];
    }
    if (in == 0) {
      V = massiv_kolzo2[in];
      massiv_kolzo2[0] = massiv_kolzo2[1];
    }
    if (in == 63) {
      massiv_kolzo2[in] = V;
    }
  }
}
/////////////////////////////////////
void fun_1() {
  for (int i = 0; i < 64; i++) {
    gruppa2(i, massiv_kolzo2[i]);
  }
  buf_ris();
  delay(75);//быстрота смены узора
  kolzo2();
  if (millis() % 5 == 0) {
    massiv_kolzo2[0] = random(0, 8);
  }
  if (millis() % 5 == 1) {
    massiv_kolzo2[0] = 0;
  }
}
/////////////////////////////////////
void gruppa1(byte n, byte cv) {
  for (int in = 0; in < 16; in++) {
    cvet_pixel(pgm_read_byte(*massiv_per1 + 16 * n + in), (cv % 2)*M, ((cv / 2) % 2)*M , ((cv / 4) % 2)*M );
  }

}
/////////////////////////////////////
void kolzo1() {
  byte V = 0;
  for (int in = 0; in < 16; in++) {
    if (in != 0 && in != 15) {
      massiv_kolzo1[in] = massiv_kolzo1[in + 1];
    }
    if (in == 0) {
      V = massiv_kolzo1[in];
      massiv_kolzo1[0] = massiv_kolzo1[1];
    }
    if (in == 15) {
      massiv_kolzo1[in] = V;
    }
  }
}
/////////////////////////////////////
void fun_3() {
  for (int i = 0; i < 16; i++) {
    gruppa1(i, massiv_kolzo1[i]);
  }
  buf_ris();
  delay(200);//быстрота смены узора
  kolzo1();
  if (millis() % 5 == 0) {
    massiv_kolzo1[0] = random(0, 8);
  }
  if (millis() % 5 == 1) {
    massiv_kolzo1[0] = 0;
  }
}
//////////////////////////////////////
void cvet_pixel(int N, byte R, byte G, byte B) {//внесение данных по цвету пикселя энного
  buffer_[3 * N] = R; buffer_[3 * N + 1] = G; buffer_[3 * N + 2] = B;
}
//////////////////////////////////////
void pusto_buf() { //очистка матрицы-ленты
  for (int ni = 0; ni < 3 * line_; ni++) {
    buffer_[ni] = 0;
  }

}
//////////////////////////////////////
void buf_ris() { // вывод данных по цветам пикселей на матрицу-ленту
  for (int ni = 0; ni < 3 * line_; ni = ni + 3) { //перебор номеров пикселей в ленте
    WS2812bOut(dataPin, buffer_[ni] , buffer_[ni + 1] , buffer_[ni + 2] ); //функция вывода данных цвета для текущего номера пикселя
  }
}
//////////////////////////////////////
//функция вывода цвета пикселя
/////////////////////////////////////////////////////////////////////////////////////////////////
static void WS2812bOut(const uint8_t _dataPin, uint8_t R, uint8_t G, uint8_t B )  {
  uint8_t _data[] = {G, R, B}; uint16_t _dataSize = 3;
  volatile uint8_t hi, lo, next, currentByte, currentBit = 0x08, *port, *ptrData = _data;
  uint8_t pinMask;

  digitalWrite(_dataPin, LOW);
  pinMode(_dataPin, OUTPUT);

  port    = portOutputRegister(digitalPinToPort(_dataPin));
  pinMask = digitalPinToBitMask(_dataPin);

  currentByte = *ptrData++;


  hi = *port |  pinMask;
  lo = *port & ~pinMask;
  next = lo;

  noInterrupts();
  asm volatile (
    "head20:"                   "\n\t" // Clk  Pseudocode    (T =  0)
    "st   %a[port],  %[hi]"    "\n\t" // 2    PORT = hi     (T =  2)
    "sbrc %[byte],  7"         "\n\t" // 1-2  if(b & 128)
    "mov  %[next], %[hi]"     "\n\t" // 0-1   next = hi    (T =  4)
    "dec  %[bit]"              "\n\t" // 1    bit--         (T =  5)
    "st   %a[port],  %[next]"  "\n\t" // 2    PORT = next   (T =  7)
    "mov  %[next] ,  %[lo]"    "\n\t" // 1    next = lo     (T =  8)
    "breq nextbyte20"          "\n\t" // 1-2  if(bit == 0) (from dec above)
    "rol  %[byte]"             "\n\t" // 1    b <<= 1       (T = 10)
    "rjmp .+0"                 "\n\t" // 2    nop nop       (T = 12)
    "nop"                      "\n\t" // 1    nop           (T = 13)
    "st   %a[port],  %[lo]"    "\n\t" // 2    PORT = lo     (T = 15)
    "nop"                      "\n\t" // 1    nop           (T = 16)
    "rjmp .+0"                 "\n\t" // 2    nop nop       (T = 18)
    "rjmp head20"              "\n\t" // 2    -> head20 (next bit out)
    "nextbyte20:"               "\n\t" //                    (T = 10)
    "ldi  %[bit]  ,  8"        "\n\t" // 1    bit = 8       (T = 11)
    "ld   %[byte] ,  %a[ptr]+" "\n\t" // 2    b = *ptr++    (T = 13)
    "st   %a[port], %[lo]"     "\n\t" // 2    PORT = lo     (T = 15)
    "nop"                      "\n\t" // 1    nop           (T = 16)
    "sbiw %[count], 1"         "\n\t" // 2    i--           (T = 18)
    "brne head20"             "\n"   // 2    if(i != 0) -> (next byte)
    : [port]  "+e" (port),
    [byte]  "+r" (currentByte),
    [bit]   "+r" (currentBit),
    [next]  "+r" (next),
    [count] "+w" (_dataSize)
    : [ptr]    "e" (ptrData),
    [hi]     "r" (hi),
    [lo]     "r" (lo)
  );
  interrupts();
}
///////////////////////////////////////////////////////


и ресурс в 55 % динамической памяти реален.

1 лайк

Напомню, что писал Логик на старом форуме:

Не. SPI там без толку юзать. Слишком импульсы короткие. Ни прерывания ни “подключить буферы в SPI” непоможит. На длительностях 350-800нсек имеем считаные такты. И они посчитаны что у меня, что в Фастледе. Тут только асм, только хард :wink: А SPI только откусит аппаратную часть под то, что и без неё работает с теми же свойствами - блокирующий вызов на все время записи в ленту.

Однако путь к поддержке дохрена светодиодов никак не закрыт. В А похвалимся художественной самодеятельностю на WS2812? | Аппаратная платформа Arduino рабочий пример. Основывается на идее определения цвета каждого светодиода в паузе после записи в предыдущий. Соответственно буфер становится не нужен, нет и ограничения на кол-во светодиодов. В примере определение цвета в void GetColor(word n, word t) делается. Надо только помнить о ограничении времени её выполнения. В даташите пишут “RES low voltage time Above 50µs” это время превышать нельзя. На самом деле даже хуже, моя лента не дает делать паузу более 10мксек, но я и в 2мксек успеваю делать GetColor. Получается чтоб поддерживать 100500 светодиодов надо: 1. Немного перевернуть мозги, чтоб уметь кодить эффекты ленты как функцию от номера светодиода и времени 2. Уметь писать быстрый код, который до 10мксек (а может и быстрей) реализовывал бы п.1

ПС. Хочу свою поделку на WS2812 из той темы переписать на новый подход, но времени нет руки не доходят. А сейчас - так вобще. Каникулы, бля! Отогнать малого от компа - нереально. Да и куча других забот. Вобщем дерзайте сами! Пока :wink:

Ранее я делал вариант по его 2 пунктам. Теперь удалось реализовать его замысел на примере генерации узоров.

Спойлер
/////////////////////////////////////
// примеры для ws2812b
//Arduino UNO

#include "Adafruit_NeoPixel.h"

#define line_ 256 //число пикселей в ленте
uint8_t dataPin = 6;// вывод для подключения
byte M = 2; //мощность свечения
byte cv=0;//
const byte massiv_per2[256]PROGMEM ={0,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0,
                                     1,15,27,26,25,24,23,22,21,20,19,18,17,16,15,14,
                                     2,16,28,38,37,36,35,34,33,32,31,30,29,28,27,13,
                                     3,17,29,39,47,46,45,44,43,42,41,40,39,38,26,12,
                                     4,18,30,40,48,54,53,52,51,50,49,48,47,37,25,11,
                                     5,19,31,41,49,55,59,58,57,56,55,54,46,36,24,10,
                                     6,20,32,42,50,56,60,62,61,60,59,53,45,35,23,9,
                                     7,21,33,43,51,57,61,63,63,62,58,52,44,34,22,8,
                                     8,22,34,44,52,58,62,63,63,61,57,51,43,33,21,7,
                                     9,23,35,45,53,59,60,61,62,60,56,50,42,32,20,6,
                                     10,24,36,46,54,55,56,57,58,59,55,49,41,31,19,5,
                                     11,25,37,47,48,49,50,51,52,53,54,48,40,30,18,4,
                                     12,26,38,39,40,41,42,43,44,45,46,47,39,29,17,3,
                                     13,27,28,29,30,31,32,33,34,35,36,37,38,28,16,2,
                                     14,15,16,17,18,19,20,21,22,23,24,25,26,27,15,1,
                                     0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,0
  }; 

byte massiv_kolzo2[64] = {0, 0, 0, 0, 1, 1, 1, 1, 3, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 5, 5, 5, 5, 7, 7, 7, 7, 0, 0, 0, 0, 6, 6, 6, 6, 4, 4, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 5, 5, 5, 5, 0, 0, 0, 0}; // начальный набор цветов фрагмента
///RGB
void setup() {
 WS2812bOut(dataPin, 0 , 0 , 0 ); //строка не нужная, но без неё не компилируется
}
void loop() {
  for (int i = 0; i <line_; i++) {
  cv = massiv_kolzo2[pgm_read_byte(massiv_per2+i)];  
  WS2812bOut(dataPin,(cv % 2)*M, ((cv / 2) % 2)*M , ((cv / 4) % 2)*M );
   }
 delay(75);//быстрота смены узора
//  
  kolzo2();
  if (millis() % 5 == 0) {
    massiv_kolzo2[0] = random(0, 8);
  }
  if (millis() % 5 == 1) {
    massiv_kolzo2[0] = 0;
  }
}
/////////////////////////////////////
void kolzo2() {
  byte V = 0;
  for (int in = 0; in < 64; in++) {
    if (in != 0 && in != 63) {
      massiv_kolzo2[in] = massiv_kolzo2[in + 1];
    }
    if (in == 0) {
      V = massiv_kolzo2[in];
      massiv_kolzo2[0] = massiv_kolzo2[1];
    }
    if (in == 63) {
      massiv_kolzo2[in] = V;
    }
  }
}
/////////////////////////////////////
//////////////////////////////////////
//функция вывода цвета пикселя
/////////////////////////////////////////////////////////////////////////////////////////////////
static void WS2812bOut(const uint8_t _dataPin, uint8_t R, uint8_t G, uint8_t B )  {
  uint8_t _data[] = {G, R, B}; uint16_t _dataSize = 3;
  volatile uint8_t hi, lo, next, currentByte, currentBit = 0x08, *port, *ptrData = _data;
  uint8_t pinMask;

  digitalWrite(_dataPin, LOW);
  pinMode(_dataPin, OUTPUT);

  port    = portOutputRegister(digitalPinToPort(_dataPin));
  pinMask = digitalPinToBitMask(_dataPin);

  currentByte = *ptrData++;


  hi = *port |  pinMask;
  lo = *port & ~pinMask;
  next = lo;

  noInterrupts();
  asm volatile (
    "head20:"                   "\n\t" // Clk  Pseudocode    (T =  0)
    "st   %a[port],  %[hi]"    "\n\t" // 2    PORT = hi     (T =  2)
    "sbrc %[byte],  7"         "\n\t" // 1-2  if(b & 128)
    "mov  %[next], %[hi]"     "\n\t" // 0-1   next = hi    (T =  4)
    "dec  %[bit]"              "\n\t" // 1    bit--         (T =  5)
    "st   %a[port],  %[next]"  "\n\t" // 2    PORT = next   (T =  7)
    "mov  %[next] ,  %[lo]"    "\n\t" // 1    next = lo     (T =  8)
    "breq nextbyte20"          "\n\t" // 1-2  if(bit == 0) (from dec above)
    "rol  %[byte]"             "\n\t" // 1    b <<= 1       (T = 10)
    "rjmp .+0"                 "\n\t" // 2    nop nop       (T = 12)
    "nop"                      "\n\t" // 1    nop           (T = 13)
    "st   %a[port],  %[lo]"    "\n\t" // 2    PORT = lo     (T = 15)
    "nop"                      "\n\t" // 1    nop           (T = 16)
    "rjmp .+0"                 "\n\t" // 2    nop nop       (T = 18)
    "rjmp head20"              "\n\t" // 2    -> head20 (next bit out)
    "nextbyte20:"               "\n\t" //                    (T = 10)
    "ldi  %[bit]  ,  8"        "\n\t" // 1    bit = 8       (T = 11)
    "ld   %[byte] ,  %a[ptr]+" "\n\t" // 2    b = *ptr++    (T = 13)
    "st   %a[port], %[lo]"     "\n\t" // 2    PORT = lo     (T = 15)
    "nop"                      "\n\t" // 1    nop           (T = 16)
    "sbiw %[count], 1"         "\n\t" // 2    i--           (T = 18)
    "brne head20"             "\n"   // 2    if(i != 0) -> (next byte)
    : [port]  "+e" (port),
    [byte]  "+r" (currentByte),
    [bit]   "+r" (currentBit),
    [next]  "+r" (next),
    [count] "+w" (_dataSize)
    : [ptr]    "e" (ptrData),
    [hi]     "r" (hi),
    [lo]     "r" (lo)
  );
  interrupts();
}
///////////////////////////////////////////////////////


Замысел прост. Динамику фрагмента храним в массиве переменной памяти, последовательность вывода фрагментов в постоянной памяти. В итоге можно узорить на любом числе пикселей, без библиотеки, без буфера в ОЗУ. В общем случае задача конечно нерешаема.

аааааааасемблеровская вставка, какой ужос для понимания мозгой…
ну да ладно, вот может будет полезно…

/////////////////////////////////////
// примеры для ws2812b с затуханием по смещению
// Arduino UNO

#include "Adafruit_NeoPixel.h"

#define line_ 64 // число пикселей в ленте
uint8_t dataPin = 6; // вывод для подключения
byte M = 20; // начальная мощность свечения (увеличена для лучшего эффекта)
byte cv = 0; // 
const byte massiv_per2[256] PROGMEM = {
0,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0,
1,15,27,26,25,24,23,22,21,20,19,18,17,16,15,14,
2,16,28,38,37,36,35,34,33,32,31,30,29,28,27,13,
3,17,29,39,47,46,45,44,43,42,41,40,39,38,26,12,
4,18,30,40,48,54,53,52,51,50,49,48,47,37,25,11,
5,19,31,41,49,55,59,58,57,56,55,54,46,36,24,10,
6,20,32,42,50,56,60,62,61,60,59,53,45,35,23,9,
7,21,33,43,51,57,61,63,63,62,58,52,44,34,22,8,
8,22,34,44,52,58,62,63,63,61,57,51,43,33,21,7,
9,23,35,45,53,59,60,61,62,60,56,50,42,32,20,6,
10,24,36,46,54,55,56,57,58,59,55,49,41,31,19,5,
11,25,37,47,48,49,50,51,52,53,54,48,40,30,18,4,
12,26,38,39,40,41,42,43,44,45,46,47,39,29,17,3,
13,27,28,29,30,31,32,33,34,35,36,37,38,28,16,2,
14,15,16,17,18,19,20,21,22,23,24,25,26,27,15,1,
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,0
}; 

byte massiv_kolzo2[64] = {
0, 0, 0, 0, 1, 1, 1, 1, 3, 3, 3, 3, 2, 2, 2, 2, 
1, 1, 1, 1, 5, 5, 5, 5, 7, 7, 7, 7, 0, 0, 0, 0, 
6, 6, 6, 6, 4, 4, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 
2, 2, 2, 2, 3, 3, 3, 3, 5, 5, 5, 5, 0, 0, 0, 0}; // начальный набор цветов фрагмента

// Массив для хранения текущего состояния каждого пикселя
byte pixelBrightness[line_]; // Яркость каждого пикселя
// не забывайте играться с переменной
byte fadeSteps = 15; // Количество шагов затухания (чем больше, тем плавнее)
byte currentStep = 0; // Текущий шаг затухания

void setup() {
WS2812bOut(dataPin, 0, 0, 0); // Инициализация ленты
// Инициализация массива яркости пикселей
for (int i = 0; i < line_; i++) { pixelBrightness[i] = 0; }
}

void loop() {
// Обновляем состояния пикселей на основе massiv_kolzo2
for (int i = 0; i < line_; i++) {
cv = massiv_kolzo2[pgm_read_byte(massiv_per2 + i)];  
// Если пиксель должен загореться, устанавливаем максимальную яркость
if (cv > 0) { pixelBrightness[i] = M; } // Устанавливаем максимальную яркость
// Вычисляем текущую яркость с учетом затухания по смещению
byte currentBrightness = pixelBrightness[i] > currentStep ? pixelBrightness[i] - currentStep : 0;
// Отправляем цвет на ленту с учетом текущей яркости
WS2812bOut(dataPin, (cv % 2) * currentBrightness, 
((cv / 2) % 2) * currentBrightness, 
((cv / 4) % 2) * currentBrightness);
}

// Увеличиваем шаг затухания
//вот так будет пульсация сердца(на самом деле нет, это что бы бить в глаза и раздражать людей, отмазываясь так)
currentStep = (currentStep + 1) % (fadeSteps + 5);
// попробуйте еще так currentStep = (currentStep + 5) % (fadeSteps + 1);

delay(75); // быстрота смены узора
kolzo2();
if (millis() % 5 == 0) { massiv_kolzo2[0] = random(0, 8); }
if (millis() % 5 == 1) { massiv_kolzo2[0] = 0; }
}

/////////////////////////////////////
void kolzo2() { byte V = 0;
for (int in = 0; in < 64; in++) {
if (in != 0 && in != 63) { massiv_kolzo2[in] = massiv_kolzo2[in + 1]; }
if (in == 0) { V = massiv_kolzo2[in]; massiv_kolzo2[0] = massiv_kolzo2[1];
} if (in == 63) { massiv_kolzo2[in] = V; }
}
}

/////////////////////////////////////
// функция вывода цвета пикселя
static void WS2812bOut(const uint8_t _dataPin, uint8_t R, uint8_t G, uint8_t B) {
uint8_t _data[] = {G, R, B}; uint16_t _dataSize = 3;
volatile uint8_t hi, lo, next, currentByte, currentBit = 0x08, *port, *ptrData = _data;
uint8_t pinMask;
digitalWrite(_dataPin, LOW);
pinMode(_dataPin, OUTPUT);
port = portOutputRegister(digitalPinToPort(_dataPin));
pinMask = digitalPinToBitMask(_dataPin);
currentByte = *ptrData++;
hi = *port | pinMask;
lo = *port & ~pinMask;
next = lo;
noInterrupts();
asm volatile (
"head20:"                   "\n\t" // Clk  Pseudocode    (T =  0)
"st   %a[port],  %[hi]"    "\n\t" // 2    PORT = hi     (T =  2)
"sbrc %[byte],  7"         "\n\t" // 1-2  if(b & 128)
"mov  %[next], %[hi]"     "\n\t" // 0-1   next = hi    (T =  4)
"dec  %[bit]"              "\n\t" // 1    bit--         (T =  5)
"st   %a[port],  %[next]"  "\n\t" // 2    PORT = next   (T =  7)
"mov  %[next] ,  %[lo]"    "\n\t" // 1    next = lo     (T =  8)
"breq nextbyte20"          "\n\t" // 1-2  if(bit == 0) (from dec above)
"rol  %[byte]"             "\n\t" // 1    b <<= 1       (T = 10)
"rjmp .+0"                 "\n\t" // 2    nop nop       (T = 12)
"nop"                      "\n\t" // 1    nop           (T = 13)
"st   %a[port],  %[lo]"    "\n\t" // 2    PORT = lo     (T = 15)
"nop"                      "\n\t" // 1    nop           (T = 16)
"rjmp .+0"                 "\n\t" // 2    nop nop       (T = 18)
"rjmp head20"              "\n\t" // 2    -> head20 (next bit out)
"nextbyte20:"               "\n\t" //                    (T = 10)
"ldi  %[bit]  ,  8"        "\n\t" // 1    bit = 8       (T = 11)
"ld   %[byte] ,  %a[ptr]+" "\n\t" // 2    b = *ptr++    (T = 13)
"st   %a[port], %[lo]"     "\n\t" // 2    PORT = lo     (T = 15)
"nop"                      "\n\t" // 1    nop           (T = 16)
"sbiw %[count], 1"         "\n\t" // 2    i--           (T = 18)
"brne head20"             "\n"   // 2    if(i != 0) -> (next byte)
: [port]  "+e" (port),
[byte]  "+r" (currentByte),
[bit]   "+r" (currentBit),
[next]  "+r" (next),
[count] "+w" (_dataSize)
: [ptr]    "e" (ptrData),
[hi]     "r" (hi),
[lo]     "r" (lo)
);
interrupts();
}

Да её и не надо понимать, её надо использовать. Посмотрел узор в этом варианте, яркость ступенчато нарастает на всех пикселях. А вот если бы вспыхивал только один, рандомно из фрагмента было бы интереснее. На всём узоре их будет 4.
…хотя можно и просто рандомно, по узору вспышки-отблески попробовать сделать.

… ну и вся эта проблематика с буфером произрастает из-за адресности светодиодов, которые на самом деле не адресные :slight_smile:

диоды вы уже сами зажигаете, все что мне надо управлять яркостью))) + не знаю как это сделать, а если и сделаю то это точно повредит эффекту… ну или добавит в него элементы рандома…
сможете скинуть видео работы ?)))
а то я прыгаю с #define line_ 256 // число пикселей в ленте
на #define line_ 64 // число пикселей в ленте и все равно не уверен в том как работает эффект)))

#include "Adafruit_NeoPixel.h"

#define line_ 256 // число пикселей в ленте
uint8_t dataPin = 6; // вывод для подключения
byte M = 20; // начальная мощность свечения (увеличена для лучшего эффекта)
byte cv = 0; // 
const byte massiv_per2[256] PROGMEM = {
0,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0,
1,15,27,26,25,24,23,22,21,20,19,18,17,16,15,14,
2,16,28,38,37,36,35,34,33,32,31,30,29,28,27,13,
3,17,29,39,47,46,45,44,43,42,41,40,39,38,26,12,
4,18,30,40,48,54,53,52,51,50,49,48,47,37,25,11,
5,19,31,41,49,55,59,58,57,56,55,54,46,36,24,10,
6,20,32,42,50,56,60,62,61,60,59,53,45,35,23,9,
7,21,33,43,51,57,61,63,63,62,58,52,44,34,22,8,
8,22,34,44,52,58,62,63,63,61,57,51,43,33,21,7,
9,23,35,45,53,59,60,61,62,60,56,50,42,32,20,6,
10,24,36,46,54,55,56,57,58,59,55,49,41,31,19,5,
11,25,37,47,48,49,50,51,52,53,54,48,40,30,18,4,
12,26,38,39,40,41,42,43,44,45,46,47,39,29,17,3,
13,27,28,29,30,31,32,33,34,35,36,37,38,28,16,2,
14,15,16,17,18,19,20,21,22,23,24,25,26,27,15,1,
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,0
}; 

byte massiv_kolzo2[64] = {
0, 0, 0, 0, 1, 1, 1, 1, 3, 3, 3, 3, 2, 2, 2, 2, 
1, 1, 1, 1, 5, 5, 5, 5, 7, 7, 7, 7, 0, 0, 0, 0, 
6, 6, 6, 6, 4, 4, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 
2, 2, 2, 2, 3, 3, 3, 3, 5, 5, 5, 5, 0, 0, 0, 0}; // начальный набор цветов фрагмента

// Массив для хранения яркости отдельных диодов
byte individualBrightness[line_] = {0}; 
// Массив для плавного затухания
byte fadeValues[line_] = {0};
// Таймеры для эффектов
unsigned long prevRandomTime = 0;
unsigned long prevFadeTime = 0;
// Генератор случайных чисел
uint32_t rnd = 0;

void setup() {
  WS2812bOut(dataPin, 0, 0, 0); // инициализация
  randomSeed(analogRead(A0)); // инициализация генератора случайных чисел
}

void loop() {
// Основной эффект
for (int i = 0; i < line_; i++) {
cv = massiv_kolzo2[pgm_read_byte(massiv_per2 + i)];
// Применяем индивидуальную яркость, но не ниже текущего эффекта
byte r = (cv % 2) * max(M, individualBrightness[i]);
byte g = ((cv / 2) % 2) * max(M, individualBrightness[i]);
byte b = ((cv / 4) % 2) * max(M, individualBrightness[i]);
WS2812bOut(dataPin, r, g, b); }
// Обновление основного эффекта
kolzo2();

// Генерация случайного числа
rnd = 0;
for (int i = 0; i < 16; i++) { rnd *= 4;
rnd += analogRead(A0) & 3; } //быстро стырил и ушел, называется нашел!!!
// не уверен что хороший рандом получился, я все еще смотрю это на матрице 8 на 8, и что то первый пиксель часто загорается...
// Случайное загорание диода на полную мощность
if (millis() - prevRandomTime > 100) { // каждые 100 мс
prevRandomTime = millis();
int randomPixel = rnd % line_; // случайный диод
individualBrightness[randomPixel] = 255; // максимальная яркость
fadeValues[randomPixel] = 255; }// начинаем затухание
// Плавное затухание
if (millis() - prevFadeTime > 30) { // каждые 30 мс
prevFadeTime = millis();
for (int i = 0; i < line_; i++) {
if (fadeValues[i] > 0) {
fadeValues[i] = fadeValues[i] - 5 > 0 ? fadeValues[i] - 5 : 0;
individualBrightness[i] = fadeValues[i]; }
}
} delay(75); }

void kolzo2() { byte V = 0;
for (int in = 0; in < 64; in++) {
if (in != 0 && in != 63) { massiv_kolzo2[in] = massiv_kolzo2[in + 1]; }
if (in == 0) { V = massiv_kolzo2[in]; massiv_kolzo2[0] = massiv_kolzo2[1]; }
if (in == 63) { massiv_kolzo2[in] = V; }
}
}

/////////////////////////////////////
// функция вывода цвета пикселя
static void WS2812bOut(const uint8_t _dataPin, uint8_t R, uint8_t G, uint8_t B) {
uint8_t _data[] = {G, R, B}; uint16_t _dataSize = 3;
volatile uint8_t hi, lo, next, currentByte, currentBit = 0x08, *port, *ptrData = _data;
uint8_t pinMask;
digitalWrite(_dataPin, LOW);
pinMode(_dataPin, OUTPUT);
port = portOutputRegister(digitalPinToPort(_dataPin));
pinMask = digitalPinToBitMask(_dataPin);
currentByte = *ptrData++;
hi = *port | pinMask;
lo = *port & ~pinMask;
next = lo;
noInterrupts();
asm volatile (
"head20:"                   "\n\t" // Clk  Pseudocode    (T =  0)
"st   %a[port],  %[hi]"    "\n\t" // 2    PORT = hi     (T =  2)
"sbrc %[byte],  7"         "\n\t" // 1-2  if(b & 128)
"mov  %[next], %[hi]"     "\n\t" // 0-1   next = hi    (T =  4)
"dec  %[bit]"              "\n\t" // 1    bit--         (T =  5)
"st   %a[port],  %[next]"  "\n\t" // 2    PORT = next   (T =  7)
"mov  %[next] ,  %[lo]"    "\n\t" // 1    next = lo     (T =  8)
"breq nextbyte20"          "\n\t" // 1-2  if(bit == 0) (from dec above)
"rol  %[byte]"             "\n\t" // 1    b <<= 1       (T = 10)
"rjmp .+0"                 "\n\t" // 2    nop nop       (T = 12)
"nop"                      "\n\t" // 1    nop           (T = 13)
"st   %a[port],  %[lo]"    "\n\t" // 2    PORT = lo     (T = 15)
"nop"                      "\n\t" // 1    nop           (T = 16)
"rjmp .+0"                 "\n\t" // 2    nop nop       (T = 18)
"rjmp head20"              "\n\t" // 2    -> head20 (next bit out)
"nextbyte20:"               "\n\t" //                    (T = 10)
"ldi  %[bit]  ,  8"        "\n\t" // 1    bit = 8       (T = 11)
"ld   %[byte] ,  %a[ptr]+" "\n\t" // 2    b = *ptr++    (T = 13)
"st   %a[port], %[lo]"     "\n\t" // 2    PORT = lo     (T = 15)
"nop"                      "\n\t" // 1    nop           (T = 16)
"sbiw %[count], 1"         "\n\t" // 2    i--           (T = 18)
"brne head20"             "\n"   // 2    if(i != 0) -> (next byte)
: [port]  "+e" (port),
[byte]  "+r" (currentByte),
[bit]   "+r" (currentBit),
[next]  "+r" (next),
[count] "+w" (_dataSize)
: [ptr]    "e" (ptrData),
[hi]     "r" (hi),
[lo]     "r" (lo)
);
interrupts();
}

или вот, меня тут отвлекли пару раз, и я уже не знаю из какого окна скидывать код)))
и времени нету)))

#include "Adafruit_NeoPixel.h"

#define line_ 256 // число пикселей в ленте
uint8_t dataPin = 6; // вывод для подключения
byte M = 2; // мощность свечения
byte cv = 0; //
const byte massiv_per2[256] PROGMEM = {
0,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0,
1,15,27,26,25,24,23,22,21,20,19,18,17,16,15,14,
2,16,28,38,37,36,35,34,33,32,31,30,29,28,27,13,
3,17,29,39,47,46,45,44,43,42,41,40,39,38,26,12,
4,18,30,40,48,54,53,52,51,50,49,48,47,37,25,11,
5,19,31,41,49,55,59,58,57,56,55,54,46,36,24,10,
6,20,32,42,50,56,60,62,61,60,59,53,45,35,23,9,
7,21,33,43,51,57,61,63,63,62,58,52,44,34,22,8,
8,22,34,44,52,58,62,63,63,61,57,51,43,33,21,7,
9,23,35,45,53,59,60,61,62,60,56,50,42,32,20,6,
10,24,36,46,54,55,56,57,58,59,55,49,41,31,19,5,
11,25,37,47,48,49,50,51,52,53,54,48,40,30,18,4,
12,26,38,39,40,41,42,43,44,45,46,47,39,29,17,3,
13,27,28,29,30,31,32,33,34,35,36,37,38,28,16,2,
14,15,16,17,18,19,20,21,22,23,24,25,26,27,15,1,
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,0
};
byte massiv_kolzo2[64] = {
0, 0, 0, 0, 1, 1, 1, 1, 3, 3, 3, 3, 2, 2, 2, 2, 
1, 1, 1, 1, 5, 5, 5, 5, 7, 7, 7, 7, 0, 0, 0, 0, 
6, 6, 6, 6, 4, 4, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 
2, 2, 2, 2, 3, 3, 3, 3, 5, 5, 5, 5, 0, 0, 0, 0}; // начальный набор цветов фрагмента
// Массив для хранения яркости отдельных диодов
byte individualBrightness[line_] = {0}; 
// Массив для плавного затухания
byte fadeValues[line_] = {0};
// Таймеры для эффектов
unsigned long prevRandomTime = 0;
unsigned long prevFadeTime = 0;
// Генератор случайных чисел
uint32_t rnd = 0;

void setup() {
WS2812bOut(dataPin, 0, 0, 0); // инициализация
randomSeed(analogRead(A0)); // инициализация генератора случайных чисел
}

void loop() {
// Основной эффект
for (int i = 0; i < line_; i++) {
cv = massiv_kolzo2[pgm_read_byte(massiv_per2 + i)];
// Применяем индивидуальную яркость, но не ниже текущего эффекта
byte r = (cv % 2) * max(M, individualBrightness[i]);
byte g = ((cv / 2) % 2) * max(M, individualBrightness[i]);
byte b = ((cv / 4) % 2) * max(M, individualBrightness[i]);
WS2812bOut(dataPin, r, g, b); }
kolzo2();  // Обновление основного эффекта
// Генерация случайного числа
//быстро стырил и ушел, называется нашел!!!
rnd = 0; for (int i = 0; i < 16; i++) { rnd *= 4; rnd += analogRead(A0) & 3; }
// Случайное загорание диода на полную мощность
if (millis() - prevRandomTime > 100) { // каждые 100 мс
prevRandomTime = millis();
int randomPixel = rnd % line_; // случайный диод
individualBrightness[randomPixel] = 255; // максимальная яркость
fadeValues[randomPixel] = 255; }// начинаем затухание
 
// Плавное затухание
if (millis() - prevFadeTime > 30) { // каждые 30 мс
prevFadeTime = millis();
for (int i = 0; i < line_; i++) {
if (fadeValues[i] > 0) {
fadeValues[i] = fadeValues[i] - 5 > 0 ? fadeValues[i] - 5 : 0;
individualBrightness[i] = fadeValues[i]; }
}
} delay(75); }
void kolzo2() { byte V = 0;
for (int in = 0; in < 64; in++) {
if (in != 0 && in != 63) {
massiv_kolzo2[in] = massiv_kolzo2[in + 1]; }
if (in == 0) { V = massiv_kolzo2[in];
massiv_kolzo2[0] = massiv_kolzo2[1]; }
if (in == 63) { massiv_kolzo2[in] = V; }
}
}
// Функция вывода цвета пикселя (без изменений)
static void WS2812bOut(const uint8_t _dataPin, uint8_t R, uint8_t G, uint8_t B) {
uint8_t _data[] = {G, R, B}; uint16_t _dataSize = 3;
volatile uint8_t hi, lo, next, currentByte, currentBit = 0x08, *port, *ptrData = _data;
uint8_t pinMask;
digitalWrite(_dataPin, LOW);
pinMode(_dataPin, OUTPUT);
port    = portOutputRegister(digitalPinToPort(_dataPin));
pinMask = digitalPinToBitMask(_dataPin);
currentByte = *ptrData++;
hi = *port |  pinMask;
lo = *port & ~pinMask;
next = lo;
noInterrupts();
asm volatile (
"head20:"                   "\n\t" // Clk  Pseudocode    (T =  0)
"st   %a[port],  %[hi]"    "\n\t" // 2    PORT = hi     (T =  2)
"sbrc %[byte],  7"         "\n\t" // 1-2  if(b & 128)
"mov  %[next], %[hi]"     "\n\t" // 0-1   next = hi    (T =  4)
"dec  %[bit]"              "\n\t" // 1    bit--         (T =  5)
"st   %a[port],  %[next]"  "\n\t" // 2    PORT = next   (T =  7)
"mov  %[next] ,  %[lo]"    "\n\t" // 1    next = lo     (T =  8)
"breq nextbyte20"          "\n\t" // 1-2  if(bit == 0) (from dec above)
"rol  %[byte]"             "\n\t" // 1    b <<= 1       (T = 10)
"rjmp .+0"                 "\n\t" // 2    nop nop       (T = 12)
"nop"                      "\n\t" // 1    nop           (T = 13)
"st   %a[port],  %[lo]"    "\n\t" // 2    PORT = lo     (T = 15)
"nop"                      "\n\t" // 1    nop           (T = 16)
"rjmp .+0"                 "\n\t" // 2    nop nop       (T = 18)
"rjmp head20"              "\n\t" // 2    -> head20 (next bit out)
"nextbyte20:"               "\n\t" //                    (T = 10)
"ldi  %[bit]  ,  8"        "\n\t" // 1    bit = 8       (T = 11)
"ld   %[byte] ,  %a[ptr]+" "\n\t" // 2    b = *ptr++    (T = 13)
"st   %a[port], %[lo]"     "\n\t" // 2    PORT = lo     (T = 15)
"nop"                      "\n\t" // 1    nop           (T = 16)
"sbiw %[count], 1"         "\n\t" // 2    i--           (T = 18)
"brne head20"             "\n"   // 2    if(i != 0) -> (next byte)
: [port]  "+e" (port),
[byte]  "+r" (currentByte),
[bit]   "+r" (currentBit),
[next]  "+r" (next),
[count] "+w" (_dataSize)
: [ptr]    "e" (ptrData),
[hi]     "r" (hi),
[lo]     "r" (lo)
);
interrupts();
}

Вот гифка, вихрь, похожий на вращение ножа мясорубки.
0122

1 лайк

Это да. Делу время, потехе час.

Забыл я убрать эту строку, она тут лишняя.

последние 3 кода я делал по последнему выложенному коду… подумал у вас есть время сидеть и делать еще какие то эффекты…
и вот тут не знаю как это работает на матрице 16 на 16, у меня 8 на 8

даже хромосом лишних не бывает, есть запасная! пусть будет)))
вы написали прикольный код, и инициализировал я так, не используя библиотеку…

WS2812bOut(dataPin, 0, 0, 0); // инициализация

код запускал на ардуино уно, в arduino идэ 1.8.19 если не компилируется…

кстате из за ассемблеровской вставки, определенная часть кода работает гораздо быстрее остальной части, и не удивляйтесь что будут ошибки, потому что другая часть будет не успевать… но может я и ошибаюсь…

Ну так переделайте на свою 8х8 мой вариант кода.
Сначала определите ход ленты на матрице, возможно 4 варианта:


Потом массив-переходник перепишите под своё расположение пикселей. Вот скетч для визуализации порядка расположения пикселей на модуле сообразно нумерации.

/////////////////////////////////////
// примеры для ws2812b
//Arduino UNO

#include "Adafruit_NeoPixel.h"

#define line_ 64 //число пикселей в ленте
uint8_t dataPin = 6;// вывод для подключения
Adafruit_NeoPixel strip = Adafruit_NeoPixel(line_,dataPin , NEO_GRB + NEO_KHZ800);// Создаем переменную strip для управления нашей лентой.
byte R=2;//
byte G=2;//
byte B=2;//
///RGB
void setup() {
 strip.begin();
 }
void loop() {
for ( int in = 0; in < line_; in++) {
strip.setPixelColor(in, R, 0, 0);
strip.show();delay(50);  
}

for ( int in = 0; in < line_; in++) {
strip.setPixelColor(in, 0, G, 0); 
strip.show();delay(50); 
}
 
for ( int in = 0; in < line_; in++) {
strip.setPixelColor(in, 0, 0, B); 
strip.show();delay(50); 
}
  
}


ой ну нафиг, незя отступать от первоначального плана))) код в начале должен быть правильным! а это значит ардуино должна только выводить анимацию! вот может будет полезно, https://rutube.ru/video/f61728c68b5dc8f20d881ee5e0efa977/?r=plemwd и это релакс, а пилить что то с 0, это расшатывание нервной системы!))) а вот тут подробно на ютубе

Джинкс, гледиатор пробовал это управление с пк лентой.

Добрый вечер. Хочу сделать табло из ws2812b и esp32 , 5 матриц по 16х16. Получается 80 диодов в ширину и 16 в высоту. Но библиотеки Adafruit_Neo не дают сделать больше 71 диодов в ширину (71 столбцов). Пробывал и как одна матрица (Adafruit_NeoMatrix(71, 16, PIN), и как 5 матриц (Adafruit_NeoMatrix(14, 16, 5, 1, PIN), не работает. Если вместо 71 поставить 72 уже перестанет работать или вместо 14 поставить 16 или 15 не запускается. На FastLed все показывает. У Adafruit_Neo может какое ограничение стоит на столбцы ?

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

А чем вас Фастлед не устраивает?
Опишите свою матрицу как обычную ленту длиной 256*5 = 1280 пикселей.