Converting DS3231 month number into word

Possibly a very simple task for C exponents !

I am trying to display the month number in alphabets ( Jan for 1 and so on )

The function below does not work and the month field comes out empty :frowning:

(Variable alphaMonth is char array with a size of 4 and string is a char array of size 30)

Help required...Thanks.

// READ COMPLETE DATE AND TIME INFO FROM rtc.
void readDS3231time(byte *second,
                    byte *minute,
                    byte *hour,
                    byte *dayOfWeek,
                    byte *dayOfMonth,
                    byte *month,
                    byte *year)
{
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0);                           // Set DS3231 register pointer to 00h
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 7); // Request seven bytes of data from DS3231 starting from register 00h
  *second = bcdToDec(Wire.read() & 0x7f);
  *minute = bcdToDec(Wire.read());
  *hour = bcdToDec(Wire.read() & 0x3f);
  *dayOfWeek = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
  *month = bcdToDec(Wire.read());
  *year = bcdToDec(Wire.read());

  switch (int(month)) {

    case 1:
      strcpy(alphaMonth, "Jan");
      break;
    case 2:
      strcpy(alphaMonth, "Feb");
      break;
    case 3:
      strcpy(alphaMonth, "Mar");
      break;
    case 4:
      strcpy(alphaMonth, "Apr");
      break;
    case 5:
      strcpy(alphaMonth, "May");
      break;
    case 6:
      strcpy(alphaMonth, "Jun");
      break;
    case 7:
      strcpy(alphaMonth, "Jul");
      break;
    case 8:
      strcpy(alphaMonth, "Aug");
      break;
    case 9:
      strcpy(alphaMonth, "Sep");
      break;
    case 10:
      strcpy(alphaMonth, "Oct");
      break;
    case 11:
      strcpy(alphaMonth, "Nov");
      break;
    case 12:
      strcpy(alphaMonth, "Dec");
      break;
  }

  sprintf(string, "  %02d-%s-%02d:%02d:%02d", dayOfMonth, alphaMonth, hour, minute, second);
  lcd.print(string);
}
  switch (int(month)) {

The switch statement requires integral values, not int(eger) values. Lose the useless conversion.

I'm always amazed at the number of people why convert a value to a string, then concatenate that string with another string, and get unexpected results, who then can't be bothered to determine where the failure occurred.

Do you KNOW that the value in month is reasonable?

I don’t see ‘alphaMonth’ defined anywhere. You say it’s a char of 4 but why not try to make a MCVE to convince us?

Or, just go for easy :wink: The LCD will not care if you print it in one go or not. So instead of double buffering it (and using strcpy()), just print it directly to the LCD.

And to add to PaulS, what I do know is that ‘month’ does NOT contain a month. And I think the change it’s between 1 and 12 is pretty slim :smiley:

You problem is that you convert a pointer to a number instead of reading the value to which the pointer points. Try to replace "switch (int(month))" with "switch (*month)" and see how it goes.

Spoilers! :stuck_out_tongue:

PS The function name 'readDS3231time' is pretty terrible if you let it also send it to the lcd.

And like I said, sprintf() is nice but a bit memory hungry, especially if you also let it make long strings to globals if you don't need to. :wink:

Danois90:
You problem is that you convert a pointer to a number instead of reading the value to which the pointer points. Try to replace "switch (int(month))" with "switch (*month)" and see how it goes.

Wow ..Simple and direct answer. Thanks . First shot it worked.

I can understand the anger and sarcasm in other posts but then everyone is not endowed and that exactly is the reason of asking. Possibly some things are so obvious to the experts that is so tough for the DIY guys.

@septillion

True … that was a simplified "condensation" to just highlight the issue I had. The full code after the correction suggested by Damois90 is as below . And even at the cost of repeating myself … there are some global variables which have not been declared in the snippet.

void displayHome()
{
  unsigned int static HomeCnt = 0;
  if ( HomeCnt >= 1000) {
    char string[20];
    ReadTime();
    lcd.setCursor(0, 0);
    lcd.write( "4 CHANNEL DATALOGGER" );
    lcd.setCursor(0, 1);
    sprintf(string, "Ch00=%03d ; Ch01=%03d ", ch_Value[0], ch_Value[1]);
    lcd.print(string); 
    lcd.setCursor(0, 2);
    sprintf(string, "Ch02=%03d ; Ch03=%03d ", ch_Value[2], ch_Value[3]);
    lcd.print(string); 
    lcd.setCursor(0,3);
    sprintf(string, "  %02d-%s %02d:%02d:%02d", dayOfMonth, alphaMonth, hour, minute, second);
    lcd.print(string);
    HomeCnt = 0;
  }
  else
  {
    HomeCnt += ScanMs;
  }

// READ COMPLETE DATE AND TIME INFO FROM rtc.
void readDS3231time(byte *second,
                    byte *minute,
                    byte *hour,
                    byte *dayOfWeek,
                    byte *dayOfMonth,
                    byte *month,
                    byte *year)
{
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0);                           // Set DS3231 register pointer to 00h
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 7); // Request seven bytes of data from DS3231 starting from register 00h
  *second = bcdToDec(Wire.read() & 0x7f);
  *minute = bcdToDec(Wire.read());
  *hour = bcdToDec(Wire.read() & 0x3f);
  *dayOfWeek = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
  *month = bcdToDec(Wire.read());
  *year = bcdToDec(Wire.read());

  switch (*month) {

    case 1:
      strcpy(alphaMonth, "Jan");
      break;
    case 2:
      strcpy(alphaMonth, "Feb");
      break;
    case 3:
      strcpy(alphaMonth, "Mar");
      break;
    case 4:
      strcpy(alphaMonth, "Apr");
      break;
    case 5:
      strcpy(alphaMonth, "May");
      break;
    case 6:
      strcpy(alphaMonth, "Jun");
      break;
    case 7:
      strcpy(alphaMonth, "Jul");
      break;
    case 8:
      strcpy(alphaMonth, "Aug");
      break;
    case 9:
      strcpy(alphaMonth, "Sep");
      break;
    case 10:
      strcpy(alphaMonth, "Oct");
      break;
    case 11:
      strcpy(alphaMonth, "Nov");
      break;
    case 12:
      strcpy(alphaMonth, "Dec");
      break;
  }
}

