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

led led-matrix

Я следовал официальному учебнику и был сбит с толку исходным кодом.

Официальный встроенный пример Arduino: RowColumnScanning

// когда строка ВЫСОКАЯ, а col НИЗКИЙ,
// светодиод, где они встречаются, загорается:
digitalWrite(col[thisCol], thisPixel);
// выключить пиксель:
if (thisPixel == LOW) {
  digitalWrite(col[thisCol], HIGH);
}

Вот мое понимание:

  1. Если thisPixel НИЗКИЙ, то pin col[thisCol] будет ВЫСОКИМ.
  2. Если этот пиксель ВЫСОК, то pin-код[thisCol] все равно будет ВЫСОКИМ.

Вопрос

Поскольку col[thisCol] всегда ВЫСОК независимо от thisPixel, имеет ли смысл иметь дополнительный оператор if?

В случае, если URL-адрес мертв

/*
  Row-Column Scanning an 8x8 LED matrix with X-Y input

  This example controls an 8x8 LED matrix using two analog inputs.

  This example works for the Lumex LDM-24488NI Matrix. See
  https://sigma.octopart.com/140413/datasheet/Lumex-LDM-24488NI.pdf
  for the pin connections.

  For other LED cathode column matrixes, you should only need to change the pin
  numbers in the row[] and column[] arrays.

  rows are the anodes
  cols are the cathodes
  ---------

  Pin numbers:
  Matrix:
  - digital pins 2 through 13,
  - analog pins 2 through 5 used as digital 16 through 19
  Potentiometers:
  - center pins are attached to analog pins 0 and 1, respectively
  - side pins attached to +5V and ground, respectively

  created 27 May 2009
  modified 30 Aug 2011
  by Tom Igoe

  This example code is in the public domain.

  https://www.arduino.cc/en/Tutorial/BuiltInExamples/RowColumnScanning
*/

// 2-dimensional array of row pin numbers:
const int row[8] = {
  2, 7, 19, 5, 13, 18, 12, 16
};

// 2-dimensional array of column pin numbers:
const int col[8] = {
  6, 11, 10, 3, 17, 4, 8, 9
};

// 2-dimensional array of pixels:
int pixels[8][8];

// cursor position:
int x = 5;
int y = 5;

void setup() {
  // initialize the I/O pins as outputs iterate over the pins:
  for (int thisPin = 0; thisPin < 8; thisPin++) {
    // initialize the output pins:
    pinMode(col[thisPin], OUTPUT);
    pinMode(row[thisPin], OUTPUT);
    // take the col pins (i.e. the cathodes) high to ensure that the LEDS are off:
    digitalWrite(col[thisPin], HIGH);
  }

  // initialize the pixel matrix:
  for (int x = 0; x < 8; x++) {
    for (int y = 0; y < 8; y++) {
      pixels[x][y] = HIGH;
    }
  }
}

void loop() {
  // read input:
  readSensors();

  // draw the screen:
  refreshScreen();
}

void readSensors() {
  // turn off the last position:
  pixels[x][y] = HIGH;
  // read the sensors for X and Y values:
  x = 7 - map(analogRead(A0), 0, 1023, 0, 7);
  y = map(analogRead(A1), 0, 1023, 0, 7);
  // set the new pixel position low so that the LED will turn on in the next
  // screen refresh:
  pixels[x][y] = LOW;

}

void refreshScreen() {
  // iterate over the rows (anodes):
  for (int thisRow = 0; thisRow < 8; thisRow++) {
    // take the row pin (anode) high:
    digitalWrite(row[thisRow], HIGH);
    // iterate over the cols (cathodes):
    for (int thisCol = 0; thisCol < 8; thisCol++) {
      // get the state of the current pixel;
      int thisPixel = pixels[thisRow][thisCol];
      // when the row is HIGH and the col is LOW,
      // the LED where they meet turns on:
      digitalWrite(col[thisCol], thisPixel);
      // turn the pixel off:
      if (thisPixel == LOW) {
        digitalWrite(col[thisCol], HIGH);
      }
    }
    // take the row pin low to turn off the whole row:
    digitalWrite(row[thisRow], LOW);
  }
}

, 👍3

Обсуждение

Это предотвращает появление ореолов, когда следующий ряд поднят высоко ... также уменьшает общий ток, так как в любой момент времени горит только один светодиод, @jsotola

Не могли бы вы скопировать полный скетч в свой вопрос, пожалуйста? Внешние ресурсы имеют тенденцию исчезать... и мы хотели бы помочь будущим читателям полностью понять эту проблему., @the busybee

@thebusybee Спасибо за напоминание. Я обновил вопрос., @Weihang Jian


2 ответа


3

Вы правы, если не имеет смысла. Не все учебники верны, и даже если они часто не очень хороши.

Причина второго digitalWrite() заключается в выключении пикселя после того, как он был потенциально включен. Если он остается включенным при изменении строки, вы можете увидеть ореолы.

Тем не менее, я бы переключил все пиксели строки, немного задержал, а затем во втором циклеснова выключил их все, прежде чем обрабатывать следующую строку.

,

1

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

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

Трудно точно определить, что такое "достаточно часто" и "достаточная доля" времени. Первое зависит от конкретного человека, который смотрит, но я бы стремился к частоте не менее 100 Гц. Последнее зависит в основном от того, насколько ярки ваши светодиоды при включении (подробнее об этом позже).

Это полезно, потому что это экономит вам много линий ввода-вывода, если бы вы хотели индивидуально управлять 256 светодиодами, вам понадобилось бы 256 линий ввода-вывода. При использовании матрицы строк/столбцов вам нужно всего 16. Конечно, с матрицей row/colum невозможно осветить все комбинации светодиодов одновременно, но на самом деле это не имеет значения, потому что до тех пор, пока вы освещаете каждый активный светодиод достаточно часто, человеческий глаз не заметит разницы.

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


Однако несколько вещей отличают этот пример от "Обычной" реализации матричного привода.

  • В этом примере одновременно горит только один светодиод. Большинство реализаций матричных приводов освещают целую строку (или столбец) за один раз. Это означает, что светодиоды горят гораздо большую часть времени, хотя у этого есть и недостатки, это означает, что ваши драйверы строк должны иметь достаточную текущую мощность привода, чтобы управлять целым рядом одновременно.
  • В этом примере нет последовательных резисторов! ток через светодиоды ограничен только внутренним сопротивлением светодиодов и драйверов выводов ввода-вывода в AVR. Это, вероятно, приводит к тому, что светодиоды и контакты GPIO работают значительно выше их номинального максимального тока!
  • В коде нет ничего, что могло бы контролировать время, а время включения светодиода очень короткое. В зависимости от того, насколько хорошо компилятор оптимизирует код, это может быть всего несколько тактов.

Некоторые из этих факторов компенсируют друг друга, ток привода, вероятно, очень высок, но он подается очень коротко и только на один светодиод за раз. Таким образом, общий результат, скорее всего, заключается в том, что ничего не жарится, а дисплей имеет полезную яркость.

Но, тем не менее, я думаю, что это именно тот пример, который приносит Arduino дурную славу. Предположительно, он работает (иначе он не был бы опубликован), но он выводит компоненты за рамки спецификации, а яркость дисплея полностью зависит от плохо заданных внутренних сопротивлений и скорости выполнения кода.

,