Raspberry Pi bináris óra
Készítsünk bináris órát néhány LED, egy MCP23017 és egy Raspberry Pi segítségével.
Már egy ideje az íróasztal fiókom mélyén tanyázik egy MCP23017 chip, amivel például a Raspberry Pi GPIO portjait lehet bővíteni, szám szerint 16 darab új csatlakozással. A 16 darab csatlakozás pedig pont elég arra, hogy 16 darab LED segítségével megjelenítsünk egy bináris órát (bár sajnos csak 12 órás megjelenítéssel).
Hardver és összedrótozás
Először is talán ismerkedjünk meg egy kicsit közelebbről az MCP23017-tel. I²C buszon lehet vele kommunikálni, a hardver címét az A0-2
lábak határozzák meg.
A GPA0-7
és GPB0-7
lábakra fogjuk rákötni a ledeket (esetleg a LED-hez kellhet még egy ellenállás is, de én attól eltekintettem), A VSS
-re és az A0-2
lábakra megy a föld (ez a 0x20
-as hardvercímet fogja eredményezni), a VDD
-re és a RESET
-re a 3.3V, az SLC
és SDA
pedig a Raspberry Pi azonos nevű kivezetéseivel lesz összekötve.
Bónuszként a kábelrengeteg miatt még úgy is fog tűnni, mintha valami bonyolult dolog lenne. Ezen kívül, ami még érdekel minket, azok az MCP23017 regiszterei és azok címei. Legalábbis egy részük:
0x00 |
IODIRA |
A GPA0-7 lábak inputként vagy outputként működjenek |
0x01 |
IODIRB |
A GPB0-7 lábak inputként vagy outputként működjenek |
0x12 |
GPIOA |
Ennek a segítségével lehet a GPA0-7 lábakat elérni |
0x13 |
GPIOB |
Ennek a segítségével lehet a GPB0-7 lábakat elérni |
A chip dokumentációjában utána lehet nézni a többinek is, ha valakit esetleg részletesebben is érdekelne.
Konfigurálás
Ennyit a hardverről, végre rátérhetünk a dolog szoftveres részére. Mint azt már fentebb említettem, a chip I²C-t használ, ami alapból nincsen bekapcsolva az RPi-n. Először is a /etc/modules
fájlba kell két új sor, mondjuk a végére:
i2c-bcm2708
i2c-dev
Aztán a /etc/modprobe.d/raspi-blacklist.conf
fájlban a blacklist i2c-bcm2708
sort kell törölni (vagy kikommentelni). Szükség van ezen kívül még néhány csomagra telepítésére is:
$ sudo apt-get install python-smbus i2c-tools
Ha ez is végzett, akkor már csak egy újraindítás, és el is kezdhetjük használatba venni a szerkezetet.
Életre keltés
Először is szükségünk lesz a chip címére, amit az i2cdetect
parancs segítségével tudunk kideríteni. A fenti drótozással elvileg ezt kell kapnunk:
$ sudo i2cdetect -y 1
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: 20 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
Amiből kiderül, hogy 0x20
az eszköz címe (régebbi RPi-n előfordulhat, hogy sudo i2cdetect -y 0
a nyerő parancs), úgyhogy rá is térhetünk a kódra.
import time
import smbus
Az már a konfigurálás során kiderült, hogy a Python smbus
modulját fogjuk használni (meg egy kis időt, ha már egyszer órát csinálunk).
i2c = 1
addr = 0x20
Néhány beállítás: az i2c
értéke ugyanaz, mint amit az i2cdetect
parancsban is használtunk -y
paraméterként, az addr
értéke pedig az i2cdetect
válaszából kinyert hardver cím.
bus = smbus.SMBus(i2c)
bus.write_byte_data(addr, 0x00, 0x00)
bus.write_byte_data(addr, 0x01, 0x00)
Kezdődhet a kommunikáció. A chip 0x00
-s és 0x01
-es regisztereit is kinullázzuk, ami mindkét nyolcas csatlakozó csoportot output-ra állítja.
try:
while True:
now = time.localtime()
h = now.tm_hour
if h > 12:
h = h - 12
x = '{:04b}{:06b}{:06b}'.format(h, now.tm_min, now.tm_sec)
bus.write_byte_data(addr, 0x12, int(x[8:], 2))
bus.write_byte_data(addr, 0x13, int(x[:8], 2))
time.sleep(0.01)
except KeyboardInterrupt:
bus.write_byte_data(addr, 0x12, 0x00)
bus.write_byte_data(addr, 0x13, 0x00)
print
Először átvarázsoljuk az aktuális időt egy nekünk megfelelő bináris formátumba, aztán beírjuk az egyes byte-okat a 0x12
-es és 0x13
-as regiszterekbe. Aztán ez megy tovább a végtelenségig. Vagyis amíg Ctrl+C-t nem nyomunk, akkor kinullázzuk mindkét regisztert, ami az összes ledet lekapcsolja. A végeredmény pedig: