Trying to monitor signals using interrupts.

First off - Thanks in advance for the help. I have exhausted other resources, and it's time I ask for help.

Here is the scenario. I am building an automated system controlling external devices and receiving feedback signals throughout the process that I then use to control other things. The code, below, is a simple test code I am writing from the main program which I am using to test and troubleshoot to see if I can actually use an interrupt to watch signals in the background while other things are still happening in the main loop.

The variable "const int SE_RunningPin = 3" will be HIGH for about 8 minutes at a time. It is a signal being provided anytime an external process, which runs for 8 minutes, is active. Whenever that signal is active, I need to be monitoring the inputs "const int SE_LsaltPin = 8;" and "const int SE_PwrFltPin = 9;"

In my test code, I am just wiring up switches to toggle signals on and off, and then connect LED's to pins 12 and 13 to verify if "SE_Lsalt" and SE_PwrFlt" are being updated within the ISR.

So far, I am a bit stuck because the only avialable interrupt modes are LOW, CHANGE, RISING, FALLING. Since there isn't a HIGH mode, I thought, maybe I could put a while loop within the ISR to constantly read the SE_LsaltPin and SE_PwrFltPin while the SE_RunningPin is HIGH. In my tests, it reads it the first time, but then doesnt record any changes beyond that.

Does anyone have a different idea, or an idea on how to improve my code to meet my goals? I am testing on an UNO, but the main project will be on a MEGA 2560 R3.

Code:

const int SE_RunningPin = 3;              //connected to switches for debugging
const int SE_LsaltPin  = 8;
const int SE_PwrFltPin  = 9;

const int SE_LsaltWarnPin = 12;           //Connected to LED's for debugging
const int SE_PwrInterruptWarnPin = 13;    //connected to LED's for debugging


volatile int SE_Lsalt = LOW;              //variables to store value read off of pins 12 & 13
volatile int SE_PwrFlt = LOW;



void faultCheck() {
 //do {
   SE_Lsalt = digitalRead(SE_LsaltPin);
   SE_PwrFlt = digitalRead(SE_PwrFltPin);
 //} while (digitalRead(SE_RunningPin) == 1);

}

void setup() {
 pinMode(SE_LsaltPin, INPUT);
 pinMode(SE_PwrFltPin, INPUT);
 pinMode(SE_LsaltWarnPin, OUTPUT);
 pinMode(SE_PwrInterruptWarnPin, OUTPUT);

 attachInterrupt(digitalPinToInterrupt(SE_RunningPin), faultCheck, LOW);
}



void loop() {
 digitalWrite(SE_LsaltWarnPin, SE_Lsalt);
 digitalWrite(SE_PwrInterruptWarnPin, SE_PwrFlt);
 delay(5);


}

The interrupt modes LOW and HIGH are used very rarely. If the pin is LOW then the interrupt will be called ALL THE TIME. Your main program will only get one clock cycle to run out of every fifty.

Also if SE_RunningPin is an input, you should declare it as an input in setup(). Although all pins do default to INPUT on startup, it's good practise to always do this because it's easy to forget to do it for outputs.

Next time use code tags.

Thanks for the Reply MorganS. I didn't see in my searching about ISR's that it would deprive the main loop so much, thanks for noting that.

Do you have any suggestions for other methods I might use to reach the same goal?

What are code tags? Sorry - I am a mechanical guy. I'm dialed on the hardware side, but this aspect of it is a bit new and quite challenging.

steve141:
What are code tags? Sorry - I am a mechanical guy. I'm dialed on the hardware side, but this aspect of it is a bit new and quite challenging.

Even a mechanical guy can read the instructions.

The forum software eats some of your code unless you tell it that it's code. You can see a button that looks like </> on the full reply editor. (Not the Quick Reply.)

You can also type

[code]your code here[/code]

in the Quick Reply to get:

your code here

Sorry, corrected.

If things are happening on the scale of seconds or minutes then I don't see any need to use interrupts. Just use digitalRead() to read the value of the different pins every iteration of loop().

You only need to use interrupts to detect things that happen very frequently (hundreds of times per second); to detect very short lived events - such as a signal that is only HIGH for a few microseconds; or to detect changes when you need to know the time of the change with microsecond accuracy.

...R

The variable "const int SE_RunningPin = 3" will be HIGH for about 8 minutes at a time.

Really? How can a const variable contain HIGH sometimes, a 3 other times?

The Arduino doesn't get bored asking "Are we high yet?" 100,000 times per second. It's rather good at that. It will do that for decades without complaint so long as it still has power. You don't need to use an interrupt on a signal that happens rarely.

steve141:
The variable "const int SE_RunningPin = 3" will be HIGH for about 8 minutes at a time. It is a signal being provided anytime an external process, which runs for 8 minutes, is active. Whenever that signal is active, I need to be monitoring the inputs "const int SE_LsaltPin = 8;" and "const int SE_PwrFltPin = 9;"

unless microseconds are important, the code would be:

void loop() {
  if(digitalRead(SE_RunningPin == HIGH)) {
    if(digitalRead(SE_LsaltPin == HIGH)) {
      // do something
    }
    if(digitalRead(SE_PwrFltPin == HIGH)) {
      // do something
    }
  
  }
}

OF course, the "do something:" will be called thousands of times for as long as LsaltPin is high. At a guess, what you really want is for something to happen if the pin becomes high while LsaltPin is high.

byte SE_Lsalt_state;
byte SE_PwrFilt_state;

void loop() {
  byte SE_Lsalt_prevState =  SE_Lsalt_state;
  SE_Lsalt_state = digitalRead(SE_Lsalt_pin)

  byte SE_PwrFilt_prevState =  SE_PwrFilt state;
  SE_PwrFilt_state = digitalRead(SE_PwrFilt_pin)

  if(digitalRead(SE_RunningPin == HIGH)) {
    if(SE_Lsalt_prevState == LOW && SE_Lsalt_state == HIGH) {
      // SE_Lstat has just gone HIGH
      turn_on_the_SE_lstat_alarm();
    }

    if(SE_PwrFilt_prevState == LOW && SE_PwrFilt_state == HIGH) {
      // SE_PwrFilt has just gone HIGH
      turn_on_the_SE_PwrFilt_alarm();
    }
  }
}

You may also want to do things like turning the alarm off again, or turn it off again after 10 seconds, or turn it off again immegaitely if the running pin goes low, or any number of other things.

3 is the pin assignment.

PaulS:
Really? How can a const variable contain HIGH sometimes, a 3 other times?

So, the state of the pin who's number is stored in the variable can be HIGH for minutes at a time... That's not what you said.

PaulS:
So, the state of the pin who's number is stored in the variable can be HIGH for minutes at a time... That's not what you said.

That's what I inferred from the OP and it is what formed the basis for my Reply #6

...R

I think there is a disconnect here, maybe I am misusing "const." I was attempting to hold the pin assignment constant, but allow the value read at that pin to be assigned at each digitalread() event, but in reality I think I've done something else.

I apologize for my inferior ability. I am here to seek council and learn and understand from the wealth of knowledge that is present on this forum.

steve141:
I think there is a disconnect here, maybe I am misusing "const." I was attempting to hold the pin assignment constant,

That is the proper thing to do. The only small problem was the way you phrased this

The variable "const int SE_RunningPin = 3" will be HIGH for about 8 minutes at a time

. A more exact way (also simpler) would be to say "The external device will hold Pin 3 HIGH for about 8 minutes at a time"

...R

No need to abbreviate variable names. They don't take up space on the Arduino and it makes the sketch harder to understand.

const byte SE_RunningPin = 3;              //connected to switches for debugging

const byte SE_LsaltPin  = 8;
const byte SE_PowerFaultPin  = 9;

const byte SE_LsaltLEDPin = 12;           //Connected to LED's for debugging
const byte SE_PowerFaultLEDPin = 13;    //connected to LED's for debugging

boolean SE_Lsalt = LOW;              //variables to store value read off of pins 12 & 13
boolean SE_PowerFault = LOW;

void setup() {
  pinMode(SE_RunningPin, INPUT_PULLUP);  // Use switch to Ground
  pinMode(SE_LsaltPin, INPUT_PULLUP);  // Use switch to Ground
  pinMode(SE_PowerFaultPin, INPUT_PULLUP);  // Use switch to Ground

  pinMode(SE_LsaltLEDPin, OUTPUT);
  pinMode(SE_PowerFaultLEDPin, OUTPUT);
}

void faultCheck() {
  SE_Lsalt = digitalRead(SE_LsaltPin);
  SE_PowerFault = digitalRead(SE_PowerFaultPin);
}

void loop() {
  if (digitalRead(SE_RunningPin)) {
    faultCheck();
    digitalWrite(SE_LsaltLEDPin, SE_Lsalt);
    digitalWrite(SE_PowerFaultLEDPin, SE_PowerFault);
  } else {
    // What happens to the LEDs if the Running signal is LOW?!?
  }
}

Thanks for all the suggestions. I've abandoned the interrupt idea. I agree, that is not appropriate here. I was mixing up ideas, and got stuck on the notion I really needed it, but in fact, a simple digitalRead() will do just fine.