Interrupting a delay

Hello there.

I'm trying to interrupt a delay function. I'm getting nowhere and have tried searching the forums, but am only getting results that indicate not to use delay in and interrupt. I'm looking at the other way round.

The reason I'm trying to do this is for a MIG welder; you set a delay on how long the gas stays on for after the trigger has been released. However the operator must be able to start welding again during this delay period.

I've included all my code below, just in case I've missed something, but the function in spot-light is delay_gas()

the board is an UNO

//definitions & declarations
#define out_WS 3  //Motor speed control pin
#define out_GAS 7  //Gas relay control pin
#define out_CON 8  //Contactor relay control pin
#define out_BRK 4  //Motor brake relay control pin
#define in_WF 12  //Wire Feed button input pin
#define in_DIR 5  //Wire feed direction control input - later version of development
#define out_DIR 6  //Wire feed control output - later version of development
#define INCH_SP 64  //Inch Speed

volatile boolean trig_EN = false; //logical state/flag indicating if trigger has been pressed from interrupt
int WS_MIN = 20;  //Minimum wire speed
int WS_MAX = 255;  //Maximum wire speed
int GDEL_MIN = 10;  //Minimum gas delay time
int GDEL_MAX = 5000;  //Maximum Gas Delay time
boolean TTO = true;  //This Time Only - for things that only need to happen once during operation

//setup
void setup() 
{
  pinMode(out_WS, OUTPUT);
  pinMode(out_GAS, OUTPUT);
  pinMode(out_CON, OUTPUT);
  pinMode(out_BRK, OUTPUT);
  pinMode(in_WF, INPUT);
  pinMode(13, OUTPUT);  //LED Alive pin
  attachInterrupt(0, trig, FALLING);  //attach interupt 0 to function trig, INT0 is on physical pin 2 on Adruino
  delay(10);
}

void loop() 
{ 
  alive();  //blinks LED on pin 13 REALLY fast
  inch();  //check to see if Inch button is pressed
  while(trig_EN == true)
  {
    while(digitalRead(2) == LOW)
    {
      weld(); //start welding
    }
    digitalWrite(out_CON, LOW);  //turn off current
    delay(100);  //delay for a little while for a small amount of wire to feed out of lance
    digitalWrite(out_BRK, LOW);  //apply brake to motor
    TTO = true;  //reset This Time Only to true - we want gas delay at start of next weld again
    trig_EN = false;  //reset the trigger flag to false
    delay_gas();
    digitalWrite(out_GAS, LOW);
  }
}

void trig() //function interupt is attached to
{
  trig_EN = true;
}

void weld()  //controls welding
{ 
  digitalWrite(out_GAS, HIGH);  //turn gas on
  while(TTO == true)
  {
    delay(50);  //delay to allow gas to flow a bit to form shroud
    TTO = false;  //change TTO to false so as not to run this dealy again when passing through again
  }
  feed_wire();  //feed wire
  digitalWrite(out_CON, HIGH);  //close contactor
}

void inch()  //feeds the wire
{
  while(digitalRead(in_WF) != HIGH)
  {
    feed_wire();
  }
  digitalWrite(out_BRK, LOW);  //turn on brake
}

void feed_wire()
{
 int i = analogRead(0);  //read input of wirefeed speed
 int WF_speed = map(i, 0, 1023, WS_MIN, WS_MAX);
 digitalWrite(out_BRK, HIGH);  //Release Brake on motor
 analogWrite(out_WS, WF_speed);  //set the output speed of feed motor
}  

void delay_gas()
{
  int d = analogRead(1);
  for(int del = map(d, 0, 1023, GDEL_MIN, GDEL_MAX); del > 1; del--)  //still having issue with interupt not cutting into this function
  {
    delay(1);
  }
}
void alive()
{
 digitalWrite(13, !digitalRead(13)); //this will cause the LED to appear to stay on, but is blinking rapidly, for diag.
 //delay(100)  //if required
}

As you can see I read the analog input from a Pot, then in the if statement, I map the variable "d" as "del" against the max and min delays defined at the start. I suppose I could have done:

for(int del = map(analogRead(1), 0, 1023, GDEL_MIN, GDEL_MAX); del > 1; del--)

Anyway, I'm using delay(1); in this for loop in hope that the interrupt will cut in whilst decrementing and checking del. But obviously its not working and when I press the trigger(interrupt) with delay up to max, it doesn't start again till after the delay period.

Could I employ the old way of just performing some long winded maths to waste some time instead? and if so, how long does one subtraction take for the arduino uno?

I'm looking at the other way round.

Think about what an interrupt means. You are sitting home, on a rainy day, watching a football game. The doorbell rings (that's an interrupt). You answer the door, to find a girl scout selling cookies. You buy some, and close the door. What happens next? You go back to watching the football game. That's what happens next.

You do NOT hit the kitchen, get the ice cream out, and have a bowl of ice cream with the cookies you just bought.

But that is what you want your code to do.

The key is to read, understand, and embrace the blink without delay philosophy, and get rid of the delay()s. Without delays, you don't need interrupts.

When the trigger is released, you note the time. Periodically, you see if the trigger is off, the gas is on, and the trigger has been off long enough. If the trigger is off, the gas is on, and the trigger has been off long enough, turn the gas off.

You can't use interrupts to get out of anything an interrupt returns to to the place where you left off and that's it.

Look at blink without delay and then Finite state machines (in the playground), forget that delay() exists and until you know a great deal more that interrupts exist!

Mark

right, got it, interrupt returns to where it left off.

so in this case, back into the middle of the delay function and all I've done is just set trig_EN to true.

So really I could do this without using interrupts.

Better way would be to take millis() at time of trigger release, plus delay time taken from A1, and check for a trigger press during that period whilst keeping the gas on?

PaulS:
You do NOT hit the kitchen, get the ice cream out, and have a bowl of ice cream with the cookies you just bought.

You really don't know me! XD

plus delay time taken from A1

It's not a delay time. Stop thinking that way. It's the gas-on-after-trigger-off interval.

and check for a trigger press during that period whilst keeping the gas on?

Something like that. Some events are independent, like pressing or releasing the trigger. Some actions happen after others. Some change the behavior of others.

Turning the trigger on should turn the gas on, and set a flag indicating that the gas is on.

Releasing the trigger should set the trigger off time.

Periodically, you see if the gas is on, the trigger is off, and the time between now and the trigger off time is greater than the gas-on-after-trigger-off interval.

You really don't know me!

I'd do the same, too, but the Arduino doesn't. It doesn't do dessert - interrupt driven or not.

You are sitting home, on a rainy day, watching a football game. The doorbell rings (that's an interrupt).

...So, you put the PVR on "pause"... :stuck_out_tongue_closed_eyes:

Here's a Quick and Dirty that will get you to the next reason why you shouldn't use delays.

void delay_gas()
{
  int d = analogRead(1);
  for(int del = map(d, 0, 1023, GDEL_MIN, GDEL_MAX); del > 1; del--)  //still having issue with interupt not cutting into this function
  {
    if ( trig_EN )  break;
    delay(1);
  }
}