Glancy, flickering leds, Arduino & MAX7219 and CC-led array

@PaulRB and @ruilviana,

I'm sorry I didn't read your replies 18, 19 and 20.
I was on tour and after returning home I made another test and failed again.
test2.ino is a little bit different: I count pulses to extract seconds, minutes and hours.
My new idea was a switch-case routine, but the result is negative. Only the led ME1, the first in row one is "on" or "off", accordingly to the decoded time. The routine TicTac() works well, as in all other clocks I built.
But I make at least one mistake in the switch-case routine.
In the program i decoded only the minutes, after I realised, that I can't light up only one led, the first, who shows that one minute has gone. This works well, all the time the minutes are odd.

The led with the name "Sec_P", the last in row two, flashes every second.
That is the only success I hat today.
What is my fault?

Yous sincerely bolsak.

Here I'm again, I forgot to send you the program test2.ino

/* test2.ino an array with 14 leds
                    Fehler:
*/
uint8_t ME1, ME2, ME4, ME8, MZ1, MZ2, MZ4, SE1, SE2, SE4, SE8, SZ1, SZ2, Sec_P;

uint8_t Display[2][8] { { ME1, ME2, ME4, ME8, MZ1, MZ2, MZ4, SE1 },
  { SE2, SE4, SE8, SZ1, SZ2, Sec_P}
};

#include <SPI.h>           // ME1=minute_ones,ME2=minute_twos,ME4=minute_fours
#include <avr/pgmspace.h>  // MZ1=minute_tens,MZ2=minute_twenties, and so on
#include <stdbool.h>       // SE1=hours_ones, and so on
                           // SZ1=hours_tens, Sec_P flashes every second
uint8_t state;
enum { one, two, three, four, five, six, seven,
       eigth, nine, ten, eleven, twelve, thirteen, fourteen
     };

const byte MAX7219_REG_NOOP        = 0x0;
const byte MAX7219_REG_DIGIT0      = 0x1;   //
const byte MAX7219_REG_DIGIT1      = 0x2;   //
const byte MAX7219_REG_DIGIT2      = 0x3;   //
const byte MAX7219_REG_DIGIT3      = 0x4;   //
const byte MAX7219_REG_DIGIT4      = 0x5;   //
const byte MAX7219_REG_DIGIT5      = 0x6;   //
const byte MAX7219_REG_DIGIT6      = 0x7;   //
const byte MAX7219_REG_DIGIT7      = 0x8;   //
const byte MAX7219_REG_DIGIT8      = 0x9;   //
const byte MAX7219_REG_DECODEMODE  = 0x9;   //
const byte MAX7219_REG_INTENSITY   = 0xA;
const byte MAX7219_REG_SCANLIMIT   = 0xB;
const byte MAX7219_REG_SHUTDOWN    = 0xC;
const byte MAX7219_REG_DISPLAYTEST = 0xF;

bool ledState = LOW;
//bool State;
uint32_t previousMillis_1, currentMillis_1;
const uint32_t Interval_1 = 75;
const byte ledPin  = 19;     //
uint32_t count;
uint8_t second, minute, hour;

void setup() {   //
  Serial.begin(115200);
  SPI.begin ();
  sendByte (MAX7219_REG_SCANLIMIT, 2);     // show 2 rows
  sendByte (MAX7219_REG_DECODEMODE, 0);    //
  sendByte (MAX7219_REG_DISPLAYTEST, 0);   // no display test
  sendByte (MAX7219_REG_INTENSITY, 10);    // range: 0 to 15
  sendByte (MAX7219_REG_SHUTDOWN, 1);      // 1 = KEIN shutdown mode

  Serial.println(" ====================================== ");
  Serial.println(" ======== test2.ino ==================== ");
  Serial.println(" ======================  29.12.21 ===== ");
  pinMode(ledPin, OUTPUT);
  for (byte col = 0; col < 8; col++)     // clear Display
  {
    sendByte(col + 1, 0);
  }

}                               //

void sendByte (const byte reg, const byte data)    {
  digitalWrite (SS, LOW);
  SPI.transfer (reg);
  SPI.transfer (data);
  digitalWrite (SS, HIGH);
}  // end of sendByte

void blink() {
  unsigned long currentMillis_1 = millis();
  if (currentMillis_1 - previousMillis_1 >= Interval_1)
  { previousMillis_1 = currentMillis_1;
    ledState == LOW ? ledState = HIGH :    ledState = LOW;
    if (ledState == HIGH) {
      count++;
    }
    digitalWrite(ledPin, ledState);
  }
}

void TicTac() {
  if (ledState == HIGH) {
    count++;
  }
  if (count % 50 == 0) {
    second++;
  }
  if (second > 59)  {
    minute++;
    second = 0;
  }
  if (minute > 59)  {
    hour++;
    minute = 0;
  }
  if (hour > 23 && minute > 59)  {
    hour = 0;
  }

  minute % 10 & 0B00000001 ? ME1 = 128  : ME1 = 0;
  minute % 10 & 0B00000010 ? ME2 =  64  : ME2 = 0;
  minute % 10 & 0B00000100 ? ME4 =  32  : ME4 = 0;
  minute % 10 & 0B00001000 ? ME8 =  16  : ME8 = 0;

  minute / 10 & 0B00000001 ? MZ1 =   8  : MZ1 = 0;
  minute / 10 & 0B00000010 ? MZ2 =   4  : MZ2 = 0;
  minute / 10 & 0B00000100 ? MZ4 =   2  : MZ4 = 0;

  count % 50 < 25 ? sendByte(2, 4) : sendByte(2, 0); // flashes every second
}

void loop() {
  TicTac();
  blink();
  switch (state) {
    case one:   sendByte(1, ME1);  break;
    case two:   sendByte(1, ME2);  break;
    case three: sendByte(1, ME4);  break;
    case four:  sendByte(1, ME8);  break;

    case five:  sendByte(1, MZ1);  break;
    case six :  sendByte(1, MZ2);  break;
    case seven: sendByte(1, MZ4);  break;
  }
  Serial.print(" ME1: "); Serial.print(ME1);
  Serial.print(" ME2: "); Serial.print(ME2);
  Serial.print(" ME4: "); Serial.print(ME4);
  Serial.print(" ME8: "); Serial.print(ME8);

  Serial.print(" MZ1: "); Serial.print(MZ1);
  Serial.print(" MZ2: "); Serial.print(MZ2);
  Serial.print(" MZ4: "); Serial.print(MZ4);

  Serial.print("   sec "); Serial.print(second);
  Serial.print("  min "); Serial.print(minute);
  Serial.print("   count "); Serial.print(count);
  Serial.println();
}

Same as before. I guess you are finding it difficult to understand what I'm trying to tell you, but you do not want to admit this, perhaps out of politeness.

@PaulRB,
I'm verry sorry if you think I am discourteous and beg your pardon.
I read your post #18 after I had sent #22 to the forum.

My difficult writing in test.ino makes no trouble to me and I have no difficulties, when I read my program :
sendByte(1,128); or sendByte(1,Display[0][0]); . Both expressions are equal.
If I send them to the MAX, the result is, when there are no other faults,the first led of my array is . In the first example I send the value of the MSB (=128) and in the second example I send the content of the first element of the array Display[0][0] (=128) to the MAX.

When I write sendByte(1,Display[0][7]); then I send to the MAX the eigth element of my array, or the LSB (=1). That is the same as sendByte(1,1). Then the 8th led is . That is in my program . Different values deliver different results.

