ARDUINO Разбор прошивки от vvip-68

Alex Kireev

✩✩✩✩✩✩✩
24 Авг 2024
7
1
Всем привет
Пытаюсь сделать следующее
3 матрицы ws2812b подключены последовательно, порядок подключения нижний правый угол, направление вверх, тип зигзаг.
На первую вывод времени
На вторую анимацию смайликов
На третью случайные эффекты

На фото показано как расположены матрицы и направление, а сбоку что в итоге пытаюсь сделать

За основу взял Прошивку от vvip-68
Урезал конкретно под себя, получилось следующее
WS:
#define COLOR_ORDER    GRB      // Порядок цветов на ленте. Если цвет отображается некорректно - меняйте. Начать можно с RGB

#define WIDTH 8                // ширина одного сегмента матрицы                                   
#define HEIGHT 8               // высота одного сегмента матрицы                                     
#define MATRIX_TYPE 0           // тип соединения диодов в сегменте матрицы: 0 - зигзаг, 1 - параллельная
#define CONNECTION_ANGLE 1      // угол подключения диодов в сегменте: 0 - левый нижний, 1 - левый верхний, 2 - правый верхний, 3 - правый нижний
#define STRIP_DIRECTION 3       // направление ленты из угла сегмента: 0 - вправо, 1 - вверх, 2 - влево, 3 - вниз                                 
#define META_MATRIX_WIDTH 1     // количество сегментов в ширину сборной матрицы                                                                 
#define META_MATRIX_HEIGHT 2    // количество сегментов в высоту сборной матрицы                                                                 
#define META_MATRIX_TYPE 0      // тип сборной матрицы: 0 - зигзаг, 1 - параллельная                                                             
#define META_MATRIX_ANGLE 3     // угол 1-го сегмента сборной матрицы: 0 - левый нижний, 1 - левый верхний, 2 - правый верхний, 3 - правый нижний
#define META_MATRIX_DIRECTION 1 // направление следующих сегментов сборной матрицы из угла: 0 - вправо, 1 - вверх, 2 - влево, 3 - вниз         

#define LED_PIN  2              // пин ленты
// =======================================================

// ************** ИСПОЛЬЗУЕМЫЕ БИБЛИОТЕКИ ****************
#include <FastLED.h>             // Установите в менеджере библиотек стандартную библиотеку FastLED
// =======================================================

#define BRIGHTNESS      32       // Яркость матрицы по-умолчанию 0..255

// ************************* УПРАВЛЕНИЕ МАТРИЦЕЙ *******************************
uint16_t   CURRENT_LIMIT = 10000;                // лимит по току в миллиамперах, автоматически управляет яркостью (пожалей свой блок питания!) 0 - выключить лимит

uint8_t    sWIDTH = WIDTH;                       // ширина одного сегмента матрицы 1..127
uint8_t    sHEIGHT = HEIGHT;                     // высота одного сегмента матрицы 1..127
uint8_t    sMATRIX_TYPE = MATRIX_TYPE;           // тип соединения диодов в сегменте матрицы: 0 - зигзаг, 1 - параллельная, 2 - карта индексов
uint8_t    sCONNECTION_ANGLE = CONNECTION_ANGLE; // угол подключения диодов в сегменте: 0 - левый нижний, 1 - левый верхний, 2 - правый верхний, 3 - правый нижний
uint8_t    sSTRIP_DIRECTION = STRIP_DIRECTION;   // направление ленты из угла сегмента: 0 - вправо, 1 - вверх, 2 - влево, 3 - вниз

uint8_t    mWIDTH = META_MATRIX_WIDTH;           // количество сегментов в ширину 1..9
uint8_t    mHEIGHT = META_MATRIX_HEIGHT;         // количество сегментов в высоту 1..9
uint8_t    mTYPE = META_MATRIX_TYPE;             // соединение сегментов мета-матрицы: 0 - зигзаг, 1 - параллельная
uint8_t    mANGLE = META_MATRIX_ANGLE;           // угол 1-го сегмента мета-матрицы: 0 - левый нижний, 1 - левый верхний, 2 - правый верхний, 3 - правый нижний
uint8_t    mDIRECTION = META_MATRIX_DIRECTION;   // направление следующих сегментов мета-матрицы из угла: 0 - вправо, 1 - вверх, 2 - влево, 3 - вниз

