Внезапный сбой в работе модулей max7219

Ну где-то же что-то ломается ))

Думаю, они здесь не при чем. Если плата исправная, значит таки библиотека портачит

Ну эта же библа на Меге пашет без претензий. Выходит, Унка дефектная попалась?

Загрузите в нее заведомо рабочий скетч и проверьте, чего гадать-то?

Когда я в первый раз взял эту библиотеку и залез в код, слегка подофигел - от обилия int в глазах рябило, все индексы были int. Явно человек привык программировать для ПК, а не для микроконтроллеров - про экономию памяти даже не думал. Только замена int на uint8_t уменьшило память скетча на килобайт-полтора (может меньше - подробностей уже не помню, но профит был впечатляющий)).

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

ЗЫ: да и плюшек у меня больше :wink:

1 лайк

Не забывай, что ты в этом “простом” скетче делаешь вызовы методов, определенных в библиотеке. А как они реализованы?..

И главное - они реализованы 9 лет назад, а сколько раз поменялось ардуиновское ядро с тех пор?

Очень интересно. Что, просто чохом поменять int на uint8_t, и сразу станет легче?

Почему “чохом” то? Там, где этого достаточно…

Я тоже всегда стараюсь использовать тот тип, которого достаточно. Это же логично - ресурсов же ограниченно.

На что только ни пойдет человек, лишь бы ничего не делать )))

Пробуйте

//UNO
int n;
//Подключение библиотеки max7219
#include <shMAX72xxMini.h>

#define CS_PIN 10
#define NUM_DEVICES 3
#define NUM_DIGITS 8

// вывод CS модуля подулючен к пину D10 Ардуино, выводы DIN и CLK модуля подключены к пинам D11 и D13 Ардуино соответственно
shMAX72xx7Segment<CS_PIN, NUM_DEVICES, NUM_DIGITS> lc_test;

void setup() 
{
  Serial.begin(115200);
  //Инициализация max7219

  lc_test.init(); //Выводим из спящего режима
  lc_test.clearAllDevices(); //Очищаем все устройства
  lc_test.setBrightnessForAllDevices(4); // Яркость дисплея на 4. Всего возможных режимов яркости от 0 до 15
}
void loop() 
{
  lc_test.setChar(0, 7, lc_test.encodeDigit(0), true, true);
  delay(500);
  lc_test.setChar(0, 6, lc_test.encodeDigit(1), true, true);
  delay(500);
  lc_test.setChar(0, 5, lc_test.encodeDigit(2), true, true);
  delay(500);
  lc_test.setChar(0, 4, lc_test.encodeDigit(3), true, true);
  delay(500);
  lc_test.setChar(0, 3, lc_test.encodeDigit(4), true, true);
  delay(500);
  lc_test.setChar(0, 2, lc_test.encodeDigit(5), true, true);
  delay(500);
  lc_test.setChar(0, 1, lc_test.encodeDigit(6), true, true);
  delay(500);
  lc_test.setChar(0, 0, lc_test.encodeDigit(7), true, true);
  delay(500);
  lc_test.clearDevice(0);    //Очистить дисплей

  lc_test.setChar(1, 7, lc_test.encodeDigit(8), true, true);
  delay(500);
  lc_test.setChar(1, 6, lc_test.encodeDigit(9), true, true);
  delay(500);
  lc_test.setChar(1, 5, lc_test.encodeDigit(0), true, true);
  delay(500);
  lc_test.setChar(1, 4, lc_test.encodeDigit(1), true, true);
  delay(500);
  lc_test.setChar(1, 3, lc_test.encodeDigit(2), true, true);
  delay(500);
  lc_test.setChar(1, 2, lc_test.encodeDigit(3), true, true);
  delay(500);
  lc_test.setChar(1, 1, lc_test.encodeDigit(4), true, true);
  delay(500);
  lc_test.setChar(1, 0, lc_test.encodeDigit(5), true, true);
  delay(500);
  lc_test.clearDevice(1);    //Очистить дисплей

  lc_test.setChar(2, 7, lc_test.encodeDigit(6), true, true);
  delay(500);
  lc_test.setChar(2, 6, lc_test.encodeDigit(7), true, true);
  delay(500);
  lc_test.setChar(2, 5, lc_test.encodeDigit(8), true, true);
  delay(500);
  lc_test.setChar(2, 4, lc_test.encodeDigit(9), true, true);
  delay(500);
  lc_test.setChar(2, 3, lc_test.encodeDigit(0), true, true);
  delay(500);
  lc_test.setChar(2, 2, lc_test.encodeDigit(1), true, true);
  delay(500);
  lc_test.setChar(2, 1, lc_test.encodeDigit(2), true, true);
  delay(500);
  lc_test.setChar(2, 0, lc_test.encodeDigit(3), true, true);
  delay(500);
  lc_test.clearDevice(2);    //Очистить дисплей
  
  n++;
  Serial.println(n);
}

