mcp23017 (i2c) a vstup/výstup na jeden pin

Odpovědět
aladin
Příspěvky: 290
Registrován: 12 kvě 2013, 06:43

mcp23017 (i2c) a vstup/výstup na jeden pin

Příspěvek od aladin »

Ahoj,
nevíte, jak se
1. zapíše na konkrétní pin hodnota a ostatní nechám jak jsou ?
2. dá připojit na jeden port tlačítko a led zároveň, jak to obsloužit?
Používám knihovnu Wire
Dík
fischertip.cz, Stavebnice.com, MerkurRobot.cz, KlubTechniku.cz
Uživatelský avatar
gilhad
Příspěvky: 215
Registrován: 29 kvě 2015, 00:36
Kontaktovat uživatele:

Re: mcp23017 (i2c) a vstup/výstup na jeden pin

Příspěvek od gilhad »

1. Obavam se, ze muzes ovladat pouze porty A a B (tedy 8 bitu), nikolik jednotlive piny. Takze si bud v nejake promenne uchovavat "spravnou hodnotu vystupu" , tu zmenit o ten bit a poslat ji tam celou, nebo si ten vystup nacist, (vrati, co tam bylo zapsano naposledy) , zmenit a zase zapsat.

Zapis do vstupnich pinu nic nedela, takze se tim nemusis zabyvat, zmeni se jen vystupy.

2. muzes ten port nastavit tak, ze cast pinu je vstupnich, cast vystupnich a zbytek je trivialni (prectes port, pomoci & vyberes tlacitko a mas hodnoru, zapisesna pin odpovidajici LED a posles to na port a LED se rozsviti ci zhasne dle te hodnoty). Navic muzes pouzit interrupt, ktery ti hlasi zmenu vstupu, takze se to ozve samo pri stisknuti tlacitka.

Pokud ovsem chces dat tlacitko i LED na stejny pin, pak mas trochu (dost) problem - bud muzes velmi rychle (z hlediska lidskeho oka, takze tak 100+Hz) prepinat vstup a vystup, na vystupu svitit LEDkou (ono to bude tak rychle blikat, ze bude jen trochu potemnela) a na vstupu cist tlacitko (nezapomen osetrit odporama stav, kdy mas tlacitko stisknute a LED je v opacnem stavu, ta nozicka snese jen urcity proud a ten nechces zkratovat tlacitkem na zem/napajeni) a pocitej s tim, ze to tlacitko ti bude tu LED ovlivnovat. Osobne bych tam pro vstup nastavil pullup (nebo jeste lepe nenastavil a naopak si ho realizoval vlastnim odporem, pak muzes dat docela vysoke hodnoty a mit tak maly proud "do zkratu" a pritom male vstupni napeti "pri cteni stisku" a velke vysputni napeti "pri zapisu 1 do LED pri stisku") , tlacitko pripojil k zemi prez odpor, ktery omezi proud pri zapnute LED na rozumnou hodnotu a LED samotnou spinal prez transistor, kvuli maximalnimu proudu a tomu, ze ti jinak bude proud skrz LED ovlivnovat cteni tlacitka, ktere uz tak mas prez odpor a nechces se dostat do "sede oblasti mezi nulou a jednickou".

(Od oka bych to strelil na radove zem, 500 ohm odpor od tlacitka k zemi (10mA do zkratu), tlacitko, pin, 10k pullup (svod 0.1mA, vstup 0.25V, vystup pro tranzistor dostacujici) - ovsem pokud pri cteni bude stisknute tlacitko, tak i rozsvicena dioda zhasne, pokud bude pustene tlacitko, i zhasnuta se rozsviti)\ - takze LED ovlivnujes jen mimo cteni.

Ten pomer muze byt vyrazne ve prospech LED, klidne 1:10 (mozna i vic), kdyz to budes stridat dost rychle (zase ne prilis, je to zbytecna zatez na sbernici a tudiz i CPU a parazitni kapacity jsou taky svine), navic muzes ten tranzistor na strane LED "premostit" malym kondenzatorem, ktery te LEDce udela jeste dosvit behem cteni tlacitka.

Zajima te totiz stav tlacitka, toovlada clovek, clovek 1/10s neodmackne tak aby si byl jist, takze cteni 100x za sec ti z jednoho stisku sejme aspon 10 hodnot, coz je vic nez dost na vyhodnoceni, ze tam nejaky stisk byl, (i kdyby byly zakmity, neco zachytis) a pokud budes cist tlacitko jen kratce, tak stejne tu hodnotu dostanes, ale na LED to bude fungovat (dobre pri stisku tlacitka ti ze 100% potemni na asi 90% a pri pusteni tlacitka ti i zhasnuta bude svitit tak na 10%, ale porad to bude dostatecny rozdil)
Le-Ze
Příspěvky: 82
Registrován: 31 kvě 2017, 15:37

