Попытка нарисовать растровое изображение на светодиодной матрице рисует только левую половину

Я КРАЙНЕ новичок в Arduino и довольно плохо знаком с программированием в целом, но я подумал, что было бы интересно попробовать написать программу, которая рисует произвольные 1-битные растровые изображения на светодиодной матрице, используя библиотеку Adafruit RGBMatrixPanel. Я пытаюсь вывести это изображение на экран:

красно-черное изображение размером 32 x 16 с текстом

Но он отключается после 16 пикселей в каждой строке...

то же изображение, но виден только ОФ - остальное изображение черное

Ниже мой код полностью. Кажется, что битовая маска работает только для первых 16 столбцов, но я не могу понять, почему она останавливается на этом этапе. Я использую Arduino Nano, если это поможет.

#define CLK  8   
#define OE   9
#define LAT 10
#define A   A0
#define B   A1
#define C   A2

RGBmatrixPanel matrix(A, B, C, CLK, LAT, OE, false);
unsigned long int pixelGrid[] = {
  0x00000000,
  0x31CEFDCE,
  0x78CCFCCC,
  0x78CC84CC,
  0x78CC04CC,
  0x78CC04CC,
  0x78CC24CC,
  0x78783CFC,
  0x783024FC,
  0x303004CC,
  0x303004CC,
  0x303004CC,
  0x003084CC,
  0x3030FCCC,
  0x3078FDCE, 
  0x00000000
};
unsigned long int bitMask = 0x00000001;
void setup() {
  matrix.begin();
  uint8_t r=0, g=0, b=0;

  for(uint8_t y=0; y<16; y++) {
    unsigned long data = pixelGrid[y]; // выбор строки битов из изображения
      for (byte x = 0; x <32; x++) { // итерация по столбцам
        if (data & (bitMask << x)) {// работает!
          r = 1; // включить светодиод
        }
        else {
          r = 0; // светодиод выключен
        }
      matrix.drawPixel(x, y, matrix.Color333(r, g, b));
    }
  }
}

void loop() {
}

Вот часть кода, которая, вероятно, работает неправильно, изолирована:

for (byte x = 0; x <32; x++) {
        if (data & (1 << x)) {
          r = 1;
        }
        else {
          r = 0;
        }

Спасибо за помощь!

Редактировать: изменение переменной data с int на long, чтобы избежать усечения ведущего, добавляет еще один столбец пикселей, но это как бы похоже, что все они по какой-то причине сжаты в столбец 16:то же изображение, что и изображение 2, за исключением вертикальной линии работает от (16, 1) до (16, 14)

Примечание. Я попытался нарисовать прямоугольник от (0,0) до (31, 15), чтобы убедиться, что все светодиоды работают, и мне это удалось.

Изменить 2: вместо битовой маски 1 я сделал так:

unsigned long int bitMask = 0x00000001;
// ...
 if (data & (bitMask << x)) { // работает!
          r = 1; // включить светодиод
        }
        else {
          r = 0; // светодиод выключен
        }

Я предполагаю, что обычные числа по умолчанию представляют собой 16-битные целые числа без знака. Проблема решена, ура! Я отредактировал большой блок кода, чтобы он соответствовал.

, 👍0

Обсуждение

Я бы попробовал поменять координаты x и y в matrix.drawPixel(x, y, matrix.Color333(r, g, b));, чтобы увидеть, расположены ли данные в альбомной, а не в портретной ориентации., @Kwasmich

Изменение координат x/y поворачивает изображение на 90 градусов, как и ожидалось: https://i.imgur.com/GXzS4LG.png Это панель размером 32x16, поэтому я, к сожалению, не могу проверить, опускается ли она ниже., @NGD


1 ответ


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

0

'pixelGrid[]' - это long, но ваша temp внутри цикла for(), 'data', является int. Таким образом, он получает только половину данных. Легко совершить ошибку (и их бывает так трудно обнаружить, когда вы прекрасно знаете, что имели в виду... :)

Обновление:

Переключив int на long, я успешно разблокировал семнадцатый столбец! К сожалению, похоже, что все пиксели сгруппированы в этот семнадцатый столбец.

Еще одна такая же ошибка (в первый раз я ее пропустил): Измените (1 << x) на (1L << x). Исходное выражение вычисляется как int, а результат расширяется при присвоении «данным» (и, кроме того, я думаю, что в коде, который это сделал, была ошибка компилятора). Исправленное выражение в первую очередь вычисляется как длинное, что, я думаю, вы и хотели.

Обновление 2:

Из вашего вопроса Изменить 2:

Я предполагаю, что обычные числа по умолчанию представляют собой 16-битные целые числа без знака.

Вы правы — целые числа неопределенного размера по умолчанию равны 16 битам в компиляторе Arduino gcc, используемом в среде разработки Arduino (и почти везде в домене Arduino, о котором я знаю). Стандарт языка оставляет разработчику компилятора свободу выбора размера int, который лучше всего соответствует архитектуре целевой машины. 16-битный — самый распространенный, но далеко не единственный размер, реализованный в большинстве компиляторов. По этой причине препроцессоры большинства компиляторов реализуют типы данных определенного размера, а авторы приложений — вы & I - рекомендуется использовать их везде, где размер данных имеет значение. Для компилятора Arduino gcc существуют предопределенные типы, такие как int8_t (8-битное целое со знаком), uint32_t (длинное целое без знака) и т. д. int — это вариант «Мне все равно, лишь бы он работал». Если вам не все равно - уточните.

(Если мой ответ помог вам, пожалуйста, проголосуйте за него или выберите лучший ответ. Последний имеет важную функцию на этом сайте, помечая вопрос как «завершенный», чтобы он не появлялся снова как вопрос без ответа. )

,

Переключив int на long, я успешно разблокировал семнадцатый столбец! К сожалению, похоже, что все пиксели сгруппированы в этом семнадцатом столбце... https://i.imgur.com/tgpcnH3.png, @NGD

возможно, вы редактируете свой вопрос? И код, и описание ошибки..., @DataFiddler

Отметил вас как лучший ответ только что. Спасибо за все что ты сделал для меня!, @NGD