That was not sarcastic, that was aimed to make you learn. A very important tool when debugging is to isolate the problem. And making a MCVE is one of the most powerful tools for it. Snippets are fine to illustrate a technique, not to illustrate problems :wink: Because devil is in the details.

Next, but why are they global to start with? :wink:

And if you want to save memory, you could do something like

 char alphaMonth[4];
  char string[16];
  const char* PROGMEM AllMonthProgmem = "JanFebMarAprMayJunJulAugSepOctNovDec";
  
  strncpy_P(alphaMonth, AllMonthProgmem + (((*month) - 1) * 3), 3);
  alphaMonth[3] = '\0'; //don't forget to null terminate.
  
  sprintf(string, "  %02hhu-%s-%02hhu:%02hhu:%02hhu", *dayOfMonth, alphaMonth, *hour, *minute, *second);

Although sprintf() is still consuming quite a lot. Can also be replaced by multiple calls to lcd.print() but somehow people prefer little code over small code…

@septillion

strncpy_P(alphaMonth, AllMonthProgmem + ((*month) - 1), 3);
  alphaMonth[3] = '\0'; //don't forget to null terminate.

Hmm.. wish I could come up with code like that :slight_smile:

And you asked why globals... well I would say part laziness and part lack of clarity. Just make them global so I can modify them wherever I want to, without worrying about the scope thing ! Bad but.... :wink:

Thanks.

Damn it, I swear I pressed "Preview", not "Post"! Be right back writing the whole answer...

[and back]
Mm, but then you would notice it's wrong. Forgot to actually jump 3 letters at a time. Fixed it. :roll_eyes:

And about scope, I think it's more useful to learn how to use it than to make everything global. One day you will get bitten by it. You run out of memory, run into name clashes, forget another function uses the same variable to do stuff and overwrite it etc.

septillion:
Damn it, I swear I pressed "Preview", not "Post"! Be right back writing the whole answer...

strncpy_P(alphaMonth, AllMonthProgmem + (((*month)-1)*3), 3);

I copy pasted the modified code but got an error as below on the above line

invalid type argument of unary '*' (have 'byte {aka unsigned char}')

Sure you get that on that line?

Compiles fine in my MCVE (except from the uninitialized warnings)

void setup() {
  byte *second;
  byte *minute;
  byte *hour;
  byte *dayOfWeek;
  byte *dayOfMonth;
  byte *month;
  byte *year;
  
  // put your setup code here, to run once:
  char alphaMonth[4];
  char string[16];
  const char* PROGMEM AllMonthProgmem = "JanFebMarAprMayJunJulAugSepOctNovDec";
  
  strncpy_P(alphaMonth, AllMonthProgmem + (((*month) - 1) * 3), 3);
  alphaMonth[3] = '\0'; //don't forget to null terminate.
  
  sprintf(string, "  %02hhu-%s-%02hhu:%02hhu:%02hhu", *dayOfMonth, alphaMonth, *hour, *minute, *second);

}

void loop() {
  // put your main code here, to run repeatedly:

}

Attaching the screen shot of the error. I tried to use the code in the LCD printing routine after commenting out my original code for that.

As you can see if I use my original sprintf() the error is thrown on the strncpy line. If I use your sprintf() then same error thrown on that line.

Possibly I am making a mistake ?

Now that's the whole trouble with snippets :wink: And why we hate them.

Met me guess, unlike the snippet in the first post you now call readDS3231time() and do the conversion afterwards? Aka, now month isn't a pointer anymore :wink: See where I'm going? Simply remove the * in front of month.

That would also explain why I changed the sprintf() to

sprintf(string, "  %02hhu-%s-%02hhu:%02hhu:%02hhu", *dayOfMonth, alphaMonth, *hour, *minute, *second);

to handle the pointers right.