Jump to content
  • 0

Real time clock DS3231


IgorS

Question

 I have seen many tutorials about connecting real time clock hardware on Orange Pi and Raspberry Pi.
What i didn't like was removing of fake-hwclock service, because I want that RTC works when it is connected, and fake-hwclock when RTC is not connected.
Therefore, I changed /sbin/fake-hwclock script to work in this way.
 

So, here is how to do this, tested on OrangePi+2E, Armbian Ubuntu legacy kernel:

Purchase cheap DS3231 module on eBay (cca. $1) like this one:

http://www.ebay.com/itm/DS3231-AT24C32-IIC-Modul-High-Precision-Real-Time-Clock-Module-Arduino-New-/292041844936?hash=item43ff0ce8c8:g:d80AAOSwdGFYtsFP

Put battery in module.

Shutdown and powerof OPi and connect module:

Orange (i2c0 bus)							RTC module (DS3231 RTC + 24C32 eeprom)
1   3.3V                                    2 VCC
3   PA12 (TWI0_SDA/DI_RX/PA_EINT12)         3 SDA
5   PA11 (TWI0_SCK/DI_TX/PA_EINT11)         4 SCL
9   GND										1 GND

Power up OPi

Install i2c-tools.

sudo apt install i2c-tools

Type command:

i2cdetect -y 0

You should see:

     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- UU -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- 57 -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- -- 

This means that module is connected properly and that we have DS3231 on address 0x68 and eeprom 24C32 on address 0x57.

Type:

sudo echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-0/new_device
i2cdetect -y 0

You should see:

     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- UU -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- 57 -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- UU -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --

This means that system is now using our RTC. Also, now should exist new device /dev/rtc1

Be sure that your system time is right, and type:

sudo hwclock -w -f /dev/rtc1

Now our RTC must have right time. Check with:

sudo hwclock -r -f /dev/rtc1

If everithing was ok, copy /sbin/fake-hwclock to bacup (just in case)

sudo cp ~/programming/sh/fake_hwclock/sbin/fake-hwclock /sbin/fake-hwclock

Edit /sbin/fake-hwclock and place this code in it:

Spoiler

 


!/bin/sh
#
# script: /sbin/fake-hwclock
# Changed by I.S. to use RTC if it is connected
#
#
# Trivial script to load/save current contents of the kernel clock
# from/to a file. Helpful as a *bootstrap* clock on machines where
# there isn't a useful RTC driver (e.g. on development boards). Using
# NTP is still recommended on these machines to get to real time sync
# once more of the system is up and running.
#
# Copyright 2012 Steve McIntyre <93sam@debian.org>
#
# License: GPLv2, see COPYING

# Config variables

# RTC is attached on bus...
i2c_bus=0
eeprom_address="57"
rtc_address="68"

# Orange  PI +2e have RTC, so our device will be:
rtc_device="rtc1"

# fake-hwclock is using cron.hourly to periodically save system clock
cronfile="/etc/cron.hourly/fake-hwclock"

# If you want to periodically synchronize rtc with system time, change this to true
update_rtc_periodically=false

# End of config variables


# I don't know are all needed programs in PATH,
# therefore I'll declare all mine
echo="/bin/echo"
i2cdetect="/usr/sbin/i2cdetect"
grep="/bin/grep"
awk="/usr/bin/awk"
ln="/bin/ln"
hwclock="/sbin/hwclock"
readlink="/bin/readlink"

progs="$echo $i2cdetect $grep $awk $ln $hwclock $readlink"

check_external_progs(){
  not_found=""
  prog=""
  for prog in ${progs}
  do
    if [ ! -e "$prog" ]; then
      not_found=$prog" "$not_found
      echo "Required program not found: $prog"
    fi
  done

  if [ "$not_found"x = ""x ] ; then
    progs_ok=true
  else
    progs_ok=false
  fi
  unset not_found
  unset prog
}

recreate_cronjob() {
if [ ! -e "$1" ]; then
cat << 'EOF' > "$1"
#!/bin/sh
#
# Simple cron script - save the current clock periodically in case of
# a power failure or other crash

if (command -v fake-hwclock >/dev/null 2>&1) ; then
  fake-hwclock save
fi
EOF
fi
}

