B4R Library Software Real Time Clock

Discussion in 'B4R Libraries' started by Starchild, Mar 10, 2017.

  1. Starchild

    Starchild Member Licensed User

    This library (called rSoftRtc), is a generic derivative of the device specific library rESP8266rtc v1-03.

    It is a software based Real Time Clock.
    You don't need any additional hardware modules.
    It does NOT run any special background code to keep the RTC alive.
    It can generate Alarm Events at required Date/Times.

    It also contains several functions to simplify the manipulation of date/times as seconds.
    It gets it's timing by calibrating the millis() function available from Arduino.
    Generated Alarm Events are managed by the B4R Scheduler class.

    Code:
    #Region Project Attributes
        
    #AutoFlushLogs: True
        
    #CheckArrayBounds: True
        
    #StackBufferSize: 300
    #End Region
    Sub Process_Globals
       
    Public Serial1 As Serial
       
    Private DT(8As Byte
       
    Private rtc As SoftRtc
    End Sub
     
    Private Sub AppStart
        Serial1.Initialize(
    115200)
        
    Log("AppStart")
     
        rtc.Initialize(
    "rtc_Alarm",True)
        
    log("RTC Initialised")
     
        
    'date .. 10th March 2017   (GMT)
        DT(0) = 21   '21st century (ie 2000)
        DT(1) = 17   'year
        DT(2) = 3     'month
        DT(3) = 10   'day
     
        
    'time .. 1:26pm  (zero sec)   (GMT)
        DT(4) = 13   'hour (0-23)
        DT(5) = 26   'minute
        DT(6) = 0     'seconds
     
        DT(
    7) = 0    'not required.
     
        rtc.SetClock(DT,
    8,0)   'offset for Western Australia. DT +08:00
        log("RTC is set")
     
        
    Log(rtc.ReadClock(DT))
        
    Log("RTC: ",DT(0),",",DT(1),",",DT(2),",",DT(3),",",DT(4),",",DT(5),",",DT(6),",",DT(7))
     
        rtc.SetAlarm(
    1,rtc.Sec2DT(rtc.DT2Sec(DT)+10))
        rtc.SetAlarm(
    2,rtc.Sec2DT(rtc.DT2Sec(DT)+5))
        rtc.SetAlarm(
    3,rtc.Sec2DT(rtc.DT2Sec(DT)+15))
        rtc.SetAlarm(
    9,rtc.Sec2DT(rtc.DT2Sec(DT)+rtc.SECONDS_1MINUTE))
     
        
    Log("RTC is running")
    End Sub
     
    private Sub rtc_Alarm(index As Byte)
        
    If index=0 Then
             
    'tick every second
             rtc.ReadClock(DT)
             
    Log("RTC: ",rtc.ShortDOW(DT),", ",rtc.ShortDate(DT),", ",rtc.Time24(DT))
             
    Return
        
    End If
        
    Log("AlarmEvent:  ",index)
    End Sub
    The above example has been revised.

    Notes: My testing over several days showed a loss of 1 to 2 sec per day. The RTC could be set (SetClock) every week or so. As the Arduino Millis() function can only count continuously for about 40days the RTC should be set at least once a month.

    Now updated to v1.02
    see posting below for version details
     

    Attached Files:

    Last edited: Sep 10, 2017
    derez, demasi, Mostez and 4 others like this.
  2. DarkMann

    DarkMann Member Licensed User

    I've been trying to integrate this into a simple project, as it seems like the ideal solution to keep things ticking over when communication to the server app for my arduino is down or otherwise unavailable.

    I've run into a serious problem with the output though. Firstly, I had to edit all the ulong declarations in the .h and .cpp files into more acceptable unsigned long declarations to even get things to compile. This is about the limit of my knowledge of C++.

    Now things compile, but when i read back a date or time, they are incorrect. For example, using this code to set date and time:
    Code:
    rtc.Initialize("rtcAlarm",False)
    DT(
    0)=21  'century
    DT(1)=17  'year
    DT(2)=9  'month
    DT(3)=3  'day
    DT(4)=17  'hour
    DT(5)=20  'minute
    DT(6)=0
    DT(
    7)=0
    rtc.SetClock(DT,
    0,0)
    returns a short date of 02/Sep/17 and a time of 23:76:00

    I guess it needs more than the ulong to unsigned long changes that I made, or that they actually broke something in the time parsing.

    Any help appreciated.

    David
     
  3. Starchild

    Starchild Member Licensed User

    I originally write the library for the ESP8266 as this hardware was WiFi enabled.
    I have limited hardware to test this "rSoftRtc" library.
    I have only tested it on ST32-Nucleo-F103RB and also the NodeMCU ESP board.
    I don't have any standard Arduino boards.

    I haven't had any problems with compiling the library as offered, ie with the ulong types.

    What is the Target hardware board you are compiling for?
    Have you set up the correct board Type/Variant in B4R>Tools>Board-Selector
    Is your B4R version current?
    What version is your Arduino environment? (I'm using v1.6.9)
     
    Last edited: Sep 7, 2017
  4. DarkMann

    DarkMann Member Licensed User

    I'm using an Arduino Mega 2560, correctly configured in B4R.
    B4R is Version 2.20.
    Arduino Environment is Version 1.8.1. B4R's download page actually specifies version 1.8+ as a requirement.

    I'm guessing that the Arduino environment version is the problem. Current Arduino documentation seems to specify the use of the long name "unsigned long" rather than "ulong" - see https://playground.arduino.cc/Code/DatatypePractices.

    As I say, it sort of works - it is ticking the seconds over, just getting the dates and times wrong and not understanding 60 minutes in an hour. I just don't understand enough about the conversions between bytes and longs to see where the logic is failing in your code - I've always tried to avoid C - hence the B4R.

    From my point of view, I may just have to add an RTC module into the hardware and work with that, but your library seemed like a neat solution to the problem without tacking another device into the circuitry we already have, as I'm already using sensors, relays, switches, LCD and Ethernet. The ethernet would allow me to set the clock regularly and that would work accurately enough.
     
  5. Starchild

    Starchild Member Licensed User

    I updated my Arduino environment to v1.8.1
    I tried running the test program for rSoftRTC library.
    It compiled and ran fine without any errors relating to "ulong" types.
    It displayed the correct time/date for the DT SetClock values.
    Tested it on a STM32-F103RB board.

    So, I dug a little deeper.
    See my next post.
     
    Last edited: Sep 8, 2017
  6. Starchild

    Starchild Member Licensed User

    Updated "rSoftRTC" library to version 1.01
    Available for download from the top post.

    The "ulong" type was defined by the Targeted Device library (but not in Arduino Mega 2560).
    B4R rCore.h file has it's own define
    ... typedef uint32_t ULong;
    My library code is now updated to use the B4R type "ULong".

    I hope this fixes any "ulong" type mismatch problems in some Arduino environments.
     
    Last edited: Sep 9, 2017
  7. DarkMann

    DarkMann Member Licensed User

    Thanks for that, it does indeed now compile without issue.

    Here's the changes I made to your above example code:-

    Code:
    Private Sub AppStart
        Serial1.Initialize(
    115200)
        
    Log("AppStart")
        rtc.Initialize(
    "rtc_Alarm",True)
        
    Log("RTC Initialised")
        
    'date .. 8th September 2017   (GMT)
        DT(0) = 21   '21st century (ie 2000)
        DT(1) = 17   'year
        DT(2) = 9     'month
        DT(3) = 8   'day
        'time .. 5:31pm  (zero sec)   (GMT)
        DT(4) = 17   'hour (0-23)
        DT(5) = 31   'minute
        DT(6) = 0     'seconds
        DT(7) = 0    'not required.
        rtc.SetClock(DT,0,0)   'offset for GMT=UTC=0
        Log("RTC is set")
        
    Log(rtc.ReadClock(DT))
        
    Log("RTC: ",DT(0),",",DT(1),",",DT(2),",",DT(3),",",DT(4),",",DT(5),",",DT(6),",",DT(7))
        rtc.SetAlarm(
    1,rtc.Sec2DT(rtc.DT2Sec(DT)+10))
        rtc.SetAlarm(
    2,rtc.Sec2DT(rtc.DT2Sec(DT)+5))
        rtc.SetAlarm(
    3,rtc.Sec2DT(rtc.DT2Sec(DT)+15))
        rtc.SetAlarm(
    9,rtc.Sec2DT(rtc.DT2Sec(DT)+rtc.SECONDS_1MINUTE))
        
    Log("RTC is running")
    End Sub
    Just changing to today's date and time and setting the offset to GMT/UTC (i'm not worried about BST at the moment, just getting a meaningful time.

    This is the start of the log output:-

    Code:
    AppStart
    RTC Initialised
    RTC 
    is set
    1
    RTC: 
    21,17,9,7,23,87,0,4
    RTC 
    is running
    RTC: Thu, 
    07/Sep/1723:87:01
    RTC: Thu, 
    07/Sep/1723:87:02
    RTC: Thu, 
    07/Sep/1723:87:03
    RTC: Thu, 
    07/Sep/1723:87:04
    When I forgot to change the offset - left it at +8, it looked like this:-

    Code:
    AppStart
    RTC Initialised
    RTC 
    is set
    1
    RTC: 
    21,17,9,8,7,18,44,5
    RTC 
    is running
    RTC: Fri, 
    08/Sep/1707:18:45
    RTC: Fri, 
    08/Sep/1707:18:46
    RTC: Fri, 
    08/Sep/1707:18:47
    RTC: Fri, 
    08/Sep/1707:18:48
    RTC: Fri, 
    08/Sep/1707:18:49
    These are both wrong for 08/Sep/17 at 17:31 GMT.

    Clearly, it compiles and ticks every second as expected, the alarms in the test program fire as well, right on schedule after the correct number of seconds.

    Thanks for your time so far,

    David
     
  8. Starchild

    Starchild Member Licensed User

    I ran the test program with your changes listed above.
    For me, I get the correct time/date log outputs.
    For both 0 and +8 offsets.
    At this point I don't know why you are getting a different result.

    I know the underlying device libraries do vary for the different target modules.
    Maybe, like the "ulong" typedef was missing from the Arduino Mega 2560 target library, some other definitions may not be the same as for the targets I am using.

    I made one other variable declaration change based on the erroneous value displayed in the Minutes field of DT of your log output.

    I have again updated the rSoftRtc ZIP in the top post, but I have not incremented the version number, still shown as v1.01

    Download it again. If this still gives you erroneous results I think we will need someone else with the same hardware as yourself (Arduino Mega 2560) to investigate further.
     
    Last edited: Sep 9, 2017
  9. DarkMann

    DarkMann Member Licensed User

    Well, I've also a couple of Arduino Unos that I've tried. I get exactly the same results as with the Mega2560.

    This prompted me to do some further testing.

    If I set the hour to any number above 9, then the time - and even the date - come out wrong immediately. Setting the hour to 8 or less seems to work just fine. I've not had time to let it run on to see when - or indeed if - it goes wrong.

    If I set the time to 9:00 it works, but this only holds true up to a time of 9:06.

    If I set the time to 9:07 it's wrong. Interestingly, if I set it to 9:06 and leave it ticking for a minute, then 9:07 comes past just as expected. Something strange going on in the time setting code?

    I'll plug it into the laptop and leave it running all day to see what happens

    EDIT: It ran fine for about 10 Hours, just from a prior to 9:00 starting time.
     
    Last edited: Sep 9, 2017
  10. Starchild

    Starchild Member Licensed User

    I still cannot get your error to present itself.

    Some Further Thoughts.
    A different compiler is used for various Target Devices. I am assuming this is the case between
    my boards and yours.
    You get a total error for hours/minutes etc. but only on larger counts.
    The library uses some large constants to spilt years/months/days/hours/minutes apart.
    After reading Arduino refs, it seems that untyped constants are treated as (int). This could be the problem. (int) can only hold maximum values of 32768. (I use 86400 in several places).
    I think my targeted compiler is treating untyped constants as (long), so I don't get a problem, but you do.

    Based on this "theory" ..
    I have again edited the rSoftRtc library and forced the large untyped constants to unsigned-long allowing them to be a larger value.
    It still works fine for me on my boards.

    I have updated the download link in the top post. I haven't changed the version number.
    it is still referenced as rSoftRtc1-01.zip

    Please give this a go.
     
  11. DarkMann

    DarkMann Member Licensed User

    Working fine with this latest version :D

    Thanks for your time and patience. I owe you a beer!

    David
     
  12. Starchild

    Starchild Member Licensed User

    Updated "rSoftRTC" library to version 1.02
    Available for download from the top post.

    I have now incremented the version number to identify the
    changes made resolving "untyped constants" compilation problems.
    This is detailed in full in the above posts.

    Cheers!
     
    Last edited: Sep 10, 2017
  13. derez

    derez Expert Licensed User

    I try to run the application on STM32 and it works , but I can't get it to run without updating the time every time I load it.
    When I comment the setclock command I get zeroes...

    Edit: I understand now that it is using the internal RTC, so of course it doesn't hold the time set before...
     
    Last edited: Sep 29, 2017
  14. Starchild

    Starchild Member Licensed User

    As you say, it does not use any hardware internal RTC. It simulates an RTC in software. As such when it is powered down it no longer retain any previous date time information. Therefore it should access a date time source st startup reset. This would require a network connection to a server or internet time source to calibrate itself.
    Even without this calibration, it can still be used as a relative timed event generator.
     
  15. derez

    derez Expert Licensed User

    Thank you.
    To connect an external RTC I tried to use RTC_DS1307 with its B4R library, connected to pins PA5,PA6,PA7 but it does not work.
    Do you know how to do it ?
     
  16. Starchild

    Starchild Member Licensed User

    I don't know anything about that library or part.
    You should start a new thread regarding this matter so others can help.
     
  17. BaGRoS

    BaGRoS Member Licensed User

    I have
    Code:
    Private Sub SetTimeNIST
       
        lcd.SetCursor(
    0,0)
        lcd.Write(TimeNIST.GetDate)
        
    Log("Date: ", TimeNIST.GetDate)
        
    Log("Time (UTC): "NumberFormat(TimeNIST.GetHours, 20), ":"NumberFormat(TimeNIST.GetMinutes, 20), _
            
    ":"NumberFormat(TimeNIST.GetSeconds, 20), "  Summer:", TimeNIST.CheckSummerTime)
        lcd.SetCursor(
    0,1)
       
        
    Dim c As String = JoinStrings(Array As String(NumberFormat(TimeNIST.GetHours, 20), ":"NumberFormat(TimeNIST.GetMinutes, 20), _
            
    ":"NumberFormat(TimeNIST.GetSeconds, 20), " S:", TimeNIST.CheckSummerTime))
        lcd.Write(c)
       
        
    'date .. 10th March 2017   (GMT)
        DT(0) = 21   '21st century (ie 2000)
        DT(1) = TimeNIST.GetYear   'year
        DT(2) = TimeNIST.GetMonth    'month
        DT(3) = TimeNIST.GetDay   'day

        
    'time .. 1:26pm  (zero sec)   (GMT)
        DT(4) = TimeNIST.GetHours   'hour (0-23)
        DT(5) = TimeNIST.GetMinutes   'minute
        DT(6) = TimeNIST.GetSeconds     'seconds

        DT(
    7) = 0    'not required.

        
    If TimeNIST.CheckSummerTime Then
            rtc.SetClock(DT,
    1,0)   'offset for London. DT +01:00 - summer
        Else
            rtc.SetClock(DT,
    0,0)   'offset for London. DT +00:00 - winter
        End If
        
    Log("RTC is set")

        
    Log(rtc.ReadClock(DT))
        
    Log("RTC: ",DT(0),",",DT(1),",",DT(2),",",DT(3),",",DT(4),",",DT(5),",",DT(6),",",DT(7))
       
    End Sub

    Private Sub rtc_Alarm(index As Byte)
        
    If index=0 Then
            
    'tick every second
            rtc.ReadClock(DT)
            
    Log("RTC: ",rtc.ShortDOW(DT),", ",rtc.ShortDate(DT),", ",rtc.Time24(DT))
            
    Return
        
    End If
        
    Log("AlarmEvent:  ",index)
          
    End Sub

    Public Sub TimeIsAvailable
        
    'Pobrany czas z internetu
        lcd.Clear
        
    'Clock.Enabled = True
        SetTimeNIST
        rtc.Initialize(
    "rtc_Alarm"True)
        
    Log("RTC Initialised")
      
        
    'rtc.SetAlarm(1,rtc.Sec2DT(rtc.DT2Sec(DT)+10))
        'rtc.SetAlarm(2,rtc.Sec2DT(rtc.DT2Sec(DT)+5))
        'rtc.SetAlarm(3,rtc.Sec2DT(rtc.DT2Sec(DT)+15))
        'rtc.SetAlarm(9,rtc.Sec2DT(rtc.DT2Sec(DT)+rtc.SECONDS_1MINUTE))
      
    End Sub
    but sub rtc_Alarm not running in every second
     
  18. Starchild

    Starchild Member Licensed User

    Is your sub "TimeIsAvailable" called at program start to initialise the rtc class.
    Have you confirmed this (write message to log)?

    Does the example code in the top post function correctly on your hardware?
    What hardware board (mcu board) are you targeting?

    To test, that the rtc class is running, does sub "rtc_alarm" run for a scheduled alarm event (use rtc function SetAlarm), say 5 seconds after start?
     
Loading...