Les extensions de GPIOs de l'ARDUINO
Nous allons explorer dans cet article les différentes possibilité d'étendre le nombre d'entrées / sorties digitales d'une carte ARDUINO.
Des schémas et sketches de base sont proposés.
1. Les GPIOs de l'ADUINO
Comme vous le savez probablement, le nombre d'entrées et de sorties digitales d'une carte ARDUINO ou de l'ESP8266 est limité.ARDUINO UNO, NANO, MINI, etc. :
- 14 GPIOs
- 6 pins analogiques utilisables en pins digitales
Cela nous laisse donc 18 GPIOs utilisables, ce qui est parfois insuffisant.
ARDUINO MEGA, DUE :
- 54 GPIOs
- 16 pins analogiques utilisables en pins digitales
ESP-01 :
- 2 GPIOs
- 8 GPIOs
Comme nous allons le voir il existe des solutions bon marché.
2. La démarche
Nous allons examiner d'abord les caractéristiques d'un certain nombre de circuits.Ensuite pour certains de ces circuits que j'ai en ma possession, je les ai expérimentés.
Je les ai raccordés à un ARDUINO NANO et des LEDs et écrit les sketches correspondants à l'aide de librairies. Les schémas, sketches et la liste des librairies sont fournis.
Ce travail peut servir de base de départ pour démarrer un projet.
Ensuite j'ai mesuré les temps d'écriture. Ceux-ci sont mesurés pour l'écriture d'un mot (8 bits ou 16 bits) sur les sorties.
Les composants I2C sont mesurés à 100KHz et 400KHz.
Enfin, deux petits tableaux récapitulent ensuite les principales caractéristiques et les performances.
3. Les décodeurs
Un décodeur permet de décoder un certain nombre de lignes binaires ou BCD.- 3 entrées / 8 sorties
- 4 entrées / 16 sorties
3.1. Le 74LS138 et le 74LS238
Le 74LS138 et le 74LS238 permettent à partir de 3 entrées binaires d'obtenir 8 sorties.3.2. Le74HC154
Le 74HC154 permet à partir de 4 entrées binaires d'obtenir 16 sorties.4. Les registres à décalage
Un registre est un convertisseur série / parallèle, il offre un certain nombre de sorties mais est dépourvu d'entrées.4.1. Le 74HC595
Le 74HC595 est un registre à décalage. Il peut être utilisé comme expander de GPIOs. Il a les caractéristiques suivantes :- 8 sorties
- courant maximal par sortie 35mA
- courant maximal pour l'ensemble des sorties 70mA
https://learn.adafruit.com/adafruit-arduino-lesson-4-eight-leds/the-74hc595-shift-register
https://eskimon.fr/tuto-arduino-901-ajouter-des-sorties-num%C3%A9riques-%C3%A0-larduino-le-74hc595
Il est possible de chaîner plusieurs 74HC595 pour obtenir un registre à décalage 16bits, 24bits, 32bits ou plus.
Voir plus bas : 7. Les schémas et sketches
Certains afficheurs du commerce en sont équipés :
Le 74HC595 existe en boîtier DIP.
Il est facile de trouver des modules "breakboard" équipés de ce circuit :
4.2. Le 74LS673
Le 74LS673 est aussi un registre à décalage pouvant être utilisé comme expander de GPIOs. Il a les caractéristiques suivantes :- 16 sorties
- courant maximal par sortie 8mA
5. Les expanders
Un expander permet de disposer de vraies entrées / sorties. Il offre souvent des fonctionnalités annexes :- broche d'interruption
- résistances PULL-UP configurables ou non
5.1. Le MCP23008 et MCP23S08
Le MCP23008 est un expander de GPIOs sur bus I2C. Le MCP23S08 est un expander de GPIOs sur bus SPI. Ils ont les caractéristiques suivantes :- 8 entrées/sorties
- résistances PULL-UP 100kΩ configurables
- courant maximal par sortie 25mA
- courant maximal pour l'ensemble des sorties 125mA
- MCP23008 : 3 broches de sélection d'adresse
- MCP23S08 : 2 broches de sélection d'adresse
- 1 sortie d'interruption
On ne trouve pas de modules "breakboard" équipés de ces circuits.
5.2. Le MCP23017 et MCP23S17
Le MCP23017 est un expander de GPIOs sur bus I2C. Le MCP23S17 est un expander de GPIOs sur bus SPI. Ils ont les caractéristiques suivantes :- 16 entrées/sorties
- résistances PULL-UP 100kΩ configurables
- courant maximal par sortie 25mA
- courant maximal pour l'ensemble des sorties 125mA
- 3 broches de sélection d'adresse
- 2 sorties d'interruption
Il est facile de trouver des modules "breakboard" équipés du MCP23017 :
5.3. Le PCA9537
Le PCA9537 est un expander de GPIOs sur bus I2C. Il a les caractéristiques suivantes :- 4 entrées/sorties
- courant maximal par sortie 50mA
- courant maximal pour l'ensemble des sorties 85mA
- 1 adresseI2C fixe
- 1 sortie d'interruption
- boîtier TSSOP10
5.4. Le PCA9555
Le PCA9555 est un expander de GPIOs sur bus I2C. Il a les caractéristiques suivantes :- 16 entrées/sorties
- résistances PULL-UP 100kΩ non configurables
- courant maximal par sortie 8mA (état bas)
- courant maximal pour l'ensemble des sorties 200mA (état bas)
- 3 broches de sélection d'adresse
- 1 sortie d'interruption
5.5. Le PCA9655
Le PCA9655 est un expander de GPIOs sur bus I2C. Il a les caractéristiques suivantes :- 16 entrées/sorties
- résistances PULL-UP 100kΩ non configurables
- courant maximal par sortie 25mA (état bas)
- courant maximal pour l'ensemble des sorties 400mA (état bas)
- 3 broches de sélection d'adresse
- 1 sortie d'interruption
5.6. Le PCF8574
Le PCF8574 est un expander de GPIOs sur bus I2C. Il a les caractéristiques suivantes :- 8 entrées/sorties en collecteur ouvert
- courant maximal par sortie 50mA (état bas), 100µA (état haut)
- courant maximal pour l'ensemble des sorties 100mA
- 3 broches de sélection d'adresse
- 1 sortie d'interruption
Attention, le PCF8574 est quasi-bidirectionnel. Il ne possède pas de registre de direction comme un MCP23008. De plus, il est incapable de fournir un courant important à l'état haut.
Il est facile de trouver des modules "breakboard" équipés de ce circuit :
5.7. Le PCF8575
Le PCF8575 est un expander de GPIOs sur bus I2C. Il a les caractéristiques suivantes :- 16 entrées/sorties en collecteur ouvert
- courant maximal par sortie 50mA (état bas), 100µA (état haut)
- courant maximal pour l'ensemble des sorties 100mA
- 3 broches de sélection d'adresse
- 1 sortie d'interruption
Il est facile de trouver des modules "breakboard" équipés de ce circuit :
5.8. Le SX1509
Le SX1509 est un expander de GPIOs sur bus I2C. Il a les caractéristiques suivantes :- 16 entrées/sorties en push-pull ou collecteur ouvert
- résistances PULL-UP PULL-DOWN 100kΩ configurables
- PWM, BLINK, FADE IN/OUT
- clavier matriciel
- courant maximal par sortie 15mA (état bas), 8mA (état haut)
- 2 broches de sélection d'adresse
- 1 sortie d'interruption
- Attention : tension d'alimentation 3.3V
La fréquence PWM est ajustable (voir la datasheet) :
ClkX = fOSC/(2^(RegMisc[6:4]-1))
J'ai fait un essai en réel avec la lib SparkFun :
io.clock(INTERNAL_CLOCK_2MHZ, 1, OUTPUT, 1); // F = 8.33KHz
io.clock(INTERNAL_CLOCK_2MHZ, 7, OUTPUT, 1); // F = 113Hz
Un lien utile :https://learn.sparkfun.com/tutorials/sx1509-io-expander-breakout-hookup-guide/all
Il est facile de trouver des modules "breakboard" équipés de ce circuit :
Le modèle SparkFun possède deux rangées de pastilles que l'on peut raccorder au 3.3V ou GND par soudure.
5.9. Le MCP23009 et MCP23S09
Le MCP23009 est un expander de GPIOs sur bus I2C. Le MCP23S09 est un expander de GPIOs sur bus SPI. Il a les caractéristiques suivantes :- 8 entrées/sorties en collecteur ouvert
- résistances PULL-UP 100kΩ configurables
- courant maximal par sortie 25mA (état bas)
- courant maximal pour l'ensemble des sorties 125mA (état bas)
- 1 broche de sélection d'adresse
- 2 sorties d'interruption
On ne trouve pas de modules "breakboard" équipés de ce circuit.
5.10. Le MCP23018 et MCP23S18
Le MCP23018 est un expander de GPIOs sur bus I2C. Le MCP23S18 est un expander de GPIOs sur bus SPI. Il a les caractéristiques suivantes :- 16 entrées/sorties en collecteur ouvert
- résistances PULL-UP 100kΩ configurables
- courant maximal par sortie 25mA (état bas)
- courant maximal pour l'ensemble des sorties 400mA (état bas)
- 1 broche de sélection d'adresse
- 2 sorties d'interruption
On ne trouve pas de modules "breakboard" équipés de ce circuit.
5.11. Le MAX7301
Le MAX7301 est un expander de GPIOs sur bus 4 fils. Il a les caractéristiques suivantes :- 20 (SSOP28) ou 28 (SSOP36) entrées/sorties
- résistances PULL-UP configurables
- courant maximal par sortie 10mA (état bas), 4.5mA (état haut)
- courant maximal pour l'ensemble des sorties 600mA (état bas)
5.12. Le MAX7311
Le MAX7311 est un expander de GPIOs sur bus I2C. Il a les caractéristiques suivantes :- 16 entrées/sorties
- résistances PULL-UP 100kΩ configurables
- courant maximal par sortie 17mA (état bas), 29mA (état haut)
- courant maximal pour l'ensemble des sorties 250mA
- 3 broches de sélection d'adresse
- 1 sortie d'interruption
5.13. Le MAX7318
Le MAX7318 est un expander de GPIOs sur bus I2C. Il a les caractéristiques suivantes :- 16 entrées/sorties
- résistances PULL-UP 100kΩ configurables
- courant maximal par sortie 17mA (état bas), 29mA (état haut)
- courant maximal pour l'ensemble des sorties 250mA
- 3 broches de sélection d'adresse
- 1 sortie d'interruption
5.14. Le TCA9534
Le TCA9534 est un expander de GPIOs sur bus I2C. Il a les caractéristiques suivantes :- 8 entrées/sorties
- résistances PULL-UP 100kΩ configurables
- courant maximal par sortie 50mA
- courant maximal pour l'ensemble des sorties 160mA
- 3 broches de sélection d'adresse
- 1 sortie d'interruption
5.15. Le PCA9685
Le PCA9685 est un driver de LEDs I2C PWM 16 canaux, mais on peut également s'en servir comme d'un expander (en sortie uniquement) :Il dispose de fonctions avancées :
- PWM 12 bits : fréquence variable de 24Hz à 1526Hz
- luminosité des LED programmable
- allumage / extinction des LED avec un temps programmable
- etc.
6. Les multiplexeurs I2C
Nous allons terminer par une dernière catégorie de circuits permettant de multiplexer un bus I2C afin d'obtenir plusieurs bus I2C à partir d'un seul.Ces composants peuvent permettre de résoudre des conflits d'adresse I2C, lorsque l'on utilise plusieurs composants I2C identiques n'ayant pas de broche de sélection d'adresse par exemple.
6.1. Le PCA9540
Le PCA9540 permet de multiplexer 2 bus I2C. Il a les caractéristiques suivantes :- 2 bus esclaves
- alimentation 2.3V - 3.6V
- pas de broche de sélection d'adresse
6.2. Le PCA9541
Le PCA9541 permet de multiplexer 2 bus I2C. Il a les caractéristiques suivantes :- 2 bus esclaves
- alimentation 2.3V - 5.5V
- 4 broches de sélection d'adresse
6.3. Le PCA9543
Le PCA9543 permet de multiplexer 2 bus I2C. Il a les caractéristiques suivantes :- 2 bus esclaves
- alimentation 2.3V - 3.6V
- 2 broches de sélection d'adresse
6.4. Le PCA9545
Le PCA9545 permet de multiplexer 4 bus I2C. Il a les caractéristiques suivantes :- 4 bus esclaves
- alimentation 2.3V - 5.5V
- 2 broches de sélection d'adresse
6.4. Le PCA9546
Le PCA9546 permet de multiplexer 4 bus I2C. Il a les caractéristiques suivantes :- 4 bus esclaves
- alimentation 2.3V - 5.5V
- 3 broches de sélection d'adresse
6.5. Le PCA9548
Le PCA9548 permet de multiplexer 8 bus I2C. Il a les caractéristiques suivantes :- 8 bus esclaves
- alimentation 2.3V - 5.5V
- 3 broches de sélection d'adresse
6.6. Le TCA9543
Le TCA9543 permet de multiplexer 2 bus I2C. Il a les caractéristiques suivantes :
- 2 bus esclaves
- alimentation 1.65V - 5.5V
- 2 broches de sélection d'adresse
6.7. Le TCA9548
Le TCA9548 permet de multiplexer 8 bus I2C. Il a les caractéristiques suivantes :- 8 bus esclaves
- alimentation 1.65V - 5.5V
- 3 broches de sélection d'adresse
7. Les librairies
- MCP23008 : https://github.com/adafruit/Adafruit-MCP23008-library.git
- MCP23SXX : https://github.com/sumotoy/gpio_MCP23SXX
- MCP23017 : https://github.com/adafruit/Adafruit-MCP23017-Arduino-Library.git
- MCP23S17 : https://github.com/n0mjs710/MCP23S17.git
- PCA9537 : https://github.com/ControlEverythingCommunity/PCA9537-04
- PCA9555 : https://github.com/nicoverduin/PCA9555
- PCF857X : https://github.com/skywodd/pcf8574_arduino_library
- PCF8574 : https://github.com/RobTillaart/PCF8574
- SX1509 : https://github.com/sparkfun/SparkFun_SX1509_Arduino_Library
- TCA9534 : https://github.com/NorthernWidget/TCA9534
- TCA9548 : https://github.com/jeremycole/TI_TCA9548A
- Autres : https://github.com/sumotoy/gpio_expander.git
Remarque : la librairie PCF8574 de Rob Tillaart est préférable. De plus elle est compatible ESP8266 et ESP32.
8. Les performances
Le tableau suivant regroupe les caractéristiques des différents circuits.Module | BUS | GPIOS | INT | Tension | Conso au repos |
Boîtier |
---|---|---|---|---|---|---|
74HC595 | Série | 8 | 0 | 2.0V - 6.0V | 80µA | DIP16 SO16 SSOP16 TSSOP16 |
2 x 74HC595 chaînés | Série | 16 | 0 | 2.0V - 6.0V | 160µA | |
MCP23008 | I2C | 8 | 1 | 1.8V - 5.5V | 1µA | DIP18 SO18S SOP20 |
MCP23S08 | SPI | 8 | 1 | 1.8V - 5.5V | 1µA | DIP18 SO18 SSOP20 |
MCP23009 | I2C | 8 | 1 | 1.8V - 5.5V | 1µA | DIP18 SO18 SSOP20 |
MCP23S09 | SPI | 8 | 1 | 1.8V - 5.5V | 1µA | DIP18 SO18 SSOP20 |
MCP23017 | I2C | 16 | 2 | 1.8V - 5.5V | 1µA | DIP28 SO28 SSOP28 |
MCP23S17 | SPI | 16 | 2 | 1.8V - 5.5V | 1µA | DIP28 SO28 SSOP28 |
MCP23018 | I2C | 16 | 2 | 1.8V - 5.5V | 1µA | DIP28 SO28 SSOP28 |
MCP23S18 | SPI | 16 | 2 | 1.8V - 5.5V | 1µA | DIP28 SO28 SSOP28 |
PCA9537 | I2C | 4 | 1 | 2.3V - 5.5V | 1µA | TSSOP10 TSSOP24 |
PCA9555 | I2C | 16 | 1 | 2.3V - 5.5V | 1µA | SO24 SSOP24 TSSOP24 |
PCA9655 | I2C | 16 | 1 | 1.65V - 5.5V | 1µA | SO24 TSSOP24 |
PCF8574 | I2C | 8 | 1 | 2.5V - 5.5V | 10µA | DIP16 SO16 |
PCF8575 | I2C | 16 | 1 | 2.5V - 5.5V | 10µA | SO24 SSOP24 TSSOP24 |
SX1509 | I2C | 16 | 1 | 1.425V - 3.6V | 1µA | QFN28 |
MAX7301 | 4W | 20 ou 28 | 0 | 2.5V - 5.5V | 11µA | SSOP28 SSOP36 |
MAX7311 | I2C | 16 | 1 | 2.0V - 5.5V | 15µA | SO24 SSOP24 TSSOP24 |
MAX7318 | I2C | 16 | 1 | 2.0V - 5.5V | 19µA | SO24 SSOP24 TSSOP24 |
TCA9534 | I2C | 8 | 1 | 1.65V - 5.5V | 22µA | TSSOP16 |
Le tableau suivant donne leurs performances en écriture.
L'augmentation de la vitesse du bus 12C de l'ARDUINO à 400KHZ permet d'obtenir une plus grande rapidité, grâce à cette simple modification :
void setup() {
Serial.begin(115200);
Serial.println("MCP23008");
mcp.begin();
Wire.setClock(400000);
for (int i = 0 ; i < 8 ; i++) {
mcp.pinMode(i, OUTPUT);
}
}
Module | Temps d'écriture |
Temps d'écriture I2C à 100KHz |
Temps d'écriture I2C à 400KHz |
---|---|---|---|
74HC595 | 121µs | ||
2 x 74HC595 chaînés | 236µs | ||
MCP23008 | 325µs | 118µs | |
MCP23S08 | 20µs | ||
MCP23009 (*) | 325µs | 118µs | |
MCP23S09 (*) | 20µs | ||
MCP23017 | 425µs | 153µs | |
MCP23S17 | 24µs | ||
MCP23018 (*) | 425µs | 153µs | |
MCP23S18 (*) | 24µs | ||
PCA9537 | |||
PCA9555 | |||
PCA9655 | |||
PCF8574 | 225µs | 79µs | |
PCF8575 | |||
SX1509 | |||
MAX7301 | |||
MAX7311 | |||
MAX7318 | |||
TCA9534 |
(*) : je n'ai pas ces composants sous la main pour les tester mais ils ont des caractéristiques probablement très proches de leurs homologues push-pull en matière de vitesse :
- MCP23009 : MCP23008
- MCP23S09 : MCP23S08
- MCP23018 : MCP23017
- MCP23S18 : MCP23S17
9. Les schémas et sketches
Les performances des différents circuits sont testées à l'aide des schémas et sketches suivants.9.1. Le 74HC595
Le schéma :Le schéma est réalisé avec KICAD. Les broches d'alimentation du 74HC595 ne sont pas représentées : VCC = 16, GND = 8.
Le sketch :
#define LATCH_PIN 5
#define CLOCK_PIN 6
#define DATA_PIN 4
void setup() {
Serial.begin(115200); Serial.println("74HC595");
pinMode(LATCH_PIN, OUTPUT);
pinMode(CLOCK_PIN, OUTPUT);
pinMode(DATA_PIN, OUTPUT);
}
void loop() {
unsigned long start = micros();
for (unsigned cnt = 0; cnt < 256; cnt++) {
digitalWrite(LATCH_PIN, LOW);
shiftOut(DATA_PIN, CLOCK_PIN, MSBFIRST, cnt);
digitalWrite(LATCH_PIN, HIGH);
}
unsigned long stop = micros();
Serial.print("Elapsed : ");
Serial.print((stop-start) / 256);
Serial.println(" µs");
}
Chaîner deux 74HC595
Le schéma :
Le schéma est réalisé avec KICAD. Les broches d'alimentation des 74HC595 ne sont pas représentées : VCC = 16, GND = 8.
Le sketch :
#define LATCH_PIN 5
#define CLOCK_PIN 6
#define DATA_PIN 4
void setup() {
Serial.begin(115200);
Serial.println("2x74HC595");
pinMode(LATCH_PIN, OUTPUT);
pinMode(CLOCK_PIN, OUTPUT);
pinMode(DATA_PIN, OUTPUT);
}
void loop() {
unsigned long start = micros();
for (unsigned long cnt = 0; cnt < 65536 ; cnt++) {
digitalWrite(LATCH_PIN, LOW);
shiftOut(DATA_PIN, CLOCK_PIN, MSBFIRST, cnt & 0xff);
shiftOut(DATA_PIN, CLOCK_PIN, MSBFIRST, cnt >> 8);
digitalWrite(LATCH_PIN, HIGH);
}
unsigned long stop = micros();
Serial.print("Elapsed : ");
Serial.print((stop-start) / 65536);
Serial.println(" µs");
}
9.2. Le MCP23008
Le schéma :Le schéma est réalisé avec KICAD. Les broches d'alimentation du MCP23008 ne sont pas représentées : VCC = 18, GND = 9.
Les deux résistances de pullup sur les lignes SDA et SCL ne sont pas représentées non plus, mais elles sont nécessaires.
L'adresse I2C est 0x20.
Le sketch :#include <SPI.h>
#include <Adafruit_MCP23008.h>
Adafruit_MCP23008 mcp;
void setup() {
Serial.begin(115200);
Serial.println("MCP23008");
mcp.begin();
Wire.setClock(400000);
for (int i = 0 ; i < 8 ; i++) {
mcp.pinMode(i, OUTPUT);
}
}
void loop() {
unsigned long start = micros();
for (int cnt = 0 ; cnt < 256 ; cnt++) {
mcp.writeGPIO(cnt);
}
unsigned long stop = micros();
Serial.print("Elapsed : ");
Serial.print((stop-start) / 256);
Serial.println(" µs");
}
9.3. Le MCP23S08
Le schéma :Le schéma est réalisé avec KICAD. Les broches d'alimentation du MCP23S08 ne sont pas représentées : VCC = 18, GND = 9.
Les deux résistances de pullup sur les lignes SDA et SCL ne sont pas représentées non plus, mais elles sont nécessaires.
#include <SPI.h>
#include <gpio_MCP23SXX.h>
gpio_MCP23SXX mcp(MCP23S08, 10, 0x20);
void setup() {
Serial.begin(115200);
Serial.println("MCP23S08");
mcp.begin();
for (int i = 0 ; i < 8 ; i++) {
mcp.gpioPinMode(i, OUTPUT);
}
}
void loop() {
unsigned long start = micros();
for (int cnt = 0; cnt < 256; cnt++) {
mcp.gpioPort(cnt);
}
unsigned long stop = micros();
Serial.print("Elapsed : ");
Serial.print((stop-start) / 256);
Serial.println(" µs");
}
9.4. Le MCP23017
Le schéma :Les deux résistances de pullup sur les lignes SDA et SCL ne sont pas représentées non plus, mais elles sont nécessaires.
L'adresse I2C est 0x20.Le sketch :
#include <SPI.h>
#include <Adafruit_MCP23017.h>
Adafruit_MCP23017 mcp;
void setup() {
Serial.begin(115200);
Serial.println("MCP23017");
mcp.begin();
Wire.setClock(400000);
for (int i = 0 ; i < 8 ; i++) {
mcp.pinMode(i, OUTPUT);
}
}
void loop() {
unsigned long start = micros();
for (unsigned cnt = 0; cnt < 256; cnt++) {
mcp.writeGPIOAB(cnt);
}
unsigned long stop = micros();
Serial.print("Elapsed : ");
Serial.print((stop-start) / 256);
Serial.println(" µs");
}
9.5. Le MCP23S17
Le schéma :Le schéma est réalisé avec KICAD. Les broches d'alimentation du MCP23S17 ne sont pas représentées : VCC = 9, GND = 10.
Le sketch :
#include <SPI.h>
#include <MCP23S17.h>
MCP mcp(0, 10);
void setup() {
Serial.begin(115200);
mcp.begin();
mcp.pinMode(0x0000);
}
void loop() {
unsigned long start = micros();
for (unsigned cnt = 0; cnt < 256; cnt++) {
mcp.digitalWrite(cnt);
}
unsigned long stop = micros();
Serial.print("Elapsed : ");
Serial.print((stop-start) / 256);
Serial.println(" µs");
}
9.6. Le PCF8574
Le schéma :
Les deux résistances de pullup sur les lignes SDA et SCL ne sont pas représentées, mais elles sont nécessaires.
Je me suis aperçu récemment que le PCF8574 ne fournit que 100µA à l'état haut. Il serait préférable de connecter les couples résistance+LED entre le +5V et les sorties si l'on veut bénéficier d'un courant supérieur.
Le sketch :
#include <Wire.h> // Required for I2C communication#include "PCF8574.h" // Required for PCF8574
PCF8574 pcf;
void setup() {
Serial.begin(115200);
Serial.println("PCF8574");
pcf.begin(0x27);
Wire.setClock(400000);
for (int i = 0 ; i < 8 ; i++) {
pcf.pinMode(i, OUTPUT);
}
}
void loop() {
unsigned long start = micros();
for (unsigned cnt = 0; cnt < 256; cnt++) {
pcf.write(cnt);
}
unsigned long stop = micros();
Serial.print("Elapsed : ");
Serial.print((stop-start) / 256);
Serial.println(" µs");
}
10. Gestion d'entrées sous interruption
MCP23017Ci-dessous un schéma avec un MCP23017 gérant un clavier à 16 touches :
Les deux résistances de pullup sur les lignes SDA et SCL ne sont pas représentées, mais elles sont nécessaires.
La broche d'interruption A du MCP23017 est reliée à la broche D2 de l'ARDUINO. Ceci va permettre d'endormir celui-ci et de le réveiller uniquement si nécessaire. Un montage de ce genre avec un ARDUINO PRO MINI modifié devrait pouvoir offrir une consommation extrêmement faible, 5 à 6 µA.Le sketch :
#include <LowPower.h>
#include <SPI.h>
#include <Adafruit_MCP23017.h>
#define INTERRUPT_A_PIN 2
Adafruit_MCP23017 mcp;
volatile boolean awakenByInterrupt = false;
void setup() {
Serial.begin(115200);
Serial.println("MCP23017");
pinMode(INTERRUPT_A_PIN, INPUT);
mcp.begin();
mcp.setupInterrupts(true, false, LOW);
for (int i = 0 ; i < 16 ; i++) {
mcp.pinMode(i, INPUT);
mcp.pullUp(i, HIGH);
mcp.setupInterruptPin(i, FALLING);
}
}
void intCallBack() {
awakenByInterrupt = true;
}
void loop() {
attachInterrupt(digitalPinToInterrupt(INTERRUPT_A_PIN), intCallBack, FALLING);
LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
detachInterrupt(digitalPinToInterrupt(INTERRUPT_A_PIN));
if (awakenByInterrupt) {
uint8_t pin = mcp.getLastInterruptPin();
uint8_t val = mcp.getLastInterruptPinValue();
Serial.print("Interrupt: pin"); Serial.print(pin); Serial.print(": "); Serial.println(val);
while (!mcp.digitalRead(pin));
EIFR=0x01;
awakenByInterrupt = false;
}
}
MCP23008
Il est possible de faire exactement la même chose avec 8 touches et un MCP23008. Par contre la gestion des interruptions n'est pas prévue dans la librairie.
Plutôt que de la modifier bêtement, il vaut mieux en hériter dans notre code :
#include <Wire.h>
#include "Adafruit_MCP23008.h"
class MyMCP23008 : public Adafruit_MCP23008
{
protected:
void write8(uint8_t addr, uint8_t data);
uint8_t i2caddr;
public:
void enableInterrupts(uint8_t data);
};
void MyMCP23008::write8(uint8_t addr, uint8_t data)
{
Wire.beginTransmission(MCP23008_ADDRESS | i2caddr);
#if ARDUINO >= 100
Wire.write((byte)addr);
Wire.write((byte)data);
#else
Wire.send(addr);
Wire.send(data);
#endif
Wire.endTransmission();
}
void MyMCP23008::enableInterrupts(uint8_t data)
{
this->write8(MCP23008_GPINTEN, data);
}
MyMCP23008 mcp;
void setup()
{
Serial.begin(115200); Serial.println("MCP23008");
mcp.begin();
for (int button = 0 ; button < 8 ; button++) {
mcp.pinMode(button, INPUT);
mcp.pullUp(button, HIGH);
mcp.enableInterrupts(0xff); }
}
La méthode write8() est celle de la librairie AdaFruit. Pourquoi la dupliquer ? parce que dans cette classe elle est "private", donc inutilisable dans les méthodes des classes dérivées, ce qui n'est pas très malin.
11. Les circuits spécialisés
Certains circuits peuvent être utilisés en lieu et place d'expanders ou de registres à décalage pour des tâches spécialisées, en particulier le pilotage d'afficheurs ou de claviers matriciels.Ces circuits se chargent à la place du processeur du multiplexage de l'afficheur.
Voir cet article :
https://riton-duino.blogspot.com/2018/09/lcd-tft-et-arduino.html
12. Conclusion
On remarque facilement la nette supériorité en vitesse des composants SPI.Malgré cela les composants I2C n'en restent pas moins intéressants quand la vitesse n'est pas un critère primordial :
- pilotage de LEDs
- pilotage d'écrans y compris LCD 7 segments
- pilotage de relais
- pilotage de claviers matriciels
- etc.
Cordialement
Henri
13. Mises à jour
04/02/2019 : 5.9. Le MCP23009 et MCP23S09.ajout de mesures de vitesse I2C à 400KHz
05/02/2019 : 5.7. Le PCF8574
ajout de mesures de vitesse PCF8574
05/02/2019 : 11. Les circuits spécialisés
09/02/2019 : 3. les decodeurs
10/02/2019 : 10. Gestion d'entrées sous interruption
17/02/2020 : 5.3. Le PCA9537
5.14. Le TCA9534
6. Les multiplexeurs I2C
Merci pour cette belle expérience
RépondreSupprimermerci à vous
RépondreSupprimermerci
RépondreSupprimerexcellent article
Merci
SupprimerJ'ai découvert depuis peu l'I2C et ton article va m'aider grandement dans le choix d'un expander. Merci pour ce partage!
RépondreSupprimerMerci Dominique. Bonne réussite.
SupprimerBonjour ! merci pour cette bible de l'I2C : un article de référence !!
RépondreSupprimer1/ J'ai relevé une erreur sur les MCP23xxx : vous parlez de commande par SPI mais c'est commandé par I2C, d'ailleurs votre schéma des paragraphes 9.2 à 9.5 le montre commandé ainsi
2/ il y a aussi le MM5451 qui permet de commander 35 leds ou 5 x 7-segments, avec résistance de pull-up intégrée, peut-être utilisable aussi en multiplexeur ?
Les deux versions existent. MCP230XX I2C, et MCP23SXX SPI. Les schémas en 9.3 et 9.5 montrent un câblage SPI.
SupprimerTop. Je réfléchis à un projet de table d'echecs avec des cellules reed et des pièces aimantées. Il me faut 64 pins, plus deux pour une imprimante et un mini écran. Votre article va m'aider à faire les bons choix, mais je reviendrai peut-être vers vous ! Merci.
RépondreSupprimerBonjour M. Bachetti. Concernant le MCP23017, est-il possible de l'utiliser pour etendre le nombre d'entrée d'un arduino UNO ? Sur tous les schémas que je vois, j'ai l'impression qu'on ne peut qu'étendre que le nombre de le sortie
RépondreSupprimerLe MCP23017 est un expander de GPIOs, capable d'étendre le nombre d'entrées ET de sorties d'un microcontrôleur.
SupprimerAvez vous un exemple de cablage du MCP23008 en entrées ?
SupprimerD'après la datasheet p.20, il faut 0.8Vcc, donc 4V pour un signal haut.
Faut-il limiter le courant vers les entrées GP ? Ou on considère qu'en mode ENTREE, les GP ont une impédance infinie ?
Je ne vois pas en fait comment le MCP sait que ses GP doivent être des sorties, ou entrées...
Aussi, faut-il limiter le courant en entrée VDD ? Page 21 de la datasheet, il est noté courant d'entrée Vdd max =125mA...
Le schéma du paragraphe 10 montre un MCP23017 et 16 boutons. Avec un MCP23008 le schéma est le même, sauf que le nombre de boutons est limité à 8.
SupprimerAucune limitation du courant d'entrée n'est nécessaire.
Pour que le MCP23008 considère que ses GPIOs sont des entrées ou des sorties, il faut le configurer. Utilisez une librairie, comme :
https://github.com/adafruit/Adafruit-MCP23017-Arduino-Library
La méthode pinMode() permet la configuration.
Le courant sur VDD n'a pas besoin d'être limité, c'est à vous de limiter le courant débité sur chaque sortie.