is_rtc_connected(){
  check_external_progs
  if $progs_ok; then
    list=$($i2cdetect -y "$i2c_bus")
    rtc=$(echo "$list" | $grep "60:" | $awk '{print $10}')
    eeprom=$(echo "$list" | $grep "50:" | $awk '{print $9}')

    if [ "$eeprom" -eq "$eeprom_address" ]; then
      case $rtc in
        "UU")
          t="/dev/$rtc_device"
          r=$($readlink -f /dev/rtc)
          if [ "$r"="$t" ]; then
            $echo "true"
          else
            $ln -sf /dev/$rtc_device /dev/rtc >/dev/null 2>&1
            if [ "$r"="$t" ]; then
              $echo "true"
            else
              $echo "false"
            fi
          fi;;

        $rtc_address)
          $echo ds1307 0x68 > /sys/class/i2c-adapter/i2c-0/new_device

          sleep 5
          
          $ln -sf /dev/$rtc_device /dev/rtc >/dev/null 2>&1
          
          t="/dev/$rtc_device"
          r=$($readlink -f /dev/rtc)

          if [ "$r"="$t" ]; then
            $echo "true"
          else
            $echo "false"
          fi;;

        *)
          $echo "false";;
      esac
    else
      $echo "false"
    fi
  else
    $echo "false"
  fi
}


# Is RTC installed?
rtc_installed=$(is_rtc_connected)

if $rtc_installed; then
  # We dont need periodically saving
  rm -f "$cronfile" >/dev/null 2>&1
else
  # Restore periodically saving
  recreate_cronjob "$cronfile"
fi


if [ "$FILE"x = ""x ] ; then
    FILE=/etc/fake-hwclock.data
fi

COMMAND=$1
if [ "$COMMAND"x = ""x ] ; then
    COMMAND="save"
fi

FORCE=false
if [ "$2"x = "force"x ] ; then
    FORCE=true
fi

case $COMMAND in
    save)
        if $rtc_installed; then
          #$echo "RTC save"
          $hwclock -w
          if $update_rtc_periodically; then
            $echo "cronjob restore"
            recreate_cronjob "$cronfile"
          fi
        else
          if [ -e $FILE ] ; then
              SAVED="$(cat $FILE)"
              SAVED_SEC=$(date -u -d "$SAVED" '+%s')
              NOW_SEC=$(date -u '+%s')
              if $FORCE || [ $NOW_SEC -ge $SAVED_SEC ] ; then
                  date -u '+%Y-%m-%d %H:%M:%S' > $FILE
              else
                  echo "Current system time: $(date -u '+%Y-%m-%d %H:%M:%S')"
                  echo "fake-hwclock saved clock information is in the future: $SAVED"
                  echo "To force the saved system clock backwards anyway, use \"force\""
              fi
          else
              date -u '+%Y-%m-%d %H:%M:%S' > $FILE
          fi
        fi
        ;;
    load)
        if $rtc_installed; then
          #$echo "RTC load"
          $hwclock -s
        else
          if [ -e $FILE ] ; then
              SAVED="$(cat $FILE)"
              SAVED_SEC=$(date -u -d "$SAVED" '+%s')
              NOW_SEC=$(date -u '+%s')
              if $FORCE || [ $NOW_SEC -le $SAVED_SEC ] ; then
                  date -u -s "$SAVED"
              else
                  echo "Current system time: $(date -u '+%Y-%m-%d %H:%M:%S')"
                  echo "fake-hwclock saved clock information is in the past: $SAVED"
                  echo "To set system time to this saved clock anyway, use \"force\""
              fi
          else
              echo "Unable to read saved clock information: $FILE does not exist"
          fi
        fi
        ;;
    *)
        echo $0: Unknown command $COMMAND
        exit 1
        ;;
esac

Reboot.
Now you should have right system time backed up by RTC.

 

Edited by Tido
added Spoiler
Link to comment
Share on other sites

Recommended Posts

Donate your old hardware to community. Start a giveaway Raffle!

  • 0

Sorry to sound ignorant and stupid.

 

I have an orange pi pc board running Android 7.

 

I keep having to set the date and time every time i power the board up.

 

I obviously have no ethernet internet connection until i do this.

 

Would this thing stop that from happening?

 

Thank you.

 

Dean

 

Link to comment
Share on other sites

  • 0
1 minute ago, KiwiChristian said:

I thought it would be just plug in and go