uint8_t    pWIDTH = sWIDTH * mWIDTH;
uint8_t    pHEIGHT = sHEIGHT * mHEIGHT;

uint32_t   NUM_LEDS = pWIDTH * pHEIGHT;
uint8_t    maxDim   = max(pWIDTH, pHEIGHT);
uint8_t    minDim   = min(pWIDTH, pHEIGHT);

CRGB       *leds;                               // обращение к светодиодам матрицы через этот массив

// ------------------- ВРЕМЕННЫЕ ПЕРЕМЕННЫЕ ----------------------
uint8_t  globalBrightness = BRIGHTNESS;     // текущая яркость (общая)

// ---------------------------------------------------------------

void setup()
{
  Serial.begin(9600);

  // пинаем генератор случайных чисел
  uint32_t seed = (int)(analogRead(0) ^ micros());
  randomSeed(seed);
  random16_set_seed(seed);

  pWIDTH = sWIDTH * mWIDTH;
  pHEIGHT = sHEIGHT * mHEIGHT;

  NUM_LEDS = pWIDTH * pHEIGHT;
  maxDim   = max(pWIDTH, pHEIGHT);
  minDim   = min(pWIDTH, pHEIGHT);

  // Настройки ленты
  leds =  new CRGB[NUM_LEDS];

  FastLED.addLeds<WS2812, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );

  FastLED.setBrightness(globalBrightness);
  if (CURRENT_LIMIT > 0) {
    FastLED.setMaxPowerInVoltsAndMilliamps(5, CURRENT_LIMIT);
  }
  FastLED.clear();
  FastLED.show();
}

void loop()
{
 
}

Funcs:
void fillAll(uint32_t color) {
  fill_solid(leds, NUM_LEDS, color);
}

// залить все
void fillAll(CRGB color) {
  fill_solid(leds, NUM_LEDS, color);
}

// функция получения цвета пикселя по его номеру
uint32_t getPixColor(int16_t thisPixel) {
  if (thisPixel < 0 || thisPixel > NUM_LEDS - 1) return 0;
  return (((uint32_t)leds[thisPixel].r << 16) | ((uint32_t)leds[thisPixel].g << 8 ) | (uint32_t)leds[thisPixel].b);
}

// функция получения цвета пикселя в матрице по его координатам
uint32_t getPixColorXY(int8_t x, int8_t y) {
  return getPixColor(getPixelNumber(x, y));
}

// функция отрисовки точки по координатам X Y
void drawPixelXY(int8_t x, int8_t y, CRGB color) {
  if (x < 0 || x > pWIDTH - 1 || y < 0 || y > pHEIGHT - 1) return;
  int16_t thisPixel = getPixelNumber(x, y);
  if (thisPixel >= 0) leds[thisPixel] = color;
}

void drawPixelXYF(float x, float y, CRGB color) {
  // extract the fractional parts and derive their inverses
  uint8_t xx = (x - (int)x) * 255, yy = (y - (int)y) * 255, ix = 255 - xx, iy = 255 - yy;
 
  // calculate the intensities for each affected pixel
  #define WU_WEIGHT(a,b) ((uint8_t) (((a)*(b)+(a)+(b))>>8))

  uint8_t wu[4] = {WU_WEIGHT(ix, iy), WU_WEIGHT(xx, iy),
                   WU_WEIGHT(ix, yy), WU_WEIGHT(xx, yy)};

  // multiply the intensities by the colour, and saturating-add them to the pixels
  for (uint8_t i = 0; i < 4; i++) {
    int16_t xn = x + (i & 1), yn = y + ((i >> 1) & 1);
    CRGB clr = getPixColorXY(xn, yn);
    clr.r = qadd8(clr.r, (color.r * wu[i]) >> 8);
    clr.g = qadd8(clr.g, (color.g * wu[i]) >> 8);
    clr.b = qadd8(clr.b, (color.b * wu[i]) >> 8);
    drawPixelXY(xn, yn, clr);
  }
}

