Ben je het beu om compromissen te sluiten door het gebrek aan I/O-poorten tijdens het ontwikkelen van je ontwerpen met je favoriete platform? Wil je er meer om je grote aantal signalen en actuatoren te verwerken? Met dit breakout board dat via de I²C-bus wordt aangestuurd, kun je 16 I/O's toevoegen op je bestaande systeem, en met een maximum van 8 boards zelfs 128 I/O's.

Er zijn verschillende praktische situaties waar het nodig is om meerdere signalen en actuatoren te sturen met een microcontroller, die echter niet genoeg I/O-pinnen heeft. In dergelijke situaties is het handig om een beroep te doen op die geïntegreerde schakelingen die bekend staan als I/O-expanders. De functie hiervan is een bepaald aantal in- en uitvoerlijnen via een enkele I/O te sturen. Een seriële communicatielijn wordt dan ingezet, zoals de veelgebruikte en zeer wijdverspreide I²C-bus, die in veel microcontrollers en, niet in de laatste plaats, in Arduino-boards te vinden is.

Om in de behoefte te voorzien om de I/O-lijnen te vermeerderen (uit te breiden, in feite, zoals de term "expander" suggereert), hebben we het breakout-board gemaakt op basis van de MCP23017, die we in dit artikel voorstellen. We vinden hierop zo'n Microchip geïntegreerde schakeling die, zoals verwacht kan worden, een 16 bit I/O expander is, evenals de minimale hardware om deze te laten werken, die in dit geval bestaat uit een dipswitch en wat pull-up weerstanden. Om je een idee te geven van wat je kunt bereiken met een I/O expander, stellen we een toepassingsvoorbeeld voor waarbij het breakout-board een serie relais aanstuurt (acht in totaal) die zijn gemonteerd op een board dat kan worden aangestuurd via TTL-niveaus of drukknopschakelaars. Maar laten we bij het begin beginnen en eerst het schema bekijken.

Inschrijven
Schrijf u in voor tag alert e-mails over Microcontrollers!

Schema uitbreidingsprint

Zoals je kunt zien in het schema in figuur 1, is het breakout-board uiterst eenvoudig, want aan boord bevindt zich de DIL-versie van de MCP23017, waarvan de pinnen een pitch hebben van 2,54 mm om de montage van pin-headers te vergemakkelijken. Met zulke headers is het eenvoudiger dit board op andere printen of breadboards te plaatsen. Er zijn drie IC pinnen voor het instellen van de minst significante bits van het I²C Bus adres. Hiervoor is een 3-weg dipschakelaar (SW1 in het schema) voorzien. De pinnen A0, A1 en A2 worden met pull-up weerstanden R1 tot R3 logisch hoog gehouden als de schakelaars open zijn.

Breakout board Schematic diagram MCP23017

Figuur 1: Het schema van het breakout-board.

Samengevat zijn alle I/O-gerelateerde pinnen van de registers A en B naar buiten geporteerd op pin headers. Deze pinnen zijn aan beide zijden geplaatst zodat we onze print gemakkelijk kunnen aansluiten. Het zijn natuurlijk digitale I/O-pinnen. Je kunt dus alles aansluiten wat je wilt, binnen de grenzen van de stroom en spanning die door het MCP23017 IC worden ondersteund. Naast de 2,54 mm-pitch headers, die het ook mogelijk maken om de module op een breadboard te plaatsen, zijn er nog eens 4 pins aanwezig op een header (ook 2,54 mm-pitch) genaamd I2C, zodat we direct aan de bovenkant van de module de bus kunnen aansluiten. Het is duidelijk dat de pinnen aan de kanten alleen in- en uitgangen zijn. De vier pinnen van de I2C connector zijn daarom parallel geplaatst aan de pinnen die op het board aanwezig zijn.

Merk op dat op de print voor het gemak de pennen van het A-register aan een kant zijn geplaatst en de pennen van het B-register aan de andere kant, om de aansluitingen te vereenvoudigen. De pinnen die horen bij de I²C bus zijn teruggezet op de header gemarkeerd met I2C, samen met +5 V en massa; beide hebben pull-ups. De reset van de I/O-expander wordt op ons breakout-board niet gebruikt; daarom hebben we, om hem uit te schakelen, de betreffende pin (18, RST) met weerstand R4 logisch hoog gezet.

Tussen de pinnen aan de zijkant van het board vinden we ook herhaaldelijk GND en +5 V aansluitingen. Het belangrijkste element van de schakeling is natuurlijk de MCP23017, die we kunnen beschouwen als een I²C Bus/parallel converter, geproduceerd door Microchip (gemarkeerd met U1). De geïntegreerde schakeling, waarvan je het interne blokschema in Figuur 2 ziet, functioneert als een Slave op de I²C bus en ondersteunt een ingangs- en een uitgangsmodus. In de eerste modus kunnen de I/O toestanden van de A en B registers in serieel formaat, één byte voor elk register, op verzoek van de I²C Bus Master via de bus naar de master worden gestuurd. In de tweede modus worden de binnenkomende data op de I²C bus in de A en B registers geschreven. De I/O lijnen worden dan in de overeenkomstige toestand gezet.

Block diagram of the MCP23017: the SPI variant, which distinguishes MCP23017 from MCP23017, is also shown.
Figuur 2: Blokschema van de MCP23017: de SPI-variant, die de MCP23017 onderscheidt van de MCP23017, is ook weergegeven.

De MCP23017

De chip die de kern vormt van het hier beschreven breakout-board is een I/O expander met 16 bits, gesplitst in twee poorten van elk 8 bits en gekoppeld via I²C-Bus. Dit betekent dat met slechts twee draden, samen met massa, de status kan worden opgevraagd, of ingesteld als uitgang, van maar liefst 16 lijnen.

De technische eigenschappen zijn als volgt:

  • Snelle I²C data-interface, werkend op 100 kHz, 400 kHz of 1,7 MHz
  • I²C-Bus adres instelbaar in 8 combinaties
  • Configureerbare interruptpinnen, per niveau en logische functie
  • Configureerbare interruptbron
  • Polariteitsregister

Voor de ingangen:

  • Externe reset-ingang
  • Stand-by stroom van 1 μA max.
  • Voedingsspanning van 1,8 V tot 5,5 V

De MCP23017 geïntegreerde schakeling is een 16-bit I/O-expander en is beschikbaar in twee versies: de hier gebruikte, is uitgerust met een I²C Bus interface. De MCP23S17 is een SPI-interface variant. De chip is een 16-bits I/O-expander, gesplitst in twee poorten van elk 8 bits, met een I²C-bus interface. Dit betekent dat met slechts twee verbindingsdraden, samen met massa, het mogelijk is de status van maar liefst 16 lijnen op te vragen (ingangsmodus) of de logische status van elk ervan in te stellen (uitgangsmodus). De I/O-lijnen werken standaard als ingangen.

De MCP23017 bezit meerdere 8-bit registers voor ingangs-, uitgangs- en polariteitsselectie. De systeemmaster kan de I/O's activeren als in- of uitgangen door de corresponderende I/O-configuratie bits (IODIRA/B) te schrijven. Data voor elke ingang of uitgang wordt opgeslagen in het corresponderende ingangs- of uitgangsregister. De polariteit van het register van de ingangspoort kan worden omgekeerd met behulp van het polariteitsregister. Alle registers kunnen worden gelezen door de systeemmaster. De 16-bits I/O-poort is structureel samengesteld uit twee 8-bits poorten, namelijk poort A en poort B, die respectievelijk aangesloten zijn aan pinnen 21-28 en 1-8. De MCP23017 kan worden geconfigureerd om te werken in 8-bit of 16-bit modus. Verder zijn er twee interruptpinnen, INTA en INTB, die kunnen worden geassocieerd met hun respectievelijke poorten (INTA voor poort A en INTB voor poort B9). Logisch OR van beide is mogelijk zodat beide pinnen worden geactiveerd als (een van) beide poorten een interrupt veroorzaken.

De interruptuitgang kan worden geconfigureerd om te triggeren onder twee (elkaar uitsluitende) condities:
  • wanneer de toestand van een ingang verschilt van de overeenkomstige toestand van het register van de ingangspoort; deze toestand wordt gebruikt om aan de systeemmaster aan te geven dat de toestand van een ingang is gewijzigd.
  • wanneer de toestand van een ingang verschilt van de vooraf geconfigureerde waarde van het register (DEFVAL-register).
 

De INTA en INTB interruptlijnen kunnen worden geconfigureerd als actief-hoog, actief-laag of open-drain. Het Interrupt Capture register legt de waarden van de poorten vast op het moment dat de interrupt wordt getriggerd, waardoor de toestand die de interrupt veroorzaakte wordt opgeslagen. De Power-On-Reset (POR) zet de registers op hun standaardwaarden en initialiseert zo het device. De noodzaak voor bidirectionele werking komt voort uit het feit dat elke I²C Bus deelnemer zowel moet kunnen schrijven (bijvoorbeeld commando's) als lezen (toestanden). Zoals alle I²C-bus devices, staat de MCP23017 toe dat zijn adres wordt ingesteld op 8 mogelijke adressen, en voor dit doel heeft hij pennen A0, A1, A2, waarmee de adressen van de slave kunnen worden ingesteld, als deze door de I²C-bus worden aangesproken. Elk van deze lijnen wordt ingesteld met een dipschakelaar SW1: elke gesloten schakelaar stelt de logische nul in op het betreffende adres, terwijl, omgekeerd, een open schakelaar de logische 1 representeert. De mogelijkheid om acht adressen te definiëren maakt het mogelijk om tot acht I/O-expanders op dezelfde bus te plaatsen en zo een maximum van 128 I/O's aan te sturen met slechts drie lijnen.

De hele schakeling wordt gevoed via de 5 V-contact pin (we hebben er eigenlijk twee: 1 en 15, die zich aan de zijden van het breakout-board bevinden) en massa (GND-contacten, d.w.z. 2 en 23 van de headers). Met deze hardware is de logica als volgt: telkens wanneer een string wordt ontvangen op de SDA-lijn van de I²C bus (geklokt door het signaal op de SCL-lijn), voert de MCP23017 het commando uit dat daarin vervat zit (in dit geval het commando dat aangeeft de databyte te laden) en regelt de 8 uitgangslijnen IOA0-IOA7 en IOB0-IOB7 als de relevante bits, d.w.z., IOA0 neemt de toestand van het eerste bit van byte 1 aan, IOA1 die van het tweede bit, enzovoort. Hetzelfde zal gebeuren op IOB0÷IOB7, die precies de bits van de tweede databyte zullen repliceren.

Natuurlijk vindt conversie en presentatie op de uitgangen alleen plaats in de veronderstelling dat de ontvangen string het I²C Bus adres bevat dat overeenkomt met het adres dat ingesteld is, via de dip-schakelaars van SW1, voor U1. Telkens wanneer een string ontvangen wordt, werkt de chip de status van zijn uitgangen bij, en de respectievelijke logische niveaus bepalen of de relais aangeschakeld worden (of uit blijven). Als er vervolgens geen string verzonden wordt, blijft de toestand zoals deze is, omdat de uitgangen van de MCP23017 vergrendeld zijn. Het bovenstaande geldt voor de uitgangsmodus, d.w.z. het schrijven van de status van de twee I²C-Bus bytes naar uitgangsregisters A en B. Als daarentegen het commando dat van de bus komt wordt gelezen, verkrijgt de MCP23017 de I/O-status van elk register en genereert twee bytes, de eerste met de status van IOA0-IOA7 en de tweede met de logische conditie van IOB0-IOB7. Deze worden vervolgens als antwoord over de I²C-bus gestuurd. Voor elke toepassing waarvoor je het breakout-board wilt gebruiken, geven we in Tabel 1 de overeenkomst tussen de adressen en de dip-switch instelling.

230469-006-94-ORIGINAL-tabella 1.png
Tabel 1: Instelling van het adres van MCP23017.

Praktische realisatie

Nu we het bedradingsschema hebben beschreven, kunnen we verder gaan met de bouwaanwijzingen. Daarna zullen we een toepassingsvoorbeeld voorstellen op basis van interfacen met een Arduino-board, vergezeld van de bijbehorende sketch. Zoals gebruikelijk hebben we een print ontworpen die je kunt downloaden (het is een dubbelzijdige print). Fotografisch kun je hiermee het ontwerp op het printmateriaal transfereren. Nadat de print is geëtst en geboord, kun je de weinige benodigde componenten monteren, die in dit project allemaal van het traditionele bedrade type zijn, goed voor degenen die niet al te veel van SMD-techniek houden. Plaats en soldeer eerst de weerstanden, ga dan verder met de socket voor de geïntegreerde schakeling (te plaatsen met de inkeping naar boven zoals getoond in het assemblageplan dat je in dit artikel ziet) en de 3-weg dipschakelaar, te monteren met schakelaar 1 naar links, kijkend naar de print met de socket voor U1 bovenop.

Plaats en soldeer tenslotte de 4-pins header in de respectievelijke gaten gemarkeerd I²C, en plaats en soldeer dan, aan de andere kant van de print, twee rijen van 12 pins headers die montage op breadboards of plaatsing op andere boards mogelijk maken. Zo kunnen we uiteindelijk verbinding maken met Arduino met behulp van klassieke draadbruggen. Zodra je klaar bent met het solderen van de componenten, plaats je de MCP23017 in de socket en houd deze vast met de inkeping naar je toe zoals getoond in het montageplan op deze pagina's. Als je dat gedaan hebt, is je breakout-board klaar om mee te experimenteren of prototypes te maken.

230469-002-94-ORIGINAL-fig. 2.png
Figuur 3: Aansluitschema van de relaisbesturingstoepassing met drukknopschakelaars.
Inschrijven
Schrijf u in voor tag alert e-mails over Arduino!

Laten we het met een Arduino in gebruik nemen

Het breakout-board is gemaakt om aangesloten te worden aan een microcontroller, aangezien I/O-expanders meestal gebruikt worden door devices die uitgerust zijn met een I²C-bus interface. Aangezien Arduino deze bus ondersteunt, kun je de voorbeeldcode voor de I/O MCP23017 downloaden, zodat je deze via de IDE naar je board kunt uploaden. Deze sketch maakt het in principe mogelijk om de toestand van het poort A-register te schrijven als functie van een byte die door Arduino over de bus wordt gestuurd, waarvan de bits overeenkomen met de toestand die op poort B wordt gelezen, die deze keer als invoer fungeert. Om het voorbeeld een concrete toepassing te geven, hebben we besloten om de logische toestanden van de I/O's van Poort A, die hier zullen werken als digitale uitgangen, te gebruiken om een relaisboard aan te sturen. Specifiek moeten we de 8 relaisuitgangscontrolelijnen van het RELAY8CH-bord aansluiten op de I/O-bank van Poort A, terwijl 8 normaal open drukknopschakelaars moeten worden aangesloten op Poort B, met als gemeenschappelijke pool die op GND wordt aangesloten. Om deze toepassing te realiseren, is het nodig om Arduino UNO, het breakout-board, het relaisboard en de schakelaars aan te sluiten, zoals weergegeven in het bedradingsschema in Figuur 3, terwijl Figuur 4 het complete prototype van deze toepassing toont. Aangezien we gebruikelijke drukknopschakelaars gebruiken (normaal open) zonder externe elektronica, werden de interne pull-ups van de MCP ingeschakeld (via de bibliotheek) om de toestandsverandering te kunnen herkennen, zodat we de respectieve uitgang activeren wanneer de schakelaar de ingang met GND verbindt. Om dit te bereiken hebben we een eenvoudige Arduino UNO-gebaseerde code geschreven die gebruik maakt van de Adafruit-bibliotheek die, zoals je ziet in Listing 1, is opgenomen in de eerste regel van de volgende sketch:

#include <Adafruit_MCP23X17.h>.
#include <Adafruit_MCP23X17.h>
Adafruit_MCP23X17 mcp;
int i = 0;
int OUT[] = {7,6,5,4,3,2,1,0};   //Represents MCP23017 PIN (A7...A0)
int IN[] = {8,9,10,11,12,13,14,15}; //Represents MCP23017 PIN (B0...B7)
int STATO[] = {0,0,0,0,0,0,0,0}; ◦ //For each output, every toggle the status is being saved

void setup()
{
Serial.begin(9600);
Serial.println("MCP23017 INPUT/OUTPUT");
if (!mcp.begin_I2C(0x20)) //0x20 is MCP23017's address with A0=A1=A2 > ON(GND)
{
Serial.println("MCP Error!"); //If MCP is not found, the error is visualized
while (1);
}
//bank A Pin set as outputs and B bank as inputs
//The STATO variable to 0 to indicate idling outputs
for (i=0; i<8; i=i+1)
{
mcp.pinMode(OUT[i], OUTPUT);
mcp.pinMode(IN[i], INPUT_PULLUP);
STATO[i] = 0;
}
}
//******************* L O O P **********************
void loop()
{
String Testo_Debug = "";
for (i=0; i<8; i=i+1)
{
//If button pressed or output not activated, I activate it
if ((mcp.digitalRead(IN[i])==0) && (STATO[i]==0))
{
STATO[i] = 1;
Testo_Debug = "Pulsante" + String(i+1) + "premuto";
Serial.println(Testo_Debug);
mcp.digitalWrite(OUT[i], HIGH);
}
//If button released and output is active, I deactivate it
if ((mcp.digitalRead(IN[i])==1) && (STATO[i]==1))
{
STATO[i] = 0;
Testo_Debug = "Pulsante" + String(i+1) + "rilasciato";
Serial.println(Testo_Debug);
mcp.digitalWrite(OUT[i], LOW);
 }
}
delay(10);
}

Voor we de code in het programmageheugen van ons Arduino-board laden, is het essentieel om de bibliotheek van Adafruit te downloaden en te installeren met behulp van de Library Manager in de IDE. We kunnen ook gewoon de inhoud van het ZIP-bestand uitpakken en dan de volledige Adafruit_MCP23017_Arduino_Library map kopiëren naar de libraries directory die normaal in het besturingssysteem te vinden is op het pad DocumentsArduino\libraries. Na het laden van de bibliotheek is het voldoende om onze voorbeeldcode te laden en deze in het board te laden nadat je de juiste COM-poort hebt gekozen in het Tools menu van de IDE.

In de code wordt de MCP23017 gevraagd een byte te sturen die de status van de drukknopschakelaars weereeft, en de gerelateerde gegevens worden verwerkt en vervolgens met een byte naar het IC gestuurd, waardoor de status van de poort A lijnen op een stabiele manier wordt ingesteld. Om het interfacen te laten werken, moeten de dipswitches A0, A1 en A2 correct worden ingesteld, want als de master niet het adres 0x20 zou krijgen, zou er een foutmelding op het seriële scherm verschijnen. Het adres van het breakout-board wordt toegewezen met de 000 combinatie van de drie bits A0, A1, A2, d.w.z. alle drie dipswitches naar massa zetten. Als je het adres wilt wijzigen, raadpleeg dan Tabel 1, met dien verstande dat je dan ook het adres moet wijzigen dat in de sketch is geschreven.

Breakout board article: The hardware for testing the example sketch.
Figuur 4: De hardware voor het testen van de voorbeeldschets.

Onderdelenlijst
  • Weerstanden: R1 to R6: 4.7 kΩ
  • Condensator: C1 100 nF, ceramic
  • Halfgeleider: U1 MCP23017-E/SP
  • Divers: SW1 3-Way Dip-Switch; 14 + 14 Pin DIL socket; 2 × 12 Pin Header, male; 1 × 4 Pin Header, male; 1 × PCB (see text)

Noot van de redactie: Dit project verscheen oorspronkelijk in Elettronica IN