Grove 7 segment LCD driver

Hi,

In the course I want to teach, I would like the students to develop a clock with several function added one by one :
1 - Just display time
2 - Add hourly chime
3 - Add alarm and so on

I use a photon because it has a network time sync and it is very easy with the functions Time.hour() and Time.minute() to get the current time.

To display the time, I use the Seeedstudio photon shield with the Seeedstudio 7 segment LCD driver. On the build.particle.io there is a library called TM1637Display that I use and all seems correct except that I can’t find how to blink the column in the middle.

Here is my sketch :

#include <TM1637Display/TM1637Display.h>

#define CLK D4
#define DIO D5

TM1637Display displayTime(CLK,DIO);

void setup() {

}

void loop() {

    int heure = Time.hour();
    int minute = Time.minute();
    
    dispTime(heure, minute);
    
}

void dispTime(int h, int m) {
    
    uint8_t timeDisp[] = {0xff,0xff,0xff,0xff};
    displayTime.setBrightness(0x0f);
    
    if (h < 10) {
        timeDisp[0] = displayTime.encodeDigit(0);
    } else {
        timeDisp[0] = displayTime.encodeDigit(h / 10);
    }
    
    timeDisp[1] = displayTime.encodeDigit((h % 10) +2);  //To adjust hours to the correct timezone
    
    if (m < 10) {
        timeDisp[2] = displayTime.encodeDigit(0);
    } else {
        timeDisp[2] = displayTime.encodeDigit(m / 10) ;
    }
    
    timeDisp[3] = displayTime.encodeDigit(m % 10);
    
    displayTime.setSegments(timeDisp);
}

Does anyone has an idea on how to turn the column between hours and minutes ON or OFF ?

Many thanks

You can look at this doc

And off will be without this 0x80 bit set

Hi ScruffR (again),

Indeed, on the paper, it should make it !!! In the reality, not really the same. I tried that but it mess up the digit just before showing a zero like a 8 or a 1 like a one with a horizontal bar light up in the middle.

I have just spend 4 hours to dig and try to find a way to do it but … Nothing.

Francois X.

Here is the fullcode with the statement from ScruffR included:

// This #include statement was automatically added by the Particle IDE.
// Postler, tested with Photon, firmware v0.6.1, Grove 4-Digit Display and Base Shield

#include <TM1637Display.h>

#define CLK D4
#define DIO D5

TM1637Display displayTime(CLK,DIO);

void setup() {

}

void loop() {

    int heure = Time.hour();
    int minute = Time.minute();
    
    dispTime(heure, minute);
    
}

void dispTime(int h, int m) {

//ScruffR - Start
    uint8_t segto;
    int value = 1244;
    segto = 0x80 | displayTime.encodeDigit((value / 100)%10); // And off will be without this 0x80 bit set
    displayTime.setSegments(&segto, 1, 1);
//ScruffR - End

    uint8_t timeDisp[] = {0xff,0xff,0xff,0xff};
    displayTime.setBrightness(0x0f);
    
    if (h < 10) {
        timeDisp[0] = displayTime.encodeDigit(0);
    } else {
        timeDisp[0] = displayTime.encodeDigit(h / 10);
    }
    
    timeDisp[1] = displayTime.encodeDigit((h % 10) +2);  //To adjust hours to the correct timezone
    
    if (m < 10) {
        timeDisp[2] = displayTime.encodeDigit(0);
    } else {
        timeDisp[2] = displayTime.encodeDigit(m / 10) ;
    }
    
    timeDisp[3] = displayTime.encodeDigit(m % 10);
    
    displayTime.setSegments(timeDisp);
}

You can use this for custom timezone: Time.zone(+2.00); // setup a time zone, which is part of the ISO6801 format

1 Like

Back to the roots, Francois.

After I played a while with your code I can repeat your error image:

#include <TM1637Display.h>

#define CLK D4
#define DIO D5

TM1637Display displayTime(CLK,DIO);

void setup() {

}

void loop() {
    Time.zone(+2.00);  // setup a time zone, which is part of the ISO6801 format 
    int h = Time.hour();
    int m = Time.minute();

//ScruffR - Start
    uint8_t segto;
    int value = 1244;
    segto = 0x80 | displayTime.encodeDigit((value / 100)%10); // And off will be without this 0x80 bit set
    displayTime.setSegments(&segto, 1, 1);
//ScruffR - End

    
    displayTime.setBrightness(0x0f);
    
    uint8_t data[] = {0xff, 0xff, 0xff, 0xff};
    
      data[0] = displayTime.encodeDigit(h / 10);
      data[1] = displayTime.encodeDigit(h % 10);
      data[2] = displayTime.encodeDigit(m / 10);
      data[3] = displayTime.encodeDigit(m % 10);
       
    displayTime.setSegments(data); 
    
}

The problem is to showing clear the field data[1] by activated center colon.
The field flickers a bit and display wrong count.

If I deactivated segto with // the time display is right but you miss the center colon.
Sorry - no idea to fix this.

Since I have no such display I’d have to guess a bit, but as I read the code something like this should do the job

      data[0] = displayTime.encodeDigit(h / 10);
      data[1] = displayTime.encodeDigit(h % 10) | (Time.second() % 2 ? 0x80 : 0x00);
      data[2] = displayTime.encodeDigit(m / 10);
      data[3] = displayTime.encodeDigit(m % 10);
      displayTime.setSegments(data); 
2 Likes

Yea, right way - Modulo works here, Buddy!
I played a bit with delay(1000) and other brightness - but yours is good for me :grinning:
Will hope that Francois close this task and spent you a beer.

// This #include statement was automatically added by the Particle IDE.
// Postler, tested with Photon, firmware v0.6.1

#include <TM1637Display.h>

#define CLK D4
#define DIO D5

TM1637Display displayTime(CLK,DIO);

void setup() {
    displayTime.setBrightness(0xff); //set the diplay to maximum brightness
    displayTime.setBrightness(0x0a); //not so bright
}



void loop() {
    Time.zone(+2.00);  // setup a time zone, which is part of the ISO6801 format 
    int h = Time.hour();
    int m = Time.minute();

    // Set center colon on without array - Start
    uint8_t segto;
    int value = 1244;
    segto = 0x80 | displayTime.encodeDigit((value / 100)%10); // And off will be without this 0x80 bit set
    displayTime.setSegments(&segto, 1, 1);
    //delay(1000) ; // constant colon
    // End

    // Print Data array - Start
    uint8_t data[] = {0xff, 0xff, 0xff, 0xff};
    
      data[0] = displayTime.encodeDigit(h / 10);
      data[1] = displayTime.encodeDigit(h % 10) | (Time.second() % 2 ? 0x80 : 0x00);
      data[2] = displayTime.encodeDigit(m / 10);
      data[3] = displayTime.encodeDigit(m % 10);
      displayTime.setSegments(data);

}

Many thanks,

You, guys, roks !!!

Indeed, my minutes display is bit flicking but not enough to be visible for newcomers !!! But the Time.zone will definitively help me not using “If…Then…” to avoid having 25:20 at 02:20 in the morning !!!

But in this 21th century, is this 7 segment display the right display ??? I therefore goes first for the RGB LCD display which is perfect for the purpose of my training and I also tested the 64x64 OLED display which is even better. Just a bit hard to get the time in the middle of the night (unless you have very good eyes) !!!

I did then abandoned the 7 segment LCD display ( RIP ) to go for the RGB LCD display… Which bring even more use case for my training.

Many thanks all of you for your very kind and helpful help.

FX

Flickering comes back and I reduced the code again - now it works as you wish:

#include <TM1637Display.h>

#define CLK D4
#define DIO D5

TM1637Display displayTime(CLK,DIO);

void setup() {
    displayTime.setBrightness(0xff); //set the diplay to maximum brightness
//    displayTime.setBrightness(0x0a); //not so bright
}

void loop() {
    Time.zone(+2.00);  // setup a time zone, which is part of the ISO6801 format 
    int h = Time.hour();
    int m = Time.minute();

    // Print Data array - Start
    uint8_t data[] = {0xff, 0xff, 0xff, 0xff};
    
      data[0] = displayTime.encodeDigit(h / 10);
      data[1] = displayTime.encodeDigit(h % 10) | (Time.second() % 2 ? 0x80 : 0x00);
      data[2] = displayTime.encodeDigit(m / 10);
      data[3] = displayTime.encodeDigit(m % 10);
      displayTime.setSegments(data);
    
}

@postler, the Time.zone() only needs to be called once on startup and next time when MESZ/MEZ changes :wink:
Not required each iteration of loop().

You can also drop theinitialisation of the data[] array as you assign a value to each element anyhow.
Or you just do

void loop() {
  static int s = 0;
  if (Time.second() != s) { // refresh only when second changes, should reduce flicker too
    int h = Time.hour();
    int m = Time.minute();
    s = Time.second();

    uint8_t data[] = 
    { displayTime.encodeDigit(h / 10)
    , displayTime.encodeDigit(h % 10) | (s % 2 ? 0x80 : 0x00)
    , displayTime.encodeDigit(m / 10)
    , displayTime.encodeDigit(m % 10)
    }
    displayTime(data, 0, sizeof(data) / sizeof(data[0])); // always guard against buffer overflow ;-)
  }
}

Many thanks @Postler and @ScruffR,

I was very busy and will try the code try later tonight.

Just one thing I don’t get. When you decalre the data[] array, on the second line, you “pipe” the (if s % 2…). What does the “Pipe” (|) do ?

Many thanks

Francois X.

That is a binary OR operation which in this case sets the most significant bit (0x80) in that byte (or not with 0x00)

Hummmmm ! I should look so stupid !!! Effectivelly, just mist that !!