It is that way. The problem will be if nothing happens :) We can't help you in reconfiguring and recompiling Amdroid kernel. We don't deal with it.

Link to comment
Share on other sites

  • 0
6 hours ago, KiwiChristian said:

I just wish i knew why i have to reset my date and time each time i power my orangepi on.

This is because the realtime clock of the Pi is not battery-powered, i.e. after powercycle it resets to factory default. The ds1307/3231 do have battery but need i2c in kernel and additional configuration to be used as main RTC instead of the Pi RTC.

 

In other words, by default the time is stored/restored on Pi RTC.

Link to comment
Share on other sites

  • 0
7 hours ago, xwiggen said:

This is because the realtime clock of the Pi is not battery-powered, i.e. after powercycle it resets to factory default. The ds1307/3231 do have battery but need i2c in kernel and additional configuration to be used as main RTC instead of the Pi RTC.

 

In other words, by default the time is stored/restored on Pi RTC.

Ah, thank you. I have been trying to work out the problem.

 

BUT, i never USED to have to do this.

 

It is only in the last couple of months.

 

I wasted money on a new orange pi and that does the same thing.

 

One thing i have noticed, it says my sd card ( i assume where android is located ) is corrupt.

 

I may try another sd card, but i only have a 4gb spare at the moment.

Link to comment
Share on other sites

  • 0
15 hours ago, KiwiChristian said:

Ah, thank you. I have been trying to work out the problem.

 

BUT, i never USED to have to do this.

 

It is only in the last couple of months.

 

I wasted money on a new orange pi and that does the same thing.

 

One thing i have noticed, it says my sd card ( i assume where android is located ) is corrupt.

 

I may try another sd card, but i only have a 4gb spare at the moment.

 

Fake hwclock saves/restores the date on SD in Armbian between reboots, don't know about the specifics in Android.

 

Link to comment
Share on other sites

  • 0

Hi @IgorS,

