Go Down

Topic: Wait in interrupt (Read 107 times) previous topic - next topic

Ranzor_07

Jan 01, 2020, 03:35 pm Last Edit: Jan 01, 2020, 03:42 pm by Ranzor_07 Reason: Forgot to add the file
I am working on a density based traffic controller using ir sensors. I added a feature to detect the presence of an emergency vehicle and give priority for that vehicle to pass. I am using a TSOP 1738 to detect the ambulance or firetruck signal when in emergency. But I'm not able to code it. I thought of using interrupt as that is better than checking the condition every now and then. But I'm not able to understand how to keep the green signal on till the time ambulance passes. Inshort how to wait inside the loop is there's any before moving on to usual circular signal pattern?.

The code is somewhat like...
1. Calling 4 functions for 4 signals in void loop
2. Declare a digital pin interrupt in void setup()
3. Whenever the interrupt is detected i want to wait with the green signal on of particular junction unless and until the ambulance has crossed the circle. Please help me.

I have attached the the code and the interrupt routine i was trying to follow

jremington

#1
Jan 01, 2020, 06:02 pm Last Edit: Jan 01, 2020, 06:10 pm by jremington
You should never wait or print in an interrupt, it defeats the entire purpose of using one, as the processor can do nothing else. Even millis() is stopped in an interrupt.

The interrupt should be as short and fast as possible, set a global flag (declared volatile) and loop() should do the waiting, without using delay(), as needed.

For inexperienced programmers, interrupts almost always cause more problems than they solve. For a signal input, just poll the pin in the loop() function using digitalRead().

Unfortunately, your code needs a major rewrite, as all the delay() calls prevent it from being responsive.

OP's code, posted properly:
Code: [Select]

#include <IRremote.h>
int signal1[] = {8, 9, 10};
int signal2[] = {3, 4, 5};
int signal3[] = {53, 51, 49};
int signal4[] = {48, 50, 52};
int start=0;
unsigned long previousMillis = 0;
const byte interruptPin = 2;
void setup() {
 for(int i=0; i<3; i++){
    pinMode(signal1[i], OUTPUT);
    pinMode(signal2[i], OUTPUT);
    pinMode(signal3[i], OUTPUT);
    pinMode(signal4[i], OUTPUT);
 }
 Serial.begin(9600);
 attachInterrupt(digitalPinToInterrupt(interruptPin), emergency, CHANGE);
}

void loop() {
  if(start==0)
  {
    start1();
    start++;
  }
   signal1Function();
   signal2Function();
   signal3Function();
   signal4Function();
}

void signal1Function()
{
  low();
  delay(1500);
  digitalWrite(signal1[0],LOW);
  digitalWrite(signal1[1],HIGH);
  delay(500);
  digitalWrite(signal1[1],LOW);
  digitalWrite(signal1[2],HIGH);
  delay(5000);
  digitalWrite(signal1[2], LOW);
  digitalWrite(signal1[1], HIGH);
  delay(500);
 
}
void signal2Function()
{
  low();
  digitalWrite(signal2[0],LOW);
  digitalWrite(signal2[1],HIGH);
  delay(500);
  digitalWrite(signal2[1],LOW);
  digitalWrite(signal2[2],HIGH);
  delay(5000);
  digitalWrite(signal2[2],LOW);
  digitalWrite(signal2[1],HIGH);
  delay(500);
}
void signal3Function()
{
  low();
  digitalWrite(signal3[0],LOW);
  digitalWrite(signal3[1],HIGH);
  delay(500);
  digitalWrite(signal3[1],LOW);
  digitalWrite(signal3[2],HIGH);
  delay(5000);
  digitalWrite(signal3[2],LOW);
  digitalWrite(signal3[1],HIGH);
  delay(500);
}
void signal4Function()
{
  low();
  digitalWrite(signal4[0],LOW);
  digitalWrite(signal4[1],HIGH);
  delay(500);
  digitalWrite(signal4[1],LOW);
  digitalWrite(signal4[2],HIGH);
  delay(5000);
  digitalWrite(signal4[2],LOW);
  digitalWrite(signal4[1],HIGH);
  delay(500);
}
void low()
{
  for(int i=0;i<3;i++)
  {
    digitalWrite(signal1[i],LOW);
    digitalWrite(signal2[i],LOW);
    digitalWrite(signal3[i],LOW);
    digitalWrite(signal4[i],LOW);
  }
  digitalWrite(signal1[0],HIGH);
  digitalWrite(signal2[0],HIGH);
  digitalWrite(signal3[0],HIGH);
  digitalWrite(signal4[0],HIGH);
}
void start1()
{
  for(int j=0;j<5;j++)
  {
    for(int i=0;i<3;i++)
  {
    digitalWrite(signal1[i],HIGH);
    digitalWrite(signal2[i],HIGH);
    digitalWrite(signal3[i],HIGH);
    digitalWrite(signal4[i],HIGH);
    delay(200);
    digitalWrite(signal1[i],LOW);
    digitalWrite(signal2[i],LOW);
    digitalWrite(signal3[i],LOW);
    digitalWrite(signal4[i],LOW);
  }
 
  }
  for(int i=0;i<3;i++)
  {
    digitalWrite(signal1[i],HIGH);
    digitalWrite(signal2[i],HIGH);
    digitalWrite(signal3[i],HIGH);
    digitalWrite(signal4[i],HIGH);
  }
  delay(1000);
 
}
void emergency()
{
  Serial.println("Emergency Service Detected");
  low();
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= 2000)
  {
    previousMillis = currentMillis;
    if(digitalRead(2)>0)
    {
      digitalWrite(signal1[0],LOW);
    digitalWrite(signal1[2],HIGH);
    }
  }
}

dougp

The code is somewhat like...
1. Calling 4 functions for 4 signals in void loop
2. Declare a digital pin interrupt in void setup()
3. Whenever the interrupt is detected i want to wait with the green signal on of particular junction unless and until the ambulance has crossed the circle. Please help me.
Suggestion:  Rethink this.

1.  Put aside the IR receiver for now.

2.  Since a traffic light goes through a repeating sequence of defined states  consider starting over using a 'state machine'.  Check out IDE -> file/examples/control/switchcase.  There are many examples and tutorials on this site and all over the web.

3.  Learn to use millis for timing.  When executing a delay(n) the processor does nothing else.  There are demos for this too in the examples sub tab.

4.  When you have a working state machine version it will be simpler to add in the emergency vehicle functionality AND the code will be responsive enough that you won't need an interrupt to do it.

Oh, and don't use Serial.print inside an interrupt routine. 

And variables declared outside the interrupt service routine and modified by same need to have the 'volatile' qualifier added.



I don't trust atoms.  They make up everything.

No private consultations undertaken!

Go Up