Re: mcp23017 (i2c) a vstup/výstup na jeden pin

Příspěvek od Le-Ze »

http://www.arduinolibraries.info/librar ... no-library
A pak google - Adafruit_MCP23017

Kód: Vybrat vše

#include <Wire.h>
#include "Adafruit_MCP23017.h"
Adafruit_MCP23017 mcp1; 

void setup() {   
  mcp1.begin(0);
  mcp1.pinMode(0, OUTPUT);  
}

void loop() {
  mcp1.digitalWrite(0, HIGH); 
  delay(1000);
  mcp1.digitalWrite(0,LOW);
  delay(1000);
}
DavidO
Příspěvky: 1005
Registrován: 01 kvě 2013, 21:27

Re: mcp23017 (i2c) a vstup/výstup na jeden pin

Příspěvek od DavidO »

Tahle knihovna to dělá tak, že si přečte celý port, změní bit a zapíše zpátky ("read-modify-write"), pro komunikaci na nižší úrovni používá knihovnu Wire.
To není špatně, jen konstatuju, jak to je. Akorát pozor, že se jedná o komunikaci přes i2c a tedy principiálně řádově pomalejší, než jak běží MCU. I když je to poslání fyzicky pomocí interruptu, tak čtení z toho MCP23017 nutně blokující je (když pro zápis potřebuju tu hodnotu znát), takže to bude trvat.
Kdyby se jednalo jen o zápis, tak to bude rychlejší (naplní se buffer, zavelí se a "ono to už pak samo", takže to je ze strany odesílatele docela rychlé, tedy dokud se nezaplní buffer, to by to pak vrátilo chybu). Čili pokud chceš, aby to v Arduinu moc nežralo čas, tak si udržuj aktuální hodnotu celého portu, nastavuj patřičný bit(y) sám a jen zapisuj, řádově takhle:

Kód: Vybrat vše

#include <Wire.h>
#include "Adafruit_MCP23017.h"
Adafruit_MCP23017 mcp1; 
uint16_t valueBA; // horni byte je B, dolni A
uint16_t maska;

void setup() {   
  mcp1.begin(0);
  mcp1.pinMode(pin, OUTPUT);  
  maska = 0x0182; // treba chci blikat pinem 0 v B a 7 a 1 v A
}

void loop() {
  valueBA ^= maska;
  mcp1.writeGPIOAB(valueBA);
  delay(1000);
}
anebo jen s jedním portem, to by sis pak musel rozlišit A a B, ale pracovalo by se s jedním bytem místo 2, čili by se něco ušetřilo jak při výpočtu, tak při komunikaci. Vlastní poslání by bylo pro port A a 8bitovou value asi takhle: mcp1.writeRegister(MCP23017_GPIOA,value);
Le-Ze
Příspěvky: 82
Registrován: 31 kvě 2017, 15:37

Re: mcp23017 (i2c) a vstup/výstup na jeden pin

Příspěvek od Le-Ze »

A to by se nedalo podobně s tou maskou pořešít u tohohle?
http://tronixstuff.com/2011/08/26/tutor ... -io-ports/
Bez použití té knihovný Adafruit MCP23017
DavidO
Příspěvky: 1005
Registrován: 01 kvě 2013, 21:27

Re: mcp23017 (i2c) a vstup/výstup na jeden pin

Příspěvek od DavidO »

Jistěže dalo. Ono v té knihovně z Adafruit to ani jinak napsané není, jen to je před uživatelem schované. Podívej se do jejích zdrojáků, tak tam je:

Kód: Vybrat vše

#define MCP23017_ADDRESS 0x20
#define MCP23017_GPIOA 0x12
...
void Adafruit_MCP23017::writeGPIOAB(uint16_t ba) {
	Wire.beginTransmission(MCP23017_ADDRESS | i2caddr);
	wiresend(MCP23017_GPIOA);
	wiresend(ba & 0xFF);
	wiresend(ba >> 8);
	Wire.endTransmission();
}
a v tom tutorialu na tronixstuff.com:

Kód: Vybrat vše

Wire.beginTransmission(0x20);
Wire.write(0x12); // address port A
Wire.write(??);  // value to send
Wire.endTransmission();
… replacing ?? with the binary or equivalent hexadecimal or decimal value to send to the register.
No a ještě musíš ten (tu?) MCP nastavit, v Adafruit se o to postará metoda pinMode zase metodou read-modify-write pro jeden každý pin, v tutoriálu si tam zapíšou sami rovnou celý.

MCP23017 je na použití jednoduchý, přímočarý, stačí umět komunikovat po i2c (to zajistí třída Wire), zbytek je obyčejné čtení nebo zapisování do konkrétního registru(ů). Knihovna od Adafriuit je udělaná obecněji a "blíže ideálům Arduino", abych tak řekl, odkazovaný tutoriál to nemá zabalené do knihovny a přistupuje k tomu přímo. Je to jako s každou jinou Arduino knihovnou - buď ti nezáleží na časování a používáš právě jednu věc, pak napsat to s knihovnou je asi nejsnazší. Anebo má tvůj projekt nějaká špecifiká a to se pak musíš zamyslet, co přesně se tam děje a správně to naprogramovat. Obvykle nejdřív prostuduješ tu knihovnu a pak si to napíše sám, ne tak obecně, ale zato úsporněji a za běhu přesněji a/nebo rychleji. Jak pořád opakuju - pro kvalitní využití Arduina je velmi užitečné, potřebné až nezbytné vědět, jak to celé funguje.
aladin
Příspěvky: 290
Registrován: 12 kvě 2013, 06:43

Re: mcp23017 (i2c) a vstup/výstup na jeden pin

Příspěvek od aladin »

Pravdu díš, Davide. Buď víš, co děláš, a pak vlastně Arduino IDE nepotřebuješ, nebo jen tušíš a opisuješ, a ono to "rychle" "nějak" zafunguje :-)

Ještě mě napadla taková otázka pro znalé: jak je to s rychlostí digitalWrite/Read čtení na i2c a přímo na Arduinu - je to stejně rychlé/pomalé nebo jinak? Vycházím z dřívější debaty o pomalosti digitalWrite
fischertip.cz, Stavebnice.com, MerkurRobot.cz, KlubTechniku.cz
DavidO
Příspěvky: 1005
Registrován: 01 kvě 2013, 21:27

Re: mcp23017 (i2c) a vstup/výstup na jeden pin

Příspěvek od DavidO »

aladin píše: 23 lis 2017, 01:06 Ještě mě napadla taková otázka pro znalé: jak je to s rychlostí digitalWrite/Read čtení na i2c a přímo na Arduinu - je to stejně rychlé/pomalé nebo jinak? Vycházím z dřívější debaty o pomalosti digitalWrite
Docela dobře, tedy alespoň ta nejnižší vrstva, tj. knihovna Wire a její pomocná twi. Ale to by sis taky v těch zdrojákách mohl přečíst sám, ne? :mrgreen:
(ještě tedy terminologické upřesnění, "digitalWrite/Read čtení na i2c a přímo na Arduinu" jsi asi spíš myslel "použití i2c za pomoci Arduino knihoven versus použití i2c přímo na AVR bez Arduino knihoven")

No ale kdo by se koukal do zdrojáků, že. Tedy: Pokud bys vzal ten příklad

Kód: Vybrat vše

Wire.beginTransmission(0x20);
Wire.write(0x12); // address port A
Wire.write(??);  // value to send
Wire.endTransmission();
Tak beginTransition je jen inicializace pár proměnných - rychlé.
write jen přidá data do bufferu ale nic neposílá - docela rychlé.
Přenost zahájí až endTransmission, ale to jen zahájí přenos a hned se vrací - docela rychlé.
Vlastní přenos je už pak řízen interrupty tak, jak se to stíhá posílat; jak tak koukám, je to klasická implementace twi/i2c podle dokumentace - docela rychlá obsluha, samozřejmě přenos dat je pomalý tak, jak je pomalé i2c, ale procesor a tedy ani uživatelův skript to moc nezdržuje.
Pak tam je v knihovně Wire ještě pár funkcí navíc, aby to bylo komfortní pro uživatele (např. různé typy parametrů), ty to zdrží jen málo, je to jen přizpůsobení parametrů a drobnosti navíc.

Celkově tedy je použití knihovny Wire pro komunikaci po i2c docela rychlé, alespoň na Arduinech s AVR (na implementaci u jiných jsem se teď nedíval). Akorát to používá hardwarovou TWI jednotku, takže si nemůžeš zvolit piny, na jaké to má být připojené a zároveň logicky nemůžeš tyhle piny použít k jinému účelu (které piny jsou "tyhle" záleží na konkrétním typu Arduina, může se to lišit).
Odpovědět