Where is this string composed? RTC Serial communication.

Hello.
I am building a project that would have some user inputs and outputs.

It will also have an RTC that would tell the system to check sensors
and to adjust the environment based on the data obtained from those sensors.

My system is going to be a more advanced version of this:

I have an RTC, ds3234. The example program that I am trying to build my project from is spitting out data over the Serial communication: 2011.11.19 21:01:13
I know how to set time and I will give my microcontroller project user an ability to do that with ease.

What I don't get is what this code does:

 DS3234_get(cs, &t);
        snprintf(buff, BUFF_MAX, "%d.%02d.%02d %02d:%02d:%02d", t.year,
             t.mon, t.mday, t.hour, t.min, t.sec);

I don't understand the commands such as .%02d that are used in the parameters of this operator.
I had no luck finding what they stand for on all the C, C++ websites out there.
Only a limited explanation of what the snprintf(); does.

I am not even sure if this operator formulates the string that I see.
By using a pointer, I suppose, I can read individual parts of the RTC code that would be my years, days, seconds, ETC.
Am I correct?

I am not quite sure how that pointer works. I know that all the data has a predictable position in the string and a fixed length.
Where is the list of those positions and lengths? Where does it say that a year is four digits long? (YYYY)

How can I extract individual char data from this string at minimal cost to the memory?
I will need to set two alarms - every 5 minutes and every 30 minute.

Those alarms would need to scan the sensors, make adjustments to humidity, temperature, etc.
If the system is runaway - too cold, doors are open, the system will timeout.
It will calculate that adding heat and humidity cannot accomplish the right changes in the right time-frame.
This is a safety feature.

Second question:
There is a special wake up pin on the ds3234.
I don't know if the module that it is soldered to has an output for that pin.
I have access to SS, MOSI, MISO, CLK, SQW, VCC, GND
All but SQW are used and I know what they do.

Is it possible to have the timer wake up Arduino, as well as the user touch of the Pseudo I2C touchpad?

Thank you.

I had no luck finding what they stand for on all the C, C++ websites out there.
Only a limited explanation of what the snprintf(); does.

Please tell me this is a wind-up

Where does it say that a year is four digits long? (YYYY)

It doesn't.

VT91:
I don't understand the commands such as .%02d that are used in the parameters of this operator.
I had no luck finding what they stand for on all the C, C++ websites out there.
Only a limited explanation of what the snprintf(); does.

they are the C format specifiers

How does the program know that it needs to extract 4 digits for a year?

YYYY as in a year 1997 or 2017.

How do I modify the program to print me just the year? Thank you.

VT91:
How does the program know that it needs to extract 4 digits for a year?

YYYY as in a year 1997 or 2017.

it is extracting an integer. (did you look at the format specifiers?)

years recently tend to be four digits :wink:

How does it know from where to where to extract?

VT91:
How does it know from where to where to extract?

did you read about format specifiers? it will clarify how that string is built

There is a time object called "t"

the sprintf function is taking the members of the struct:

DS3234_get(cs, &t);
        snprintf(buff, BUFF_MAX, "%d.%02d.%02d %02d:%02d:%02d", t.year,
             t.mon, t.mday, t.hour, t.min, t.sec);

like t.mon (month) t.hour (the hour), etc.... and building a string.

if you posted all of your code, we could show you where the "t" is created/updated

Somewhere in your code you have declared a variable 't' of type 'tm struct'. The 'tm struct' will look like below (from man ctime(3))

struct tm {
    int tm_sec;         /* seconds */
    int tm_min;         /* minutes */
    int tm_hour;        /* hours */
    int tm_mday;        /* day of the month */
    int tm_mon;         /* month */
    int tm_year;        /* year */
    int tm_wday;        /* day of the week */
    int tm_yday;        /* day in the year */
    int tm_isdst;       /* daylight saving time */
};

In your mind, remove the 'tm_'.

You fill that variable when you call DS3234_get(); it's the second argument for that function. So now t.year (or t.tm_year) contains the year. If you want to see how it exactly works, you will have to analyse the libraries that you use.

