Случайные светодиоды загораются на 10 модулях MAX7219

Я пытаюсь создать часы IoT, используя 10 модулей MAX7219 (последовательно взаимодействующие 8-значные драйверы светодиодных дисплеев). Я создал следующий код:

//clock.ino
#define MODULES_X 5
#define MODULES_Y 2
#define MODULES_COUNT MODULES_X*MODULES_Y
#define PIXELS_X MODULES_X*8
#define PIXELS_Y MODULES_Y*8
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 10
#define CLK_PIN   7  // or SCK
#define DATA_PIN  6  // or MOSI
#define CS_PIN    5  // or SS

#include <MD_MAX72xx.h>
#include <avr/pgmspace.h>
#include <SPI.h>
#include "font.h"

MD_MAX72XX mx = MD_MAX72XX(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
bool FrameBuffer[PIXELS_Y][PIXELS_X];
uint8_t g = 0, m = 0, s = 0;
long int lastSecond = 0;

void clearBuffer()
{
  for (size_t i = 0; i < PIXELS_Y; i++)
    for (size_t j = 0; j < PIXELS_X; j++)
      FrameBuffer[i][j] = false;
}

void resetMatrix(void)
{
  mx.control(MD_MAX72XX::INTENSITY, 0);
  mx.control(MD_MAX72XX::UPDATE, MD_MAX72XX::ON);
  mx.clear();
}

void redisplay()
{
  mx.update(MD_MAX72XX::OFF);

  for (size_t i = 0; i < PIXELS_Y / 2; i++)
  {
    for (size_t j = 0; j < PIXELS_X; j++)
    {
      mx.setPoint(i, PIXELS_X - j - 1, FrameBuffer[i][j]);
    }
  }

  for (size_t i = PIXELS_Y / 2; i < PIXELS_Y; i++)
  {
    for (size_t j = 0; j < PIXELS_X; j++)
    {
      mx.setPoint(i - (PIXELS_Y / 2), PIXELS_X - j + 39, FrameBuffer[i][j]);
    }
  }

  mx.update(MD_MAX72XX::ON);
}

void draw8x16(size_t posY, size_t posX, uint8_t number)
{
  if(number > 9 || number < 0) number = 0;

  for (size_t i = 0; i < 16; i++)
  {
    for (size_t j = 0; j < 8; j++)
    {
      FrameBuffer[posY + i][posX + j] = pgm_read_byte(&(font8x16[number][i])) & (1 << (7 - j));
    }
  }
}

void setup()
{
  clearBuffer();
  mx.begin();
  resetMatrix();
}

void loop()
{
  if (millis() - lastSecond >= 1000) {
    s++;
    lastSecond = millis();

    draw8x16(0, 0, (g / 10) % 10);
    draw8x16(0, 9, g % 10);
    draw8x16(0, 23, (m / 10) % 10);
    draw8x16(0, 32, m % 10);

    FrameBuffer[5][20] = true; FrameBuffer[6][20] = true; FrameBuffer[5][19] = true; FrameBuffer[6][19] = true;
    FrameBuffer[9][20] = true; FrameBuffer[10][20] = true; FrameBuffer[9][19] = true; FrameBuffer[10][19] = true;

    redisplay();
    clearBuffer();
  }

  if (s == 60) {
    s = 0;
    m++;
  }

  if (m == 60) {
    m = 0;
    g++;
  }

  if (g == 24) {
    g = 0;
  }
}

Массив байтов, используемый для заполнения буфера кадров пикселями цифр:

//font.h
const byte PROGMEM font8x16[10][16] = {
  { 
    B00111100,
    B01111110,
    B11100111,
    B11000011,
    B11000011,
    B11000011,
    B11000011,
    B11000011,
    B11000011,
    B11000011,
    B11000011,
    B11000011,
    B11000011,
    B11100111,
    B01111110,
    B00111100
  },
  { 
    B00000011,
    B00000111,
    B00001111,
    B00011111,
    B00111011,
    B01110011,
    B11100011,
    B11000011,
    B00000011,
    B00000011,
    B00000011,
    B00000011,
    B00000011,
    B00000011,
    B00000011,
    B00000011
  },
  { 
    B00111100,
    B01111110,
    B11100111,
    B11000011,
    B00000011,
    B00000011,
    B00000011,
    B00000111,
    B00001110,
    B00011100,
    B00111000,
    B01110000,
    B11100000,
    B11000000,
    B11111111,
    B11111111
  },
  { 
    B00111100,
    B01111110,
    B11100111,
    B11000011,
    B00000011,
    B00000111,
    B00001110,
    B00111100,
    B00111100,
    B00001110,
    B00000111,
    B00000011,
    B11000011,
    B11100111,
    B01111110,
    B00111100
  },
  { 
    B00000011,
    B00000111,
    B00001110,
    B00011100,
    B00111000,
    B01110000,
    B11100000,
    B11000000,
    B11000000,
    B11111111,
    B01111111,
    B00000011,
    B00000011,
    B00000011,
    B00000011,
    B00000011
  },
  { 
    B11111111,
    B11111111,
    B11000000,
    B11000000,
    B11000000,
    B11000000,
    B11111100,
    B11111110,
    B00000111,
    B00000011,
    B00000011,
    B00000011,
    B11000011,
    B11100111,
    B01111110,
    B00111100
  },
  { 
    B00111100,
    B01111110,
    B11100111,
    B11000011,
    B11000000,
    B11000000,
    B11000000,
    B11111100,
    B11111110,
    B11100111,
    B11000011,
    B11000011,
    B11000011,
    B11100111,
    B01111110,
    B00111100
  },
  { 
    B11111111,
    B11111111,
    B11000011,
    B11000111,
    B00000110,
    B00001110,
    B00001100,
    B00011100,
    B00011000,
    B00111000,
    B00110000,
    B01110000,
    B01100000,
    B11100000,
    B11000000,
    B11000000
  },
  { 
    B00111100,
    B01111110,
    B11100111,
    B11000011,
    B11000011,
    B11000011,
    B11100111,
    B01111110,
    B01111110,
    B11100111,
    B11000011,
    B11000011,
    B11000011,
    B11100111,
    B01111110,
    B00111100
  },
  { 
    B00111100,
    B01111110,
    B11100111,
    B11000011,
    B11000011,
    B11000011,
    B11100111,
    B01111111,
    B00111111,
    B00000011,
    B00000011,
    B00000011,
    B11000011,
    B11100111,
    B01111110,
    B00111100
  }
};

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

Этот код работает отлично, но примерно через 30 минут моя светодиодная матрица показывает только случайные пиксели, и мне приходится сбрасывать arduino. Мой вопрос таков: что не так с моим кодом?

Фото моих рабочих часов: Clock

, 👍1

Обсуждение

Используйте последовательный монитор и добавьте операторы отладки для печати переменных, чтобы проверить, где происходит повреждение. Кроме того, если ваши часы показывают только часы и минуты, почему вы обновляете дисплей каждую секунду, а не по минутам и часам? Кроме того, вам нужно прокомментировать свой код., @Greenonline

Я обновляю свой дисплей каждую секунду только в целях тестирования. Я добавил код для печати переменных, и вот что я получил: https://pastebin.com/mSvYFuBn Вроде бы все в порядке., @Wychoniu

печать же (жестко) время в течение получаса все еще крах его? если это так, посмотрите на тепло или подводное течение., @dandavis

Мои часы довольно холодные, когда они подключены к адаптеру переменного тока 2А. Он использует около 800 мА при самой низкой яркости. Я удалил весь код из void() и вызвал один раз функцию redispaly (), чтобы показать цифры на дисплее, но она все еще не работает даже после подключения к источнику питания., @Wychoniu


2 ответа


0

В вашем скетче допущена ошибка. Попробуйте изменить long int lastSecond = 0; на unsigned long lastSecond = 0;.

Вот скетч, который вы можете использовать для проверки вашего часового, минутного, секундного кода. То, что я вижу, - это увеличение секунд с 1 до 60, затем оно обновляет секунды до 0 и минуты до 1. Попробуйте этот скетч и следите за выводом в течение 1 минуты, чтобы понять, о чем я говорю.

unsigned long lastSecond = 0;
uint8_t g = 0, m = 0, s = 0;

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

void loop()
{
  if (millis() - lastSecond >= 1000) {
    s++;
    lastSecond = millis();
    Serial.print(s);
    Serial.print(" ");
    Serial.print(m);
    Serial.print(" ");
    Serial.print(g);
    Serial.println();
  }
  if (s == 60) {
    s = 0;
    m++;
  }
  if (m == 60) {
    m = 0;
    g++;
  }
  if (g == 24) {
    g = 0;
  }
}

Я не уверен, что в расчете H:M:S есть логическая ошибка, поэтому вы можете использовать точный отрезок времени с этим скетчем, чтобы убедиться в его правильности.

РЕДАКТИРОВАТЬ: Вот обновленная версия тестового скетча с изменениями, обсуждаемыми в комментариях. Если вы попробуете оба скетча, вы увидите, что обновленный отсчитывается до 59 секунд, затем переходит к 0 секундам, 1 минуте, как и должно быть.

unsigned long lastSecond = 0;
uint8_t g = 0, m = 0, s = 0;

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

void loop()
{
  if (millis() - lastSecond >= 1000) {
    s++;
    lastSecond = millis();
    if (s > 59) {
      s = 0;
      m++;
    }
    if (m > 59) {
      m = 0;
      g++;
    }
    if (g > 23) {
      g = 0;
    }
    Serial.print(s);
    Serial.print(" ");
    Serial.print(m);
    Serial.print(" ");
    Serial.print(g);
    Serial.println();

    // Добавьте код для светодиодного дисплея здесь

  }
}
,

Это все еще не работает, @Wychoniu

Ваш код H:M:S следует переместить чуть ниже этой строки: lastSecond = millis(); Затем обновите светодиодную матрицу. Кроме того, измените минуты и секунды с "== 60" на "> 59", а часы с "==24" на ">> 23". Начните с этого простого скетча (который я скопировал прямо с вашего скетча). Как только он выведет правильные цифры на последовательный монитор, мы сможем интегрировать ваш код отображения., @VE7JRO

Я думаю, что моя проблема не связана с подсчетом времени. Я могу передать в свою функцию любую цифру от 0 до 9, и она должна появиться на моем дисплее. К сожалению, иногда он показывает случайные пиксели. Я заменил провода и сменил библиотеку, но мне ничего не помогло., @Wychoniu


0

"Он потребляет около 800 мА при самой низкой яркости".

USB-порты большинства компьютеров обеспечивают только 500 мА (и выключите выше этого для защиты вашего компьютера).

  • Возможно, +5 В провисает. Вы измеряли его во время работы ваших часов и когда он выходит из строя?
  • Попробуйте включить питание системы или, по крайней мере, светодиодных драйверов от другого источника +5, возможно, 4 последовательно расположенных элементов типа АА или ААА? Если вы включаете только драйверы, подключите два заземления.
  • Попробуйте запустить все это со скоростью 100 раз ( если (millis() - последняя секунда >= 10) {> ). По-прежнему ли сбой занимает 30 минут или 18 секунд? Если первое, скорее всего, тепло. Если последнее, это, вероятно, программное обеспечение.
,