Bonjour !
Pour un projet j'ai besoin d'un expander de GPIO, utilisé avec un clone de Pro Micro 5V.
Je fais avec ce que j'ai sous la main, en l'occurrence un MCP23S17, donc sur bus SPI.
Dans mon projet final, j'aurais besoin d'utiliser une partie des broches en sortie et une autre en entrée, j'ai donc fait un circuit sur breadboard avec d'une part 10 leds et de l'autre 4 boutons.
Les leds forment un chenillard, cette partie fonctionne sans problème, c'est avec mes boutons que j'ai un souci.
Plutôt que de constamment tester leur état, je souhaite utiliser une des deux sorties d'interruption du MCP23S17.
Les boutons sont sur le port B, configurés comme entrées avec pull-up et interruption sur FALLING, la broche 19 (INTB) du MCP23S17 est reliée à la D3 de l'Arduino (INT0). Quand une interruption intervient sur le MCP23S17, INTB doit passer à l'état LOW, ce qui doit déclencher un interrupt sur l'Arduino qui est en mode FALLING.
Mon problème est que ça ne fonctionne qu'une fois, la broche du MCP23S17 reste à l'état LOW, même après lecture du port B. De ce que je comprends de la documentation de la librairie et du datasheet de la puce, l'interrupt devrait être "nettoyé" après la lecture des valeurs du port et donc la broche revenir à l'état HIGH, mais ça n'arrive pas.
Si je débranche et rebranche le fil qui va à D3, ça déclenche une nouvelle interruption (alors qu'on passe de LOW à HIGH, on serait donc plutôt sur un mode CHANGE ou RISING ???) et la broche du MCP23S17 revient à l'état HIGH.
Je pense que l'erreur vient de moi et doit être toute bête, mais j'avoue que je sèche...
Merci d'avance d'éclairer ma lanterne !
Le script utilise actuellement la bibliothèque de Majenko, j'ai essayé aussi avec celles d'Adafruit et de Rob Tillaart, avec à chaque fois le même résultat.
Voici mon code et le schéma du circuit:
#include <MCP23S17.h>
// SPI Chip Select
#define CS_PIN 10
// MCP23S17 Reset pin
#define MCP_RESET 9
// Arduino's external interrupt pin (INT0)
#define INTERRUPT_PIN 3
MCP23S17 mcp(&SPI, CS_PIN, 0); // address 0: Pins A0,A1,A2 grounded
volatile uint8_t flagMCPB = 0;
int theLeds = 1;
void isr();
void handleKeyPressed();
void setup() {
Serial.begin(9600);
while (!Serial)
;
pinMode(MCP_RESET, OUTPUT);
// Reset MCP23S17
digitalWrite(MCP_RESET, LOW);
delay(100);
digitalWrite(MCP_RESET, HIGH);
mcp.begin();
// set Port Expander Interrupt configuratons
mcp.setMirror(false);
mcp.setInterruptOD(false);
mcp.setInterruptLevel(LOW);
// clear all interrupts on MCP23S17
mcp.getInterruptValue();
mcp.getInterruptPins();
// uint16_t mcpReading = mcp.getInterruptValue();
// uint16_t mcpPins = mcp.getInterruptPins();
// Arduino's Interrupt
pinMode(INTERRUPT_PIN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), isr, FALLING);
// configure pins for 10 leds
// GPA0..7, GPB0, GPB1
for (uint8_t i = 0; i < 10; i++) {
mcp.pinMode(i, OUTPUT);
}
// configure pins for buttons
// GPB2, GPB3, GPB4, GPB5
for (uint8_t i = 10; i < 14; i++) {
mcp.pinMode(i, INPUT_PULLUP);
mcp.enableInterrupt(i, FALLING);
}
Serial.println();
Serial.println("-------------------------------------------");
Serial.println("MCP23S17 Ready!");
Serial.println("-------------------------------------------");
Serial.println();
}
void loop() {
// Btns interrupts
if (flagMCPB == 1) {
handleKeyPressed();
}
// Blinking leds
theLeds = theLeds << 1;
if (theLeds == 1024) theLeds = 1;
mcp.writePort(0, theLeds); // Port, Val
mcp.writePort(1, (int)theLeds >> 8);
delay(80);
}
void isr() {
flagMCPB = 1;
}
void handleKeyPressed() {
// read port B (and hopefully clears the interrupt)
uint8_t mcpBReading = mcp.getInterruptBValue(); // reads PORTB
mcpBReading = mcpBReading >> 2; // first btn is GPB2
mcpBReading = ~mcpBReading; // flip the bits (PORTB is 0b1111 by default, due to pullups)
Serial.print("InterruptPins: 0b");
Serial.println(mcp.getInterruptPins(), 2);
Serial.print("InterruptValue: 0b");
Serial.println(mcp.getInterruptValue(), 2);
Serial.print("B Pins: 0b");
Serial.println(mcp.getInterruptBPins(), 2);
Serial.print("B Values: 0b");
Serial.println(mcp.getInterruptBValue(), 2);
if ((int)(mcpBReading & 0b1000) == 8) {
Serial.println("Bouton 1");
}
if ((int)(mcpBReading & 0b0100) == 4) {
Serial.println("Bouton 2");
}
if ((int)(mcpBReading & 0b0010) == 2) {
Serial.println("Bouton 3");
}
if ((int)(mcpBReading & 0b0001) == 1) {
Serial.println("Bouton 4");
}
delay(100); // de-bounce before we re-enable interrupts
flagMCPB = 0; // Ready for next interrupt
mcpBReading = 0;
}