After following the how to's on this forum and the internets, would like to share some other things I did to make it work even better on my OrangePi Zero.

 

  1. Connect DS3231 to TWI0 (PA11+PA12 and +5V/GND of course).
     
  2. Add i2c0 overlay to /boot/armbianEnv.txt (or use armbian-config to enable the i2c0 overlay).
    [...]
    overlays=usbhost2 usbhost3 uart1 pps-gpio i2c0
    [...]

     

  3. Add custom overlay to add DS3231 RTC (using DS3232 module instead of DS1307).
    Spoiler
    /dts-v1/;
    /plugin/;
    
    / {
            compatible = "allwinner,sun4i-a10", "allwinner,sun7i-a20", "allwinner,sun8i-h3", "allwinner,sun50i-a64", "allwinner,sun50i-h5";
    
            /* 
             * Aliases can be used to set the external RTC as rtc0.
             * Needs supplying the correct path to the I2C controller RTC is connected to,
             * this example is for I2C0 on H2+ (TWI0 on PA11/PA12).
             * NOTE: setting time at boot by the kernel
             * may not work in some cases if the external RTC module is loaded too late
             */
            fragment@0 {
                    target-path = "/aliases";
                    __overlay__ {
                            rtc0 = "/soc/i2c@1c2ac00/ds3231@68";
                    };
            };
    
            fragment@1 {
                    target = <&i2c0>;
                    __overlay__ {
                            #address-cells = <1>;
                            #size-cells = <0>;
                            ds3231@68 {
                                    compatible = "dallas,ds3232";
                                    reg = <0x68>;
                                    status = "okay";
                            };
                    };
            };
    
    };

     

    Save as rtc0-i2c0-ds3231.dts.
     

  4. Add the custom DT overlay:
    sudo armbian-add-overlay rtc0-i2c0-ds3231.dts

     

  5. Add custom overlay to rename H2+ SoC RTC to rtc1.
    Spoiler
    /dts-v1/;
    /plugin/;
    
    / {
            compatible = "allwinner,sun4i-a10", "allwinner,sun7i-a20", "allwinner,sun8i-h3", "allwinner,sun50i-a64", "allwinner,sun50i-h5";
    
            /* 
             * Aliases can be used to set the internal RTC as rtc1.
             */
            fragment@0 {
                    target-path = "/aliases";
                    __overlay__ {
                            rtc1 = "/soc/rtc@1f00000";
                    };
            };
    
            fragment@1 {
                    target = <&rtc>;
                    __overlay__ {
                            rtc@1f00000 {
                                    status = "disabled";
                            };
                    };
            };
    };

     

    Save as rtc1-soc.dts.
     

  6. Add the custom DT overlay:
    sudo armbian-add-overlay rtc1-soc.dts

     

  7. Disable fake-hwclock service:
    sudo systemctl stop fake-hwclock.service    # stop
    sudo systemctl disable fake-hwclock.service # disable
    sudo systemctl mask fake-hwclock.service    # really disable
  8. Reboot and verify that you now have 2x RTC on your OrangePi Zero:
    root@sinaspi:~# ls -l /dev/rtc*
    lrwxrwxrwx 1 root root      4 Aug  5 22:57 /dev/rtc -> rtc0
    crw------- 1 root root 253, 0 Aug  5 22:57 /dev/rtc0
    crw------- 1 root root 253, 1 Aug  5 22:57 /dev/rtc1
  9. As mentioned in another post, on the H2+ the SoC supplied RTC is indeed running fast, confirm this as follows:
    for RTC in /dev/rtc[0-9]
    do
    	hwclock --rtc="${RTC:?}" --adjust
    	hwclock --rtc="${RTC:?}" --systohc
    done
    
    sleep $(( 5 * 60 ))
    
    for RTC in /dev/rtc[0-9]
    do
    	echo "${RTC:-N/A}:"
    	hwclock --rtc="${RTC:?}" --get 
    	date --rfc-3339=ns
    done

    On my OrangePi Zero the SoC RTC is dashing ahead:
     

    /dev/rtc0:
    2021-08-08 09:17:52.760046+08:00
    2021-08-08 09:17:52.526062078+08:00
    /dev/rtc1:
    2021-08-08 11:59:11.150733+08:00
    2021-08-08 09:17:54.392611945+08:00

    (rtc0 = DS3231 and rtc1 = SoC RTC.)
     

  10. On the same OrangePi Zero, there is also a GPS receiver connected that has PPS output. Used @Elektrický's how to, to set up GPS and ntpsec. After successfully following the how to, ntp will synchronize and adjust system clock to high(er) accuracy. Once system clock is synchronized, the kernel will also update the RTC (/dev/rtc0) every 11 minutes, giving you a system as follows:

    root@sinaspi:~# timedatectl 
                   Local time: Sun 2021-08-08 09:24:01 CST
               Universal time: Sun 2021-08-08 01:24:01 UTC
                     RTC time: Sun 2021-08-08 01:24:02
                    Time zone: Asia/Taipei (CST, +0800)
    System clock synchronized: yes
                  NTP service: inactive
              RTC in local TZ: no
    
    root@sinaspi:~# ntpq -p
         remote                                   refid      st t when poll reach   delay   offset   jitter
    =======================================================================================================
     0.debian.pool.ntp.org                   .POOL.          16 p    -  256    0   0.0000   0.0000   0.0019
     1.debian.pool.ntp.org                   .POOL.          16 p    -  256    0   0.0000   0.0000   0.0019
     2.debian.pool.ntp.org                   .POOL.          16 p    -  256    0   0.0000   0.0000   0.0019
     3.debian.pool.ntp.org                   .POOL.          16 p    -   64    0   0.0000   0.0000   0.0019
    oPPS(0)                                  .PPS.            0 l   56   64  377   0.0000  -0.0072   0.0035
    xSHM(0)                                  .GPS.            0 l   21   64  377   0.0000 -15.3659   1.7862
    +SHM(2)                                  .PPS.            0 l   18   64  377   0.0000  -0.0163   0.0094
    +europa.ellipse.net                      209.180.247.49   2 u   40   64  377 167.9069  -0.9358   0.1437
    +ntp1.time.nl                            .MRS.            1 u   43   64  377 210.9643   1.7869   0.1945
    +promethee.boudot.one                    94.198.159.10    2 u   21   64  377 220.2528   2.3322   0.0931
    root@sinaspi:~# 

    As the DS3231 is now set as rtc0, the udev rules in /lib/udev/rules.d/85-hwclock.rules will make sure to read the DS3231 clock time after a reboot, making sure your system clock has a nice starting offset after being powered off for a while.

 

Hope this helps anyone out there,

Groetjes,

Edited by djurny
formatting and added link to 11 minute sync
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Answer this question...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
×
×
  • Create New...