SD2405 or SD2403 Real Time Clock

Anyone have one of these as DFRobot sells/sold them as a Gadgeteer module and I’m looking for some testers for 4.3 module driver I’m putting together. The old driver had the ability to store a date/time and retrieve it, but in this version I’m adding some of the alarm features of the module (Countdown and Time Alarms) and a couple other features.

The data sheet can be found here http://www.dfrobot.com/image/data/TOY0021/SD2405AL%20datasheet%20(Angelo%20v0.1).pdf
Anybody think something needs to be in this version of the driver?

When I’m done I’ll post the driver and code on my GitHub site.

@ Duke Nukem I have both.

So there is a count time alarm

_realTimeClock.SetAlarmCountDown(count, count down speed, repeat);

count down speeds are seconds, minutes, 1/64 second, 1/4096 second, and the maximum duration is 256 (ie its a byte).

the other alarm is

_realTimeClock.SetAlarmDateTime(seconds, minutes, hours, days, months, years, mask of alarm triggers, repeat, mask of days of the weeks)

So you can do something like set an alarm to go off every Wednesday and Tuesday at 10:43 in May.

I’m still thinking about the Frequency Alarm.

send me a private message if you are interested in testing this and I’ll send you some code or an installer, whatever.

I’ve got the module, it just came actually. I can test it for you, but I need the 4.3 drivers.

Here is a test app that I wrote to show some of the things I’m doing with this.

  • countdown and time alarms
  • persistent user storage
  • persistent date time

So I only connect wifi to a NTP server if I press button 1, but the SD2405 has the date time kept current in it. SD2405 Real-Time clock Module(Arduino Gadgeteer Compatible)


using System;
using System.Collections;
using System.Net;
using System.Text;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Presentation;
using Microsoft.SPOT.Presentation.Controls;
using Microsoft.SPOT.Presentation.Media;
using Microsoft.SPOT.Presentation.Shapes;
using Microsoft.SPOT.Touch;

using Gadgeteer.Networking;
using GT = Gadgeteer;
using GTM = Gadgeteer.Modules;
using Gadgeteer.Modules.DFRobot;
using Gadgeteer.Modules.GHIElectronics;
using GHI.Processor;
using Microsoft.SPOT.Hardware;
using Microsoft.SPOT.Net.NetworkInformation;
using Microsoft.SPOT.Time;

namespace rtctest
{
    public partial class Program
    {

        #region Confidential Settings

        private const string SSID = "YourSSID";
        private const string WIFI_PASSWORD = "YourPassword";

        #endregion

        //TimeServer Settings
        private int _daylightSavingsShift;
        private const int LocalTimeZone = -7 * 60;

        private Font _font = Resources.GetFont(Resources.FontResources.NinaB);

        // This method is run when the mainboard is powered up or reset.   
        void ProgramStarted()
        {
            /*******************************************************************************************
            Modules added in the Program.gadgeteer designer view are used by typing 
            their name followed by a period, e.g.  button.  or  camera.
            
            Many modules generate useful events. Type +=<tab><tab> to add a handler to an event, e.g.:
                button.ButtonPressed +=<tab><tab>
            
            If you want to do something periodically, use a GT.Timer and handle its Tick event, e.g.:
                GT.Timer timer = new GT.Timer(1000); // every second (1000ms)
                timer.Tick +=<tab><tab>
                timer.Start();
            *******************************************************************************************/


            // Use Debug.Print to show messages in Visual Studio's "Output" window during debugging.
            Debug.Print("Program Started");

            displayN18.Orientation = GTM.Module.DisplayModule.DisplayOrientation.UpsideDown;

            var time = sD2405_Real_Time_Clock.GetDateTime();

            Utility.SetLocalTime(time);
            RealTimeClock.SetDateTime(time);

            NetworkChange.NetworkAddressChanged += NetworkChange_NetworkAddressChanged;
            NetworkChange.NetworkAvailabilityChanged += NetworkChange_NetworkAvailabilityChanged;

            button.ButtonPressed += button_ButtonPressed;
            button2.ButtonPressed += button2_ButtonPressed;

            sD2405_Real_Time_Clock.CountDownAlarm += sD2405_Real_Time_Clock_CountDownAlarm;
            sD2405_Real_Time_Clock.TimeAlarm += sD2405_Real_Time_Clock_TimeAlarm;

            DisplayData(GetUserData()); //User Data could be something like the wifi password
        }

