I2C potřetí: rozsvěcíme LED diodu složitěji a dráže

Ve svém druhém příspěvku jsem ukazoval,  jak rozsvítit LED připojenou na GPIO. Je to snadné, že? Tak teď to bude znovu, ale složitěji.


Přímé připojení vstupů a výstupů na GPIO porty RPi je hezké (a na výuku/předvádění je to super), ale má to dva háčky:

  • Není zcela zjevné, kolik proudu je možno z jednotlivých GPIO krátkodobě a dlouhodobě odebírat – a když to přeženete, nedopadne to dobře.
  • Většina „bastlířského“ světa funguje na pětivoltové logice – a pokud přivedete 5 V na vstup, můžete RPi říct jen „pápá“.

Oba tyto problémy lze vyřešit například použitím I2C GPIO expandéru. Pod označením MCP23009-E/P najdete 8-bitový I2C port expander s otevřeným kolektorem – tj. čip, který má na straně RPi jeden I2C port a směrem ven nabízí 8 I/O portů. Každý z portů si můžete nastavit jako vstupní nebo výstupní.

Port nakonfigurovaný jako vstup je tolerantní k pětivoltové logice, tj. korektně přežije spolupráci s TTL zařízením.

Port nakonfigurovaný jako výstup má tyto parametry:

  • Je tolerantní k 5 V signálům.
  • Má maximální proud 25 mA (a součet přes celý čip nesmí přesáhnout 200 mA).
  • otevřený kolektor – tj. když je na něm logická 0, je sepnutý na zem; když je na něm logická 1, není připojený nikam. Tj. logickou jedničku dosáhnete tím, že výstup přes odpor připojíte k napájení. Kouzlo tohoto řešení je v tom, že při připojení odporu k 3.3V můžete komunikovat se zařízeními s třívoltovou logikou; při připojení odporu k 5 V můžete komunikovat s běžnými TTL (5 V) zařízeními.

Datasheet k obvodu.

Takže to zapojíme:

  • Napájení obvodu na +3.3V a na GND.
  • I2C SDA a SCL na odpovídající výstupy na expanzním konektoru.
  • Dále zde máme /RESET – aby se obvod nahodil, musí tam být logická 1 = přes odpor na +3.3V.
  • Kouzelný vstup ADDR určuje, jakou adresu na I2C sběrnici čip obsadí. Je analogový (!!!) a umožňuje tak jedním drátem určit jednu z osmi adres (=až osm těchto expandérů na jedné I2C sběrnici). Pro zjednodušení si s tím nebudeme hrát a připojíme ADDR na GND = základní adresa 0x20.
  • GP0 až GP7 jsou jednotlivé GPIO vstupy/výstupy.
  • Ostatní nožičky necháme volné.

Mezi +5 V a pin GP0 zapojíme odpor 330 ohm a LEDku. Tj. LED bude svítit, pokud na GP0 bude „0“ = připojeno na zem. Opačně by to nefungovalo – otevřený kolektor, viz výše.

Jako vedlejší efekt tohoto cvičení jsem si chtěl vyzkoušet nějaký nástroj na kreslení schémátek. Zde tedy je výstup z aplikace Fritzing. Vypadá jako vhodná na podobná malování – má hotové moduly i např. pro RPi, nepájivé kontaktní pole má logiku a automaticky propojuje součástky. Kreslí se v tom rychle a pohodlně.

 

Zapojeno máme, co teď s tím?

Po bootu se RPi zeptáme, zda je tam něco nového na I2C sběrnici.

pi@raspberrypi ~ $ i2cdetect -y 0
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: — — — — — — — — — — — — —
10: — — — — — — — — — — — — — — — —
20: 20 — — — — — — — — — — — — — — —
30: — — — — — — — — — — — — — — — —
40: — — — — — — — — 48 — — — — 4d — —
50: — — — — — — — — — — — — — — — —
60: — — — — — — — — — — — — — — — —
70: — — — — — — — —

Na adrese 0x20 vidíme nové zařízení. 0x48 a 0x4d jsou teplotní čidla z minulého dílu.

Nastavíme registr IODIRA (0), který určuje, zda jsou piny vstupní nebo výstupní. 1 = vstup, 0 = výstup. Pro komunikac použijeme i2cset, kterému předáme parametry:

  • -y = neptej se na nic
  • 0 = sběrnice 0
  • 0x20 = adresa čipu na sběrnici
  • 0 = adresa registru v čipu
  • 0xfe = hodnota, co nastavujeme (1111 1110)
  • b = zapisujeme 1 byte

