STM32F103C8T6 RTC to get date and time

Post here all questions related to LibMaple core if you can't find a relevant section!
soundaryasundaram
Posts: 8
Joined: Fri Jan 31, 2020 6:13 am

Re: STM32F103C8T6 RTC to get date and time

Post by soundaryasundaram »

Thanks. I tried your modified code with bluepill. It works well as you mentioned above and i tried without removing PC14 and PC15 Pins. It is very accurate too. This is accurate only with power supply condition. But incase of 0v main supply, the RTC should work as it is, for precise time and date measurement applications. Can you give me few hits to make the RTC to work even without main power supply?. I read about VBAT pin in datasheet. Does connecting a 3.3v battery to VBAT pin is enough for precise time applications? Also guide me how to configure backup registers and procedure for backup..
ag123
Posts: 1657
Joined: Thu Dec 19, 2019 5:30 am
Answers: 25

Re: STM32F103C8T6 RTC to get date and time

Post by ag123 »

soundaryasundaram wrote: Tue Feb 04, 2020 12:29 pm Thanks. I tried your modified code with bluepill. It works well as you mentioned above and i tried without removing PC14 and PC15 Pins. It is very accurate too. This is accurate only with power supply condition. But incase of 0v main supply, the RTC should work as it is, for precise time and date measurement applications. Can you give me few hits to make the RTC to work even without main power supply?
connect a 3v coin cell at vbat. there are plenty supply of coin cell holders
https://www.aliexpress.com/wholesale?ca ... 032+holder
soundaryasundaram
Posts: 8
Joined: Fri Jan 31, 2020 6:13 am

Re: STM32F103C8T6 RTC to get date and time

Post by soundaryasundaram »

In bluepill, i connected 3.3v supply from another arduinouno microcontroller to VBAT pin of bluepill and i connected both controllers ground. I used Arduinouno instead of coin battery and uploaded the previous code. I set the initial time as 1580903310.
Soon after i disconnected the bluepill's main supply, the RTC should work by getting supply from Arduinouno's 3.3V. But in my case, it did not work. When i reconnect the mainsupply, the RTC restarts from the initial setup time 1580903310. I checked the voltage at Vbat pin using multimeter, it shows 3.26V. Do i need to change anything in coding part to make it work with Vbat?
Last edited by soundaryasundaram on Wed Feb 05, 2020 6:59 am, edited 1 time in total.
ag123
Posts: 1657
Joined: Thu Dec 19, 2019 5:30 am
Answers: 25

Re: STM32F103C8T6 RTC to get date and time

Post by ag123 »

check that in your code

Code: Select all

 rt.setTime(1580903310);
is called only when you really want to change the clock time. otherwise, it shouldn't be called
it shouldn't be simply a statement in setup(), you'd need to implement a means of calling it only when needed
one way is to comment that line, build and flash the sketch again
soundaryasundaram
Posts: 8
Joined: Fri Jan 31, 2020 6:13 am

Re: STM32F103C8T6 RTC to get date and time

Post by soundaryasundaram »

yes,it works. When i referred datasheet, i came across backup registers that works with VBAT supply. May i know the usage of backup registers and its working..? where can i find backup register's configuration, working procedure and explanations, ?.. it may be helpful for me..
In datasheet, i can find few of its details, but only working library examples helps to understand about (STM32backup registers) more clear.
ag123
Posts: 1657
Joined: Thu Dec 19, 2019 5:30 am
Answers: 25

Re: STM32F103C8T6 RTC to get date and time

Post by ag123 »

backup registers are actually different from the RTC itself, though they are powered from the same VBAT

to use the backup registers call
https://github.com/rogerclarkmelbourne/ ... st.ino#L63

Code: Select all

bkp_init();
the commands to write backup registers are

Code: Select all

	uint16_t data = 1234;
	uint8_t register = 8;

	bkp_enable_writes();
	bkp_write(register, data);
	bkp_disable_writes();