        private void DisplayData(string s)
        {
            displayN18.SimpleGraphics.ClearNoRedraw();
            displayN18.SimpleGraphics.DisplayText(s, _font, GT.Color.Green, 0, 0);

            displayN18.SimpleGraphics.DisplayText(DateTime.Now.Date.ToString(), _font, GT.Color.Red, 0, 15);
            displayN18.SimpleGraphics.DisplayText(DateTime.Now.TimeOfDay.ToString(), _font, GT.Color.Red, 0, 35);
        }

        private string GetUserData()
        {
            var data = sD2405_Real_Time_Clock.GetUserData();
            var charArray = Encoding.UTF8.GetChars(data);
            return new string(charArray);
        }

        void sD2405_Real_Time_Clock_TimeAlarm(SD2405_Real_Time_Clock sender, SD2405_Real_Time_Clock.AlarmType type)
        {
            DisplayData("Time Alarm");
        }

        void sD2405_Real_Time_Clock_CountDownAlarm(SD2405_Real_Time_Clock sender, SD2405_Real_Time_Clock.AlarmType type)
        {
            DisplayData("Count Down");
        }

        void button2_ButtonPressed(GTM.GHIElectronics.Button sender, GTM.GHIElectronics.Button.ButtonState state)
        {
            var data = sD2405_Real_Time_Clock.GetUserData();
            var charArray = Encoding.UTF8.GetChars(data);
            var s = new string(charArray);
            Debug.Print("User Data was " + s);

            switch (sD2405_Real_Time_Clock.EnabledAlarm)
            {
                case SD2405_Real_Time_Clock.AlarmType.None:
                    sD2405_Real_Time_Clock.SetAlarmCountDown(1, SD2405_Real_Time_Clock.CountDownSpeed.Second, true);
                    //sD2405_Real_Time_Clock.DisplayRegisters("Count Down Alarm Set");
                    data = Encoding.UTF8.GetBytes("Count Down Alarm");
                    break;
                case SD2405_Real_Time_Clock.AlarmType.CountDownAlarm:
                    sD2405_Real_Time_Clock.SetAlarmDateTime(0, 0, 0, 0, 0, 0,
                        (byte)(SD2405_Real_Time_Clock.Alarm.Second), true,
                        (byte)(SD2405_Real_Time_Clock.Days.Clear));
                    //sD2405_Real_Time_Clock.DisplayRegisters("Time Alarm Set");
                    data = Encoding.UTF8.GetBytes("Time Alarm");
                    break;
                case SD2405_Real_Time_Clock.AlarmType.TimeAlarm:
                    sD2405_Real_Time_Clock.ResetAlarms();
                    //sD2405_Real_Time_Clock.DisplayRegisters("NO Alarm Set");
                    data = Encoding.UTF8.GetBytes("No Alarm Set");

                    DisplayData("No Alarms");

                    break;
            }
            sD2405_Real_Time_Clock.SetUserData(data);
        }

        void button_ButtonPressed(GTM.GHIElectronics.Button sender, GTM.GHIElectronics.Button.ButtonState state)
        {
            WifiSetup(SSID,WIFI_PASSWORD);
        }

        private void WifiSetup(string ssid, string key)
        {
            //wifiRS21.NetworkInterface.UpdateFirmware();

            wifiRS21.NetworkInterface.Open();

            wifiRS21.NetworkInterface.EnableDhcp();

            wifiRS21.NetworkInterface.EnableDynamicDns();

            try
            {
                wifiRS21.NetworkInterface.Join(ssid, key);
            }
            catch (Exception e)
            {
                Debug.Print(e.Message);
            }
        }

        private void NetworkChange_NetworkAddressChanged(object sender, EventArgs e)
        {
            Debug.Print("Network Address Change to: " + wifiRS21.NetworkInterface.IPAddress);
            if (wifiRS21.NetworkInterface.IPAddress != "0.0.0.0")
            {
                Debug.Print("Gateway Address: " + wifiRS21.NetworkInterface.GatewayAddress);
                foreach (var dns in wifiRS21.NetworkInterface.DnsAddresses)
                {
                    Debug.Print("DNS Address: " + dns);
                }

                // get Internet Time using SNTP
                GetInternetTime();

                Debug.Print(DateTime.Now.ToString());

                wifiRS21.NetworkInterface.Disconnect();

                wifiRS21.NetworkInterface.Close();
            }
        }

        private void NetworkChange_NetworkAvailabilityChanged(object sender, NetworkAvailabilityEventArgs e)
        {
            //if (!e.IsAvailable)
            //{
            //    Debug.Print("Network disconnected");
            //}
            Debug.Print("network is " + (e.IsAvailable ? "Available" : "Isn't Available"));
        }