As indicated, read up on the format specifiers. %d prints a number, %2d prints a number with a minimum of two places (padded with a leading spaces) and %02d prints a number with a minimum of two places (padded with leading zeroes).

There is no tm struct, yet there is struct ts t;
Is it a similar operator? I am still confused.

Thank you.

VT91:
There is no tm struct, yet there is struct ts t;
Is it a similar operator? I am still confused.

Thank you.

Its not really an operator, it is an object, a struct.

The struct name would be defined by the library you selected to use.

why not post your entire sketch?

I did research on how t is defined in struct ts t;

This is the code. It is a mix of three examples for three hardware modules that I am trying to utilize in my project.

What is inp2toi (); ? I googled it and I found no explanation of how this operator works.
It is something very specific to the RTC library that I am wrestling with.

DS3234_get_a2(cs, &buff[0], 59);
What does 59 stand for?

in expression uint8_t flags[5] = { 0, 0, 0, 0, 0 };
What does [5] stand for?

Thank you.

#include <SPI.h>
#include "ds3234.h"
#include <LiquidCrystal_I2C.h>
#define BUFF_MAX 256 //(++)
const int cs = 9;              // chip select pin

// Define the digital pins used for the clock and data - TOUCHPAD
#define CLOCK_PIN 8 //SCL_PIN
#define DATA_PIN 7 //SDO_PIN
byte Key;
// - TOUCHPAD

uint8_t sleep_period = 5;       // the sleep interval in minutes between 2 consecutive alarms // from 5m alarm example
uint8_t time[8];
char recv[BUFF_MAX];
unsigned int recv_size = 0;
unsigned long prev, interval = 5000;

void parse_cmd(char *cmd, int cmdsize);

LiquidCrystal_I2C lcd(0x27,2,1,0,4,5,6,7,3,POSITIVE); // Set the LCD I2C address

void set_next_alarm(void)// from 5m alarm example
{
    struct ts t;
    unsigned char wakeup_min;

    DS3234_get(cs, &t);

    // calculate the minute when the next alarm will be triggered
    wakeup_min = (t.min / sleep_period + 1) * sleep_period;
    if (wakeup_min > 59) {
        wakeup_min -= 60;
    }

    // flags define what calendar component to be checked against the current time in order
    // to trigger the alarm
    // A2M2 (minutes) (0 to enable, 1 to disable)
    // A2M3 (hour)    (0 to enable, 1 to disable) 
    // A2M4 (day)     (0 to enable, 1 to disable)
    // DY/DT          (dayofweek == 1/dayofmonth == 0)
    uint8_t flags[4] = { 0, 1, 1, 1 };

    // set Alarm2. only the minute is set since we ignore the hour and day component
    DS3234_set_a2(cs, wakeup_min, 0, 0, flags);

    // activate Alarm2
    DS3234_set_creg(cs, DS3234_INTCN | DS3234_A2IE);
}// from 5m alarm example

void setup()
{
    Serial.begin(9600);   /* Initialise the serial interface */
    DS3234_init(cs, DS3234_INTCN);
    memset(recv, 0, BUFF_MAX - 1);
          DS3234_clear_a2f(cs);// from 5m alarm example
          set_next_alarm(); // from 5m alarm example
    Serial.println("GET time");

    lcd.begin(20,4); // Initialize LCD (define size)

  //lcd.home ();                   // go home
  lcd.setCursor ( 0, 1 );

// Configure the clock and data pins  - TOUCHPAD
  pinMode(CLOCK_PIN, OUTPUT);
  pinMode(DATA_PIN, INPUT);
  digitalWrite(CLOCK_PIN, HIGH);
//- TOUCHPAD  
}