// получить номер пикселя в ленте по координатам
int16_t getPixelNumber(int8_t x, int8_t y) {

  if (x < 0 || x >= pWIDTH || y < 0 || y >= pHEIGHT) return -1;
 
  uint8_t xx,yy,ww,sx,sy,mx,my,mw,snum,num;

  if (sMATRIX_TYPE == 0 || sMATRIX_TYPE == 1) {
    
    // --------------------------------------------------
    // Матрица состоит из одного сегмента, адресация по углу подключения, типу, направлению
    // --------------------------------------------------

    if (mWIDTH == 1 && mHEIGHT == 1) {
      xx = THIS_X(x, y);
      yy = THIS_Y(x, y);
      ww = THIS_W();
    
      return (yy % 2 == 0 || sMATRIX_TYPE == 1)
          ? yy * ww + xx // если чётная строка
          : yy * ww + ww - xx - 1; // если нечётная строка
    }

    // --------------------------------------------------
    // Матрица - сборная, состоит из нескольких сегментов, адресация по углу подключения, типу, направлению
    // --------------------------------------------------
    
    sx = x / sWIDTH;    // номер сегмента по ширине
    sy = y / sHEIGHT;   // номер сегмента по высоте
    x = x % sWIDTH;     // позиция x относительно сегмента
    y = y % sHEIGHT;    // позиция y относительно сегмента
 
    // Номер сегмента в последовательности сборной матрицы
    mx = THIS_SX(sx, sy);
    my = THIS_SY(sx, sy);
    mw = THIS_SW();
 
    snum = (my % 2 == 0 || mTYPE == 1)
        ? my * mw + mx           // если чётная строка мета-матрицы
        : my * mw + mw - mx - 1; // если нечётная строка мета-матрицы
    
    // Номер дода в сегменте
    xx = THIS_X(x, y);
    yy = THIS_Y(x, y);
    ww = THIS_W();
    
    num = (yy % 2 == 0 || sMATRIX_TYPE == 1)
        ? yy * ww + xx           // если чётная строка
        : yy * ww + ww - xx - 1; // если нечётная строка 
 
    return snum * sWIDTH * sHEIGHT + num;
  }
 
  return -1;
}

uint8_t THIS_X(uint8_t x, uint8_t y) {
    /*
        CONNECTION_ANGLE; // угол подключения: 0 - левый нижний, 1 - левый верхний, 2 - правый верхний, 3 - правый нижний
        STRIP_DIRECTION;  // направление ленты из угла: 0 - вправо, 1 - вверх, 2 - влево, 3 - вниз
     */
    if (sCONNECTION_ANGLE == 0 && sSTRIP_DIRECTION == 0) return x;
    if (sCONNECTION_ANGLE == 0 && sSTRIP_DIRECTION == 1) return y;
    if (sCONNECTION_ANGLE == 1 && sSTRIP_DIRECTION == 0) return x;
    if (sCONNECTION_ANGLE == 1 && sSTRIP_DIRECTION == 3) return sHEIGHT - y - 1;
    if (sCONNECTION_ANGLE == 2 && sSTRIP_DIRECTION == 2) return sWIDTH - x - 1;
    if (sCONNECTION_ANGLE == 2 && sSTRIP_DIRECTION == 3) return sHEIGHT - y - 1;
    if (sCONNECTION_ANGLE == 3 && sSTRIP_DIRECTION == 2) return sWIDTH - x - 1;
    if (sCONNECTION_ANGLE == 3 && sSTRIP_DIRECTION == 1) return y;
    return x;
}