Только пины переподключить не забудьте - библиотека работает на аппаратном SPI

2 лайка

Сколько всего цифр в каждом модуле?

ИМХО может быть маловато для 3-х модулей + UNO.
Добавьте хотя-бы конденсаторы ~ 470мкф на каждый модуль, как можно ближе к модулю

Да нет, там яркость 4 из 15, много не возьмет

Всё равно, я бы конденсаторы поставил. Сами модули помеху дают по питанию.
P.S. Если яркость повышать не планируете, то и по 100мкф может быть достаточно.

Сколько скетч занимает памяти при компиляции?

Кондеры стоят

Гигантское спасибо! Вечером попробую применить. А насчет ничего не делать - вот с этим не успел разобраться
#define CS_PIN 10
#define NUM_DEVICES 3
#define NUM_DIGITS 24
А тут Ваша помощь пришла, и всё в голове устаканилось.

По 8 штук.

Есть вопросы для осмысления до вечера:

  1. Напрямую пины для Din и CLK не переназначаются?
  2. Команда setChar вносит в индикатор только цифры, а буквы - нет?
  3. Что означает двойное true?

Скетч использует 2880 байт (1%) памяти устройства. Всего доступно 253952 байт.
Глобальные переменные используют 97 байт (1%) динамической памяти, оставляя 8095 байт для локальных переменных. Максимум: 8192 байт.

На UNO - нет, на esp32 и rp2040 - легко. Собственно, отказ от софтверного SPI, который у LedControl в пользу аппаратного был продиктован слишком медленной работой. Аппаратный в сравнении с софтовым просто летает, но на uno/nano/pro mini пины заданы жестко

Нет, любой символ, который вообще можно отобразить на семисегментнике:

void setChar(uint8_t addr, uint8_t num_index, uint8_t value, bool showDot = false, bool upd = false); - вывод битовой маски на цифровой индикатор; здесь:

  • addr - индекс устройства в каскаде, начиная с нуля;

  • num_index - индекс знака в устройстве, начиная с нуля (0…7);

  • value - битовая маска выводимого символа;

  • showDot - показывать или нет десятичную точку;

  • upd - признак обновления устройства; при upd = false, то будет изменен только программный буфер устройства, само изображение будет обновлено только после вызова метода update().

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

Есть еще один вариант метода setChar()

void setChar(uint16_t index, uint8_t value, bool showDot = false, bool upd = false) - вывод битовой маски на цифровой индикатор; здесь:

  • index - индекс знака в каскаде, начиная с нуля; например, для второго знака второго устройства индекс будет равен 9

  • value - битовая маска символа, может быть получена с помощью метода encodeDigit() или создана “вручную”; например, value = 0x63 (т.е. 0b01100011) выведет на индикатор значок градуса Цельсия;

  • showDot - включать или нет десятичную точку для этого разряда;

  • upd - признак обновления устройства; при upd = false, то будет изменен только программный буфер устройства, само изображение будет обновлено только после вызова метода update()

См. описание выше - зажигать десятичную точку для разряда и сразу обновлять картинку на индикаторах. Обычно это не нужно, т.к. сильно замедляет работу, поэтому сначала устанавливаются все разряды, а потом вызывается метод update() для прорисовки всего и сразу. Но в вашем случае нужно выводить каждую цифру по отдельности, поэтому и второй true ))

Чрезвычайно благодарен! Кратко, ёмко, понятно.

Там в redme все довольно подробно расписано