void loop()
{
    char buff[BUFF_MAX];
    unsigned long now = millis();
    int in;
    struct ts t;

    // show time once in a while
    if ((now - prev > interval) && (Serial.available() <= 0)) {
        DS3234_get(cs, &t);
        snprintf(buff, BUFF_MAX, "%d.%02d.%02d %02d:%02d:%02d", t.year,
             t.mon, t.mday, t.hour, t.min, t.sec);
             
        lcd.clear();
        lcd.println(buff);
        Serial.println(buff);

// Read the current state of the keypad - TOUCHPAD 
    for (int button = 1; button < 17; button++)
      {
        digitalWrite(CLOCK_PIN, LOW);//set clock
        int databit = digitalRead(DATA_PIN);//read bit
        Serial.print(databit);
        digitalWrite(CLOCK_PIN, HIGH); //reset clock  
      };
        Serial.println();
//  - TOUCHPAD
        
        lcd.print("RTC out: ");
        delay (1000);

        //from 5m alarm example
        
        // display a2 debug info
        DS3234_get_a2(cs, &buff[0], 59);
        //Serial.println(buff);
        
        if (DS3234_triggered_a2(cs)) {
            Serial.println(" -> alarm2 has been triggered");
            set_next_alarm();
            // clear a2 alarm flag and let INT go into hi-z
            DS3234_clear_a2f(cs);          
        }
        //END from 5m alarm example

           
        prev = now;
    }

    if (Serial.available() > 0) {
        in = Serial.read();

        //snprintf(buff,200,"%d",in);
        //Serial.println(buff);

        if ((in == 10 || in == 13) && (recv_size > 0)) {
            parse_cmd(recv, recv_size);
            recv_size = 0;
            recv[0] = 0;
        } else if (in < 48 || in > 122) { // ~[0-9A-Za-z]
            // ignore 
        } else if (recv_size > BUFF_MAX - 2) {
            // drop
            recv_size = 0;
            recv[0] = 0;
        } else if (recv_size < BUFF_MAX - 2) {
            recv[recv_size] = in;
            recv[recv_size + 1] = 0;
            //snprintf(buff,200,"partial,%d: %s,%d,%d\n",recv_size,recv,recv[recv_size],in);
            //Serial.print(buff);
            recv_size += 1;
        }

    }
}

void parse_cmd(char *cmd, int cmdsize)
{
    uint8_t i;
    uint8_t reg_val;
    char buff[BUFF_MAX];
    struct ts t;

    //snprintf(buf, 200, "cmd was '%s' %d\n", cmd, cmdsize);
    //Serial.print(buf);

  
        DS3234_set(cs, t);
        Serial.println("OK");
    } else if (cmd[0] == 49 && cmdsize == 1) {  // "1" get alarm 1
        DS3234_get_a1(cs, &buff[0], 59);
        //Serial.println(buff);
    } else if (cmd[0] == 50 && cmdsize == 1) {  // "2" get alarm 1
        DS3234_get_a2(cs, &buff[0], 59);
        //Serial.println(buff);
    } else if (cmd[0] == 51 && cmdsize == 1) {  // "3" get aging register
        Serial.print("aging reg is ");
        Serial.println(DS3234_get_aging(cs), DEC);
    } else if (cmd[0] == 52 && cmdsize == 1) {  // "4" read sram
        int i;
        for (i = 0; i < BUFF_MAX-1; i++) {
            buff[i] = DS3234_get_sram_8b(cs, i);
        }
        for (i = 0; i < BUFF_MAX-1; i++) {
            Serial.print(buff[i], DEC);
            Serial.print(" ");
        }
    } else if (cmd[0] == 65 && cmdsize == 9) {  // "A" set alarm 1
        DS3234_set_creg(cs, DS3234_INTCN | DS3234_A1IE);
        //ASSMMHHDD
        for (i = 0; i < 4; i++) {
            time[i] = (cmd[2 * i + 1] - 48) * 10 + cmd[2 * i + 2] - 48; // ss, mm, hh, dd
        }
        uint8_t flags[5] = { 0, 0, 0, 0, 0 };
        DS3234_set_a1(cs, time[0], time[1], time[2], time[3], flags);
        DS3234_get_a1(cs, &buff[0], 59);
        //Serial.println(buff);
    } else if (cmd[0] == 66 && cmdsize == 7) {  // "B" Set Alarm 2
        DS3234_set_creg(cs, DS3234_INTCN | DS3234_A2IE);
        //BMMHHDD
        for (i = 0; i < 4; i++) {
            time[i] = (cmd[2 * i + 1] - 48) * 10 + cmd[2 * i + 2] - 48; // mm, hh, dd
        }
        uint8_t flags[5] = { 0, 0, 0, 0 };
        DS3234_set_a2(cs, time[0], time[1], time[2], flags);
        DS3234_get_a2(cs, &buff[0], 59);
        //Serial.println(buff);
    } else if (cmd[0] == 67 && cmdsize == 1) {  // "C" - get temperature register
        Serial.print("temperature reg is ");
        Serial.println(DS3234_get_treg(cs), DEC);
    } else if (cmd[0] == 68 && cmdsize == 1) {  // "D" - reset status register alarm flags
        reg_val = DS3234_get_sreg(cs);
        reg_val &= B11111100;
        DS3234_set_sreg(cs, reg_val);
    } else if (cmd[0] == 71 && cmdsize == 1) {  // "G" - set aging status register
        DS3234_set_aging(cs, 0);
    } else if (cmd[0] == 77 && cmdsize == 1) {  // "M" - write to sram
        int i;
        for (i = 0; i < BUFF_MAX-1; i++) {
            DS3234_set_sram_8b(cs, i, i);
        }
    } else if (cmd[0] == 83 && cmdsize == 1) {  // "S" - get status register
        Serial.print("status reg is ");
        Serial.println(DS3234_get_sreg(cs), DEC);
    } else {
        Serial.print("unknown command prefix ");
        Serial.println(cmd[0]);
        Serial.println(cmd[0], DEC);
    }
}

