Как работать с необычной неопиксельной сеткой

Я собрал у себя дома собственную инсталляцию из 896 светодиодов WS2812, управляемых ArduinoMega 2560 и питающихся от нескольких шин. Однако инсталляция организована в шахматном порядке. Она состоит из 14 панелей с 8 полосами по 8 светодиодов на каждой (64 светодиода на панель). Полосы припаяны зигзагом к панели, а плитки соединены выводами в порядке «по столбцам».

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

Моё решение — «подделать», как будто у меня гораздо больше пикселей, и использовать функцию setRemapFunction(), чтобы отбросить эти фиктивные точки сетки. Но по мере добавления фиктивных пикселей я предполагаю, что для них выделяется дополнительная оперативная память, и я исчерпаю её до конца. Всего у меня 896 реальных пикселей, но при таком темпе я буду объявлять их 1792. Это моя попытка справиться со смещением, и работа над ней ещё не закончена. Пока что используется примерно половина всей сетки:

const int16_t grid[] = {
0,  15,  16,  31,  32,  47,  48,  63,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 256, 271, 272, 287, 288, 303, 304, 319,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
1,  14,  17,  30,  33,  46,  49,  62,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 257, 270, 273, 286, 289, 302, 305, 318,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
2,  13,  18,  29,  34,  45,  50,  61,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 258, 269, 274, 285, 290, 301, 306, 317,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
3,  12,  19,  28,  35,  44,  51,  60,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 259, 268, 275, 284, 291, 300, 307, 316,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
4,  11,  20,  27,  36,  43,  52,  59,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 260, 267, 276, 283, 292, 299, 308, 315,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
5,  10,  21,  26,  37,  42,  53,  58,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 261, 266, 277, 282, 293, 298, 309, 314,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
6,   9,  22,  25,  38,  41,  54,  57,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 262, 265, 278, 281, 294, 297, 310, 313,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
7,   8,  23,  24,  39,  40,  55,  56,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 263, 264, 279, 280, 295, 296, 311, 312,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,

-1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 128, 143, 144, 159, 160, 175, 176, 191,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 384, 399, 400, 415, 416, 431, 432, 447,
-1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 129, 142, 145, 158, 161, 174, 177, 190,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 385, 398, 401, 414, 417, 430, 433, 446,
-1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 130, 141, 146, 157, 162, 173, 178, 189,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 386, 397, 402, 413, 418, 429, 434, 445,
-1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 131, 140, 147, 156, 163, 172, 179, 188,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 387, 396, 403, 412, 419, 428, 435, 444,
-1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 132, 139, 148, 155, 164, 171, 180, 187,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 388, 395, 404, 411, 420, 427, 436, 443,
-1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 133, 138, 149, 154, 165, 170, 181, 186,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 389, 394, 405, 410, 421, 426, 437, 442,
-1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 134, 137, 150, 153, 166, 169, 182, 185,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 390, 393, 406, 409, 422, 425, 438, 441,
-1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 135, 136, 151, 152, 167, 168, 183, 184,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 391, 392, 407, 408, 423, 424, 439, 440,

64,  79,  80,  95,  96, 111, 112, 127,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 320, 335, 336, 351, 352, 367, 368, 383,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
65,  78,  81,  94,  97, 110, 113, 126,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 321, 334, 337, 350, 353, 366, 369, 382,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
66,  77,  82,  93,  98, 109, 114, 125,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 322, 333, 338, 349, 354, 365, 370, 381,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
67,  76,  83,  92,  99, 108, 115, 124,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 323, 332, 339, 348, 355, 364, 371, 380,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
68,  75,  84,  91, 100, 107, 116, 123,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 324, 331, 340, 347, 356, 363, 372, 379,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
69,  74,  85,  90, 101, 106, 117, 122,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 325, 330, 341, 346, 357, 362, 373, 378,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
70,  73,  86,  89, 102, 105, 118, 121,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 326, 329, 342, 345, 358, 361, 374, 377,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,
71,  72,  87,  88, 103, 104, 119, 120,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 327, 328, 343, 344, 359, 360, 375, 376,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,

-1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 192, 207, 208, 223, 224, 239, 240, 255,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 448, 463, 464, 479, 480, 495, 496, 511,
-1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 193, 206, 209, 222, 225, 238, 241, 254,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 449, 462, 465, 478, 481, 494, 497, 510,
-1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 194, 205, 210, 221, 226, 237, 242, 253,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 450, 461, 466, 477, 482, 493, 498, 509,
-1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 195, 204, 211, 220, 227, 236, 243, 252,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 451, 460, 467, 476, 483, 492, 499, 508,
-1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 196, 203, 212, 219, 228, 235, 244, 251,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 452, 459, 468, 475, 484, 491, 500, 507,
-1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 197, 202, 213, 218, 229, 234, 245, 250,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 453, 458, 469, 474, 485, 490, 501, 506,
-1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 198, 201, 214, 217, 230, 233, 246, 249,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 454, 457, 470, 473, 486, 489, 502, 505,
-1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 199, 200, 215, 216, 231, 232, 247, 248,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1, 455, 456, 471, 472, 487, 488, 503, 504,

};

