Pages: [1] 2   Go Down
Author Topic: Interrupting a 4 hour ordeal.  (Read 1611 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 35
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hey Guys
Im relatively new to Arduino and I got asked to build a machine that reacts on Pulses received.I am using the Arduino NANO.
Trick is when ever a pulse is received it gets locked into a piece of code roughly 4 hours until fully executed.
Now the 1 interrupt pin also serves as the pin that gets the pulse.
If the Pin gets the Pulse it switches on the long duration of code, my Problem comes when I need it to stop with whatever its doing immediately by PULSING it again from the same source onto the same Pin
that started the 4 hour code.

Is there some way that I can avoid using interrupts or what should I make the interrupt do to make the code that is busy executing prior to the interrupt to stop?

So basically if it gets a Pulse it starts but at any given time I want to be able to pulse it again and it should stop or "Break;" the code its busy with and just exit on the Same pin.
The reason Im asking is because I cant seem to use any functions inside an Interrupt with Delays in them and I have read why but now im clueless with ways to dodge this problem.

Thanks allot guys.
Ard

Logged

Offline Offline
Edison Member
*
Karma: 26
Posts: 1339
You do some programming to solve a problem, and some to solve it in a particular language. (CC2)
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Not much can be said without seeing the code.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 35
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for the reply.
Well theres not to much to say about the code since its really simple code but here it is.

Code:

const int led = 13;
const int Op1 = 8;
const int Op2 = 9;
const int Op3 = 10;
const int Op4 = 11;

const int int1 = 2; //Interrupt 0;

int lState = LOW;
int buttonState = 0;
long previousMillis = 0;
long inter = 1000;
long UniTime = 10000;
int StateCheck =0;


void setup()
  {
    // digital pins=output
    pinMode(led, OUTPUT);
    pinMode(Op1, OUTPUT);
    pinMode(Op2, OUTPUT);
    pinMode(Op3, OUTPUT);
    pinMode(Op4, OUTPUT);
    pinMode(int1, INPUT);
    //attachInterrupt(0, stop1. HIGH);
   
  }
 
  void loop()
    {
      buttonState = digitalRead(int1);
     
     
      if (buttonState == LOW)
        {
         
            StateCheck =1;
          digitalWrite(Op1, HIGH);   
          delay(UniTime);               
          digitalWrite(Op1, LOW);   
          delay(1000);               
       
          digitalWrite(Op2, HIGH);   
          delay(UniTime);               
          digitalWrite(Op2, LOW);   
          delay(1000);
       
          digitalWrite(Op3, HIGH);   
          delay(UniTime);               
          digitalWrite(Op3, LOW);   
          delay(1000);
       
          digitalWrite(Op4, HIGH);   
          delay(UniTime);               
          digitalWrite(Op4, LOW);   
          delay(1000);
          StateCheck = 0;
         
         
           
           
  }
  }

Is there some way that I can make the interrupt check values and then execute functions depending on the value?
Because I was hoping to maybe make the button itself an interrupt instead of using "if (digitalRead(xx)) etc" and take things from there.For instance when it gets an interrupt while no code is currently running it should switch to some functions BUT if the code is indeed currently active it should do something else like break out of the functions it was currently in.
The StateCheck is a remnant of my attempt to set up a system like this.
One other thing is.It would be really cool to save the function that it needs to breaks, Current stage.I know I can do that using switch statements and increments but first things first.
Logged

Offline Offline
Edison Member
*
Karma: 26
Posts: 1339
You do some programming to solve a problem, and some to solve it in a particular language. (CC2)
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

When you call delay(10000) the mcu sits there doing nothing for 10 seconds. By nothing I mean no other code is running for a whole 10 seconds.

Answer this: how much time passes between two subsequent digitalRead()s ? That's the problem.

You need to throw away all those delay() calls and switch to non-blocking, state-based code. Which is simpler than it sounds. Start with the blink without delay example.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 35
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I will most definitely check in to the "non-blocking, state-based code" but for now I need to finish this off because I only have about 2 days to do this.
So this is a little Trial and error code that I have written.

Please tell me what you think and WHY this doesn't work.

I have added these and changed the function in the interrupts name to Check().
It does seem to do the one set of Code but while that code is running and StateCheck = 1 it still doesnt seem to break out of the code when the pin is made LOW again.

Code:
void setup()
{
 attachInterrupt(0, Check, LOW);
}


 void loop()
    {
       
 
   
        unsigned long currentMillis = millis();
 
          if(currentMillis - previousMillis > interval) {
            // save the last time you blinked the LED
            previousMillis = currentMillis;   
       
            // if the LED is off turn it on and vice-versa:
            if (ledState == LOW)
              ledState = HIGH;
            else
              ledState = LOW;
       
            // set the LED with the ledState of the variable:
            digitalWrite(led, ledState);
        }
     
    }

    void Check()
{
  if (StateCheck == 0)
    {
      RUNcycle();
    }
    else if(StateCheck == 1)
     {
       BREAKcycle();
     }
 
 
}

void RUNcycle()
  {
       StateCheck = 1;
          digitalWrite(Op1, HIGH);   
          delay(UniTime);               
          digitalWrite(Op1, LOW);   
          delay(1000);               
       
          digitalWrite(Op2, HIGH);   
          delay(UniTime);               
          digitalWrite(Op2, LOW);   
          delay(1000);
       
          digitalWrite(Op3, HIGH);   
          delay(UniTime);               
          digitalWrite(Op3, LOW);   
          delay(1000);
       
          digitalWrite(Op4, HIGH);   
          delay(UniTime);               
          digitalWrite(Op4, LOW);   
          delay(1000);
          StateCheck = 0;
         
  }
 
  void BREAKcycle()
    {
   
    }

This is not the whole code its just changes. void loop() now only shines a LED to show its working and then basically waiting for an interrupt it what I want it to do.

Thanks
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 308
Posts: 26465
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You've still got delays in there.
They all need to go.
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 220
Posts: 13836
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


long previousMillis  ==> unsigned long previousMillis

as millis() returns unsigned long ...
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Offline Offline
Edison Member
*
Karma: 26
Posts: 1339
You do some programming to solve a problem, and some to solve it in a particular language. (CC2)
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It doesn't work because you still use delay()s. You can't interrupt a delay() call.

Also, the interrupt routine should be very small, perhaps just set a flag that tells the main loop that the button was pressed. You should definitely _not_ call delay() inside an ISR.
But the fact is you don't need to use interrupts here, just structure your code as a set of states that gets executed when a certain amount of time has passed.

The following code compiles but I didn't test it on real hardware:

Code:

#define ARY_LEN(a) (sizeof(a)/sizeof(a[0]))

//////////////////////////////////////////////
//          led blink section
//////////////////////////////////////////////

boolean isBlinkRunning = false;

unsigned long blink_prevMillis;
unsigned long blink_interval;
byte currPinState;

const unsigned long BLINK_LONG_DELAY = 10000;
const unsigned long BLINK_SHORT_DELAY = 1000;

struct pinState {
    byte pinNumber;
    byte pinState;
    unsigned long interval;
};

struct pinState pinStates[] = {
    {  8, HIGH, BLINK_LONG_DELAY  },
    {  8, LOW,  BLINK_SHORT_DELAY },
    {  9, HIGH, BLINK_LONG_DELAY  },
    {  9, LOW,  BLINK_SHORT_DELAY },
    // etc.
};

const byte NUM_PIN_STATES = ARY_LEN(pinStates);


// directly go to satate number 0
void resetPinState() {
    currPinState = 0;
    applyPinState(currPinState);
}


// turn off all leds
void resetPins() {
    for (int i = 0; i < NUM_PIN_STATES; i++) {
        digitalWrite(pinStates[i].pinNumber, LOW);
    }
}


void applyPinState(byte stateIndex) {
    digitalWrite(pinStates[stateIndex].pinNumber, pinStates[stateIndex].pinState);
    blink_interval = pinStates[stateIndex].interval;
}



//////////////////////////////////////////////
//          button section
//////////////////////////////////////////////

// let's suppose a pushbutton is connected to pin 4 and ground
// the button is active low (LOW when pressed)
byte btnPin = 4;
byte btnState = HIGH;
byte btnPrevState = HIGH;

unsigned long btn_prevMillis;
unsigned long btn_interval = 30;        // check the button every 30 ms


void btnPressed() {
    if (isBlinkRunning) {
        isBlinkRunning = false;
        resetPins();
        resetPinState();
    }
}


void btnReleased() {
}



//////////////////////////////////////////////
//          main
//////////////////////////////////////////////

void setup() {
    for (int i = 0; i < NUM_PIN_STATES; i++) {
        pinMode(pinStates[i].pinNumber, OUTPUT);
    }
    
    pinMode(btnPin, INPUT);
    digitalWrite(btnPin, HIGH);        // activate internal pullup

    resetPins();
    resetPinState();
}


void loop() {

    // button section
    if (millis() - btn_prevMillis >= btn_interval) {
        btnState = digitalRead(btnPin);

        if ((btnPrevState == HIGH) && (btnState == LOW)) {
            btnPressed();
        }
        else if ((btnPrevState == LOW) && (btnState == HIGH)) {
            btnReleased();
        }

        btnPrevState = btnState;
    }


    // blink section
    if (isBlinkRunning) {
        if (millis() - blink_prevMillis >= blink_interval) {
            blink_prevMillis = millis();

            currPinState++;
            if (currPinState >= NUM_PIN_STATES) {
                currPinState = 0;
            }

            applyPinState(currPinState);
        }
    }
}
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 35
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok so...

I have revised the code.Sorry for messing everyone around but this should be pretty easy to read + its allot less code and it works...for now.

Obviously you guys would know the repercussions that I will have later on with the Code.For now I cant see what can possibly go wrong accept for me not being able to pulse the interrupt with my Hands and a wire quick enough.

Code:
const int l = 13;
const int Op1 = 8;
const int Op2 = 9;
const int Op3 = 10;
const int Op4 = 11;

const int in1 = 2; //Interrupt 0;
//const int in2 = 3; //Interrupt 1;
int ledState = LOW;
int buttonState =0;
long previousMillis = 0;
long interval = 1000;
long UniTime = 10;
int StateCheck =0;


void setup()
  {
    // digital pins=output
    pinMode(l, OUTPUT);
    pinMode(Op1, OUTPUT);
    pinMode(Op2, OUTPUT);
    pinMode(Op3, OUTPUT);
    pinMode(Op4, OUTPUT);
    pinMode(in1, INPUT);
    attachInterrupt(0, Check, LOW);
    //attachInterrupt(1, startstop2, CHANGE};
  }
 
  void loop()
    {
        if (StateCheck == 1)
       {
          digitalWrite(zone1, HIGH);   
          StateCheckDelay(UniTime);               
          digitalWrite(zone1, LOW);   
          delay(1000);               
       
          digitalWrite(zone2, HIGH);   
          StateCheckDelay(UniTime);               
          digitalWrite(zone2, LOW);   
          delay(1000);
       
          digitalWrite(zone3, HIGH);   
          StateCheckDelay(UniTime);               
          digitalWrite(zone3, LOW);   
          delay(1000);
       
          digitalWrite(zone4, HIGH);   
          StateCheckDelay(UniTime);               
          digitalWrite(zone4, LOW);   
          delay(1000);
          StateCheck = 0;
       } 
}
 
   
    void Check()
{
  if (StateCheck == 0)
    {
      StateCheck = 1;
      digitalWrite(led, HIGH);
    }
    else if(StateCheck == 1)
     {
       StateCheck = 0;
       digitalWrite(led, LOW);
     }
}


 void StateCheckDelay(int x)
    {
      for (int i=0;i<x+1;i++)
      {
      if (StateCheck == 1)
        {delay(850);}
        else if(StateCheck == 0)
        {break;}
      } 
  }
 
 


Please note while typing this someone replied so will quickly read.
Thanks allot smiley
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 35
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks Tux.
Quite allot to absorb but will check it out quickly.

Please check the code that I have just pasted a while ago.Right after your reply post.

Appreciated.
Ard
Logged

Offline Offline
Edison Member
*
Karma: 26
Posts: 1339
You do some programming to solve a problem, and some to solve it in a particular language. (CC2)
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I checked your code. I'm sorry, but there's no way it can do what you want unless you delete _all_ of the delay() calls. If you delay() for 1 second, nothing else will happen during that second. An interrupt won't er... interrupt a delay() call.
Logged

Offline Offline
Edison Member
*
Karma: 26
Posts: 1339
You do some programming to solve a problem, and some to solve it in a particular language. (CC2)
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

If you're in a real hurry and need working code you can post a request in "gigs and collaborations" section. Otherwise, keep asking and learning smiley-grin
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 308
Posts: 26465
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
An interrupt won't er... interrupt a delay() call.

It will interrupt it, but it won't break out of it prematurely.
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Offline Offline
Edison Member
*
Karma: 26
Posts: 1339
You do some programming to solve a problem, and some to solve it in a particular language. (CC2)
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Of course smiley
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 35
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

So what do I do if I cant use Delays though?
Must be something that needs to keep 1 port HIGH for almost an hour.
Logged

Pages: [1] 2   Go Up
Jump to: