Switch-case loop problem?!

The following code does:

  1. wait for a movement to trigger the sensor
  2. wait 5 seconds and lift the tollbooth
  3. wait another 5 seconds and lower the tollbooth
    __*__3) go in the first case and be ready for another cycle (detects movement then do those up/down motor steps)

It's only one problem( at 3rd point) -> the cycle doesn't repeat after the 2nd detection of movement, why is that?

#include <Servo.h> 



int var = 0;



int Lstate = 2;      // pin 2 - reading the proximity sensor
int var_Lstate = 0;  

int pos_tm1 = 120;     // 127 best
int pos_tm2 = 30;    // variable to store the servo position 
Servo myservo_tm;

int flag_tm1 = 0;
int flag_tm2 = 0;
long prag_steptm1 = 0;
long prag_steptm2 = 0;
long prag_tm1 = 0;
long prag_tm2 = 0;


void setup()
{
pinMode (Lstate, INPUT);  // sets pin 2 as digital input 

 myservo_tm.attach(5);
  myservo_tm.write(120);
}

void loop()
{
  
  var_Lstate = digitalRead(Lstate);    // reads the status of the sensor
  
  
   if(flag_tm1 == 1)
  {
    if(millis() - prag_steptm1 > 55) 
    {
      prag_steptm1 = millis();
      if(pos_tm1 > 29)
      {  
        pos_tm1--;
        myservo_tm.write(pos_tm1);

      }
    }
  }
  
   if(flag_tm2 == 1)
  {
    if(millis() - prag_steptm2 > 50) 
    {
      prag_steptm2 = millis();
      if(pos_tm2 < 121)
      {  
        pos_tm2++;
        myservo_tm.write(pos_tm2);

      }
    }
  }
  
  
  switch(var)
  {
  case 0:
      if(var_Lstate == 0) 
    {
      prag_tm1 = millis();
      prag_tm2 = millis();
      var = 1;
    }
  break;
  
  
  case 1:
      if( millis() - prag_tm1 > 5000)
    {
      flag_tm1 = 1;
    }
    if( millis() - prag_tm2 > 10000)
    {
      flag_tm2 = 1;
      var = 0;
    }
  break;
  
  
  }
}

Your flags are never set back to 0.

I set the flags 0 in case 0: before IF statement and no luck, still doesn't go all over again...
I set the flags 0 even in case 1: in the 2nd IF right before "var= 0" and still doesn't go all over again..

SparksInside:
I set the flags 0 in case 0: before IF statement and no luck, still doesn't go all over again...
I set the flags 0 even in case 1: in the 2nd IF right before "var= 0" and still doesn't go all over again..

They should be in the else block of the if statement that writes to the servos.

You should also add some debug prints to check the values like the current state and the current reading.

      prag_tm1 = millis();
      prag_tm2 = millis();
 ...
      if( millis() - prag_tm1 > 5000)
    {
      flag_tm1 = 1;
    }
    if( millis() - prag_tm2 > 10000)
    {
      flag_tm2 = 1;
      var = 0;

Having two prog_tmX variables with the same value is redundant.

if(flag_tm1 == 1)
  {
    if(millis() - prag_steptm1 > 55) 
    {
      prag_steptm1 = millis();
      if(pos_tm1 > 29)
      {  
        pos_tm1--;
        myservo_tm.write(pos_tm1);
      }
      else
      flag_tm1 = 0;
    }
    
  }

Still don't work :frowning:

Still don't see any debug prints.

#include <Servo.h> 



int var = 0;



int Lstate = 2;      // pin 2 - citire
int var_Lstate = 0;  

int pos_tm1 = 120;     // 127 best
int pos_tm2 = 30;    // variable to store the servo position 
Servo myservo_tm;

int flag_tm1 = 0;
int flag_tm2 = 0;
long prag_steptm1 = 0;
long prag_steptm2 = 0;
long prag_tm1 = 0;
long prag_tm2 = 0;


void setup()
{Serial.begin(9600);
pinMode (Lstate, INPUT);  // sets pin 2 as digital input 

 myservo_tm.attach(5);
  myservo_tm.write(120);
}

void loop()
{
  
  var_Lstate = digitalRead(Lstate);    // reads the status of the sensor
  //Serial.println(flag_tm2);
  //Serial.println(flag_tm1);
  //Serial.println(var_Lstate);

   if(flag_tm1 == 1)
  {
    if(millis() - prag_steptm1 > 55) 
    {
      prag_steptm1 = millis();
      if(pos_tm1 > 29)
      {  
        pos_tm1--;
        myservo_tm.write(pos_tm1);
      }
     // else
     // flag_tm1 = 0;
    }
    
  }
  
   if(flag_tm2 == 1)
  {
    if(millis() - prag_steptm2 > 55) 
    {
      prag_steptm2 = millis();
      if(pos_tm2 < 121)
      {  
        pos_tm2++;
        myservo_tm.write(pos_tm2);
      }
      else
      flag_tm2 = 0;
    }
  }
  
  
  switch(var)
  {
  case 0:
      
      if(var_Lstate == 0) 
    {   
      prag_tm1 = millis();
      prag_tm2 = millis();
      var = 1;
    }
  break;
  
  
  case 1:
      if( millis() - prag_tm1 > 3000)
    {
      flag_tm1 = 1;
    }
    if( millis() - prag_tm2 > 10000)
    {
      flag_tm2 = 1;
      var = 0;
    }
  break;
  
  
  }
}

I've checked with serial.print....the sensor reading and the 2 flags turn by turn...and they're doing just fine.... reading is 0 only when the sensor detected movement, and flags have the value "1" only when the motor is moving....after that, they're set back to "0".

So i still dont know why the cycle isn't repeated....

You don't bother to check the state variable?

#include <Servo.h> 



int var = 0;



int Lstate = 2;      // pin 2 - citire
int var_Lstate = 0;  

int pos_tm1 = 120;     // 127 best
int pos_tm2 = 30;    // variable to store the servo position 
Servo myservo_tm;

int flag_tm1 = 0;
int flag_tm2 = 0;
long prag_steptm1 = 0;
long prag_steptm2 = 0;
long prag_tm1 = 0;
long prag_tm2 = 0;


void setup()
{Serial.begin(9600);
pinMode (Lstate, INPUT);  // sets pin 2 as digital input 

 myservo_tm.attach(5);
  myservo_tm.write(120);
}

void loop()
{
  
  var_Lstate = digitalRead(Lstate);    // reads the status of the sensor
  //Serial.println(flag_tm2);
  //Serial.println(flag_tm1);
  //Serial.println(var_Lstate);
Serial.println(var);
   if(flag_tm1 == 1)
  {
    if(millis() - prag_steptm1 > 55) 
    {
      prag_steptm1 = millis();
      if(pos_tm1 > 29)
      {  
        pos_tm1--;
        myservo_tm.write(pos_tm1);
      }
      else
      flag_tm1 = 0;
    }
    
  }
  
   if(flag_tm2 == 1)
  {
    if(millis() - prag_steptm2 > 55) 
    {
      prag_steptm2 = millis();
      if(pos_tm2 < 121)
      {  
        pos_tm2++;
        myservo_tm.write(pos_tm2);
      }
      else
      flag_tm2 = 0;
    }
  }
  
  
  switch(var)
  {
  case 0:
      
      if(var_Lstate == 0) 
    {   
      prag_tm1 = millis();
      prag_tm2 = millis();
      var = 1;
    }
  break;
  
  
  case 1:
      if( millis() - prag_tm1 > 3000)
    {
      flag_tm1 = 1;
    }
    if( millis() - prag_tm2 > 10000)
    {
      flag_tm2 = 1;
      var = 0;
    }
  break;
  
  
  }
}

Serial.println(var) - it starts in "0", after the sensor is triggered it goes to "1", it's doing what it should do with the motor, then it returns back in "0" state...then if the sensor is triggered again...it goes again in "1" but nothing happens [ the motor is not moving]..

LE: I checked and the flag is switching to "1" in the 2nd cycle[when the sensor detects movement again] but the motor doesn't move....

SparksInside:
LE: I checked and the flag is switching to "1" in the 2nd cycle[when the sensor detects movement again] but the motor doesn't move....

pos_tm1 and pos_tm2 aren't getting reset to their original values.

yeah, I saw that now too.

But I have a question:

pos = 120;


if(pos > 29)
      {  
        pos--;

After my logic this runs like this:

  • if pos > 29 (it really is 120) it decrements the position until it will be 30 because 30>29 and 29=29

But the program in this case seems to decrement the position till 29.How is that possible?

SparksInside:
But the program in this case seems to decrement the position till 29.How is that possible?

Because it checks if 30 is greater than 29. It is, so it proceeds into the if block which decrements 30 to 29.

So where in program should i re-declare the value of pos_tm1 and pos_tm2 in order not to cause any other problems?

SparksInside:
So where in program should i re-declare the value of pos_tm1 and pos_tm2 in order not to cause any other problems?

You can't re-declare the variables, you can only re-assign them their original values. Declaration and Assignment aren't the same thing. The best place would probably be in your idle or 0 state.

First, let me say; You've done a good job utilizing loop() and timers correctly. It's like fresh air not to be typing "learn BlinkWi....".

But in this case I think you've overdone it with the control variables. It needs to be simpler.

  case 1:
      if( millis() - prag_tm1 > 3000) // this keeps being true
    {
      flag_tm1 = 1;
    }
    if( millis() - prag_tm2 > 10000) // even when this is true
    {
      flag_tm2 = 1;
      var = 0;
    }
  break;

You have 1 variable for gate to go up and another for gate to go down.
And then here you have the gate-up variable being set every time after 3 seconds.

I suggest that you have twice the control variables and timers that you need.
Just use one gate movement variable with 0=no move, 1=up, 2=down.
Just use one timer. Where do they ever get set different?
Increase the number of states that var can have to 2 and break up case 1 into 2 cases.

Possibly use 1 control variable with more than 3 states to combine var and the gate control.

Possibly in a block of comments, outline the action in steps and use pseudocode as needed to make the needed steps clear. You can check your code against that.

@Arrch

#include <Servo.h> 



int var = 0;



int Lstate = 2;      // pin 2 - citire
int var_Lstate = 0;  

int pos_tm1 = 120;     // 127 best
int pos_tm2 = 30;    // variable to store the servo position 
Servo myservo_tm;

int flag_tm1 = 0;
int flag_tm2 = 0;
long prag_steptm1 = 0;
long prag_steptm2 = 0;
long prag_tm1 = 0;
long prag_tm2 = 0;


void setup()
{Serial.begin(9600);
pinMode (Lstate, INPUT);  // sets pin 2 as digital input 

 myservo_tm.attach(5);
  myservo_tm.write(120);
}

void loop()
{
  
  var_Lstate = digitalRead(Lstate);    // reads the status of the sensor
  //Serial.println(flag_tm2);
  //Serial.println(flag_tm1);
  //Serial.println(var_Lstate);
Serial.println(var);
   if(flag_tm1 == 1)
  {
    if(millis() - prag_steptm1 > 55) 
    {
      prag_steptm1 = millis();
      if(pos_tm1 > 29)
      {  
        pos_tm1--;
        myservo_tm.write(pos_tm1);
      }
      else
      flag_tm1 = 0;
    }
    
  }
  
   if(flag_tm2 == 1)
  {
    if(millis() - prag_steptm2 > 55) 
    {
      prag_steptm2 = millis();
      if(pos_tm2 < 121)
      {  
        pos_tm2++;
        myservo_tm.write(pos_tm2);
      }
      else
      flag_tm2 = 0;
    }
  }
  
  
  switch(var)
  {
  case 0:
      pos_tm1 = 120;
      pos_tm2 = 30;
      if(var_Lstate == 0) 
    {   
      
      prag_tm1 = millis();
      prag_tm2 = millis();
      var = 1;
    }
  break;
  
  
  case 1:
      if( millis() - prag_tm1 > 3000)
    {
      flag_tm1 = 1;
    }
    if( millis() - prag_tm2 > 10000)
    {
      flag_tm2 = 1;
      var = 0;
    }
  break;
  
  
  }
}

Still doesn't work properly...

SparksInside:
Still doesn't work properly...

... but you aren't going to tell us what it's doing wrong?

  var_Lstate = digitalRead(Lstate);    // reads the status of the sensor
  //Serial.println(flag_tm2);
  //Serial.println(flag_tm1);
  //Serial.println(var_Lstate);
Serial.println(var);

Read something. Print something else. I miss how the print() is useful.

[code]    if( millis() - prag_tm2 > 10000)
    {
      flag_tm2 = 1;
      var = 0;
    }

So after 10 seconds, go back to state 0 and

  case 0:
      pos_tm1 = 120;
      pos_tm2 = 30;

Reset your positions, regardless of whether or not the servos have run their course? Once you hit state 0, your increments and decrements become ineffective. You should only be resetting your values until after you are sure that they are done moving. Perhaps it would be better to do that the same time you clear their flags, or better yet, add a 3rd state that will wait until both flags are cleared before resetting the position values and returning to state 0. Paying closer attention to what happens during the states and during the transitions will also help down the road. That was why I posted the previous helper functions for changing states.

switch (state)
{
  case FIRST:
    // this happens every loop, when it is in this state
    if (some condition exists)
    {
      // set the state variable to SECOND
      // this will only occur once, during the transition from FIRST to SECOND
    }
    break;
  case SECOND:
  ...
}

You also should take some steps to remove redundant code. Obviously, you are going to be expanding on this, so having additional lines of code and variables is going to make it more difficult to debug. Hint: You don't need two prag_tmX variables and your check for flag and check for interval can be done on a single line.[/code]

It's working now, thank you very much Arrch

#include <Servo.h> 



int var = 0;



int Lstate = 2;      // pin 2 - citire
int var_Lstate = 0;  

int pos_tm1 = 120;     // 127 best
int pos_tm2 = 30;    // variable to store the servo position 
Servo myservo_tm;

int flag_tm1 = 0;
int flag_tm2 = 0;
long prag_steptm1 = 0;
long prag_steptm2 = 0;
long prag_tm1 = 0;
long prag_tm2 = 0;

long prag_pos = 0;

void setup()
{Serial.begin(9600);
pinMode (Lstate, INPUT);  // sets pin 2 as digital input 

 myservo_tm.attach(5);
  myservo_tm.write(120);
}

void loop()
{
  
  var_Lstate = digitalRead(Lstate);    // reads the status of the sensor
//  Serial.println(flag_tm2);
//  Serial.println(flag_tm1);
//  Serial.println(var_Lstate);
Serial.println(flag_tm1);
//Serial.println(pos_tm2);

   if(flag_tm1 == 1)
  {
    if(millis() - prag_steptm1 > 55) 
    {
      prag_steptm1 = millis();
      if(pos_tm1 > 29)
      {  
        pos_tm1--;
        myservo_tm.write(pos_tm1);
      }
      else     
      flag_tm1 = 0;  
      }
    }
  
  
   if(flag_tm2 == 1)
  {
    if(millis() - prag_steptm2 > 55) 
    {
      prag_steptm2 = millis();
      if(pos_tm2 < 121)
      {  
        pos_tm2++;
        myservo_tm.write(pos_tm2);
      }
      else
      flag_tm2 = 0;
    }
  }
  
  
  
  switch(var)
  {
  case 0:
      
      if(var_Lstate == 0) 
    {   
     // pos_tm1 = 120;
     // pos_tm2 = 30;
      prag_tm1 = millis();
      prag_tm2 = millis();
      var = 1;
    }
  break;
  
  
  case 1:
      if( millis() - prag_tm1 > 3000)
    {
      flag_tm1 = 1;
    }
    if( millis() - prag_tm2 > 10000)
    {
      flag_tm2 = 1;   
      prag_pos = millis(); 
      var = 2;
    }
  
  break;
  case 2:
     if(millis() - prag_pos > 10)
     {
       if(flag_tm1 == 0 && flag_tm2 == 0)
       {
         pos_tm1 = 120;
         pos_tm2 = 30;
         var = 0;
       }
     }
  break;
  }
  }

I know I used different variables for all things i wanted to do, and i know i could use the same variable for more than one thing but, the comitee of examiners don't know so well all this programming stuff and i wanted to be easy for them to track all the commands using representative variable names.
I know i could use one case for every action i want but, in this way it seems more easier to track the program (for ex: case 2 does x,y and z actions).

My entire code for the bridge is almost ready.If some1 is interested i'll post it too.
Thank you all again for your help.