pi@raspberrypi ~ $ i2cset -y 0 0x20 0 0xfe b

LED se rozvítila! Defaultní hodnota výstupního pinu je totiž „0“.

No a teď můžeme blikat LEDkou. Piny se ovládají v registru OLATA (0x0a).

pi@raspberrypi ~ $ i2cset -y 0 0x20 0x0a 0x01 b

(1 = zhasnuto)

pi@raspberrypi ~ $ i2cset -y 0 0x20 0x0a 0x00 b

(0 = svítí)

pi@raspberrypi ~ $ i2cset -y 0 0x20 0x0a 0x01 b

(1 = zhasnuto)

Kdybych chtěl číst stav vstupních pinů, je to k nalezení v registru GPIOA (0x09).

Takže děláme stejnou práci, jako na začátku. Blikáme LEDkou. Ale daleko sofistikovaněji než předtím.

Tipy a triky:

  • Od stejného výrobce se dá pořídit MCP23017, což je 16-bitová verze téhož. Více nožiček a více pinů, stejná logika ovládání.
  • Chci-li nastavit jen jeden bit nějakého I2C registru, příkaz i2cset na to má volbu „mask“ – maskou řeknete, které bity chcete nastavit; i2cset si hodnotu ostatních bitů načte z čipu a pak je doplní do zapisovaného bajtu.

1 = I2C čidla teploty z minulého článku
2 = MCP23009-E/P
3 = LEDka. Bliká na rozkaz.
4+5 = 1-wire bus adaptér a čidlo DS18B20 – bude v dalším článku, stay tuned

10 thoughts on “I2C potřetí: rozsvěcíme LED diodu složitěji a dráže

  1. zdravím děkuju za článek, dříve než jsem ho však našel udělal jsem si to sam:( škoda.

    mám však jednu otázku. nemohu zaboha příjít na to, jak mám ovládat pouze jeden pin expanderu.
    například:
    odešlu přikaz i2cset -y 0 0x20 0x13 0xff
    což znamená zápis 1111 1111 a všech 8 gpio B je sepnuto.
    ja chci zapsat 0 na pin 1B tak odešlu i2cset -y 0 0x20 0x13 0xfe, takže 1111 1110 a pin 1B ma hodnotu nula.

    je nějak možné, aby jsem zapsal pouze hodnotu pro pin 1B a ostatni zustaly stejné?

    • Ano, je to možné a píšu to v článku.

      chci zapsat 0 na pin 1B tak odešlu

      i2cset -y 0 0×20 0×13 0 1

      Poslední hodnota je maska – do kterých bitů zapisuješ. Cituju návod: „The mask parameter, if specified, describes which bits of value will be actually written to data-address. Bits set to 1 in the mask are taken from value, while bits set to 0 will be read from data-address and thus preserved by the operation.“

      • Chviličku jsem se stím pral a podařilo se mi to, ale s jiným zápisem.

        např:
        pro zapsání 1 na 1B
        i2cset -y -m 0x01(0000 0001) 0 0x20 0x13 0xff

        nebo pro zapsání 1 na 4B
        i2cset -y -m 0x08(0000 1000) 0 0x20 0x13 0xff

        třeba to někomu pomůže

    • bezva řešení. Nevíte náhodou někdo o tom kde se dá MCP23009-E/P koupit v Praze ? Nechce se mi platit 200,- za poštovné za součástku za necelých 50,-….

    • s krizkem po funuse – tak kdyby to resil nekdo dalsi:
      MCP23016 I-SP pouzit lze, ovsem musel jsem pridat odpor a kondik pro vstup CLK; zapojeni pinu je jine a adresace registru take. napr. prepnuti IODIR0 na out: i2cset -y 0 0x20 6 0xfe b .. viz datasheet

  2. Znovu jsem si četl celý článek a…z číny mi jdou tyhle dvě vychytávky..
    http://www.dx.com/p/keyes-3-3v-5v-ttl-logic-level-converter-module-red-334669
    to mám na propojení arduina s RPi B+. A na I2C zařízení http://www.dx.com/p/iic-i2c-level-conversion-module-compatible-with-3-5v-system-sensor-blue-197198#.VIbhPdJhnjs
    prostě tohle píchnu do pole, spojím pár částí pole a napíchám tam klidně 50 I2C věcí co nebudu řešit jestli jsou na 5V nebo 3,3V…..

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna.