Pages: [1]   Go Down
Author Topic: Interrupt on PCF8574 as input  (Read 699 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Jr. Member
**
Karma: 2
Posts: 84
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi!

I'm trying to make a sketch that outputs a serial code containing the status of 8 buttons connected via 2x PCF8574 chips.
The idea is that, when nothing has changed on the state of the buttons, the code gets send every second. However, if there is a change, I want it to output the code immediately.

The code gets constructed from input 2-8 from the first expander, and if expander 2 has at least one button pressed, I simply add 128 to the calculated value. This is obviously a bit strange, but this is just so for testing purposes as I don't care on which pin of the second expander the value has changed.

So: button 1 = 2^0
     button 2 = 2^1
     button 3 = 2^2
     ... and so on

This is not even the problem, it's just to give you an explanation of what I'm trying to do.
The problem lies in the interrupt procedure. When a state has been changed, the program just stops working (the led stops flashing). As long as the buttons states remain the same, everything works fine.

I've installed a pull-up resistor to the interrupt line of 100k.

This is the sketch:

Code:
#include <Wire.h>
#include <math.h>
#define expander1 B0100000 //tally 1 - 8
#define expander2 B0100001 //tally 9 - 16

int DecVal = 0;
int DecVal2 = 0;
int Start1 = 240;
int Start2 = 15;
int led = 0;

byte returnByte = 0;
byte returnByte2 = 0;

unsigned long marker = millis();

void setup(){
  Serial.begin(9600);
  Wire.begin();
  attachInterrupt(0,plots,LOW);
  pinMode(8,OUTPUT);
 
}





void loop(){
  if(millis() - marker > 1000){
    verandering(); }
 
}

void plots(){
 
 
  returnByte = expanderRead(1);
  returnByte2 = expanderRead(2);
  returnByte = ~returnByte;
  returnByte2 =~returnByte2;
  DecVal = 0;
  DecVal2 = 0;
 
  for(int i=1;i<8;i++){
    if(bitRead(returnByte,i)==1){
      DecVal = DecVal + pow(2,i-1);}
      if(returnByte2>0){
        DecVal = DecVal + 128; }
       
  }
   
    Serial.write(Start1);
    Serial.write(Start2);
    Serial.write(DecVal);
    Serial.write(DecVal);
   
    led = 1 - led;
    if(led==0){digitalWrite(8,LOW); }else { digitalWrite(8,HIGH);}
   
}

void verandering(){
  plots();
 
   
    marker = millis();
   
   
   
 
   
     
 
}

byte expanderRead(int id) {
byte _data;
switch(id){
  case 1:
    Wire.requestFrom(expander1, 1);
    if(Wire.available()) {
      _data = Wire.read();
    }
    return _data;
  case 2:
    Wire.requestFrom(expander2, 1);
    if(Wire.available()) {
      _data = Wire.read();
    }
    return _data;
}
}

I don't see what I'm missing, but I'm sure it's something silly. Any help is greatly appreciated!
Thanks a lot!

Jens
Logged

Germany
Offline Offline
Jr. Member
**
Karma: 0
Posts: 89
Walking on Nails
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Problem: an interrupt routine (ISR) blocks all other interrupts until it returns. This can be altered, but you should not try to change anything there. Knowing this the conclusion should be: make the ISR as short as possible.

The result is something like this: create a global volatile variable signaling that the interrupt fired. In the ISR you only set this variable. In the main loop() you check the status of the variable and start your routines accordingly. They should reset the global variable after getting all information the interrupt was meant to inform about.

You can do more in the ISR, but nothing that depends on other interrupts like for instance serial communication.
Logged

loved the 68000 assembler back then and now I have to deal with THIS 8 bit thingy

Pages: [1]   Go Up
Jump to: