7 segment digital clock

Hi all,

I’m currently trying to make a digital clock using an uno, a DS3231 RTC and a serial 7 segment display.

Using code i’ve found through googling etc i’ve got the RTC printing fine to the serial monitor, but when it prints to the 7 segment display its not using the 3rd set of 7 segments. It shows “12 3”. See below for my attempt at mashing bits of code together. The stuff after — may be pointless but I’d thought I’d leave it in just in case.

#include <Wire.h> // Include the Arduino SPI library
#include <DS3231.h>

DS3231 rtc(SDA, SCL);

// Here we'll define the I2C address of our S7S. By default it
//  should be 0x71. This can be changed, though.
const byte s7sAddress = 0x71;

char tempString[10];  // Will be used with sprintf to create strings

void setup()
{
  Wire.begin(); // Initialize hardware I2C pins

  Serial.begin(9600);

  rtc.begin();

  // The following lines can be uncommented to set the date and time
  rtc.setDOW(SUNDAY);     // Set Day-of-Week to WEDNESDAY
  rtc.setTime(12,34, 0);     // Set the time to 12:00:00 (24hr format)
  rtc.setDate(9,04,2017);   // Set the date to February 22nd, 2017

  // Clear the display, and then turn on all segments and decimals
  clearDisplayI2C();  // Clears display, resets cursor

  // Custom function to send four bytes via I2C
  //  The I2C.write function only allows sending of a single
  //  byte at a time.
  s7sSendStringI2C("0000");
  setDecimalsI2C(0b111111);  // Turn on all decimals, colon, apos

  // Flash brightness values at the beginning
  setBrightnessI2C(0);  // Lowest brightness
  delay(1500);
  setBrightnessI2C(255);  // High brightness
  delay(1500);

  // Clear the display before jumping into loop
  clearDisplayI2C();  
}

void loop()
{
  // Send Day-of-Week
  Serial.print(rtc.getDOWStr());
  Serial.print(" ");
  
  // Send date
  Serial.print(rtc.getDateStr());
  Serial.print(" -- ");

  // Send time
  Serial.println(rtc.getTimeStr());
  
  // Wait one second before repeating :)
  delay (1000);
  
  // Magical sprintf creates a string for us to send to the s7s.
  sprintf(tempString, rtc.getTimeStr());

  // This will output the tempString to the S7S
  s7sSendStringI2C(tempString);

  // Print the decimal at the proper spot
  
  delay(100);  // This will make the display update at 10Hz.*/
}

---
// This custom function works somewhat like a serial.print.
//  You can send it an array of chars (string) and it'll print
//  the first 4 characters in the array.
void s7sSendStringI2C(String toSend)
{
  Wire.beginTransmission(s7sAddress);
  for (int i=0; i<4; i++)
  {
    Wire.write(toSend[i]);
  }
  Wire.endTransmission();
}

// Send the clear display command (0x76)
//  This will clear the display and reset the cursor
void clearDisplayI2C()
{
  Wire.beginTransmission(s7sAddress);
  Wire.write(0x76);  // Clear display command
  Wire.endTransmission();
}

The code you supplied will not compile because some of the function definitions are missing eg setDecimalsI2C(). A complete example with all the helper functions is here.

If you are having trouble formatting the display, you should look at the example which contains:

  // Magical sprintf creates a string for us to send to the s7s.
  //  The %4d option creates a 4-digit integer.
  sprintf(tempString, "%4d", counter);

Your attempt at sprintf() :

sprintf(tempString, rtc.getTimeStr());

is lacking the formatting characters which, in the example above, is printing 4 decimal digits. What you have to do is discover which formatting characters are necessary to extract 4 digits out of the data returned by rtc.getTimeStr(). Do a Serial.print of the results of rtc.getTimeStr() and post these here if you need help in determining the correct formatting characters.

Thanks for the response.

The code does compile. setDecimalsI2C() is in void setup but all it does is turn on and off the decimal points, colons and commas so it doesn't affect the 7 segments.

The serial monitor displays the time in the follow format. 12:46:04

Looking at the DS3231.h file the lines relating to it are

Time getTime(); void setTime(uint8_t hour, uint8_t min, uint8_t sec);

char *getTimeStr(uint8_t format=FORMAT_LONG);

If I'm understand you right I need to format it in 2 2digit integers?

The code does compile. setDecimalsI2C() is in void setup but all it does is turn on and off the decimal points, colons and commas so it doesn't affect the 7 segments.

I was not aware that the compiler would neglect to complain about a function call, where the matching function definition is missing, if it determines that the call to that function would not have done anything useful in the user's code. A high level of optimisation must be involved here.

Anyway, sprint() is not really useful here because you need to eliminate characters from the input stream, in this case the ':' character and I don't believe that this can easily be achieved with this.

Try something like this to send the time to the display:

  // This will output the tempString to the S7S
  // getTimeStr() returns a String of sample format "12:46:04"
  s7sSendStringI2C( (rtc.getTimeStr()).substring(0,2) + (rtc.getTimeStr()).substring(3,5)  );

I guess you are using this: ? I couldn't find the library itself.

Yeah i’m not sure why it ignored the lack of function call, I’m pretty new to coding which is why i’m just trying to adapt other peoples.

I get this error when it tries to compile that line of code

display2:91: error: request for member ‘substring’ in ‘rtc.DS3231::getTimeStr(2u)’, which is of non-class type ‘char*’

See attached for the DS3231 library.

DS3231.h (3.04 KB)

OK. The documentation says the datatype returned by rtc.getTimeStr() is String. The header file states that it is a character array.

Maybe something like this will work. Untested:

// This will output the tempString to the S7S
// getTimeStr() returns a String of sample format "12:46:04"

char tv[5] ;
tempString = rtc.getTimeStr() ;
strncpy ( tv[0], tempString[0] ,  2   ) ;
strncpy ( tv[2], tempString[3] ,  2   ) ;
tv[4] = 0 ;
Serial.println( tv ) ;
s7sSendStringI2C( String( tv )  );

It doesn’t seem to like that at all, see error message below.

E:\Nathan\Programming\display2\display2.ino: In function 'void loop()':

display2:90: error: incompatible types in assignment of 'char*' to 'char [10]'

 tempString = (rtc.getTimeStr()) ;

            ^

E:\Nathan\Programming\display2\display2.ino:91:15: warning: invalid conversion from 'char' to 'char*' [-fpermissive]

 strncpy ( tv[0], tempString[0] ,  2   ) ;

               ^

In file included from C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/Arduino.h:25:0,

                 from sketch\display2.ino.cpp:1:

c:\program files (x86)\arduino\hardware\tools\avr\avr\include\string.h:449:14: note: initializing argument 1 of 'char* strncpy(char*, const char*, size_t)'

 extern char *strncpy(char *, const char *, size_t);

              ^

E:\Nathan\Programming\display2\display2.ino:91:30: warning: invalid conversion from 'char' to 'const char*' [-fpermissive]

 strncpy ( tv[0], tempString[0] ,  2   ) ;

                              ^

In file included from C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/Arduino.h:25:0,

                 from sketch\display2.ino.cpp:1:

c:\program files (x86)\arduino\hardware\tools\avr\avr\include\string.h:449:14: note: initializing argument 2 of 'char* strncpy(char*, const char*, size_t)'

 extern char *strncpy(char *, const char *, size_t);

              ^

E:\Nathan\Programming\display2\display2.ino:92:15: warning: invalid conversion from 'char' to 'char*' [-fpermissive]

 strncpy ( tv[2], tempString[3] ,  2   ) ;

               ^

In file included from C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/Arduino.h:25:0,

                 from sketch\display2.ino.cpp:1:

c:\program files (x86)\arduino\hardware\tools\avr\avr\include\string.h:449:14: note: initializing argument 1 of 'char* strncpy(char*, const char*, size_t)'

 extern char *strncpy(char *, const char *, size_t);

              ^

E:\Nathan\Programming\display2\display2.ino:92:30: warning: invalid conversion from 'char' to 'const char*' [-fpermissive]

 strncpy ( tv[2], tempString[3] ,  2   ) ;

                              ^

In file included from C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/Arduino.h:25:0,

                 from sketch\display2.ino.cpp:1:

c:\program files (x86)\arduino\hardware\tools\avr\avr\include\string.h:449:14: note: initializing argument 2 of 'char* strncpy(char*, const char*, size_t)'

 extern char *strncpy(char *, const char *, size_t);

              ^

exit status 1
incompatible types in assignment of 'char*' to 'char [10]'

I've done a quick test with this which you may also try:

  // This will output the tempString to the S7S
  // getTimeStr() returns a String of sample format "12:46:04"

  char tv[5] ;
  strcpy( tempString,  rtc.getTimeStr() ) ;
  Serial.print( "tempString: " ) ;
  Serial.println( tempString ) ;
  strncpy ( &tv[0], &tempString[0] ,  2   ) ;
  strncpy ( &tv[2], &tempString[3] ,  2   ) ;
  tv[4] = 0 ;
  Serial.println( tv ) ;
  s7sSendStringI2C( String( tv )  );

Works perfectly! Thanks so much for all your help!