ISR Trigger

Hello all,

I have a badly behaved ISR and no idea why. The interrupt is attached at the beginning of a function and is supposed to trigger when pin 3 goes from low to high. The pin is reading low when the function is entered because it can only be entered if this is the case.

However, the first time through, it runs the interrupt. If I leave the switch down so the pin is low, it will not run it again, but every time the interrupt runs, it runs a second time, and I don't know why.

Any help would be appreciated.

Relevant code:

void loop ()
{
  currenttime = millis();
 if (digitalRead(safety)==LOW) //safety is on Pin 3
 {
  if (digitalRead(LED)==HIGH)
  {
    //stuff
  if (digitalRead(start)==LOW)
  {
    digitalWrite(LED,LOW);
    robot();
  }
  }
}

void robot()
{
  //set interrupt to trigger
  attachInterrupt(1,safetyISR,RISING);

  //does stuff
  
  detachInterrupt(1);
  //digitalWrite(reset,LOW);
}

void safetyISR()
{
  detachInterrupt(1);
  wdt_reset();                       //reset board
  wdt_enable(WDTO_60MS);
}

I have a badly behaved ISR and no idea why.

Why are you continually detaching and reattaching the interrupt handler?

Relevant code

I'm calling bulls**t on this. If you KNOW that this is the relevant code, then fix your problem. If you don't KNOW that this is the relevant code, post all of it.

The reason I keep attaching and detaching the ISR trigger is because I don’t want it to run in loop() but I do want it to run in robot()

As for the entire code, most of it is just telling the robot to do stuff, but since you asked…

#define start 2 //trigger to start robot
#define safety 3 //hardware interrupt for safety system
#define EM 5 //exacto knife subsystem motor
#define ES 4 //exacto knife subsystem switch
#define AM 6 //paper advance assembly motors
#define AS 7 //paper advance assembly switch
#define LAU 8 //switch that triggers when exacto system raised
#define LAM 9 //linear actuator motor
#define LAMDir 10 //directional control for linear actuator motor
#define LAD 11 //switch that triggers when exacto system lowered
#define LED 12

#include <avr/wdt.h>
//variables for blinking LED
const long LEDon = 750;
const long LEDoff = 250;
unsigned long LEDtime;
unsigned long currenttime;
//variables for robot program
byte a;
byte i;
void setup()
{
  Serial.begin(9600);
  //disable Reset Interrupt
  //digitalWrite(reset,LOW);
  //define I/O
  pinMode(start,INPUT);
  pinMode(safety,INPUT);
  pinMode(ES,INPUT);
  pinMode(EM,OUTPUT);
  pinMode(AM,OUTPUT);
  pinMode(AS,INPUT);
  pinMode(LAU,INPUT);
  pinMode(LAM,OUTPUT);
  pinMode(LAMDir,OUTPUT);
  pinMode(LAD,INPUT);
  pinMode(LED,OUTPUT);
  //preset hardware
  Serial.println("Hello");
  LAUp();
  digitalWrite(LED,HIGH);
  LEDtime = millis();
}
void loop ()
{
  currenttime = millis();
  if (digitalRead(safety)==LOW)
  {
    if (digitalRead(LED)==HIGH)
    {
      if (currenttime - LEDtime >= LEDon)
      {
        digitalWrite(LED,LOW);
        LEDtime = currenttime;
      }
    }
    if (digitalRead(LED)==LOW)
    {
      if (currenttime - LEDtime >= LEDoff)
      {
        digitalWrite(LED,HIGH);
        LEDtime = currenttime;
      }
    }
    if (digitalRead(start)==LOW)
    {
      digitalWrite(LED,LOW);
      robot();
    }
  }
}
void robot()
{
  Serial.println("Robot");
  Serial.println(digitalRead(safety));
  //set interrupt to trigger
  attachInterrupt(1,safetyISR,RISING);
  for (byte a=0;a<2;a++)
  {
    LAUp();
    Advance();
    LADown();
    Exacto();
  }
  LAUp();
  Advance();
  detachInterrupt(1);
  //digitalWrite(reset,LOW);
}
void Exacto() //goes around twice and stops
{
  Serial.println("Exacto");
  delay(3000); //adjust this to get to 30s total
  digitalWrite(EM,HIGH);
  for(byte i=0; i<2; i++)
  {
    Serial.println(i,DEC);
    while(digitalRead(ES)==HIGH)
    {
      delay(10);
    }
    delay(200);
  }
  digitalWrite(EM,LOW);
}
void LAUp() //raises linear actuator until it hits switch
{
  Serial.println("up");
  delay(2000); //adjust to get to 30s total
  digitalWrite(LAM,HIGH);
  while (digitalRead(LAU)==HIGH)
  {
  }
  digitalWrite(LAM,LOW);
}
void LADown()
{
  Serial.println("down");
  delay(2000);
  Serial.println(digitalRead(LAD));
  digitalWrite(LAMDir,HIGH);
  digitalWrite(LAM,HIGH);
  Serial.println(digitalRead(LAD));
  while (digitalRead(LAD)==HIGH)
  {
    delay(50);
  }
  digitalWrite(LAM,LOW);
  digitalWrite(LAMDir,LOW);
}
void Advance ()
{
  Serial.println("Advance");
  delay(2000);
  digitalWrite(AM,HIGH);
  for(byte i=0;i<5;i++)
  {
    Serial.println(i,DEC);
    while(digitalRead(AS)==HIGH)
    {
      delay(50);
    }
    delay(200);
  }
  digitalWrite(AM,LOW);
  Serial.println(digitalRead(LAD));
}
void safetyISR()
{
  Serial.println("safety");
  detachInterrupt(1);
  wdt_reset();
  wdt_enable(WDTO_60MS);
}

EDIT: Correct code
Moderator edit: Code reposted after applying Auto-format tool (ctrl-T) in the IDE.

The reason I keep attaching and detaching the ISR trigger is because I don't want it to run in loop() but I do want it to run in robot()

That makes little sense, you either need the ISR active all the time or you don't need an ISR at all and you can pole for the condition in the robot() function.
Anyway all the ISR seems to do is to detach an interrupt. (Well it did when I first wrote this comment) This is a bad thing to do inside an ISR.

Another Bad Idea is wasting nearly 10 milliseconds doing serial I/O in an ISR.

Mike,

My loop program blinks an LED, and during that point, I don't want the ISR to run and reset the board. When the robot is running, I want to reset it if the cover is removed, so that's why I detach the ISR.

How would you poll for the change?

AWOL,

I'm just using that right now to test the program. All the Serial.println commands will be removed in the final program; they're just they're for troubleshooting.

How would you poll for the change?

By seeing if the value you read on a particular cycle is the same as the value you read on the previous cycle.

they're just they're for troubleshooting.

They are likely to be the cause of trouble. It's like hunting for a gas leak with a flame and saying it's only for fault finding when there is no gas leak I will not have the flame.

AWOL,

Where could I put that in my code since I want it to be checking constantly during robot()?

Mike,

I tried taking that serial command out, and it still triggered when it wasn't supposed to. I also replace a possibly offending switch with a wire, so it's not a connection problem.