Arduino trafficlights

Hi, I ve got a question concerning traffic lights. I d like to know how to use attachinterrupt on my program to allow it to run correctly. Here the program so far :

//Déclaration des variable temps
unsigned long temps_init;
unsigned long temps_act;
//Affectation des numéros de Pin aux LEDs
const int FeuVert1=4;
const int FeuRouge1=8;
const int FeuOrange1=3;

const int FeuVert2=7;
const int FeuRouge2=5;
const int FeuOrange2=6;

//Affectation un pin au bouton
const int Button=2;
//Initilisation de variable qui récupère l'etat du bouton
int etatButton=0;

void setup() {
Serial.begin(9600);
//Déclaration des LEDs en sortie
pinMode(FeuVert1,OUTPUT);
pinMode(FeuRouge1,OUTPUT);
pinMode(FeuOrange1,OUTPUT);

pinMode(FeuVert2,OUTPUT);
pinMode(FeuRouge2,OUTPUT);
pinMode(FeuOrange2,OUTPUT);
//Déclaration du bouton en entrée
pinMode(Button,INPUT);

}

void loop() {
int temps_act=millis();

//Lecture de l'etat du bouton et stockage dans etatButton
etatButton=digitalRead(Button);
Serial.print("Temps : \n");
Serial.println(temps_act);// on affiche le temps
Serial.print("Temps : ");
Serial.println(etatButton);// on affiche l'état du bouton

if((etatButton==HIGH) && digitalRead(FeuRouge1)==HIGH ){
   temps_init=temps_act;
}
if((etatButton==HIGH) && digitalRead(FeuOrange1)==HIGH ){
   temps_init=temps_act;
}
if((etatButton==HIGH) && digitalRead(FeuVert1)==HIGH ){
   temps_init=temps_act-10000;
}

if (temps_act-temps_init<=4000) // 1er étape
{
digitalWrite(FeuRouge1,HIGH);
digitalWrite(FeuOrange1,LOW);
digitalWrite(FeuVert1,LOW); 
digitalWrite(FeuVert2,HIGH); 
digitalWrite(FeuRouge2,LOW); 
digitalWrite(FeuOrange2,LOW); 
}
if(((temps_act-temps_init)>4000) && ((temps_act-temps_init)<=6000)) // 2eme étape
{ 
digitalWrite(FeuVert1,LOW);
digitalWrite(FeuOrange1,LOW); 
digitalWrite(FeuRouge1,HIGH);
digitalWrite(FeuVert2,LOW);
digitalWrite(FeuRouge2,LOW);
digitalWrite(FeuOrange2,HIGH);

}
if(((temps_act-temps_init)>6000)&& ((temps_act-temps_init)<10000)){
digitalWrite(FeuRouge1,LOW);
digitalWrite(FeuOrange1,LOW);
digitalWrite(FeuVert1,HIGH); 
digitalWrite(FeuVert2,LOW); 
digitalWrite(FeuRouge2,HIGH); 
digitalWrite(FeuOrange2,LOW); 
}
if (((temps_act-temps_init)>10000) && ((temps_act-temps_init)<=12000)){
digitalWrite(FeuRouge1,LOW);
digitalWrite(FeuOrange1,HIGH);
digitalWrite(FeuVert1,LOW); 
digitalWrite(FeuVert2,LOW); 
digitalWrite(FeuRouge2,HIGH); 
digitalWrite(FeuOrange2,LOW); 
}
if ((temps_act-temps_init)>12000)
{
temps_init = temps_act;
}
}

I found a program like this on a website, here the link

Why do you think you need to use an interrupt?

Hi Amine13,

A similar question came up recently - you may find the answers you need here (including some sample code that I wrote to use interrupts).

Does that help?

In fact i want to set the attachinterrupt to toogle immediatly to redlight
After that the program resets

Many ways you could do it. One way would be to have the Interrupt Service Routine set a volatile flag that the main loop polls for. Another really crude way could be to have the ISR just turn off the light(s) directly (not recommended).

I encourage you to look at the examples I've pointed you to - download them - and modify them to do what you want; it's all part of the learning experience.

because i need to switch directly to the next state for both traffic light after pushing on it

No, that's not a very good reason.

because i need to switch directly to the next state for both traffic light after pushing on

Have you been told you must use interrupts for this assignment, or is it your own (bad) decision?

I'm at a loss to understand why some quarters appear to be so against using interrupts for handling button presses; they're eloquent, efficient, and CAN (depending on other factors) simplify & streamline core code and totally negate the need to poll inputs tens of thousands of time per hour.

Frankly, I think that attacking someone like this for wanting to use them is poor form, and a bad look.

I don't think it really buys you anything. You are kinda' limited on what you can do during an interrupt. Yeah, you can do as much as you want, but that is a bad deal for the rest of the internals, timers, serial n such.

So you end up being limited to something like setting a flag that a button was pushed. Then you need to look for the flag in the main loop()...

Might as well just look at the port anyway and leave the interrupt alone for critical timing stuff.

At least that was my feeling on it. Not that I'd beat you up for it. Well, maybe a little. Depending on how much I was beaten up for my code ideas at the time.

-jim lee

...and are so frequently misunderstood by noobs, that folks here spend ages fishing said noobs out of the holes they have dug for themselves.

Or have been dug for them by their cruel, callous instructors.

Noob gets confused and frustrated in equal measures, and is never seen again, resulting in much wasted time.

Look carefully at the wording of the original post - the implication is that the user expects a call to a simple, well-documented function will cause a sketch that is not structured for interrupts to automagically spring into life.

I'd be glad to help. Would you like me to write you a sketch and post it here?

If so then I'd just like a little more info on how you need it to behave - would really help if you could "spell it out" in terms like: "red light for 5 seconds - amber light for 1 second - green light for 10 seconds - if button pushed then amber light for one second and then red light for 5 seconds etc.

Cheers,

@amine13 your funny variable naming *) makes it very difficult to follow your code.

this is my best guess whithout understanding your variables :slight_smile:
untested:

//https://forum.arduino.cc/t/arduino-trafficlights/874392/12

//Déclaration des variable temps
unsigned long temps_init;
unsigned long temps_act;
//Affectation des numéros de Pin aux LEDs
const int FeuVert1 = 4;
const int FeuRouge1 = 8;
const int FeuOrange1 = 3;

const int FeuVert2 = 7;
const int FeuRouge2 = 5;
const int FeuOrange2 = 6;

//Affectation un pin au bouton
const int Button = 2;
//Initilisation de variable qui récupère l'etat du bouton
int etatButton = 0;

//name the states according to one traffic light
enum class State {RED, RED2, ORANGE, GREEN} state;

const uint32_t interval = 2000;



void setup() {
  Serial.begin(9600);
  //Déclaration des LEDs en sortie
  pinMode(FeuVert1, OUTPUT);
  pinMode(FeuRouge1, OUTPUT);
  pinMode(FeuOrange1, OUTPUT);

  pinMode(FeuVert2, OUTPUT);
  pinMode(FeuRouge2, OUTPUT);
  pinMode(FeuOrange2, OUTPUT);
  //Déclaration du bouton en entrée
  pinMode(Button, INPUT);

}

void loop() {
  uint32_t temps_act = millis();
  static State previousState;                           // the variable must survive the loop, therfore static
  static uint32_t previousMillis;                       // see the example "Blink Without Delay" 
  //Lecture de l'etat du bouton et stockage dans etatButton
  etatButton = digitalRead(Button);
  Serial.print("Temps : \n"); Serial.println(temps_act);// on affiche le temps

  if (etatButton == HIGH)  {                            // will Reset to RED as long as the button is pressed
    Serial.println("button press - force RED");
    state = State::RED;                                 // switch to new status 
    previousMillis = temps_act;
  }

  switch (state)
  {
    case State::RED : // 4000
      if (previousState != State::RED)                      // if we enter a new state
      {
        Serial.println("start RED");
        digitalWrite(FeuRouge1, HIGH);
        digitalWrite(FeuOrange1, LOW);
        digitalWrite(FeuVert1, LOW);
        digitalWrite(FeuVert2, HIGH);
        digitalWrite(FeuRouge2, LOW);
        digitalWrite(FeuOrange2, LOW);
        previousMillis = temps_act;                         // "start" the timer
      }
      if (temps_act - previousMillis > interval) state = State::RED2;   // if time has passed switch to next status
      break;
      
    case State::RED2 : // 4000 - 6000;
      if (previousState != State::RED2)
      {
        Serial.println("start RED2");
        digitalWrite(FeuVert1, LOW);
        digitalWrite(FeuOrange1, LOW);
        digitalWrite(FeuRouge1, HIGH);
        digitalWrite(FeuVert2, LOW);
        digitalWrite(FeuRouge2, LOW);
        digitalWrite(FeuOrange2, HIGH);
        digitalWrite(FeuOrange2, LOW);
        previousMillis = millis();
      }
      if (temps_act - previousMillis > interval) state = State::GREEN;
    break;
    
    case State::GREEN : // 6000 -10000
      if (previousState == State::GREEN) {
        Serial.println("start GREEN");
        digitalWrite(FeuRouge1, LOW);
        digitalWrite(FeuOrange1, LOW);
        digitalWrite(FeuVert1, HIGH);
        digitalWrite(FeuVert2, LOW);
        digitalWrite(FeuRouge2, HIGH);
        digitalWrite(FeuOrange2, LOW);
        digitalWrite(FeuOrange2, LOW);
        previousMillis = millis();
      }
      if (temps_act - previousMillis > interval) state = State::ORANGE;
    break;
    
    case State::ORANGE : // 10000 - 12000
      if (previousState != State::ORANGE) {
        Serial.println("start ORANGE");
        digitalWrite(FeuRouge1, LOW);
        digitalWrite(FeuOrange1, HIGH);
        digitalWrite(FeuVert1, LOW);
        digitalWrite(FeuVert2, LOW);
        digitalWrite(FeuRouge2, HIGH);
        digitalWrite(FeuOrange2, LOW);
        previousMillis = millis();
      }
      if (temps_act - previousMillis > interval) state = State::RED;
      break;
  }
  previousState = state;
}

try with your hardware. The serial messages should enable you to follow what the code is doing.
Correct it - where it is wrong.
If you have further questions - ask.

What happend to your code:
I gave each sequence of digitalWrite a state name.
Each state has an behaviour to do something "on start"
Each state has an exit condition to leave the state - and defines what should happen (= the next state).

The button just forces a new state. And I guessed it should restart the timer for RED.

the concept is called "finite state machine" and you will find tons of information in the internet. Wikipedia is a good start...

*) if you consider to get help in an international forum like this in the future, only use variable names which can be read by others.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.