e.g.
https://github.com/rogerclarkmelbourne/ ... t.cpp#L144

the command to read backup register is

Code: Select all

	uint8_t register = 8;
	uint16_t data = bkp_read(register);
e.g.
https://github.com/rogerclarkmelbourne/ ... t.cpp#L180

those commands are part of the libmaple core
https://github.com/rogerclarkmelbourne/ ... bkp.h#L156
https://github.com/rogerclarkmelbourne/ ... e/bkp_f1.c
soundaryasundaram
Posts: 8
Joined: Fri Jan 31, 2020 6:13 am

Re: STM32F103C8T6 RTC to get date and time

Post by soundaryasundaram »

Ok, i will see all the links soon..

In the previous code, i done modifications.
here is the code

Code: Select all

#include <RTClock.h>
RTClock rtclock (RTCSEL_LSE); // initialise Low speed External clock for RTCclock
uint32 tt;
tm_t mtt;
uint32 last_ms = 0;
uint32 period = 0;
#define LED_PIN PC13

double count = 0;
const char * months[] = {"Dummy", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
const char * delim = " :";
char s[128]; // for sprintf
char buf[25];
const char * weekdays[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};

// This function is called in the attachSecondsInterrpt
void blink ()
{
  digitalWrite(LED_PIN, (~ digitalRead(LED_PIN)) & 1);
  uint32_t ms = millis();
  if (last_ms == 0)
  {
    last_ms = ms;
  }
  else
  {
    period = ms - last_ms;
    last_ms = ms;
  }
}

uint8_t str2month(const char * d)
{
  uint8_t i = 13;
  while ( (--i) && strcmp(months[i], d) != 0 );
  return i;
}

void ParseBuildTimestamp(tm_t & mt)
{
  // Timestamp format: "Dec  8 2017, 22:57:54"
  sprintf(s, "Timestamp: %s, %s\n", __DATE__ , __TIME__);
  Serial.print(s);
  char * token = strtok(s, delim); // get first token

  while ( token != NULL )
  {
    uint8_t m = str2month((const char*)token);
    if ( m > 0 )
    {
      mt.month = m;
      Serial.print(" month: "); Serial.println(mt.month);
      token = strtok(NULL, delim); // get next token
      mt.day = atoi(token);
      Serial.print(" day: "); Serial.println(mt.day);
      token = strtok(NULL, delim); // get next token
      mt.year = atoi(token) - 1970;
      Serial.print(" year: "); Serial.println(mt.year);
      token = strtok(NULL, delim); // get next token
      mt.hour = atoi(token);
      Serial.print(" hour: "); Serial.println(mt.hour);
      token = strtok(NULL, delim); // get next token
      mt.minute = atoi(token);
      Serial.print(" minute: "); Serial.println(mt.minute);
      token = strtok(NULL, delim); // get next token
      mt.second = atoi(token);
      Serial.print(" second: "); Serial.println(mt.second);
    }
    token = strtok(NULL, delim);
  }
  sprintf(s, "Build: %02d-%02d-%02d %02d:%02d:%02d\n", mt.year + 1970, mt.month, mt.day, mt.hour, mt.minute, mt.second);
  Serial.println(s);
}

void setup()
{
   delay(5000);
  pinMode(LED_PIN, OUTPUT);
  ParseBuildTimestamp(mtt);  //setting initial time. here, instant compilation time is considered as initial time setup
  tt = rtclock.makeTime(mtt) + 8;  //since compilation time is 8sec delayed when compared with actual time, so adding 8seconds with the compilation time here.
  //  Serial.println("make time value 1 is:: ");  Serial.println(tt); //printing the adjusted time
  rtclock.setTime(tt);
  rtclock.attachSecondsInterrupt(blink);// Call blink
}

void loop()
{

  if (rtclock.getTime() != tt)
  {
    tt = rtclock.getTime(); //gets the instatnt time
    Serial.print("___________time is: ");
    Serial.println(tt);
    Serial.print("period : ");
    Serial.println(period);
    rtclock.breakTime(rtclock.now(), mtt); //gets the instant time in day,month,year,hour,minute,seconds
    sprintf(s, "RTC timestamp: %s %u %u, %s, %02u:%02u:%02u\n",
            months[mtt.month], mtt.day, mtt.year + 1970, weekdays[mtt.weekday], mtt.hour, mtt.minute, mtt.second);
    Serial.print(s);
  }
}
OUTPUT

Code: Select all

12:44:13.168 -> Timestamp: Feb  6 2020, 12:44:05
12:44:13.168 ->  month: 2
12:44:13.168 ->  day: 6
12:44:13.168 ->  year: 50
12:44:13.168 ->  hour: 12
12:44:13.168 ->  minute: 44
12:44:13.168 ->  second: 5
12:44:13.168 -> Build: 2020-02-06 12:44:05
12:44:13.168 -> 
12:44:14.187 -> ___________time is: 1580993054
12:44:14.187 -> period : 1000
12:44:14.187 -> RTC timestamp: Feb 6 2020, Thu, 12:44:14
12:44:15.175 -> ___________time is: 1580993055
12:44:15.175 -> period : 1000
12:44:15.175 -> RTC timestamp: Feb 6 2020, Thu, 12:44:15
12:44:16.160 -> ___________time is: 1580993056
12:44:16.160 -> period : 1000
12:44:16.160 -> RTC timestamp: Feb 6 2020, Thu, 12:44:16
12:44:17.181 -> ___________time is: 1580993057
12:44:17.181 -> period : 1002
12:44:17.181 -> RTC timestamp: Feb 6 2020, Thu, 12:44:17
12:44:18.166 -> ___________time is: 1580993058
12:44:18.166 -> period : 1000
12:44:18.166 -> RTC timestamp: Feb 6 2020, Thu, 12:44:18
12:44:19.161 -> ___________time is: 1580993059
12:44:19.161 -> period : 1003
12:44:19.161 -> RTC timestamp: Feb 6 2020, Thu, 12:44:19
12:44:20.181 -> ___________time is: 1580993060
12:44:20.181 -> period : 1000
12:44:20.181 -> RTC timestamp: Feb 6 2020, Thu, 12:44:20
12:44:21.169 -> ___________time is: 1580993061
12:44:21.169 -> period : 1003
12:44:21.169 -> RTC timestamp: Feb 6 2020, Thu, 12:44:21
12:44:22.191 -> ___________time is: 1580993062
12:44:22.191 -> period : 1000
12:44:22.191 -> RTC timestamp: Feb 6 2020, Thu, 12:44:22
12:44:23.171 -> ___________time is: 1580993063
12:44:23.171 -> period : 1003
12:44:23.171 -> RTC timestamp: Feb 6 2020, Thu, 12:44:23
12:44:24.191 -> ___________time is: 1580993064
12:44:24.191 -> period : 1000
12:44:24.191 -> RTC timestamp: Feb 6 2020, Thu, 12:44:24
12:44:25.183 -> ___________time is: 1580993065
12:44:25.183 -> period : 1003
12:44:25.183 -> RTC timestamp: Feb 6 2020, Thu, 12:44:25
12:44:26.173 -> ___________time is: 1580993066
12:44:26.173 -> period : 1000
12:44:26.173 -> RTC timestamp: Feb 6 2020, Thu, 12:44:26
12:44:27.195 -> ___________time is: 1580993067
12:44:27.195 -> period : 1002
12:44:27.195 -> RTC timestamp: Feb 6 2020, Thu, 12:44:27
12:44:28.184 -> ___________time is: 1580993068
12:44:28.184 -> period : 1000
12:44:28.184 -> RTC timestamp: Feb 6 2020, Thu, 12:44:28
12:44:29.185 -> ___________time is: 1580993069
12:44:29.185 -> period : 1003
12:44:29.185 -> RTC timestamp: Feb 6 2020, Thu, 12:44:29
12:44:30.178 -> ___________time is: 1580993070
12:44:30.178 -> period : 1000
12:44:30.178 -> RTC timestamp: Feb 6 2020, Thu, 12:44:30
12:44:31.203 -> ___________time is: 1580993071
12:44:31.203 -> period : 1003
12:44:31.203 -> RTC timestamp: Feb 6 2020, Thu, 12:44:31
12:44:32.188 -> ___________time is: 1580993072
12:44:32.188 -> period : 1000
12:44:32.188 -> RTC timestamp: Feb 6 2020, Thu, 12:44:32
I got output period as 1001,1003,1004. If i let the controller to run for longer time, the period value changes to 1500. If this continuous, it would definitely show wrong time in few days. What is the reason for this change in period? How could i rectify it?
ag123
Posts: 1657
Joined: Thu Dec 19, 2019 5:30 am
Answers: 25

Re: STM32F103C8T6 RTC to get date and time

Post by ag123 »

the main issue is that you are setting time in setup() directly from a value read. this will vary with the time you call the time setting routine.

for a command processor, i tend to use codes as such:

Code: Select all

#define CMD_SETTIME 'S'

#define BUFSIZE 30
uint8_t buf[BUFSIZE];

void loop()  {
  if(Serial.available()) {
    int i = 0;
    memset(buf,0,BUFSIZE);    
    while(Serial.available()) {
      uint8_t c = Serial.read();
      if( c == '\n' || c == '\r' ) 
        break;
      buf[i++] = c;
    }
    uint8_t command = buf[0];
    switch(command) {
    case CMD_SETTIME:
	set_time(&buf+1);
	break;
    case ... :
    default:
       break;
    }    
}
there is a catch with this rather naive code, it reads whatever is found from Serial.available() and start processing.
this approach handles single line commands one line at a time, and i use the first char received as the command.
if you want to make it less susceptible to characters arriving between pauses of Serial.available() you would need to code additional logic such as timeout etc. and in addition to check for buffer size not exceeded

setup() runs each time you press reset or power up the board. hence it isn't a most appropriate place to place time setting codes.
it'd be better to implement a command processor in loop() to receive the text string and use that for setting time

setting time would depend on how you account for the delays in the time setting part of the process, from your host/pc etc.
for instance the time between when you read a wall clock time and say hitting return to send the command manually alone could already account
for a random delay.

but for the RTC, the time drift between all subsequent seconds is normally rather small. if you use a lousy crystal, there may be drifts, but that's another issue. i normally ignore the initial random differences when setting time, after all a few seconds off the wall clock doesn't bother me.
soundaryasundaram
Posts: 8
Joined: Fri Jan 31, 2020 6:13 am

Re: STM32F103C8T6 RTC to get date and time

Post by soundaryasundaram »

Thanks ag123. Sure, i will implement a code to get time from serial to set time for RTC and discuss about it soon..
ag123
Posts: 1657
Joined: Thu Dec 19, 2019 5:30 am
Answers: 25

Re: STM32F103C8T6 RTC to get date and time

Post by ag123 »

fyi, there is an RTCAdjustment sketch, app in the libmaple core RTC Clock examples
https://github.com/rogerclarkmelbourne/ ... les/RTCAdj
it is pretty much a full fledged RTC app/sketch
you may like to copy that out into a sketch folder and try it out
time setting with that sketch is something like

Code: Select all

sYYYY-MM-DD HH:MM:SS
on the serial terminal, the first character 's' being the command itself

if your core is rather recent you can find it in libraries for F1 within the RTC Clock library in examples
typically i set the time manually comparing against clock time, so you can expect some seconds or at least fraction of a second random differences.

if you want to go the distance you can try to make an app that interact with the serial terminal to send the commands with the time.
that is a bit of work, so i'd guess most people would simply use a common serial terminal app/utility (it can even be the arduino IDE terminal itself)
and type the time/command manually
Post Reply

Return to “General discussion”