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
}