1

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++)
 delayMicroseconds(1000);
 Check=1;
 for(j=0; j<8; j++){
 digitalWrite(latchPin, LOW);
 delayMicroseconds(500);
 SPI.transfer(Check);
 SPI.transfer(Output);
 digitalWrite(latchPin, HIGH);
 delayMicroseconds(500);
 if(digitalRead(interruptPin)==HIGH){
 //Serial.println(Check);
 if(bitRead(Output, j)==1)
 bitWrite(Output, j, 0);
 else
 bitWrite(Output, j, 1);
 }//dig check
 Check = Check<<1;
 }
 digitalWrite(latchPin, LOW);
 delayMicroseconds(500);
 SPI.transfer(255); //to push buttons
 SPI.transfer(Output); //to LEDs
 digitalWrite(latchPin, HIGH);
 delayMicroseconds(500);
}//pin_read
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
 delay(1000); 
 // the LEDs don't change while you're sending in bits:
 digitalWrite(latchPin, LOW);
 SPI.setBitOrder(MSBFIRST);
 SPI.setDataMode(SPI_MODE0);
 SPI.setClockDivider(SPI_CLOCK_DIV2);
 SPI.begin();
 SPI.transfer(255);
 SPI.transfer(255);
 //take the latch pin high so the LEDs will light up:
 digitalWrite(latchPin, HIGH);
 Serial.begin(115200);
 attachInterrupt(0, pin_read, RISING); 
 Wire.begin(8); // join i2c bus with address #8
 Wire.onRequest(requestEvent); // register event
 Wire.onReceive(receiveEvent);
 Serial.println("Initialized...");
}
void loop() {
 Serial.println("Interrupting...");
 digitalWrite(espPin, HIGH);
 while(digitalRead(interruptPin)==HIGH){}
 delayMicroseconds(500);
 digitalWrite(espPin, LOW);
 delayMicroseconds(500);
 Serial.println("Done...");
Serial.print("Output:");
Serial.println(Output);
delay(3000);
}
// 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;
 Serial.println("received::");
 while (Wire.available()) { // loop through all
 char c = Wire.read(); // receive byte as a character
 arduinoStatus[i++]=c;
 Serial.print(c); // print the character
 }
 arduinoStatus[i]='0円';
 Serial.println("###");
}
// function that executes whenever data is requested by master
// this function is registered as an event, see setup()
void requestEvent() {
 Serial.println("Sending...");
 Wire.write("hello"); // respond with message of 6 bytes
 Wire.write(Output);
 Serial.println("Sent");
 // as expected by master
}
asked Aug 13, 2016 at 16:10
7
  • 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. Commented Aug 13, 2016 at 16:22
  • 1
    Are you using delay() functions in your code? Commented Aug 13, 2016 at 16:24
  • A question like this really needs to include your code. Commented 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. Commented 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? Commented Aug 13, 2016 at 17:25

2 Answers 2

1

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.

answered Aug 13, 2016 at 18:00
0

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.

answered Aug 13, 2016 at 19:19
3
  • 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. Commented Aug 13, 2016 at 19:56
  • That won't solve the problem if the interrupt is getting missed while interrupts are disabled. Commented Aug 13, 2016 at 20:08
  • True. I didn't notice anything disabling the interrupts though. Commented Aug 13, 2016 at 20:10

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.