Fragen zu Port Expander

falko1985:
Sorry, ich habe das vergessen zu entfernen.

Das passiert schon mal :slight_smile:

Wichtiger ist pinMode vor und nach der Ausgabe.

Danke Dir, aber was genau meinst Du mit "Wichtiger ist pinMode vor und nach der Ausgabe."?
Reicht es nicht einfach nur in der Setup Methode diese pinMode zu setzen?

Edit: Ich habe gerade gemerkt, das ich für beide Arrays einen Input gesetzt habe, das Array matrixMaster sollte Output sein.
Ich hab mal zum Test die Pin Nummer 0 auslesen lassen und bekomme immer den Wert 0, egal ob an dem Input ein High Signal anliegt oder nicht:

#include <Wire.h>
#include <Adafruit_MCP23017.h>

Adafruit_MCP23017 mcp1; // Create MCP 1
Adafruit_MCP23017 mcp2; // Create MCP 2

const uint8_t addr1 = 0; // Adresse 0x20 / 0
const uint8_t addr2 = 1; // Adresse 0x21 / 1

int masterLines = 4;
int slaveLines = 16;
int matrixMaster[] = {0, 1, 2, 3};
int matrixSlave[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};

void setup() {  
  Serial.begin(9600);
  mcp1.begin(addr1);      // Start MCP 1
  mcp2.begin(addr2);      // Start MCP 2

  for (int i = 0; i < slaveLines; i++) {       
    mcp1.pinMode(matrixSlave[i],INPUT);
    mcp1.pullUp(matrixSlave[i],HIGH);
  }
  for (int i = 0; i < masterLines; i++) {         
    mcp2.pinMode(matrixMaster[i],OUTPUT);       
    mcp2.digitalWrite(matrixMaster[i], HIGH);     
  }
}

void loop() {
  Serial.println(mcp1.digitalRead(matrixSlave[0])); 
  delay(1000);
}

Woran könnte das Problem denn liegen?

Gruss

falko1985:
Danke Dir, aber was genau meinst Du mit "Wichtiger ist pinMode vor und nach der Ausgabe."?
Reicht es nicht einfach nur in der Setup Methode diese pinMode zu setzen?

Nein.
Du mußt eine Spalte auf HIGH setzen und die anderen 7 Spalten auf hochohmig (= Eingang).
Ansonsten kann es passieren wenn Du 2 "gedrückte Tasten" auf der gleichen Zeile hast daß Du einen schönen Kurzschluß zwischen HIGH und LOW hast und den Expander kaputtmachst.

Grüße Uwe

falko1985:
Woran könnte das Problem denn liegen?

Ich habe jetzt mal meine beiden MCP23017 aus der Bastelkiste geholt.

Erste gute Nachricht: Dein Programm aus #21 tut, was es soll. Wenn es nur bei mir funktioniert, hast Du einen Schaltungsfehler oder die ICs gegrillt.

Ich habe zunächst mit einem UNO den I2C-Scanner laufen lassen, 0x20 und 0x21 werden erkannt. Dann habe ich das Bibliotheksbeispiel button.ino erfolgreich probiert. Auch Dein Programm aus #21 gibt "1" oder "0" aus.

Auch mit dem ESP32 funktioniert Dein Programm.

Wenn es dann mal funktioniert, habe ich im Beispiel custom_frequency.ino noch diese Beschleunigung gefunden:

Wire.setClock(1700000); // ESP32: set I2C frequency to 1.7mhz

Zweite gute Nachricht: Dein Programm aus #15 tut mit kleinen Modifikationen, was es soll. Allerdings wird der Pfeil erst beim Rausziehen erkannt. Getestet mit ESP32:

#include <Wire.h>
#include <Adafruit_MCP23017.h>

Adafruit_MCP23017 mcp1; // Create MCP 1
Adafruit_MCP23017 mcp2; // Create MCP 2

const uint8_t addr1 = 0; // Adresse 0x20 / 0
const uint8_t addr2 = 1; // Adresse 0x21 / 1

const uint8_t masterLines = 4; // Change here to the number of lines of your Master Layer
const uint8_t slaveLines = 16; // Change here to the number of lines of your Slave Layer
const uint8_t matrixMaster[] = {0, 1, 2, 3}; // Put here the pins you connected the lines of your Master Layer
const uint8_t matrixSlave[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; // Put here the pins you connected the lines of your Slave Layer

void setup() { 
  Wire.setClock(1700000); // ESP32: set I2C frequency to 1.7mhz
  mcp1.begin(addr1);      // Start MCP 1
  mcp2.begin(addr2);      // Start MCP 2

  for(int i = 0; i < slaveLines; i++){
    mcp2.pinMode(matrixSlave[i],INPUT);
    mcp2.pullUp(matrixSlave[i],HIGH);
  }
  for(int i = 0; i < masterLines; i++){         
    mcp1.pinMode(matrixMaster[i],INPUT);       
    mcp1.pullUp(matrixMaster[i], HIGH);     
  }
  delay(500);
  Serial.begin(115200);
  Serial.println("\nStart");
}

void loop() {
  String key = getKey();
  if( key != 0) {
    Serial.println(key);
  }
}


String getKey()
{
  String key = "";  // 0 indicates no key pressed
  for(uint8_t i = 0; i < masterLines; i++){         
    mcp1.pinMode(matrixMaster[i],OUTPUT);       
    mcp1.digitalWrite(matrixMaster[i], LOW);         
    for(int j = 0; j < slaveLines; j++){             
      if(mcp2.digitalRead(matrixSlave[j]) == LOW){  // Is a key pressed?     
        while(mcp2.digitalRead(matrixSlave[j]) == LOW);  // wait for key to be released   
        key = String(i)+","+String(j);  // Remember which key                     
      }         
    }         
    mcp1.pinMode(matrixMaster[i],INPUT);   // De-activate the current column.   
    mcp1.pullUp(matrixMaster[i], HIGH);     
  }
  return key;
}

Vielen Dank für die Antwort.

Im Setup Bereich:

mcp1.pinMode(matrixMaster[i],INPUT);

müsste das hier auf OUTPUT gesetzt werden, ich habe mich bei meinem vorherigen Post vertan, Sorry.

Leider klappt das bei mir alles nicht.
Irgendwie scheint meine Schaltung Probleme zu machen, Plötzlich sind alle 16 Pins auf HIGH geschaltet, beim 1ten MCP23017.
Der 1te MCP23017 sollte ja nur 4 Pins auf HIGH geschaltet sein.

Ich werde meine Schaltung nochmal komplett Prüfen und Melde mich dann wieder, ob es nun geklappt hat oder nicht.

Vielen Dank nochmal für die Hilfe.

Gruß

falko1985:
Im Setup Bereich:

mcp1.pinMode(matrixMaster[i],INPUT);

müsste das hier auf OUTPUT gesetzt werden, ich habe mich bei meinem vorherigen Post vertan, Sorry.

Nein!

Siehe #22, Du machst einen Kurzschluß, der möglicherweise Deine ICs schon zerstört hat.

In #23 siehst Du, wie es richtig funktioniert.

Danke für den Hinweis, hatte das leider nicht so verstanden.

Ich werde später meine Schaltung nochmal neu Aufbauen und testen.

Ist mein Schaltplan, Siehe #15, überhaupt in Ordnung?

Gruß

falko1985:
Ist mein Schaltplan, Siehe #15, überhaupt in Ordnung?

Mir fehlen PullUp-Widerstände für I2C.

Ich habe den MCP23017 jetzt so verkabelt, wie es auf dieser Seite im ersten Bild zusehen ist:

Jetzt funktioniert es endlich und vielen Dank für die Zeit und die Hilfe. :slight_smile:

Gruß

falko1985:
Jetzt funktioniert es endlich und vielen Dank für die Zeit und die Hilfe. :slight_smile:

LadyAda und ihre Firma sind doch häufig ein Quell der Freude!

Hallo nochmal.
Ich habe noch ein großes Problem mit dem MCP23017.
Die Matrix von meiner Dartscheibe ist ja an dem MCP23017 verbunden und funktioniert auch soweit, wenn ich die Segmente mit dem Finger drücke.
Aber sobald ich einen Pfeil schmeiße, dann reagiert der MCP23017 anscheinend nicht, also ich bekomme auch keine Ausgabe zusehen.
Ist der MCP23017 eventuell so langsam, das der geworfene Pfeil einfach viel zu schnell dafür ist und er dann immer noch sagt, das nichts gedrückt wurde?

Ich bedanke mich schon mal im Voraus.

Gruss

Ich auch: Wie sieht Dein aktuelles Programm aus und auf welcher Hardware läuft es?

Wie darf ich mir das elektromechanisch vorstellen, denn ich habe keine elektronische Dartscheibe.

Kannst Du das Signal mit einem Logikanalysator bildlich darstellen?

Möglich, aber erstmal tippe ich auf Dein Programm.

Es läuft auf meinem Esp32 mit dem Code aus Beitrag #24. Wie du geschrieben hast, wird der Pfeil erst erkannt, wenn er rausgezogen wurde.

Hinter den Dart Segmente befindet sich eine Matrix und funktioniert so:
Pfeil trifft auf einen der Segmente auf meiner Dartscheibe, drückt die Matrix zusammen und gibt diese wieder automatisch frei und dann bekomme ich die Werte angezeigt.

Dies funktioniert ohne Probleme, wenn ich die Dartsegmente mit dem Finger reindrücke und wieder loslasse. Nur wenn ich den Pfeil drauf Werfe, klappt das leider nicht.
Anscheinend drückt der Pfeil zu schnell die Matrix zusammen und gibt diese wieder frei, so dass der MCP das nicht registriert.

Ich habe leider keinen Logikanalysator .

Ich denke du wirst nicht um die Nutzung von Interupts kommen. Stichwort FastCounter.

Hierbei wäre es Sinnvoll über Entprellung der Inputs nachzudenken.

Grüsse Nano

1 Like

Ich danke Dir für die Antwort.
Könntest Du mir Vielleicht einen Beispiel zeigen, wie man das für meine Zwecke lösen kann?

Ich habe einige Beispiele aus dem Netz getestet, leider besteht das Problem weiterhin.
Nun habe ich mir jetzt den MCP23S17 besorgt, das scheint etwas besser zu funktionieren, aber auch nicht so gut.
Von z.B. 6 Pfeilen, werden mal 2 oder 3 Pfeile erkannt und die anderen wurden nicht erkannt.
Ich denke auch, das es was mit Entprellung zu tun hat, nur weiß ich leider nicht, wie ich das Problem beheben kann.

Hier ist mein Beispiel Code, den ich versuchen möchte zum laufen zu bringen:

#include <MCP23S17.h>

#ifdef _PIC32MX_
// chipKIT uses the DSPI library instead of the SPI library as it's better
#include <DSPI.h>
DSPI0 SPI;
#else
// Everytying else uses the SPI library
#include <SPI.h>
#endif

const uint8_t masterLines = 16; // Change here to the number of lines of your Master Layer
const uint8_t slaveLines = 4; // Change here to the number of lines of your Slave Layer
const uint8_t matrixSlave[] = {0, 1, 2, 3}; // Put here the pins you connected the lines of your Master Layer
const uint8_t matrixMaster[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; // Put here the pins you connected the lines of your Slave Layer

const uint8_t chipSelect = 5;
const uint8_t PIN = 0;

// Create an object for each chip
// Bank 0 is address 0
// Bank 1 is address 1.
// Increase the addresses by 2 for each BA value.

MCP23S17 mcp1(&SPI, chipSelect, 0);
MCP23S17 mcp2(&SPI, chipSelect, 1);
//MCP23S17 mcp3(&SPI, chipSelect, 2);


void setup() {
  mcp1.begin();
  mcp2.begin();
  for(int i = 0; i < masterLines; i++){
    mcp1.pinMode(matrixMaster[i],INPUT_PULLUP);
  }
  for(int i = 0; i < slaveLines; i++){        
    mcp2.pinMode(matrixSlave[i],INPUT_PULLUP);        
  }
  delay(500);
  Serial.begin(9600);
}

void loop() {
  String key = getKey();
  if( key != 0) {
    Serial.println(key);
    key = "";
    delay(500);
  }
}

String getKey()
{
  String key = "";  // 0 indicates no key pressed
  for(uint8_t i = 0; i < slaveLines; i++){        
    mcp2.pinMode(matrixSlave[i],OUTPUT);      
    mcp2.digitalWrite(matrixSlave[i], LOW);        
    for(int j = 0; j < masterLines; j++){            
      if(mcp1.digitalRead(matrixMaster[j]) == LOW){  // Is a key pressed?    
        while(mcp1.digitalRead(matrixMaster[j]) == LOW);  // wait for key to be released  
        key = String(i)+","+String(j);  // Remember which key                    
      }        
    }        
    mcp2.pinMode(matrixSlave[i],INPUT_PULLUP);   // De-activate the current column.    
  }
  return key;
}

Ich bedanke mich im Voraus für die Hilfe.

Gruss

Ich komme leider erst heute Abend dazu mir das genauer anzusehen. Aber im Grunde ist es so das deine mcp23 (ob nun s oder 0) interruptausgänge haben die du auswerten kannst.

Wir benutzen das nicht in der gebäudeautomation zum schnellen zählen bis in die 100Hz (verbrauchsdaten)

Hier aus dem Forum etwas Lektüre.

Da ich gerade keine passenden ics hier habe können wir das leider nur theoretisch durchgehen

1 Like

Schade. "Es ist, wie es ist, aber es kommt darauf an, was wir daraus machen!" Also etwas mehr probieren.

Das denke ich auch.

Vermutlich nicht nötig.

Dann könntest Du auf dem richtigen Weg sein.

Plan (ich schaue wohl zu viel Dr. Who!):

  1. matrixSlave[i] in einer Schleife laufen lassen.
  2. Bei einem Interrupt "Interrupt capture" von mcp1 auslesen.
  3. Der Schlüssel bildet sich aus i und dem Wert aus mcp1.

Schau mal im Thema Interrupt MCP23017 und dort auch meinen Beitrag. Das ist für einen AVR, nicht für den ESP32.

Die Bibliothek MCP23S17 hat die Methoden enableInterrupt() und getInterruptValue(), das sollte passen.

Vielen Dank für die Antworten.
Zum Test habe ich mit dem ESP32 einen Push Button verbunden und Interrupt verwendet, das hatte funktioniert.
Nur bekomme ich es mit dem MCP23S17 nicht hin.
Ich habe ja 2 MCP23S17, 1 für die Zeilen und 1 für die Spalten und müsste, denke ich, nur einen MCP23S17 Interrupts verwenden für die Inputs, oder?.

Ich habe zuvor leider noch nie was mit Interrupts getan und muss mich da erstmal etwas einlesen, wie ich das am besten machen kann und auf was ich Achten muss usw.
Bei dem MCP23S17 kann ich ja IntA und IntB zusammen verbinden und als einen Interrupt Pin verwenden, oder?
Und wenn die gewünschte Funktion bei Interrupt aufgerufen wird, muss ich dann in diese Funktion alle Eingänge nochmal durchlaufen und auf HIGH oder LOW Prüfen?

Ich werde mich mit Interrupts mal mehr beschäftigen, da ich noch nicht all zu viel Ahnung habe.

Gruss

Ja.

Ja.

Nein, alle 16 Bit zusammen lesen mittels getInterruptValue().

Super, vielen Dank.

Ich habe zum Test mal das hier hinbekommen:

void setup() {
  pinMode(INTPIN, INPUT_PULLUP);
  mcp1.begin();
  mcp2.begin();
  for(int i = 0; i < masterLines; i++){
    mcp1.pinMode(matrixMaster[i],INPUT_PULLUP);
  }
  for(int i = 0; i < slaveLines; i++){        
    mcp2.pinMode(matrixSlave[i],INPUT_PULLUP);        
  }
  Serial.begin(9600);

  for(uint8_t i = 0; i < 16; i++) {
     mcp1.enableInterrupt(i, RISING); // Should this be RISING or CHANGE? enable Interrupt on all pins. When change is noticed it will be driven to configured level and stay until port is read (readPort, digitalRead or getInterruptValue)
  }
  mcp1.setMirror(true); //Ties GPA and GPB together for interrupts.

  mcp1.setInterruptLevel(HIGH);
  //attachInterrupt(digitalPinToInterrupt(INTPIN), interrupt_call, RISING);

}

void loop() {
  Serial.println(counter);
  counter++;

  unsigned int pinValuesBank1 = mcp1.getInterruptValue();
  Serial.println(pinValuesBank1);
  //delay(1000);
}

Somit bekomme ich bei jeder Eingang einen anderen Wert und hoffe, das es so richtig ist.
Muss mcp2 auch als Input definiert sein?

Ich werde demnächst die Schaltung an meiner Matrix nochmal anschließen, Testen und dann nochmal Benachrichtigen, ob es nun funktioniert.

Edit: Es funktioniert doch noch nicht so richtig.
Das Programm hängt sich langsam auf.

Edit2: Es scheint doch zu gehen, keine Ahnung was das Problem war.
Habe den delay noch auf 10 Millisekunde eingestellt.
Werde das ganze dann später nochmal genauer Testen.

Gruss