RTC cho RPi – Cách nào và để làm gì?

Image result for DS3231

Mạch thời gian thực RTC DS1307/DS3231 bán ở VN giá khoảng 80k đồng, lắp vào RPi để máy có đồng hồ thời gian thực mà không cần kết nối internet.

I. Bằng cách nào?

RTC giao tiếp với RPi qua giao thức I2C nên trước hết phải bật I2C khi khởi động.

sudo raspi-config -> Advanced Options -> A6 I2C -> [Yes]

Với Wheezy

  1. Tạo file /etc/modules-load.d/rtc-i2c.conf
# /etc/modules-load.d/rtc-i2c.conf
i2c-dev
i2c_bcm2708

2. Tạo file /etc/udev/rules.d/rtc-i2c.rules để đặt giờ hệ thống từ RTC mỗi khi có RTC

# /etc/udev/rules.d/rtc-i2c.rules
ACTION=="add", SUBSYSTEM=="rtc", ATTRS{hctosys}=="0", RUN+="/sbin/hwclock -s --utc"

3. Nạp các module cần thiết

sudo modprobe i2c-bcm2708 
sudo modprobe i2c-dev
sudo modprobe rtc-ds1307

4. Tắt RPi bằng lệnh sudo halt hay sudo shutdown -h now, sau đó lắp RTC tại đầu dãy GPIO phía trong và quay vào trong

Plugging the RTC onto the Raspberry Pi

5. Bật nguồn RPi, cài đặt i2c_tools qua lệnh

sudo apt-get install i2c-tools

sau đó kiểm tra xem RTC có được nhận biết không qua lệnh

sudo i2cdetect -y 1

I2C Device Detection

68 là địa chỉ I2C của RTC

6. Tạo systemd service rtc-i2c.service. Service này gọi systemd tạo thiết bị RTC mỗi khi khởi động. Khi udev thấy thiết bị xuất hiện, nó sẽ gọi công cụ hwclock để đặt giờ hệ thống từ RTC. Ta cần tạo 2 file:

File cấu hình (tạo thư mục /etc/conf.d trước)

# /etc/conf.d/rtc-i2c 
CHIP="ds1307"
ADDRESS="0x68"
BUS="1"

file systemd service

# /lib/systemd/system/rtc-i2c.service

[Unit]
Description=Initialize i2c hardware RTC device driver
DefaultDependencies=no
Requires=systemd-modules-load.service
After=systemd-modules-load.service
Before=sysvinit.target
ConditionPathExists=/sys/class/i2c-adapter
Conflicts=shutdown.target

[Service]
Type=oneshot
RemainAfterExit=yes
EnvironmentFile=/etc/conf.d/rtc-i2c
ExecStart=/bin/sh -c "echo ${CHIP} ${ADDRESS} > /sys/class/i2c-adapter/i2c-${BUS}/new_device"

[Install]
WantedBy=sysinit.target

7. Cuối cùng, cho phép service vừa tạo hoạt động

sudo systemctl enable rtc-i2c.service

Chạy thử lệnh sau đây, nếu có lỗi thì tìm nguyên nhân khắc phục (thí dụ lỗi watchdog, không liên quan đến RTC)

service rtc-i2c start

8. Xóa fake-hwclock: fake-hwclock trước kia định giờ cho RPi nhưng giờ không cần nữa, giữ lại có thể gây nhiểu cho RTC

sudo apt-get remove fake-hwclock -y
update-rc.d -f fake-hwclock remove

9. Script cài đặt

#!/bin/bash
[ -e /dev/rtc0 ] && return 0
#--Load up the RTC module
#modprobe i2c-bcm2708
#modprobe i2c-dev
#modprobe rtc-ds1307
echo "Cấu hình rtc-i2c..."
cat <<'EOF' | sudo tee /etc/modules-load.d/rtc-i2c.conf &> /dev/null
# /etc/modules-load.d/rtc-i2c.conf
i2c-dev
i2c_bcm2708
EOF
echo "Thiết lập giờ hệ thống mỗi khi thấy RTC..."
cat <<'EOF' | sudo tee /etc/udev/rules.d/rtc-i2c.rules &> /dev/null
# /etc/udev/rules.d/rtc-i2c.rules
ACTION=="add", SUBSYSTEM=="rtc", ATTRS{hctosys}=="0", RUN+="/sbin/hwclock -s --utc"
EOF
echo "Tham số cho rtc-i2c service..."
[ ! -d /etc/conf.d ] && sudo mkdir /etc/conf.d
cat <<'EOF' | sudo tee /etc/conf.d/rtc-i2c &> /dev/null
# /etc/conf.d/rtc-i2c
CHIP="ds1307"
ADDRESS="0x68"
BUS="1"
EOF
echo "Tạo service rtc-i2c..."
cat <<'EOF' | sudo tee /lib/systemd/system/rtc-i2c.service &> /dev/null
[Unit]
Description=Initialize i2c hardware RTC device driver
DefaultDependencies=no
Requires=systemd-modules-load.service
After=systemd-modules-load.service
Before=sysvinit.target
ConditionPathExists=/sys/class/i2c-adapter
Conflicts=shutdown.target

[Service]
Type=oneshot
RemainAfterExit=yes
EnvironmentFile=/etc/conf.d/rtc-i2c
ExecStart=/bin/sh -c "echo ${CHIP} ${ADDRESS} > /sys/class/i2c-adapter/i2c-${BUS}/new_device"

[Install]
WantedBy=sysinit.target
EOF
echo "dtoverlay=i2c-rtc,ds3231" | sudo tee -a /boot/config.txt
echo "Chạy service rtc-i2c..."
sudo systemctl enable rtc-i2c.service
echo "Xóa fake-hwclock..."
sudo apt-get remove fake-hwclock -y
sudo update-rc.d -f fake-hwclock remove
echo -e "\nreboot và chạy thử 'hwclock -r' để kiểm tra xem RTC có hoạt động hay không?"

Với Jessie

  1. Thêm vào cuối file config.txt dòng
dtoverlay=i2c-rtc,ds3231

2. Mở file /lib/udev/hwclock-set, và đặt dấu # trước các dòng sau

if [ -e /run/systemd/system ] ; then
    exit 0
fi

3. Gõ lệnh date, nếu ngày giờ đúng thì gõ tiếp

sudo hwclock -w
sudo hwclock -s

4. Script cài đặt

#!/bin/bash
grep -qF "dtoverlay=i2c-rtc,ds3231" "/boot/config.txt" || echo "dtoverlay=i2c-rtc,ds3231" | sudo te$
sudo sed -n '/^if \[ -e \/run\/systemd\/system \]/, +2 s|^|#|' -i /lib/udev/hwclock-set
sudo hwclock -w
sudo hwclock -s
if [ -e /lib/systemd/system/rtc-i2c.service ]; then
 sudo systemctl disable rtc-i2c.service
 sudo rm -f /lib/systemd/system/rtc-i2c.service
 sudo rm -R /etc/conf.d
 sudo rm -f /etc/udev/rules.d/rtc-i2c.rules
 sudo rm -f /etc/modules-load.d/rtc-i2c.conf
fi

Kiểm tra

Khởi động lại RPi để các cài đặt có tác dụng. Gõ lệnh hwclock -r để xem giờ từ RTC, nếu có thông báo lỗi thì xem xét lại các bước.


II. Để làm gì?

Trước mắt, chỉ đế RPi có đồng hồ thời gian thực mà không cần kết nối internet. Các chức năng thường có với RTC như sleep, hypernate đều không có tác dụng.

Leave a Comment

Filed under Software

Leave a Reply