Hallo zusammen,
nach dem meine Hardware nun vernünftigt arbeitet sitze ich schon mehrere Tage an der Programmierung des MCP23017-Bausteins.
Auf meinem Pi läuft node.js mit express 4.0. Um mit dem MCP23017 zu kommunizieren habe ich das wiring-pi node plugin installiert.
Angeschlossen ist das MCP wie folgt (I2C Adresse: 0x20):
GPB0-GPB7 Inputs die ein Interrupt auslösen sollen bei Veränderung.
GPA0-GPA7 Outputs die ein Relais steuern.
INTB ist am GPIO 18 (bzw wiring-pi pin 1) am Pi angeschlossen.
!RESET ist auf 3,3V.
Mein Problem ist nun folgendes:
Ich kann nur ein Interrupt auslösen, indem ich in der Konsole "i2cget -y 1 0x20 0x13" eingebe.
Dort sehe ich dann auch welche Bits sich verändert haben. Aber dieser Interrupt soll doch allein auslösen
Meine Software:
/**
I2C Adress of the MCP23017
**/
const I2C_ADRESS = 0x20;
/**
Interrupt Pin which connects INTB from the MCP23017 with the Pi.
wiring-pi pin 1 represents GPIO 18
**/
const INTERRUPT_PIN = 1;
/**
I/O DIRECTION REGISTER
----------------------
IO7:IO0:
1 = Pin is configured as an input.
0 = Pin is configured as an output.
**/
const IODIRA = 0x00;
const IODIRB = 0x01;
/**
INTERRUPT-ON-CHANGE CONTROL REGISTER
------------------------------------
IP7:IP0:
1 = GPIO register bit will reflect the opposite logic state of the input pin
0 = GPIO register bit will reflect the same logic state of the input pin
**/
const IPOLA = 0x02;
const IPOLB = 0x03;
/**
INTERRUPT-ON-CHANGE CONTROL REGISTER
------------------------------------
GPINT7:GPINT0:
1 = Enable GPIO input pin for interrupt-on-change event.
0 = Disable GPIO input pin for interrupt-on-change event.
**/
const GPINTENA = 0x04;
const GPINTENB = 0x05;
/**
DEFAULT COMPARE REGISTER FOR INTERRUPT-ON-CHANGE
------------------------------------------------
DEF7:DEF0:
These bits set the compare value for pins configured for interrupt-on-change from defaults <7:0>.
Refer to INTCON.
If the associated pin level is the opposite from the register bit, an interrupt occurs.
**/
const DEFVALA = 0x06;
const DEFVALB = 0x07;
/**
INTERRUPT CONTROL REGISTER
--------------------------
IOC7:IOC0:
1 = Controls how the associated pin value is compared for interrupt-on-change.
0 = Pin value is compared against the previous pin value.
**/
const INTCONA = 0x08;
const INTCONB = 0x09;
/**
PULL-UP RESISTOR CONFIGURATION REGISTER
---------------------------------------
GPPU7:GPPU0:
1 = Pull-up enabled.
0 = Pull-up disabled.
**/
const GPPUA = 0x0C;
const GPPUB = 0x0D;
/**
INTERRUPT FLAG REGISTER
-----------------------
INT7:INT0: Will reflect the change only if interrupts are enabled (GPINTEN)
1 = Pin caused interrupt.
0 = Interrupt not pending.
**/
const INTFA = 0x0E;
const INTFB = 0x0F;
/**
PORT REGISTER
-------------
GP7:GP0:
1 = Logic-high.
0 = Logic-low.
**/
const GPIOA = 0x12;
const GPIOB = 0x13;
...
// Initialize wiring-pi
wpi.wiringPiSetup();
// Setup i2c
var fd = wpi.wiringPiI2CSetup(I2C_ADRESS);
// Configure MCP23017
if (fd != -1) {
console.log('I2C detected');
// Set interrupt pin from Pi to input
wpi.pinMode(INTERRUPT_PIN, wpi.INPUT);
// Set all GPIOB's to input
wpi.wiringPiI2CWriteReg8(fd, IODIRB, 0xFF);
// Reverse all GPIOB's logic because active input is grounded
wpi.wiringPiI2CWriteReg8(fd, IPOLB, 0xFF);
// Set pullup for all GPIOB's input
wpi.wiringPiI2CWriteReg8(fd, GPPUB, 0xFF);
console.log('State: ' + decTobin(wpi.wiringPiI2CReadReg8(fd, GPIOB),8));
// Activate interrupts for all GPIOB's
wpi.wiringPiI2CWriteReg8(fd, GPINTENB, 0xFF);
// Set interrupt option
wpi.wiringPiI2CWriteReg8(fd, INTCONB, 0xFF);
// Set default values
wpi.wiringPiI2CWriteReg8(fd, DEFVALB, 0x00);
// Listen for an interruption and check values
wpi.wiringPiISR(INTERRUPT_PIN, wpi.INT_EDGE_RISING, function(delta) {
console.log('INTERRUPT! \nCaused by: ' + decTobin(wpi.wiringPiI2CReadReg8(fd, INTFB),8) + ' \nDelta: ' + delta);
});
} else {
console.log('I2C Setup failed!');
}
function decTobin(dec,length){
var out = "";
while(length--)
out += (dec >> length ) & 1;
return out;
}
...
Alles anzeigen
Die Inputs arbeiten mit dem internen Pullup und sind daher Softwareseitig invertiert, damit es sich besser arbeiten lässt.
Meine Ausgabe sieht nach dem oben gennanten i2cget Befehl so aus:
Oder wenn sich Zustände geändert haben und ich noch einmal den i2cget Befehl ausführe:
Wie gesagt möchte ich aber, dass der Interrupt automatisch ausgelöst wird, sobald der Defvalue von 0 sich verändert. Sprich wenn sich der Status von 0 auf 1 ändert. Sonst aber nie.
Achja der Interrupt-Pin bleibt immer bei 0. Beim auselesen kann ich es aus zeitkritischen Gründen nicht bestimmen ob dieser kurzzeitig auf 1 war.
EDIT:
So wie es ausschaut, muss man wohl immer einmalig einen read Befehl senden, damit die Interrupts automatisch starten. Ich probiere noch mal ein paar Sachen aus