        private void GetInternetTime()
        {
            try
            {
                var NTPTime = new TimeServiceSettings();
                NTPTime.AutoDayLightSavings = true;
                NTPTime.ForceSyncAtWakeUp = true;
                NTPTime.RefreshTime = 3600;
                //Thread.Sleep(1500);
                NTPTime.PrimaryServer = Dns.GetHostEntry("2.ca.pool.ntp.org").AddressList[0].GetAddressBytes();
                NTPTime.AlternateServer = Dns.GetHostEntry("time.nist.gov").AddressList[0].GetAddressBytes();
                //Thread.Sleep(1500);
                TimeService.Settings = NTPTime;
                TimeService.SetTimeZoneOffset(LocalTimeZone); // MST Time zone : GMT-7
                TimeService.SystemTimeChanged += OnSystemTimeChanged;
                TimeService.TimeSyncFailed += OnTimeSyncFailed;
                TimeService.Start();
                //Thread.Sleep(500);
                TimeService.UpdateNow(0);
                //Thread.Sleep(9000);
                //Debug.Print("It is : " + DateTime.Now);

                var time = DateTime.Now;

                Utility.SetLocalTime(time);
                RealTimeClock.SetDateTime(time);

                sD2405_Real_Time_Clock.SetDateTime(time);

                TimeSpan diff = DateTime.Now.Subtract(sD2405_Real_Time_Clock.GetDateTime());

                DisplayData(FormatDuration(diff));

                TimeService.Stop();
            }
            catch (Exception ex)
            {
                Debug.Print(ex.Message);
            }
        }

        private string FormatDuration(TimeSpan x)
        {
            return x.Days.ToString("D") + ":" + x.Hours.ToString("D2") + ":" + x.Minutes.ToString("D2") + ":" +
                   x.Seconds.ToString("D2") + "." + x.Milliseconds.ToString("D3");
        }

        private void OnSystemTimeChanged(object sender, SystemTimeChangedEventArgs e)
        // Called on successful NTP Synchronization
        {
            var now = DateTime.Now; // Used to manipulate dates and time

            #region Check if we are in summer time and thus daylight savings apply

            // Check if we are in Daylight savings. The following algorithm works pour Europe and associated countries
            // In Europe, daylight savings (+60 min) starts the last Sunday of march and ends the last sunday of october

            var aprilFirst = new DateTime(now.Year, 4, 1);
            var novemberFirst = new DateTime(now.Year, 11, 1);
            var sundayshift = new[] { 0, -1, -2, -3, -4, -5, -6 };
            var marchLastSunday = aprilFirst.DayOfYear + sundayshift[(int)aprilFirst.DayOfWeek];
            var octoberLastSunday = novemberFirst.DayOfYear + sundayshift[(int)novemberFirst.DayOfWeek];

            if ((now.DayOfYear >= marchLastSunday) && (now.DayOfYear < octoberLastSunday))
                _daylightSavingsShift = 60;
            else
                _daylightSavingsShift = 0;

            TimeService.SetTimeZoneOffset(LocalTimeZone + _daylightSavingsShift);

            #endregion

            // Display the synchronized date on the Debug Console

            now = DateTime.Now;
            var date = now.ToString("dd/MM/yyyy");
            var here = now.ToString("HH:mm:ss");
            Debug.Print(date + " // " + here);
        }

        private void OnTimeSyncFailed(object sender, TimeSyncFailedEventArgs e)
        // Called on unsuccessful NTP Synchronization
        {
            Debug.Print("NTPService : Error synchronizing system time with NTP server");
        }


        private void _realTimeClock_TimeAlarm(SD2405_Real_Time_Clock sender, SD2405_Real_Time_Clock.AlarmType type)
        {
            Debug.Print("Time Alarm!!");
            var test = sD2405_Real_Time_Clock.GetDateTime();
            Debug.Print(test.ToString());
        }

        private void _realTimeClock_CountDownAlarm(SD2405_Real_Time_Clock sender, SD2405_Real_Time_Clock.AlarmType type)
        {
            Debug.Print("Count Down Alarm!!");
            var test = sD2405_Real_Time_Clock.GetDateTime();
            Debug.Print(test.ToString());
        }
    }
}


I can use most of what you sent. I don’t need an ‘alarm’, but the countdown code with work for what I’m doing (automatic a model railroad layout), turning things on the layout on and off.

However I need an updated driver. I’m using the 4.3 framework.

@ DanCio - The driver I put on my one drive and sent you a link for is a 4.3 driver