Event sequencer / duration start button

Hi everyone!

Here I am, Marc, an arduino newbie. Long time electronic enthusiast (doesn't mean my electronic skills are much higher than my coding ones...) and new comer to ucontroller programming.

I am currently trying to do a simple event sequencer.
I wrote a couple of lines to test and confront myself with reality :slight_smile:

And of course I did run into some problems!

So here they are :

1 : I intended to make a 3seconds button pressed condition but when I press it multiple times, it seems I block the sketch and even though the led respond (it blinks with the press of the button) I cannot "unblock" the sequence

2 : sometimes the timed action (10seconds in this case) doesn't do the 10seconds at all. It varies from 2 to 10seconds.
And it usually varies more when I press the start button multiple times (in order to try the condition).

I am a bit lost right now since I thought I had made a pretty "clear" sketch and I can't seem to see where does theses errors come from...

Thanks by advance for your help!

Marc

//  START Sequence


// Pin 13 has an LED connected on most Arduino boards.
// give it a name:
int start = 2;     //Start button
int Emerg = 3;     //Emergency stop button
int PPump = 4;     //Preheat pump Relay
int servo = 5;     //PWM output for servo
int motor = 6;     //PWM output for motor speed
int modesw = 7;    //Mode Ventilation/Start switch
int spark = 8;     //Spark output
int led = 9;        //status led
unsigned long teststart = 0;
unsigned long test = 0;
boolean startok=false;   //start condition
boolean running=false;
int sw_laststate=LOW;

unsigned long time;

// the setup routine runs once when you press reset:
void setup() {       
  Serial.begin(9600);  
  Serial.println("StartSequence");  
  // initialize the digital pin as an output.
  pinMode(start, INPUT); 
  pinMode(Emerg, INPUT);  
  pinMode(PPump, OUTPUT);
  pinMode(servo, OUTPUT);
  pinMode(motor, OUTPUT);
  pinMode(modesw, INPUT);
  pinMode(spark, OUTPUT);
  pinMode(led, OUTPUT);
}

void loop() {
  
  sw_laststate = digitalRead(start);
   if (startok==false && digitalRead(start)==true)
  {
   digitalWrite(led,HIGH);
   if (test==0)
   {
   test=millis();
   Serial.println(test,2); 
   }
   if ((millis()-test)>3000 && digitalRead(start)==true)
   {
   teststart==millis() ;
   Serial.println(teststart,2); 
   startok=true;
   test=0;
   digitalWrite(led,LOW);
   }
  }
  else{
    test=millis();
    digitalWrite(led,LOW);
}
  
  

  if (startok==true && (millis()-teststart)<10000)
  {
    running=true;
    digitalWrite(spark,HIGH);
    Serial.println(millis(),2);
  }
  else
  {
    digitalWrite(servo,HIGH);
    digitalWrite(spark,LOW);
    startok=false;
    running=false;
  }
}
int start = 2;     //Start button

Use 'const int' for pin numbers and other constants that don't change, not 'int'.

   if (startok==false && digitalRead(start)==true)

Don't compare the return value of digitalRead with true, compare it with HIGH or LOW.

   teststart==millis() ;

This compares teststart with the result of calling millis(), and throws the result away. You probably meant to use = instead of ==.

Hi DC42,

Thanks for the guidance!

Indeed the == was a mistake and I meant =

About the const int. I did my homework and understood that it makes read-only and saves some RAM & ROM space but what about the #define? Is it any different than this line?

Thanks,

Marc

"#define" is not type-safe, but "const int" is. So "const int" is better because it protects you from various mistakes that you can make when using #define. Using either will normally use less memory than plain "int".

Thanks a lot,

Redid my code with the const int.

It actually grew quite a bit! Might seem like a 1hour work to you but I never thought I could do so much in so little time. :slight_smile:

But of course I am stuck again... With a weird behaviour this time :

So I have two modes : one is starting sequence and the other is ventilation.

They both trigger different sequence of events.

Now my start sequence was working fine and then I added the ventilation sequence and a switch to be able to choose between the two.
Except that my start sequence now doesn't want to end! Well my blinking led keeps on blinking so it means it didn't reset my running variable to false.

The ventilation sequence is fine and will end at the end of the time I set.

But now here's the weird thing : my starting sequence is 35seconds total and my ventilation is 30.
If I set the starting sequence anywhere under 30seconds (for example by dividing by two all the phases' times) but if I set it over, it will not....

What's happening inside that makes it not work!?

Thanks for your help,

Marc

//  START Sequence


// Pin 13 has an LED connected on most Arduino boards.

const int start = 2;     //Start button
const int Emerg = 3;     //Emergency stop button
const int PPump = 4;     //Preheat pump Relay
const int servo = 5;     //PWM output for servo
const int motor = 6;     //PWM output for motor speed
const int modesw = 7;    //Mode Ventilation/Start switch
const int spark = 8;     //Spark output
const int led = 9;        //status led
const int switchv = 10 ;  //switch ventil/start
const int sparkf = 50;    //time between two sparks = frequency
const int t1 = 10000;    //phase 1 duration in ms
const int t2 = 14000;    //phase 2 duration in ms
const int t3 = 1500;    //phase 3 duration in ms
const int t4 = 30000;    //phase 4 duration in ms
const int t5 = 35000;    //phase 5 duration in ms
const int tv = 30;  //ventilation in s
unsigned long teststart = 0;
unsigned long test = 0;
unsigned long ledtime=0;
unsigned long sparktime=0;
boolean startok=false;   //start condition
boolean running=false;
boolean switchventil=HIGH;  //switchventil
int sw_laststate=LOW;
int ledstate=LOW;

unsigned long time;

// the setup routine runs once when you press reset:

void setup() {       
  Serial.begin(9600);  
  Serial.println("StartSequence");  
  // initialize the digital pin as an output.
  pinMode(start, INPUT); 
  pinMode(Emerg, INPUT);  
  pinMode(PPump, OUTPUT);
  pinMode(servo, OUTPUT);
  pinMode(motor, OUTPUT);
  pinMode(modesw, INPUT);
  pinMode(spark, OUTPUT);
  pinMode(led, OUTPUT);
  pinMode(switchv,INPUT);
  
  attachInterrupt(1, emergstop, RISING);
}

void loop() 
{
   if (startok==false && digitalRead(start)==HIGH)
  {
       digitalWrite(led,HIGH);
       if (test==0)
       {
       test=millis(); 
       }
       if ((millis()-test)>3000 && digitalRead(start)==HIGH)
           {
           teststart=millis() ;
           startok=true;
           test=0;
           digitalWrite(led,LOW);
           }
    }
  else{
    test=millis();
    digitalWrite(led,LOW);
       }



if (running==false) {switchventil=digitalRead(switchv);};

//DEBUT SEQUENCE


  // BLINKING LED
  if (running==true && (millis()-ledtime)<500)   
      {
      digitalWrite(led,ledstate);
      }
  else  {
        ledstate=!ledstate;
        ledtime=millis();
        }
        
        
  //BLINKING LED


                        //PHASE 1 : 0-10seconds
if (startok==true && (millis()-teststart)<t1 && switchventil==LOW)
    
    {
    running=true;
    if((millis()-sparktime)>sparkf)
      {
      sparktime=millis();
      digitalWrite(spark,HIGH);    //HIGH means coil is charging (dwell time = 0,3s)
      delay(3);
      digitalWrite(spark,LOW);     //LOW means coil -side is disconnected and sparking 
      }
    }
    
  else                //PHASE 2 : 10-14seconds
    {
                 if (startok==true && (millis()-teststart)<t2 && switchventil==LOW)
              {
                   if((millis()-sparktime)>sparkf)
                        {
                        sparktime=millis();
                        digitalWrite(spark,HIGH);    //HIGH means coil is charging (dwell time = 0,3s)
                        delay(3);
                        digitalWrite(spark,LOW);     //LOW means coil -side is disconnected and sparking 
                        }
                   analogWrite(servo,255);
                   analogWrite(motor,127);
                   digitalWrite(PPump,HIGH);
              }
              else        //PHASE 3 : 14-15seconds
              {
                         if (startok==true && (millis()-teststart)<t3 && switchventil==LOW)
                    {
                         if((millis()-sparktime)>50)
                              {
                              sparktime=millis();
                              digitalWrite(spark,HIGH);    //HIGH means coil is charging (dwell time = 0,3s)
                              delay(3);
                              digitalWrite(spark,LOW);     //LOW means coil -side is disconnected and sparking 
                              }
                         analogWrite(servo,255);
                         analogWrite(motor,255);
                         digitalWrite(PPump,HIGH);
                  }
               
                    else  //PHASE 4 : 15-30seconds
                     {         if (startok==true && (millis()-teststart)<t4 && switchventil==LOW)
                          {
                               digitalWrite(spark,LOW);
                               analogWrite(servo,255);
                               analogWrite(motor,255);
                               digitalWrite(PPump,HIGH);
                        }
                     
                        else
                        {
                              if (startok==true && (millis()-teststart)<t5 && switchventil==LOW)
                              {
                                   digitalWrite(spark,LOW);
                                   analogWrite(motor,0);
                                   analogWrite(servo,0);
                                   digitalWrite(PPump,HIGH);
                            }
                            else
                            {
                              if (switchventil==LOW && running==true && startok == true)
                              {
                                startok=false;
                                running=false;
                              }
                           }   
                            
                       }
                     } 
          }
    
    }
    
    //VENTILATION


//PHASE 1 : 0-30seconds
if (startok==true && (millis()-teststart)<(tv*1000) && switchventil==HIGH)
    
    {
    running=true;
    analogWrite(servo,255);
    analogWrite(motor,127);
    }
    
  else
        {
          if (switchventil==HIGH && running==true && startok == true)
          {
          startok=false;
          running=false;
          }
        }
              
}

      

void emergstop()
{
        startok=false;
        running=false;
        analogWrite(motor,0);
        analogWrite(servo,0);
        digitalWrite(PPump,LOW);
        digitalWrite(spark,LOW);
}

I
gave
up
on
reading
that
poorly
indented code.

There is a menu item, Auto Format, on the Tools menu. Learn to use it before posting code.

Real
Sorry
About
That

:sweat_smile:

I didn't know about the autoformat function...
I am very new to coding... :slight_smile:

//  START Sequence


// Pin 13 has an LED connected on most Arduino boards.

const int start = 2;     //Start button
const int Emerg = 3;     //Emergency stop button
const int PPump = 4;     //Preheat pump Relay
const int servo = 5;     //PWM output for servo
const int motor = 6;     //PWM output for motor speed
const int modesw = 7;    //Mode Ventilation/Start switch
const int spark = 8;     //Spark output
const int led = 9;        //status led
const int switchv = 10 ;  //switch ventil/start
const int sparkf = 50;    //time between two sparks = frequency
const int t1 = 10000;    //phase 1 duration in ms
const int t2 = 14000;    //phase 2 duration in ms
const int t3 = 1500;    //phase 3 duration in ms
const int t4 = 30000;    //phase 4 duration in ms
const int t5 = 35000;    //phase 5 duration in ms
const int tv = 30;  //ventilation in s
unsigned long teststart = 0;
unsigned long test = 0;
unsigned long ledtime=0;
unsigned long sparktime=0;
boolean startok=false;   //start condition
boolean running=false;
boolean switchventil=HIGH;  //switchventil
int sw_laststate=LOW;
int ledstate=LOW;

unsigned long time;

// the setup routine runs once when you press reset:

void setup() {       
  Serial.begin(9600);  
  Serial.println("StartSequence");  
  // initialize the digital pin as an output.
  pinMode(start, INPUT); 
  pinMode(Emerg, INPUT);  
  pinMode(PPump, OUTPUT);
  pinMode(servo, OUTPUT);
  pinMode(motor, OUTPUT);
  pinMode(modesw, INPUT);
  pinMode(spark, OUTPUT);
  pinMode(led, OUTPUT);
  pinMode(switchv,INPUT);

  attachInterrupt(1, emergstop, RISING);
}

void loop() 
{
  if (startok==false && digitalRead(start)==HIGH)
  {
    digitalWrite(led,HIGH);
    if (test==0)
    {
      test=millis(); 
    }
    if ((millis()-test)>3000 && digitalRead(start)==HIGH)
    {
      teststart=millis() ;
      startok=true;
      test=0;
      digitalWrite(led,LOW);
    }
  }
  else{
    test=millis();
    digitalWrite(led,LOW);
  }



  if (running==false) {
    switchventil=digitalRead(switchv);
  };

  //DEBUT SEQUENCE


  // BLINKING LED
  if (running==true && (millis()-ledtime)<500)   
  {
    digitalWrite(led,ledstate);
  }
  else  {
    ledstate=!ledstate;
    ledtime=millis();
  }


  //BLINKING LED


  //PHASE 1 : 0-10seconds
  if (startok==true && (millis()-teststart)<t1 && switchventil==LOW)

  {
    running=true;
    if((millis()-sparktime)>sparkf)
    {
      sparktime=millis();
      digitalWrite(spark,HIGH);    //HIGH means coil is charging (dwell time = 0,3s)
      delay(3);
      digitalWrite(spark,LOW);     //LOW means coil -side is disconnected and sparking 
    }
  }

  else                //PHASE 2 : 10-14seconds
  {
    if (startok==true && (millis()-teststart)<t2 && switchventil==LOW)
    {
      if((millis()-sparktime)>sparkf)
      {
        sparktime=millis();
        digitalWrite(spark,HIGH);    //HIGH means coil is charging (dwell time = 0,3s)
        delay(3);
        digitalWrite(spark,LOW);     //LOW means coil -side is disconnected and sparking 
      }
      analogWrite(servo,255);
      analogWrite(motor,127);
      digitalWrite(PPump,HIGH);
    }
    else        //PHASE 3 : 14-15seconds
    {
      if (startok==true && (millis()-teststart)<t3 && switchventil==LOW)
      {
        if((millis()-sparktime)>50)
        {
          sparktime=millis();
          digitalWrite(spark,HIGH);    //HIGH means coil is charging (dwell time = 0,3s)
          delay(3);
          digitalWrite(spark,LOW);     //LOW means coil -side is disconnected and sparking 
        }
        analogWrite(servo,255);
        analogWrite(motor,255);
        digitalWrite(PPump,HIGH);
      }

      else  //PHASE 4 : 15-30seconds
      {         
        if (startok==true && (millis()-teststart)<t4 && switchventil==LOW)
        {
          digitalWrite(spark,LOW);
          analogWrite(servo,255);
          analogWrite(motor,255);
          digitalWrite(PPump,HIGH);
        }

        else
        {
          if (startok==true && (millis()-teststart)<t5 && switchventil==LOW)
          {
            digitalWrite(spark,LOW);
            analogWrite(motor,0);
            analogWrite(servo,0);
            digitalWrite(PPump,HIGH);
          }
          else
          {
            if (switchventil==LOW && running==true && startok == true)
            {
              startok=false;
              running=false;
            }
          }   

        }
      } 
    }

  }

  //VENTILATION


  //PHASE 1 : 0-30seconds
  if (startok==true && (millis()-teststart)<(tv*1000) && switchventil==HIGH)

  {
    running=true;
    analogWrite(servo,255);
    analogWrite(motor,127);
  }

  else
  {
    if (switchventil==HIGH && running==true && startok == true)
    {
      startok=false;
      running=false;
    }
  }

}



void emergstop()
{
  startok=false;
  running=false;
  analogWrite(motor,0);
  analogWrite(servo,0);
  digitalWrite(PPump,LOW);
  digitalWrite(spark,LOW);
}

Ok, now I don't really understand.

On the very code I pasted in the last post, I changed the ventilation from 30seconds to 40seconds to see if the start sequence would then stop on it's own...
It appears that if I put 40seconds to ventilation time, neither stops. Not the starting sequence nor the ventilation sequence.

And of course if I set it back to 30seconds, I do have the ventilation stopping and the start sequence not stopping (as before).

:relaxed:

unsigned long time;

You are recording when an event of interest occurs. The name of the variable ought to reflect what that event is.

boolean startok=false;   //start condition
boolean running=false;
boolean switchventil=HIGH;  //switchventil
int sw_laststate=LOW;
int ledstate=LOW;

Spacesmakeyourcodemorereadable.

      teststart=millis() ;

Again, a poor choice of names for the variable. Please try to come up with a better name.

      startok=false;
      running=false;

I don't think these are great names, either.

Adding some Serial.print() statements to the code is going to be necessary. You have a lot of decision points, based on booleans that you assume to know the state of, on switch states that you assume to know the state of, and on time, that you assume to know. It is possible that one or more of your assumptions is false.

You have not, for instance, defined how the switches are wired. A floating pin would lead to all the issues you seem to be having.

I tried to clean my code up to satisfy the beauty standards :wink:

//  START Sequence


// Pin 13 has an LED connected on most Arduino boards.

const int start = 2;     //Start button
const int Emerg = 3;     //Emergency stop button
const int PPump = 4;     //Preheat pump Relay
const int servo = 5;     //PWM output for servo
const int motor = 6;     //PWM output for motor speed
const int modesw = 7;    //Mode Ventilation(LOW)/Start(HIGH) switch   PULLDOWN
const int spark = 8;     //Spark output
const int led = 9;        //status led

const int sparkf = 50;    //time between two sparks = frequency

const long int t1 = 10000;    //phase 1 duration in ms
const long int t2 = 14000;    //phase 2 duration in ms
const long int t3 = 15000;    //phase 3 duration in ms
const long int t4 = 30000;    //phase 4 duration in ms
const long int t5 = 35000;    //phase 5 duration in ms

const long int tv = 40;  //ventilation in s

unsigned long sequencestart = 0;
unsigned long test = 0;
unsigned long ledtime=0;
unsigned long sparktime=0;

boolean sequence_auth=false;   //start condition
boolean sequence_running=false;
boolean modeswpos=LOW;  //mode switch reading Ventilation=LOW ; Start=HIGH
int sw_laststate=LOW;
int ledstate=LOW;


// the setup routine runs once when you press reset:

void setup() {       


  pinMode(start, INPUT); 
  pinMode(Emerg, INPUT);  
  pinMode(PPump, OUTPUT);
  pinMode(servo, OUTPUT);
  pinMode(motor, OUTPUT);
  pinMode(modesw, INPUT);
  pinMode(spark, OUTPUT);
  pinMode(led, OUTPUT);


  attachInterrupt(1, emergstop, RISING);
}

void loop() 
{
  if (sequence_auth==false && digitalRead(start)==HIGH)
  {
    digitalWrite(led,HIGH);
    if (test==0)
    {
      test=millis(); 
    }
    if ((millis()-test)>3000 && digitalRead(start)==HIGH)
    {
      sequencestart=millis() ;
      sequence_auth=true;
      test=0;
      digitalWrite(led,LOW);
    }
  }
  else{
    test=millis();
    digitalWrite(led,LOW);
  }



  if (sequence_running==false) {
    modeswpos=digitalRead(modesw);
  };

  //DEBUT SEQUENCE


  // BLINKING LED
  if (sequence_running==true && (millis()-ledtime)<500)   
  {
    digitalWrite(led,ledstate);
  }
  else  {
    ledstate=!ledstate;
    ledtime=millis();
  }


  //BLINKING LED


  //PHASE 1 : 0-10seconds
  if (sequence_auth==true && (millis()-sequencestart)<t1 && modeswpos==HIGH)

  {
    sequence_running=true;
    if((millis()-sparktime)>sparkf)
    {
      sparktime=millis();
      digitalWrite(spark,HIGH);    //HIGH means coil is charging (dwell time = 0,3s)
      delay(3);
      digitalWrite(spark,LOW);     //LOW means coil -side is disconnected and sparking 
    }
  }

  else                //PHASE 2 : 10-14seconds
  {
    if (sequence_auth==true && (millis()-sequencestart)<t2 && modeswpos==HIGH)
    {
      if((millis()-sparktime)>sparkf)
      {
        sparktime=millis();
        digitalWrite(spark,HIGH);    //HIGH means coil is charging (dwell time = 0,3s)
        delay(3);
        digitalWrite(spark,LOW);     //LOW means coil -side is disconnected and sparking 
      }
      analogWrite(servo,255);
      analogWrite(motor,127);
      digitalWrite(PPump,HIGH);
    }
    else        //PHASE 3 : 14-15seconds
    {
      if (sequence_auth==true && (millis()-sequencestart)<t3 && modeswpos==HIGH)
      {
        if((millis()-sparktime)>50)
        {
          sparktime=millis();
          digitalWrite(spark,HIGH);    //HIGH means coil is charging (dwell time = 0,3s)
          delay(3);
          digitalWrite(spark,LOW);     //LOW means coil -side is disconnected and sparking 
        }
        analogWrite(servo,255);
        analogWrite(motor,255);
        digitalWrite(PPump,HIGH);
      }

      else  //PHASE 4 : 15-30seconds
      {         
        if (sequence_auth==true && (millis()-sequencestart)<t4 && modeswpos==HIGH)
        {
          digitalWrite(spark,LOW);
          analogWrite(servo,255);
          analogWrite(motor,255);
          digitalWrite(PPump,HIGH);
        }

        else
        {
          if (sequence_auth==true && (millis()-sequencestart)<t5 && modeswpos==HIGH)
          {
            digitalWrite(spark,LOW);
            analogWrite(motor,0);
            analogWrite(servo,0);
            digitalWrite(PPump,HIGH);
          }
          else
          {
            if (sequence_running==true && sequence_auth == true && modeswpos==HIGH)
            {
              sequence_auth=false;
              sequence_running=false;
            }
          }   

        }
      } 
    }

  }




  //VENTILATION

  //PHASE 1 : 0-30seconds
  if (sequence_auth==true && (millis()-sequencestart)<(tv*1000) && modeswpos==LOW)

  {
    sequence_running=true;
    analogWrite(servo,255);
    analogWrite(motor,127);
  }

  else
  {
    if (sequence_running==true && sequence_auth==true && modeswpos==LOW)
    {
      sequence_auth=false;
      sequence_running=false;
    }
  }

}



void emergstop()
{
  sequence_auth=false;
  sequence_running=false;
  analogWrite(motor,0);
  analogWrite(servo,0);
  digitalWrite(PPump,LOW);
  digitalWrite(spark,LOW);
}

As it turns out, the only problem was that (obviously now...) 35000 for an int is too much! Turned it to long int and everything went back to normal!

Got a hint when I figured out that it would work with 32167 but not 32169...

marc426:
What's happening inside that makes it not work!?

You're storing your durations as (signed) ints. The maximum value a signed int can hold is 32767. Assigning any value bigger that this will cause the value to be truncated.

Time values should be defined and stored as unsigned long values.

PS please use CODE tags to post code, not quote tags.

Hi Peter,

Sorry about the quote mistake.

Everything seems to be working now, I implemented a small ramp for the motor speed.
It's all going like I want it to.

BUT...

My blinking led that's made by comparing the millis() value with a ON/OFF time value and then toggling the state of the LED seems to be flickering...
It's still blinking perfectly but when on ON time I seem to perceive a small flickering which would probably be <10Hz since I can see it with the naked eye.

Any hints as to why it's flickering like that? I don't have any line that makes it LOW before being switched ON again so I don't understand why...

Marc