Я использую это вот так:

#define PIN 6

#define WIDTH 32 // Пока что. Будет 56, когда я закончу создание массива.
#define HEIGHT 32

/**
 * Setup the lightwall matrix.
 *
 * Each panel is 8x8 pixels. There are 7 columns and 2 rows,
 * but they are arranged in a checkerboard pattern.
 */
Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(WIDTH, HEIGHT,PIN,
  NEO_MATRIX_TOP     + NEO_MATRIX_LEFT +
  NEO_MATRIX_COLUMNS + NEO_MATRIX_ZIGZAG,
  NEO_GRBW           + NEO_KHZ800
);

uint16_t remapXY(uint16_t x, uint16_t y) {
  y = y * WIDTH + x;
  return grid[y];
}

void setup() {
  matrix.setRemapFunction(remapXY);
  matrix.begin();
}

Итак, функция remapXY() возвращает правильный ключ массива, отсюда и этот безумный массив, вставленный выше. И этот массив готов только наполовину (нудно его набирать!)

Но пока что это работает. У меня есть анимация Пакмана (не показана на картинке), которая прокручивается по экрану и довольно долго находится «за кадром». В этом и есть весь смысл этого безумия. Но может быть, я всё делаю неправильно? Прилагаю изображение всей видимой матрицы для наглядности.

lightwall

Начиная с верхнего левого угла, идет панель 1, затем нижняя левая панель 2. В следующем верхнем столбце идет панель 3, внизу – панель 4. И так далее.

Так мне понадобится больше оперативной памяти для повышения производительности? Или есть более эффективный способ обойти эту проблему? У меня запланировано много анимаций и эффектов окружения, но не все из них будут строго требовать это смещение.

Есть ли другой способ «замаскировать» или временно задержать некоторые пиксели за пределами экрана, исходя из их местонахождения? Чтобы потом вернуть их на место?

, 👍5


2 ответа


Лучший ответ:

3

Разбейте его на блоки, чтобы определить верхний левый угол любой сетки 8x8

const int16_t grid[8][8] = {
       {0,  15,  16,  31,  32,  47,  48,  63},
       {1,  14,  17,  30,  33,  46,  49,  62},
       {2,  13,  18,  29,  34,  45,  50,  61},
       {3,  12,  19,  28,  35,  44,  51,  60},
       {4,  11,  20,  27,  36,  43,  52,  59},
       {5,  10,  21,  26,  37,  42,  53,  58},
       {6,   9,  22,  25,  38,  41,  54,  57},
       {7,   8,  23,  24,  39,  40,  55,  56}
};

const int16_t block[7][4] = {
       { 0,  -1,   4,  -1,   8,  -1,  12},
       {-1,   2,  -1,   6,  -1,  10,  -1},
       { 1,  -1,   5,  -1,   9,  -1,  13},
       {-1,   3,  -1,   7,  -1,  11,  -1}
};



blockNumber = block[x/8][y/8];

// проверка на значение -1

pixelNumber = blockNumber * 64 + grid[x%8][y%8]   

//
,

2

Это действительно выглядит потрясающе!

Я предлагаю избавиться от большого массива grid и вместо этого сгенерировать Программное отображение. Учитывая, что это очень регулярно, отображение может вычисляться, а не храниться:

uint16_t remapXY(uint16_t x, uint16_t y) {

    // Вычислить положение панели и смещение пикселя внутри этой панели.
    uint8_t pannel_x = x / 8;
    uint8_t offset_x = x % 8;
    uint8_t pannel_y = y / 8;
    uint8_t offset_y = y % 8;

    // Это отсутствующая панель?
    if ((pannel_x + pannel_y) & 1)
        return -1;

    // Вычислить номер панели.
    uint8_t pannel = pannel_y / 2 + pannel_x * 2;

    // Светодиодный индекс на панели.
    uint8_t led = 8 * offset_x;

    if (offset_x & 1)  // нумеруются снизу вверх
        led += 7 - offset_y;
    else               // пронумеровано сверху вниз
        led += offset_y;

    return pannel * 64 + led;
}

Надеюсь, это сэкономит достаточно памяти, чтобы все заработало.

,