Prvotně publikováno na raspi.cz 7.7.2012. Článek již není zcela aktuální – dnešní distribuce Raspbian má již podporu I2C zabudovanou, je to popsáno v dalším článku.
RPi nemá hodiny reálného času. Bez připojení na internet tedy neví, kolik je hodin. Pokud používáte Debian squeeze, po startu budete mít nastaveny hodiny na čas posledního shutdownu; ve Fedoře jsem viděl i 1.1.1970.
To je docela neštěstí, pokud chcete RPi použít jako datalogger, tj. zařízení, které někde bez připojení autonomně získává údaje a ty se pak dávkově předají například na výměnném médiu (nebo sice konektivitu má, ale jen občas).
Co s tím můžeme udělat? Připojit RTC – hodiny reálného času.
Hardware
Na svém oblíbeném e-shopu jsem našel tento levný modul RTC. Za méně než 6 USD, s dopravou zdarma, obsahuje standardní čip PCF8563, potřebnou bižuterii (krystal atd), držák na baterii a zálohovací baterku. A je kompatibilní s 3.3V rozhraním RPi.
Jeho připojení je jednoduché – má rozhraní I2C. Takže připojit na I2C data a hodiny (SDA, SCL), GND na zem a VCC na napájení 3.3V.
SPI, I2C – co to je?
Aha, teď jsem použil nějaká sprostá slova. Na expanzní konektor RPi jsou vyvedeny dvě sériové sběrnice – SPI a I2C.
SPI je relativně hloupá sběrnice. Má hodiny (RPi udává takt), data směrem ven, data směrem dovnitř. A pak pro každé připojené zařízení musíte mít jeden volný GPIO pin, kterým mu řeknete „teď si povídám s tebou“. Není stanoven přesný protokol, co po sběrnici běhá – je to vždy specifické podle zařízení. Více info: wiki, root.
I2C je výrazně chytřejší. Používá jen dva dráty: hodiny SCL (RPi udává takt) a obousměrná data SDA, na kterých se všechny připojené zařízení střídají. Ke sběrnici může být připojeno až 127 zařízení. Je přesně definovaný protokol, kterým RPi řekne např. „teď chci zapsat hodnotu 27 do registru 66 na zařízení 34“ nebo „zařízení 52, řekni mi stav svého registru 22“. Více info: wiki, root.
Kouzlo I2C je v tom, že jí linux zná. Tedy můžeme ušetřit spoustu času a nemusíme programovat posílání jedniček a nul přes jednotlivé dráty.
Software
Debian squeeze ve verzi 2012-04-19 nemá (ani po posledních updatech v červnu 2012) podporu pro I2C. Ale tenhle borec jí tam dodělal.
Postup pro rozchození I2C:
1) Nainstalujte si a spusťte rpi-update, abyste měli nejnovější firmware a kernel (u mne 3.2.18). Nastavte memory split na 192 MB.
2) Stáhněte si opatchované jádro (linux-image-3.2.18-rpi1+_5_armel.deb) z odkazu.
POZOR! Vždy kontrolujte verzi svého kernelu a na home stránce si najděte odpovídající patchovaný kernel! Pokud pomícháte kernel s nevhodnou verzí firmware, nebude to fungovat.
3) Stažený soubor rozbalte:
dpkg -i linux-image-3.2.18-rpi1+_5_armel.deb
což vytvoří /boot/vmlinuz-3.2.18-rpi1+
4) Překopírujte /boot/vmlinuz-3.2.18-rpi1+ do /boot/kernel.img a restartujte systém.
Po nabootování se nic špatného nestalo, je tedy načase začít zkoušet I2C:
5) Otevřeme si terminál a přepneme se pod roota, protože většina dalších akcí chce root privilegia:
sudo bash
6) Vyzkoušíme načíst ovladač pro I2C:
modprobe i2c-dev
Pokud je vše v pořádku, vzniknou dvě nová zařízení: /dev/i2c-0 a /dev/i2c-1 . Bus 0 je vyveden na expanzní konektor, bus 1 končí na konektoru pro kamery, tedy je pro nás zatím nedostupný.
7) Pro práci s I2C si nainstalujeme patřičné nástroje:
apt-get install i2c-tools
8) A vyzkoušíme, jestli se něco děje:
i2cdetect 0
WARNING! This program can confuse your I2C bus, cause data loss and worse!
I will probe file /dev/i2c-0.
I will probe address range 0x03-0x77.
Continue? [Y/n]
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: — — — — — — — — — — — — —
10: — — — — — — — — — — — — — — — —
20: — — — — — — — — — — — — — — — —
30: — — — — — — — — — — — — — — — —
40: — — — — — — — — — — — — — — — —
50: — 51 — — — — — — — — — — — — — —
60: — — — — — — — — — — — — — — — —
70: — — — — — — — —
pi@raspberrypi:~$
Hele, je tam! Na adrese 51 si s námi něco povídá! Takže I2C sběrnice funguje.
Takže teď stačí vzít datasheet k PCF8563, naprogramovat komunikaci a nastavit podle něj hodiny, ne? Ehm … neudělal to už někdo? Kouknu do Googlu … a zjistím, že hotovo je dokonce víc, než jsem si myslel – linux má přímou podporu pro tento RTC čip na I2C busu.
9) Vysvětlíme kernelu, že máme na I2C busu 0 zařízení 51 a to zařízení je PCF8563:
echo pcf8563 0x51 > /sys/class/i2c-adapter/i2c-0/new_device
a to je všechno. Odteď je to standardní RTC zdroj, který linux umí!
10) Zkusíme z něj načíst uložený čas:
hwclock -r
Wed 06 Jun 2012 18:08:46 BST -0.057931 seconds
Hotovo.
Test řešení
Někdy kolem 18:07 reálného času jsem zařízení zapnul.
pi@raspberrypi:~$ sudo bash
root@raspberrypi:/home/pi# date
Wed Jun 6 17:52:28 BST 2012
Čas není dobře – je to čas posledního shutdownu, předpokládám.
root@raspberrypi:/home/pi# modprobe i2c-dev
root@raspberrypi:/home/pi# echo pcf8563 0x51 > /sys/class/i2c-adapter/i2c-0/new_device
root@raspberrypi:/home/pi# hwclock -r
Wed 06 Jun 2012 18:08:46 BST -0.057931 seconds
Čas v RTC je správně.
root@raspberrypi:/home/pi# date
Wed Jun 6 17:53:33 BST 2012
Ale čas systému je stále špatně. Tak mu řekneme, ať se nastaví podle RTC:
root@raspberrypi:/home/pi# hwclock -s
root@raspberrypi:/home/pi# date
Wed Jun 6 18:09:24 BST 2012
A vše je OK.