In my TicTac()-routine is the decoding of the values of the bits, to send to the MAX: ME1 = minutes_ones 1, ME2 = minutes_ones 2,
ME4 = minutes_fours 4, ME8 = minutes_ones 8.
MZ1 = minutes_tens 1, MZ2 = minutes_tens 2,
MZ4 = minutes_tens 4 .
In the same manner for the hours: SE1 .... SE8 and SZ1, SZ2.
Therefor I don't need to send two values in one assign.

When I will read the actual time, I must add all the values of the bits.
The leds are arranged in 4 vertically columns.
At left 2 for hours-tens, then 4 for the hours-ones, next 3 for the minutes-tens and on the right 4 for the minutes-ones. The most significant value is on top.

The Sec_P led flashes, when a second has passed, is on top of the hours-tens led.

My problem is the "unequal lighting" of the leds, due to the scanning of the MAX. To get rid of this, I tried in test2.ino a switch-case routine.

But I failed again. Only the led ME1 is on or off, according to the actual time, all the others are off. But the values sent to the MAX are correct.
I don't know, what to do.

Sincerely bolsak.

As you were told in post #4, it is not due to the scanning of the max chip, it is caused by the high frequency of updates the max is receiving from your code, which may be several hundred per second. 2 updates per second are required, I think.

But you do need that. For example when minutes is 7, you need to light 3 LEDs. You need to send a single update to the max chip to make 3 LEDs light together. If you send an update to light only the first of those 3 LEDs, and then send a second update to light the second of the 3 LEDs, the first led will be switched off again. When you send the third update, the second led gets switched off. This is what makes your LEDs flicker and be dim.

Only that ME1 value is ever sent to the max chip. Your switch-case is controlled by the variable "state" which is always zero and is never changed.

But the switch-case was the totally the wrong idea, it can never fix your problem. You need to combine the values and update the max chip only when the result has changed.

Hi @bolsak
Have you tested the code I posted in #20?

I do not think that at all. I am concerned that your politeness is preventing you from saying that you do not understand or do not believe what I am describing to you.

@ruilviana
Thank you for the code in post #20.
I don't need code for a clock. My problem is the unequal lighting of all the leds, who are needed, to show the actual time. I will try another idea, proposed from PaulRB.

At the end of this post i add an image of the prototype of my clock.
The small led ( 5 mm) in top of the left vertical row flashes every second.
The bigger leds show the time, the left two the ten hours. Ten is on the bottom, twenty above it. In the same manner for the one hours, of course there are four: hours_one value 1, hours_one value 2, and 4 and 8.
The third row from left are minutes_tens, only three leds and at the right side the minute_ones.

To get the actual time you must read all lighting leds and add their values.
After a little bit of training it is as easy as any other clock.

@PaulRB
In post 25 you wrote that i need to send three values, when the 7 minutes are gone. Until now I thought, that this is the case, when I in my TitTac-routine the comparison minute%10 & 0B00000001 or 0B00000010 or 0B00000100 is made.
The knowledge, that the MAX needs 3 values at the same time, is new for me. That mislead me to the switch-case-rouine. I thought, the variable "state" is actualised by passing case one, case two and so on.
Still learning every day.
I will try another method and let you know and see.
I shure you that I believe you, but my understanding is another thing.

I wish you and all other fellows in our forum

                          Happy New Year and good luck all the time.

Sincerely bolsak.

Happy New Year to all of You.

Hi, here I am again to report my last results.
Finally I got my leds shining bright. I changed my test and display a fixed time.
Here is my program:

/* test.ino an array with 14 leds & a fixed value
   time = 23:37 h 
   the leds ME1,ME2,ME4,MZ1,MZ4,SE1,SE2,SZ2 are "on"
*/
byte     ME1, ME2, ME4, ME8,   MZ1, MZ2, MZ4,     //
         SE1, SE2, SE4, SE8,   SZ1, SZ2,      Sec_P;

byte  Display[2][8] { {0, 0, 0, 0, 0, 0, 0, 0 },
                      {0, 0, 0, 0, 0, 0, 0, 0 }
};

#include <SPI.h>
#include <avr/pgmspace.h>
#include <stdbool.h>
//
const byte MAX7219_REG_NOOP        = 0x0;
const byte MAX7219_REG_DIGIT0      = 0x1;   //
const byte MAX7219_REG_DIGIT1      = 0x2;   //
const byte MAX7219_REG_DIGIT2      = 0x3;   //
const byte MAX7219_REG_DIGIT3      = 0x4;   //
const byte MAX7219_REG_DIGIT4      = 0x5;   //
const byte MAX7219_REG_DIGIT5      = 0x6;   //
const byte MAX7219_REG_DIGIT6      = 0x7;   //
const byte MAX7219_REG_DIGIT7      = 0x8;   //
const byte MAX7219_REG_DIGIT8      = 0x9;   //
const byte MAX7219_REG_DECODEMODE  = 0x9;   //
const byte MAX7219_REG_INTENSITY   = 0xA;
const byte MAX7219_REG_SCANLIMIT   = 0xB;
const byte MAX7219_REG_SHUTDOWN    = 0xC;
const byte MAX7219_REG_DISPLAYTEST = 0xF;

bool ledState = LOW;                    // blinking
uint32_t previousMillis, currentMillis;
const uint32_t Interval = 1000;
const byte ledPin  = 19;     //
uint8_t second, minute, hour;

void setup() {   //             =================== setup

  Serial.begin(115200);
  SPI.begin ();
  sendByte (MAX7219_REG_SCANLIMIT, 2);     // show 2 rows
  sendByte (MAX7219_REG_DECODEMODE, 0);    // single leds
  sendByte (MAX7219_REG_DISPLAYTEST, 0);   // no display test
  sendByte (MAX7219_REG_INTENSITY, 10);    // range: 0 to 15
  sendByte (MAX7219_REG_SHUTDOWN, 1);      // 1 = KEIN shutdown mode

  for (byte col = 0; col < 8; col++)       // clear display
    sendByte (col + 1, 0);

  Serial.println(" ====================================== ");
  Serial.println(" ======== test.ino ==================== ");
  Serial.println(" ======================== 5. 1.22 ===== ");
  pinMode(ledPin, OUTPUT);
  minute = 57, hour = 23;                     // time to display
}

void sendByte (const byte reg, const byte data)    {
  digitalWrite (SS, LOW);
  SPI.transfer (reg);
  SPI.transfer (data);
  digitalWrite (SS, HIGH);
}  // end of sendByte

void blink() {
  uint16_t currentMillis = millis();
  if (currentMillis - previousMillis >= Interval)
  { previousMillis = currentMillis;
    ledState == LOW ? ledState = HIGH :    ledState = LOW;
    digitalWrite(ledPin, ledState);
  }
}