You mean this ?

uint8_t inp2toi(char *cmd, const uint16_t seek)
{
  uint8_t rv;
  rv = (cmd[seek] - 48) * 10 + cmd[seek + 1] - 48;
  return rv;
}

Well, let's make it a little clearer

uint8_t inp2toi(char *cmd, const uint16_t seek)
{
    return(uint8_t)( (cmd[seek] - '0') * 10 + cmd[seek + 1] - '0');
}

I dont understand. What part of my question does this tie to? It did not make anything clearer, I am sorry.
'40' is zero
the whole expression still makes very little sense to me.

What is [seek]?

It is not related to this: SD - Arduino Reference

I dont understand. What part of my question does this tie to?

This bit

What is inp2toi (); ?

'40' is zero

No, 48 is '0'

What is [seek]?

uint8_t inp2toi(char *cmd, const uint16_t seek

seek is simply an offset into cmd.

VT91:
I dont understand. What part of my question does this tie to? It did not make anything clearer, I am sorry.
'40' is zero
the whole expression still makes very little sense to me.

What is [seek]?

It is not related to this: SD - Arduino Reference

You are asking a lot of questions that are really fundamental to Arduino/C++.

If you cannot understand what an array index looks like, know about ASCII characters or how an integer is printed, you may find it useful to get a book on starting with Arduino and start there. Otherwise you are pecking at a typewriter... in Cyrillic.

I read a book about arduino. This command is clearly not there.

uint8_t inp2toi(char *cmd, const uint16_t seek)
{
return(uint8_t)( (cmd[seek] - '0') * 10 + cmd[seek + 1] - '0');
}

What does this whole expression do? What does it calculate? Why do we need a letter "O" of all things?

What is this part: const uint16_t seek?
Where does a numerical value of the constant come from?

It takes two consecutive ASCII characters in an array, say '4' and '2', converts each to decimal by subtracting '0', multiplies the first by 10 and adds the second and voilà, 42.

I read a book about arduino. This command is clearly not there.

It's not in the book because it is nothing directly to do with Arduino.

Thank you. I have done it a little bit differently in the past.
We had an assignment like this in a Java class in college.

What is uint8_t and uint16_t?

*cmd is a pointer that itself resembles an array?
What navigates what in search of two consecutive characters?

Java has arrays, functions and parameters too

Yes. I forgot Java.

And I never used pointers in combination with arrays because I am not a professional programmer and saving memory was not an issue for me.

This is a very condensed expression.

What follows what? What is a pointer and what does it point to? cmd is a pointer and an array at the same time? Is that possible