uint8_t THIS_Y(uint8_t x, uint8_t y) {
    /*
        CONNECTION_ANGLE; // угол подключения: 0 - левый нижний, 1 - левый верхний, 2 - правый верхний, 3 - правый нижний
        STRIP_DIRECTION;  // направление ленты из угла: 0 - вправо, 1 - вверх, 2 - влево, 3 - вниз
     */
    if (sCONNECTION_ANGLE == 0 && sSTRIP_DIRECTION == 0) return y;
    if (sCONNECTION_ANGLE == 0 && sSTRIP_DIRECTION == 1) return x;
    if (sCONNECTION_ANGLE == 1 && sSTRIP_DIRECTION == 0) return sHEIGHT - y - 1;
    if (sCONNECTION_ANGLE == 1 && sSTRIP_DIRECTION == 3) return x;
    if (sCONNECTION_ANGLE == 2 && sSTRIP_DIRECTION == 2) return sHEIGHT - y - 1;
    if (sCONNECTION_ANGLE == 2 && sSTRIP_DIRECTION == 3) return sWIDTH - x - 1;
    if (sCONNECTION_ANGLE == 3 && sSTRIP_DIRECTION == 2) return y;
    if (sCONNECTION_ANGLE == 3 && sSTRIP_DIRECTION == 1) return sWIDTH - x - 1;
    return y;
}

uint8_t THIS_W() {
    /*
        CONNECTION_ANGLE; // угол подключения: 0 - левый нижний, 1 - левый верхний, 2 - правый верхний, 3 - правый нижний
        STRIP_DIRECTION;  // направление ленты из угла: 0 - вправо, 1 - вверх, 2 - влево, 3 - вниз
     */
    if (sCONNECTION_ANGLE == 0 && sSTRIP_DIRECTION == 0) return sWIDTH;
    if (sCONNECTION_ANGLE == 0 && sSTRIP_DIRECTION == 1) return sHEIGHT;
    if (sCONNECTION_ANGLE == 1 && sSTRIP_DIRECTION == 0) return sWIDTH;
    if (sCONNECTION_ANGLE == 1 && sSTRIP_DIRECTION == 3) return sHEIGHT;
    if (sCONNECTION_ANGLE == 2 && sSTRIP_DIRECTION == 2) return sWIDTH;
    if (sCONNECTION_ANGLE == 2 && sSTRIP_DIRECTION == 3) return sHEIGHT;
    if (sCONNECTION_ANGLE == 3 && sSTRIP_DIRECTION == 2) return sWIDTH;
    if (sCONNECTION_ANGLE == 3 && sSTRIP_DIRECTION == 1) return sHEIGHT;
    return sWIDTH;
}

uint8_t THIS_SX(uint8_t x, uint8_t y) {
    /*
        CONNECTION_ANGLE; // угол подключения: 0 - левый нижний, 1 - левый верхний, 2 - правый верхний, 3 - правый нижний
        STRIP_DIRECTION;  // направление ленты из угла: 0 - вправо, 1 - вверх, 2 - влево, 3 - вниз
     */
    if (mANGLE == 0 && mDIRECTION == 0) return x;
    if (mANGLE == 0 && mDIRECTION == 1) return y;
    if (mANGLE == 1 && mDIRECTION == 0) return x;
    if (mANGLE == 1 && mDIRECTION == 3) return mHEIGHT - y - 1;
    if (mANGLE == 2 && mDIRECTION == 2) return mWIDTH - x - 1;
    if (mANGLE == 2 && mDIRECTION == 3) return mHEIGHT - y - 1;
    if (mANGLE == 3 && mDIRECTION == 2) return mWIDTH - x - 1;
    if (mANGLE == 3 && mDIRECTION == 1) return y;
    return x;
}

uint8_t THIS_SY(uint8_t x, uint8_t y) {
    /*
        CONNECTION_ANGLE; // угол подключения: 0 - левый нижний, 1 - левый верхний, 2 - правый верхний, 3 - правый нижний
        STRIP_DIRECTION;  // направление ленты из угла: 0 - вправо, 1 - вверх, 2 - влево, 3 - вниз
     */
    if (mANGLE == 0 && mDIRECTION == 0) return y;
    if (mANGLE == 0 && mDIRECTION == 1) return x;
    if (mANGLE == 1 && mDIRECTION == 0) return mHEIGHT - y - 1;
    if (mANGLE == 1 && mDIRECTION == 3) return x;
    if (mANGLE == 2 && mDIRECTION == 2) return mHEIGHT - y - 1;
    if (mANGLE == 2 && mDIRECTION == 3) return mWIDTH - x - 1;
    if (mANGLE == 3 && mDIRECTION == 2) return y;
    if (mANGLE == 3 && mDIRECTION == 1) return mWIDTH - x - 1;
    return y;
}