void loop() {   //   ================================
  blink();

  minute % 10 & 0B00000001 ? ME1 = 128  : ME1 = 0; //
  minute % 10 & 0B00000010 ? ME2 =  64  : ME2 = 0;
  minute % 10 & 0B00000100 ? ME4 =  32  : ME4 = 0;
  minute % 10 & 0B00001000 ? ME8 =  16  : ME8 = 0;

  minute / 10 & 0B00000001 ? MZ1 =   8  : MZ1 = 0;
  minute / 10 & 0B00000010 ? MZ2 =   4  : MZ2 = 0;
  minute / 10 & 0B00000100 ? MZ4 =   2  : MZ4 = 0;

  hour   % 10 & 0B00000001 ? SE1 =   1  : SE1 = 0;
  hour   % 10 & 0B00000010 ? SE2 = 128  : SE2 = 0;
  hour   % 10 & 0B00000100 ? SE4 =  64  : SE4 = 0;
  hour   % 10 & 0B00001000 ? SE8 =  32  : SE8 = 0;

  hour   / 10 & 0B00000001 ? SZ1 =  16  : SZ1 = 0;
  hour   / 10 & 0B00000010 ? SZ2 =   8  : SZ2 = 0;

  sendByte(1, ME1 + ME2 + ME4 + ME8 + MZ1 + MZ2 + MZ4 + SE1);
  sendByte(2, SE2 + SE4 + SE8 + SZ1 + SZ2);

  Serial.print(" test: ");
  SZ1 != 0 ? Serial.print("*") : Serial.print("-");
  SZ2 != 0 ? Serial.print("*") : Serial.print("-");
  Serial.print(" ");
  SE1 != 0 ? Serial.print("*") : Serial.print("-");
  SE2 != 0 ? Serial.print("*") : Serial.print("-");
  SE4 != 0 ? Serial.print("*") : Serial.print("-");
  SE8 != 0 ? Serial.print("*") : Serial.print("-");
  Serial.print(" ");
  MZ1 != 0 ? Serial.print("*") : Serial.print("-");
  MZ2 != 0 ? Serial.print("*") : Serial.print("-");
  MZ4 != 0 ? Serial.print("*") : Serial.print("-");
  Serial.print(" ");
  ME1 != 0 ? Serial.print("*") : Serial.print("-");
  ME2 != 0 ? Serial.print("*") : Serial.print("-");
  ME4 != 0 ? Serial.print("*") : Serial.print("-");
  ME8 != 0 ? Serial.print("*") : Serial.print("-");

  Serial.print("   time :"); Serial.print(hour);
  Serial.print(":"); Serial.print(minute);
  Serial.println();
}

Sincerely bolsak.

Hi, here I am again and my problem is solved.
When I started this thread, i did not know, how to use the MAX7219 in decodemode 0.

Before i used decodemode 0F, to drive a 4 digit 7 segment display, found in an old
microwave oven. This lost by and by several segments and I had to look for a substitute.

My program test1.ino shows all the necessary ten digits 0 . . 9 and a space, which I need for my clock.
The double colon between the hours ones and the minutes tens are two extra leds, controlled by UNO port 18.
The array consists of 4 columns and 7 rows, so one MAX can drive 2 digits. In this case only 26 leds are necessary, two are not used.

/* test1.ino
  an array with 4x7 leds displays the digits  0.. 9 + space
the leds are wired as common cathode to replace a 7 segment display
as well as in my first program test.ino
*/

#define digit10 space

byte const digits_font [11][7] PROGMEM = {
  { 0x06, 0x09, 0x09, 0x09, 0x09, 0x09, 0x06 }, // 0
  { 0x02, 0x06, 0x02, 0x02, 0x02, 0x02, 0x07 }, // 1
  { 0x06, 0x09, 0x01, 0x02, 0x04, 0x08, 0x0F }, // 2
  { 0x0E, 0x01, 0x01, 0x06, 0x01, 0x01, 0x0E }, // 3
  { 0x08, 0x0A, 0x0A, 0x0F, 0x02, 0x02, 0x02 }, // 4
  { 0x0F, 0x08, 0x08, 0x0E, 0x01, 0x01, 0x0E }, // 5
  { 0x07, 0x08, 0x08, 0x0E, 0x09, 0x09, 0x06 }, // 6
  { 0x0F, 0x01, 0x02, 0x04, 0x08, 0x08, 0x08 }, // 7
  { 0x06, 0x09, 0x09, 0x06, 0x09, 0x09, 0x06 }, // 8
  { 0x06, 0x09, 0x09, 0x07, 0x01, 0x01, 0x0E }, // 9
  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // = space
};

const byte ledPin =  19;
bool ledState = LOW;
unsigned long previousMillis = 0;
const unsigned long interval = 500;
unsigned long previousMillis1;
const unsigned long interval_1 = 10;

#include <SPI.h>

