I am trying to create my own home automation using Arduino. I am using shift register for reading input(via push buttons) and writing output to led's. I am using SPI interface to communicate with shift registers.

Apart from SPI Arduino also deals with I2C devices. When push button is clicked Arduino ISR is invoked via pin 2, which then checks exact button that was pushed and takes action accordingly. The functionality currently works well with one small problem.

Sometimes when push button is clicked Arduino ignores the button press. After debugging for some time I observed that it happens when Arduino is busy with I2C communication with other devices.

I would like to know if it is possible to temporarily delay the push button input while Arduino busy with I2C communication? or is it possible to prioratize interrupt handling over I2C communication?

Below is the simplified code

#include <SPI.h>
#include <Wire.h>
byte Input=1;
volatile byte Check=1;
volatile byte Output=1;

int j;
//Pin connected to ST_CP of 74HC595
int latchPin = 8;
//Pin connected to SH_CP of 74HC595
int clockPin = 13;
////Pin connected to DS of 74HC595
int dataPin = 11;

int interruptPin=2;

int espPin=7;

char arduinoStatus[100]="\0";

 void pin_read(){

    for(j=0; j<50; j++)

    for(j=0; j<8; j++){
      digitalWrite(latchPin, LOW);


     digitalWrite(latchPin, HIGH);


      if(bitRead(Output, j)==1)
      bitWrite(Output, j, 0);
      bitWrite(Output, j, 1);
    }//dig check

    Check = Check<<1;


    digitalWrite(latchPin, LOW);
    SPI.transfer(255); //to push buttons
    SPI.transfer(Output); //to LEDs

    digitalWrite(latchPin, HIGH);


void setup() {
  //set pins to output so you can control the shift register
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  pinMode(espPin, OUTPUT);
  pinMode(interruptPin, INPUT);//Input from buttons

  // the LEDs don't change while you're sending in bits:
    digitalWrite(latchPin, LOW);
   //take the latch pin high so the LEDs will light up:
    digitalWrite(latchPin, HIGH);

    attachInterrupt(0, pin_read, RISING); 

    Wire.begin(8);                // join i2c bus with address #8
  Wire.onRequest(requestEvent); // register event


void loop() {
 digitalWrite(espPin, HIGH);

 digitalWrite(espPin, LOW);

// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany) {
  int i=0;
  while (Wire.available()) { // loop through all
    char c = Wire.read(); // receive byte as a character

    Serial.print(c);         // print the character


// function that executes whenever data is requested by master
// this function is registered as an event, see setup()
void requestEvent() {
  Wire.write("hello"); // respond with message of 6 bytes
  // as expected by master
  • 1
    Sounds like you need to re-organize your software, in particular you probably need to use non-blocking I2C routines, at least if you have any peripherals that do clock-stretching. Most likely you could get away with only servicing the user inputs between i2c words, but if clock-stretching is possible, they could take longer. Aug 13, 2016 at 16:22
  • 1
    Are you using delay() functions in your code?
    – Transistor
    Aug 13, 2016 at 16:24
  • A question like this really needs to include your code. Aug 13, 2016 at 16:24
  • @ChrisStratton,@Transistor: have tried to search for non blocking I2C library for Arduino, but it looks like many people are looking for the same and not finding., I have posted the simplified code I am using.
    – Xinus
    Aug 13, 2016 at 17:21
  • "When push button is clicked Arduino ISR is invoked via pin 2" - where is the ISR in your code?
    – Bruce Abbott
    Aug 13, 2016 at 17:25

2 Answers 2


Without looking any further than the first delaymicroseconds() command I would say that that's where the trouble lies. The delay() functions are very handy for getting the beginner's first LED to blink and are a big problem after that. The problem is that the CPU is completely tied up during the delay and can't do anything else other than interrupts and you only have a limited supply of those. Your button press is missed.

You need to develop your own timers in the code and keep the main loop running constantly checking on each pass to see if the delay is complete.


What about polling the buttons periodically instead of using an interrupt? If you check them every 10 ms or so, you should still be able to detect a button press reliably. Connecting buttons to interrupt inputs is not necessarily the best idea due to contact bounce - this can cause a number of back-to-back interrupts. My guess is that interrupts are being disabled during some part of your code and when the interrupt pin level changes during that period, it gets ignored.

  • Close. I would use the interrupt to set a flag. Then, in the main loop, you process the button press whenever the loop comes back around.
    – RubberDuck
    Aug 13, 2016 at 19:56
  • That won't solve the problem if the interrupt is getting missed while interrupts are disabled. Aug 13, 2016 at 20:08
  • True. I didn't notice anything disabling the interrupts though.
    – RubberDuck
    Aug 13, 2016 at 20:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.