uint8_t THIS_SW() {
    /*
        CONNECTION_ANGLE; // угол подключения: 0 - левый нижний, 1 - левый верхний, 2 - правый верхний, 3 - правый нижний
        STRIP_DIRECTION;  // направление ленты из угла: 0 - вправо, 1 - вверх, 2 - влево, 3 - вниз
     */
    if (mANGLE == 0 && mDIRECTION == 0) return mWIDTH;
    if (mANGLE == 0 && mDIRECTION == 1) return mHEIGHT;
    if (mANGLE == 1 && mDIRECTION == 0) return mWIDTH;
    if (mANGLE == 1 && mDIRECTION == 3) return mHEIGHT;
    if (mANGLE == 2 && mDIRECTION == 2) return mWIDTH;
    if (mANGLE == 2 && mDIRECTION == 3) return mHEIGHT;
    if (mANGLE == 3 && mDIRECTION == 2) return mWIDTH;
    if (mANGLE == 3 && mDIRECTION == 1) return mHEIGHT;
    return mWIDTH;
}

// функция плавного угасания цвета для всех пикселей
void fader(uint8_t step) {
  for (uint8_t i = 0; i < pWIDTH; i++) {
    for (uint8_t j = 0; j < pHEIGHT; j++) {
      fadePixel(i, j, step);
    }
  }
}

void fadePixel(uint8_t i, uint8_t j, uint8_t step) {     // новый фейдер
  int16_t pixelNum = getPixelNumber(i, j);
  if (pixelNum < 0 || getPixColor(pixelNum) == 0) return;

  if (leds[pixelNum].r >= 8 ||
      leds[pixelNum].g >= 8 ||
      leds[pixelNum].b >= 8) {
    leds[pixelNum].fadeToBlackBy(step);
  } else {
    leds[pixelNum] = 0;
  }
}

uint32_t getColorInt(CRGB color) {
  return color.r << 16 | color.g << 8 | color.b;
}

// Вычисление значения яркости эффектов по отношению к общей яркости
// Общая яркость регулируется через FastLED.setBrightness();
// Вычисленная яркость эффекта влияет на компонент яркости V в модели HCSV
uint8_t getBrightnessCalculated(uint8_t brightness, uint8_t contrast) {
  // В данном варианте общая яркость не учитывается в расчете
  return map8(contrast, 16, 255);
}

uint8_t wrapX(int8_t x) {
  return (x + pWIDTH) % pWIDTH;
}

uint8_t wrapY(int8_t y) {
  return (y + pHEIGHT) % pHEIGHT;
}

// Сдвиг всей матрицы вниз
void shiftDown() {
  for (uint8_t x = 0; x < pWIDTH; x++) {
    for (uint8_t y = 0; y < pHEIGHT - 1; y++) {
      drawPixelXY(x, y, getPixColorXY(x, y + 1));
    }
  }
}

// Сдвиг всей матрицы вверх
void shiftUp() {
  for (uint8_t x = 0; x < pWIDTH; x++) {
    for (uint8_t y = pHEIGHT - 1; y > 0; y--) {
      drawPixelXY(x, y, getPixColorXY(x, y - 1));
    }
  }
}

// Сдвиг всей матрицы по диагонали
void shiftDiag() {
  for (uint8_t y = 0; y < pHEIGHT - 1; y++) {
    for (uint8_t x = pWIDTH - 1; x > 0; x--) {
      drawPixelXY(x, y, getPixColorXY(x - 1, y + 1));
    }
  }
}
Для теста пытаюсь вывести анимацию сердца на каждую матрицу, которое есть в прошивке, нашел массив сердца, но не могу понять как выводить все на нужную матрицу.
 

Вложения