1

I'm trying to create an IoT clock using 10 MAX7219 (Serially Interfaced, 8-Digit, LED Display Drivers) modules. I've created the following code:

//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;
  }
}

Array of bytes used to fill FrameBuffer with pixels of digits:

//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
  }
};

I know, that this is not a good idea to count the time in this way, but this is only for testing purposes.

This code works perfectly, but after about 30 minutes, my LED matrix shows only random pixels and I have to reset arduino. My question is: what's wrong with my code?

Photo of my working clock: Clock

4
  • Use the serial monitor and add debugging statements to print your variables, to check where the corruption occurs. Also, if your clock only shows hours and minutes why are you refreshing the display every second, and not on the minute and hour changes? Also you need to comment your code. – Greenonline Jul 11 '18 at 20:15
  • I refreshing my display every second only for testing purposes. I added some code to print variables, and this is what I got: pastebin.com/mSvYFuBn Everything seems to be ok. – Wychoniu Jul 11 '18 at 21:14
  • does printing the same (hard-coded) time for a half hour still crash it? if so, look into heat or undercurrent. – dandavis Jul 12 '18 at 8:33
  • My clock is quite cold when it's connected to 2A AC adapter. It uses about 800mA with the lowest brightness. I removed all code from void() and called once redispaly() function to show digits on display, but it's still not working even after connecting to power. – Wychoniu Jul 12 '18 at 18:43
0

There is an error in your sketch. Try changing long int lastSecond = 0; to unsigned long lastSecond = 0;.

Here is a sketch you can use to test your hour, minute, second code. What I'm seeing is the seconds incrementing from 1 to 60, then it updates the seconds to 0 and minute to 1. Try this sketch and monitor the output for 1 minute to see what I'm talking about.

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;
  }
}

I'm not positive there is a logic error with the H:M:S calculation, so you could use an accurate time piece with this sketch to verify it's correct.

EDIT: Here is an updated version of the test sketch with the changes discussed in comments. If you try both sketches, you'll see the updated one counts to 59 seconds then goes to 0 seconds, 1 minute as it should.

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();

    // Add you code for the LED display here

  }
}
3
  • It's still not working – Wychoniu Jul 11 '18 at 20:31
  • 1
    Your H:M:S code should be moved to just under this line: lastSecond = millis(); Then update your LED matrix. Also, change the minutes and second from " == 60" to " > 59" and the hours from "==24" to " > 23". Start with this simple sketch (which I copied right out of your sketch). Once you have it printing out the correct digits to the serial monitor, then we can integrate your display code. – VE7JRO Jul 11 '18 at 20:41
  • I think, that my problem isn't connected with time calculating. I can pass any digit form 0 to 9 to my function and it should appear on my display. Unfortunately it sometimes shows random pixels. I replaced wires and changed library, but nothing helped me. – Wychoniu Jul 11 '18 at 21:07
0

"It uses about 800mA with the lowest brightness."

Most computers' USB ports provide only 500 mA (and shut down above that to protect your computer).

  • Perhaps the +5V is sagging. Have you measured it while your clock is running, and when it fails?
  • Try powering the system, or at least the LED drivers, from a different source of +5, perhaps 4 AA or or AAA cells in series? If you power just the drivers, connect the two grounds.
  • Try running the whole thing a 100x rate ( if (millis() - lastSecond >= 10) { ). Does the failure still take 30 minutes or 18 seconds? If the former, heat is likely. If the latter, it's probably the software.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.