I try to use 8 buttons (at the end there will be 24) on the IO Pi Plus bus1. I dont like to poll the button pins each 200ms, so I connected the IA and IB to the GPIO Pin 23 and 24 of the Raspberry. To divide the voltage I'm using this level shifter: XCSOURCE® 5STK IIC I2C
The code is written in C++ including the wiringPi library. The demo program works for just 3 to 5 interrupts, after that the program crashes.
If I'm using INT_EDGE_FALLING as signal to call my callback function on the wiringPi library I will get this error message:
terminate called after throwing an instance of 'std::runtime_error'
what(): Failed to read from slave
Aborted
If I'm using INT_EDGE_BOTH as signal to call my callback function on the wiringPi library I will get this error message:
terminate called after throwing an instance of 'std::runtime_error'
what(): Failed to write to i2c device for read
Aborted
At the end I need this type of signal watching: INT_EDGE_BOTH, because I need a callback for button down and button up.
Find the Code attached. Has any one some idea, what I'm doing wrong?
Best regards
Oliver
#include <stdio.h>#include <stdexcept>#include <cerrno>#include <string.h>#include <time.h>#include <unistd.h>#include <iostream>#include <wiringPi.h>#include "ABE_IoPi.h"using namespace std;using namespace ABElectronics_CPP_Libraries;IoPi *bus1;void printPressedButtonNumber(){ printf("%d\n", bus1->read_interrupt_capture(0)); printf("%d\n", bus1->read_interrupt_capture(1));}void interruptCallback(){ cout << "interruptCallback" << endl; printPressedButtonNumber();}int main(int argc, char **argv){ setvbuf(stdout, NULL, _IONBF, 0); // needed to print to the command line try { bus1 = new IoPi(0x20); // initialise one of the io pi buses on i2c address default address for bus 1 bus1->set_port_direction(0, 0xFF); // set bank 0 to be inputs bus1->set_port_direction(1, 0xFF); // set bank 1 to be inputs /* Normally you would need to use a resistor to act as a pull-up so there is a constant 5V supply to the pin when the button is not pressed but luckily the IO Pi comes with pull-up resistors inside of the chip which you can enable using the following method. */ bus1->set_port_pullups(0, 0xFF); // disable internal pullups for port 0 bus1->set_port_pullups(1, 0xFF); // disable internal pullups for port 1 /* One downside of using a pull-up resistor rather than a pull-down is that when the button is not pressed the IO Pi will always read the pin as active, so it would read 1 or on when the button is off and 0 or on when the button is pressed, which is backwards to what you would normally expect from a switch. This can be easily fixed with another useful method called invert_pin. invert_pin does exactly what it says, it inverts the reading on an input pin so 1 becomes 0 and 0 becomes 1 and everything starts to look how it should again. The method uses the same variables as setPinPullup with the first setting the pin to invert and the second enables or disables the inverter with 1 or 0. */ bus1->invert_port(0, 0xFF); bus1->invert_port(1, 0xFF); // Set the interrupt polarity to be active high and mirroring disabled, so // pins 1 to 8 trigger INT A and pins 9 to 16 trigger INT B bus1->set_interrupt_polarity(0); bus1->mirror_interrupts(1); // Set the interrupts default value to trigger when 5V is applied to any pin bus1->set_interrupt_defaults(0, 0x00); // 0xFF); bus1->set_interrupt_defaults(1, 0x00); // 0xFF); // Set the interrupt type to be 1 for ports A and B so an interrupt is // fired when the pin matches the default value bus1->set_interrupt_type(0, 0xFF); bus1->set_interrupt_type(1, 0xFF); // Enable interrupts for pins 1 to 16 bus1->set_interrupt_on_port(0, 0xFF); bus1->set_interrupt_on_port(1, 0xFF); bus1->reset_interrupts(); // sets up the wiringPi library // http://www.science.smith.edu/dftwiki/index.php/Tutorial:_Interrupt-Driven_Event-Counter_on_the_Raspberry_Pi if (wiringPiSetupGpio () < 0) { // http://www.fayewilliams.com/2011/10/19/using-errno/ fprintf (stderr, "Unable to setup wiringPi: %s\n", strerror (errno)); return 1; } pinMode(23, INPUT); // Set button as INPUT pullUpDnControl(23, PUD_UP); // PUD_UP); // PUD_DOWN); // Enable pull-up resistor on button // set Pin xyz to generate an interrupt on high-to-low transitions // and attach callback function to the interrupt // INT_EDGE_FALLING, INT_EDGE_RISING, INT_EDGE_BOTH if ( wiringPiISR (23, INT_EDGE_FALLING, &interruptCallback) < 0 ) { cout << "Unable to setup ISR" << endl; fprintf (stderr, "Unable to setup ISR: %s\n", strerror (errno)); return 1; } pinMode(24, INPUT); // Set button as INPUT pullUpDnControl(24, PUD_DOWN); // PUD_UP); // PUD_DOWN); // Enable pull-up resistor on button // set Pin xyz to generate an interrupt on high-to-low transitions // and attach callback function to the interrupt if ( wiringPiISR (24, INT_EDGE_FALLING, &interruptCallback) < 0 ) { cout << "Unable to setup ISR" << endl; fprintf (stderr, "Unable to setup ISR: %s\n", strerror (errno)); return 1; } cout << "Press 'ESC' to Exit" << endl; const static char ESC = 0x1B; char c = 0; do { c = getchar(); } while(c != ESC); } catch (exception &e) { cout << e.what(); } delete bus1; return (0);}