const byte MAX7219_REG_NOOP         = 0x0;
const byte MAX7219_REG_DIGIT0       = 0x1; // 1. LED-Reihe
const byte MAX7219_REG_DIGIT1       = 0x2;
const byte MAX7219_REG_DIGIT2       = 0x3;
const byte MAX7219_REG_DIGIT3       = 0x4;
const byte MAX7219_REG_DIGIT4       = 0x5;
const byte MAX7219_REG_DIGIT5       = 0x6;
const byte MAX7219_REG_DIGIT6       = 0x7;
const byte MAX7219_REG_DIGIT7       = 0x8; // 8. LED-Reihe
const byte MAX7219_REG_DECODEMODE   = 0x9;
const byte MAX7219_REG_INTENSITY    = 0xA;
const byte MAX7219_REG_SCANLIMIT    = 0xB;
const byte MAX7219_REG_SHUTDOWN     = 0xC;
const byte MAX7219_REG_DISPLAYTEST  = 0xF;

void setup()  {
  Serial.begin(115200);
  Serial.println("=======================================");
  Serial.println("======= 4x7.ino ======================");
  Serial.println("======================== 12.1.22 =======");
  SPI.begin();
  pinMode(ledPin, OUTPUT);

  sendByte (MAX7219_REG_SCANLIMIT, 7);   //  all, 0 ... 7
  sendByte (MAX7219_REG_DECODEMODE, 0);  //  single LED
  sendByte (MAX7219_REG_DISPLAYTEST, 0); //  Anzeige=0, Test=1
  sendByte (MAX7219_REG_INTENSITY, 0);   // 0 .. 15
  sendByte (MAX7219_REG_SHUTDOWN, 1);    // 1 = KEIN Abschalten

  for (byte col = 0; col < 8; col++)     // clear Display
  {
    sendByte(col + 1, 0);
  }
}

void sendByte(const byte reg, const byte data)
{ digitalWrite(SS, LOW);
  SPI.transfer (reg);
  SPI.transfer (data);
  digitalWrite(SS, HIGH);
}

void digit (const byte c)                // only 7 rows!!
{
  for (byte col = 0; col < 7; col++)
    sendByte (col + 1, pgm_read_byte (&digits_font [c] [col]));
}

void clear() {
  for (byte col = 0; col < 8; col++)     // clear Display
  {
    sendByte(col + 1, 0);
  }
}

void blink() {
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval)
  { previousMillis = currentMillis;
    ledState == LOW ? ledState = HIGH :    ledState = LOW;
    digitalWrite(ledPin, ledState);
  }
}

void loop() {    //===========================================
  static uint16_t count;

  blink();
  for (byte k = 0; k < 11; k++)
  { digit(k);
    Serial.print(k);
    delay(1000);
  }

//  clear();
  count++;
  Serial.print("  LOOP : ");  Serial.print(count);
  Serial.println();
}

I thank you all for the replies to my thread. I am still learning every day.

Sincerely bolsak.

I am glad that you are happy. But I'm also confused, and so will anyone else reading this topic. At first, it seemed like your LEDs were indicating the time in a binary or binary-coded-decimal way. But in your last post I think this changed? Is it now a conventional 4x7 led matrix that can display a decimal digit? You say there are only 26 LEDs, not 4x7=28, and that somehow it can display 2 digits?

Hi, PaulRB.

I'm verry sorry, that you are confused, the last sentence of my reply is nonsense.

My program In post 30 I demonstrates, that my 13 leds, how they are arranged is to see in post 29, show the fixed time (=23:57 h) bcd-coded. They are bright and the "glancy" flickering disappeared.

Now I know, how to handle the MAX in decodemode 0.

My last post is my next project: to replace a 4 digit 7-segment-display with single leds.
To minimize the amount of leds my array consists of 4x7 leds.
But two of them not used, they are not necessary to show the digits from null to nine.

The more I write in the forum, the better my english conversation?

Greetings bolsak.