millis() delay revisited

Hello all,
Have spent so long on this I cannot see the trees from the forest.
I have examined the blink without delay examples as well as Nick Gammon’s blog but cannot get the timing for the following pseudo code correct. Currently, the solenoid is not activated. The timing for the flash On occurs at end of cycle instead of 259 ms from start.The timing for the shutter On is correct at 3000 ms. However, the shutter is “activated” at end of 3000 ms instead of 80 ms.

I just want someone to check whether there are any glaring mistakes in the code.
Thanks in advance.

The code of interest starts at Case ‘A’ switch statement in the void loop().
When ‘A’ is pressed in keypad:
Start timing.
Turn on camera shutter for 3000 ms duration.
Within this duration:
Wait 80 ms after start to ensure shutter is fully open(shutter_lag).
Activate solenoid for duration of 59 ms (DropSize).
Turn off solenoid.
Delay from Start timing to turn on flash.(Interval_before_flash).
Flash stays on for 10 ms ( Flash_On_Duration)
Turn off flash.
After 3000 ms has elapsed turn off shutter.

void loop(){// open void
  if (Interrupt_fired) // call Rotary Encoder routine if ISR has triggered   
  {// open if
    menuDisplay();// Display menu options on LCD
    Interrupt_fired = false;
  }// close if
  // -------end of encoder
  char key = getKey();// this routine will be used to change all integer variables like 
  // DropSize, interval_before_FLASH , Number of drops etc
  if(key != 0) // Do nothing if no key is pressed.
  {// open first if
    switch (key)
    {// open switch key
    case '#':        // user wants to change variable displayed
      enterNewNumber();
      getNumber(0,1,rotaryCount,rCount);
      break;

    case 'A':// Accepted for ***  Start Controller *** menu item 
      lcd.clear();
      displayRunningController();// **Running**
      when_timer_started = millis();// use this as the starting point for all timing
      Shutter_timer_ON = millis ();
      while (  millis() - when_timer_started <= Shutter_Open_Interval)
      {// open while
        digitalWrite (AutoFocus, HIGH);
        digitalWrite (Shutter, HIGH);// Open the camera shutter
        Shutter_Flag = true;// shutter is open
        //Serial.println(millis());
        if(Shutter_Flag == HIGH && Solenoid_Flag == LOW && millis() - when_timer_started > shutter_lag )
        {// if
          turn_On_Solenoid();
        }// close if
        if(Shutter_Flag == HIGH && Solenoid_Flag == HIGH && millis() > Solenoid_On_duration)
          turn_OFF_Solenoid();
        if ( (millis() - (when_timer_started) >= interval_before_FLASH))
        {// open if   
          turn_On_Flash ();
          if(Shutter_Flag == HIGH && Solenoid_Flag == LOW && Flash_Flag == HIGH && millis() > Flash_On_duration) 
            turn_OFF_Flash ();
        }// close if
      }// close while 
      turn_OFF_Shutter ();// Shutter closed and end of sequence
      Run_Completed = millis();
      displayRun_Completed();// LCD display
      printTimerResults ();// Serial print out
      break; 

    }// close switch
  }// close first if
}// close void loop returns with the key pressed, or 0 if no key is pressed
//========================

Serial output of timing:

Timing start at: 8030
Shutter open at: 8030
Solenoid activated at: 11030
Solenoid stoped at : 11030

Flash ON at : 11030
Flash OFF at : 11030
Shutter closed at : 11031
Run completed at : 11031


Some of the variables used

Shutter open Interval = 3000
Drop Size = 59
Interval bf Flash = 259
Flash On interval = 10

boolean  Shutter_Flag, Solenoid_Flag,Flash_Flag = false;
unsigned long shutter_lag = 80;
unsigned long Flash_On_interval;
unsigned long Shutter_Open_Interval; //interval for the shutter to stay open  
unsigned long interval_before_FLASH ;// time before firing flash 
unsigned long DropSize;   //time  that the solenoid is open
unsigned long Shutter_timer_ON, Solenoid_timer_ON, Flash_timer_ON;// 
unsigned long when_timer_started;
unsigned long Shutter_timer_OFF;
unsigned long Solenoid_timer_OFF;
unsigned long Flash_timer_OFF;
unsigned long Solenoid_On_duration = millis() - DropSize;
unsigned long Shutter_lag_duration = millis() - when_timer_started;

Some of the functions called.

void turn_On_Shutter (){                    //This function opens the camera shutter. 
  digitalWrite (AutoFocus, HIGH);
  digitalWrite (Shutter, HIGH);
  Shutter_Flag = true;
  //remember when we toggled it
  Shutter_timer_ON = millis ();
}// end turn_On_Shutter

void turn_OFF_Shutter (){                    //This function closes the camera shutter. 
  digitalWrite (Shutter, LOW);
  digitalWrite (AutoFocus, LOW);
  Shutter_Flag = false;
  //remember when we toggled it
  Shutter_timer_OFF = millis ();
}// end turn_On_Shutter

void turn_On_Flash ()
{   
  digitalWrite(Flash,HIGH);
  Flash_Flag = true;
  Flash_timer_ON = millis();// remember when we toggled it
}// close turn_on_Flash

void turn_OFF_Flash ()
{   
  digitalWrite(Flash, LOW);
  Flash_Flag = false;
  Flash_timer_OFF = millis();//remember when we toggled it
}// end of turn_OFF_Flash 

void turn_On_Solenoid ()// create a single drop 
{
  digitalWrite (Solenoid, HIGH);
  Solenoid_Flag = true;
  Solenoid_timer_ON = millis ();
}// end of turn_On_Solenoid

void turn_OFF_Solenoid ()// create a single drop 
{
  digitalWrite (Solenoid, LOW);
  Solenoid_Flag = false;
  Solenoid_timer_OFF = millis ();
}// end of turn_On_Solenoid

I can hardly read it due too much comments. so I removed obsolete comments and added some white space to make it a more readable, also added some debug statements but as I do not have the whole code I cannot test it. SO please test these modifications and post the output

void loop()
{
  if (Interrupt_fired) // call Rotary Encoder routine if ISR has triggered   
  {
    menuDisplay();// Display menu options on LCD
    Interrupt_fired = false;
  }

  char key = getKey();    // this routine will be used to change all integer variables like DropSize, interval_before_FLASH , Number of drops etc

  if (key != 0) 
  {
    switch (key)
    {
    case '#':        // user wants to change variable displayed
      enterNewNumber();
      getNumber(0, 1, rotaryCount, rCount);
      break;

    case 'A':         // Accepted for ***  Start Controller *** menu item 
      lcd.clear();
      displayRunningController();

      when_timer_started = millis();
      Shutter_timer_ON = millis ();

      while (  millis() - when_timer_started <= Shutter_Open_Interval)
      {
        digitalWrite (AutoFocus, HIGH);
        digitalWrite (Shutter, HIGH);

        Shutter_Flag = true;   
        if (Shutter_Flag == HIGH && Solenoid_Flag == LOW && millis() - when_timer_started > shutter_lag )
        {
          Serial.println("solenoid on");
          turn_On_Solenoid();
        }

        if (Shutter_Flag == HIGH && Solenoid_Flag == HIGH && millis() > Solenoid_On_duration)
        {
          Serial.println("solenoid off");
          turn_OFF_Solenoid();
        }

        if ( (millis() - when_timer_started) >= interval_before_FLASH)
        { 
          Serial.println("flash on");
          turn_On_Flash ();
          if (Shutter_Flag == HIGH && Solenoid_Flag == LOW && Flash_Flag == HIGH && millis() > Flash_On_duration) 
          {
            Serial.println("flash off");
            turn_OFF_Flash ();
          }
        }
      }

      turn_OFF_Shutter ();

      Run_Completed = millis();
      displayRun_Completed();

      printTimerResults ();
      break; 

    } 
  } 
}

Thanks Rob. Despite all the flash on and off serial statements the flash and solenoid operate only once as they should. However, the solenoid should be activated 80 ms after the shutter is activated. Also, the flash is being activated toward the the end of the sequence as is the solenoid. The solenoid should be on for 59 ms instead of 7ms.

..... about 200 of flash on and flash off
flash on
flash off
solenoid on
solenoid off
flash on
flash off
Run Completed
Timing start at  :    21227

Shutter open at :   21227
Solenoid activated at:  24212
Solenoid stoped at   :     24219

Flash ON at          :     24224
Flash OFF at         :  24229
Shutter closed at     :   24229
Run completed at      :  24229

Cheers, Austin

Below is a bare bones sketch.
I tired to replace the keypad with a Serial.read() using the Z on the keyboard but cannot get it to work.

#include <Arduino.h>  // for type definitions

char ch;
boolean  Shutter_Flag, Solenoid_Flag,Flash_Flag = false;
//Definition of the pins.
const int pin_led_focus = 10;		// led for focus
const int pin_led_fireShutter = 11;	// led for shutter fire
const int Flash     = 23;       // the number of the Flash Trigger pin 
const int AutoFocus = 25;    // the number of the Autofocus pin
const int Shutter   = 27;      // the number of the camera shutter pin
const int Solenoid  = 29;      // the number of the Sako water Valve pin


unsigned long DropSize = 50;   //size of drop is determined by the time in milliseconds that the solenoid is open  0
unsigned long Flash_On_interval= 10; 
unsigned long shutter_lag = 80;
unsigned long Shutter_Open_Interval =70; //interval for the shutter to stay open  //rCount = 7
unsigned long interval_before_FLASH = 250 ;// time in milliseconds before firing flash (2)
unsigned long Shutter_timer_ON, Solenoid_timer_ON, Flash_timer_ON;// variables for holding timer value so far
unsigned long when_timer_started;
unsigned long Shutter_timer_OFF;
unsigned long Solenoid_timer_OFF;
unsigned long Flash_timer_OFF;
unsigned long Solenoid_On_duration = millis() - DropSize;
unsigned long Shutter_lag_duration = millis() - when_timer_started;
unsigned long Flash_On_Duration    = millis() - Flash_On_interval;
unsigned long Run_Completed;

void setup()
{ 

  pinMode(Solenoid, OUTPUT);
  pinMode(Flash, OUTPUT);
  pinMode(Shutter, OUTPUT);
  pinMode(AutoFocus, OUTPUT);
  digitalWrite (Solenoid, LOW);
  digitalWrite(AutoFocus, LOW);
  digitalWrite(Shutter, LOW);
  Serial.begin(19200);// 
}// close setup()

void loop()
{
  if (Serial.available())
 char ch = Serial.read();
 switch(ch)
 {
   case 'Z':

      when_timer_started = millis();
      Shutter_timer_ON = millis ();

      while (  millis() - when_timer_started <= Shutter_Open_Interval)
      {
        digitalWrite (AutoFocus, HIGH);
        digitalWrite (Shutter, HIGH);

        Shutter_Flag = true;   
        if (Shutter_Flag == HIGH && Solenoid_Flag == LOW && millis() - when_timer_started > shutter_lag )
        {
          Serial.println("solenoid on");
          turn_On_Solenoid();
        }

        if (Shutter_Flag == HIGH && Solenoid_Flag == HIGH && millis() > Solenoid_On_duration)
        {
          Serial.println("solenoid off");
          turn_OFF_Solenoid();
        }

        if ( (millis() - when_timer_started) >= interval_before_FLASH)
        { 
          Serial.println("flash on");
          turn_On_Flash ();
          if (Shutter_Flag == HIGH && Solenoid_Flag == LOW && Flash_Flag == HIGH && millis() > Flash_On_Duration) 
          {
            Serial.println("flash off");
            turn_OFF_Flash ();
          }
        }
      }// close while

      turn_OFF_Shutter ();
      Run_Completed = millis();
      printTimerResults ();
      break;
   }// close switch

    } // close loop



void turn_On_Shutter (){                    //This function opens the camera shutter. 
  digitalWrite (AutoFocus, HIGH);
  digitalWrite (Shutter, HIGH);
  Shutter_Flag = true;//remember when we toggled it
  Shutter_timer_ON = millis ();
}// end turn_On_Shutter

void turn_OFF_Shutter ()
{                    //This function closes the camera shutter. 
  digitalWrite (Shutter, LOW);
  digitalWrite (AutoFocus, LOW);
  Shutter_Flag = false; //remember when we toggled it
  Shutter_timer_OFF = millis ();
}// end turn_On_Shutter

void turn_On_Flash ()
{   
  digitalWrite(Flash,HIGH);
  Flash_Flag = true;
  Flash_timer_ON = millis();
}// close turn_on_Flash

void turn_OFF_Flash ()
{   
  digitalWrite(Flash, LOW);
  Flash_Flag = false;
  Flash_timer_OFF = millis();//remember when we toggled it
}// end of turn_OFF_Flash 

void turn_On_Solenoid ()// create a single drop 
{
  digitalWrite (Solenoid, HIGH);
  Solenoid_Flag = true;
  Solenoid_timer_ON = millis ();
}// end of turn_On_Solenoid

void turn_OFF_Solenoid ()// create a single drop 
{
  digitalWrite (Solenoid, LOW);
  Solenoid_Flag = false;
  Solenoid_timer_OFF = millis ();
}// end of turn_On_Solenoid

void printTimerResults ()
{
  Serial.print("Timing start at:  ");
  Serial.print("\t");
  Serial.println(when_timer_started);
  Serial.println();
  Serial.print("Shutter open at: ");
  Serial.print("\t");
  if(Shutter_Flag == HIGH)
  {
    Serial.print("Shutter: ");
    Serial.print("\t");
    Serial.println("On");
  }
  Serial.println(Shutter_timer_ON);
  Serial.print("Solenoid activated at: ");// 
  Serial.print("\t");
  Serial.println(Solenoid_timer_ON);
  Serial.print("Solenoid stoped at   : ");
  Serial.print("\t");
  Serial.println(Solenoid_timer_OFF);
  Serial.println();
  Serial.print("Flash ON at          : ");
  Serial.print("\t");
  Serial.println(Flash_timer_ON);
  Serial.print("Flash OFF at         : ");
  Serial.print("\t");
  Serial.println(Flash_timer_OFF);
  Serial.print("Shutter closed at     : ");
  Serial.print("\t");  
  Serial.println(Shutter_timer_OFF);
  Serial.print("Run completed at      : ");
  Serial.print("\t");
  Serial.println(Run_Completed);
}

Shouldn't the "switch" be part of the Serial.available condition too? (Auto format would make your intention clearer)

Shouldn’t the “switch” be part of the Serial.available condition too?

Thanks AWOL
Still cannot get the Serial.read() to work.

#include <Arduino.h>  // for type definitions

char ch;
boolean  Shutter_Flag, Solenoid_Flag,Flash_Flag = false;
//Definition of the pins.
const int pin_led_focus = 10;		// led for focus
const int pin_led_fireShutter = 11;	// led for shutter fire
const int Flash     = 23;       // the number of the Flash Trigger pin 
const int AutoFocus = 25;    // the number of the Autofocus pin
const int Shutter   = 27;      // the number of the camera shutter pin
const int Solenoid  = 29;      // the number of the Sako water Valve pin


unsigned long DropSize = 50;   //size of drop is determined by the time in milliseconds that the solenoid is open  0
unsigned long Flash_On_interval= 10; 
unsigned long shutter_lag = 80;
unsigned long Shutter_Open_Interval =70; //interval for the shutter to stay open  //rCount = 7
unsigned long interval_before_FLASH = 250 ;// time in milliseconds before firing flash (2)
unsigned long Shutter_timer_ON, Solenoid_timer_ON, Flash_timer_ON;// variables for holding timer value so far
unsigned long when_timer_started;
unsigned long Shutter_timer_OFF;
unsigned long Solenoid_timer_OFF;
unsigned long Flash_timer_OFF;
unsigned long Solenoid_On_duration = millis() - DropSize;
unsigned long Shutter_lag_duration = millis() - when_timer_started;
unsigned long Flash_On_Duration    = millis() - Flash_On_interval;
unsigned long Run_Completed;

void setup()
{ 

  pinMode(Solenoid, OUTPUT);
  pinMode(Flash, OUTPUT);
  pinMode(Shutter, OUTPUT);
  pinMode(AutoFocus, OUTPUT);
  digitalWrite (Solenoid, LOW);
  digitalWrite(AutoFocus, LOW);
  digitalWrite(Shutter, LOW);
  Serial.begin(19200);// 
  Serial.println("Enter Z");
}// close setup()

void loop()
{
  if (Serial.available())
  { 
    char ch = Serial.read();
    switch(ch)
    {
    case 'Z':
      Serial.println(ch);
      when_timer_started = millis();
      Shutter_timer_ON = millis ();

      while (  millis() - when_timer_started <= Shutter_Open_Interval)
      {
        digitalWrite (AutoFocus, HIGH);
        digitalWrite (Shutter, HIGH);

        Shutter_Flag = true;   
        if (Shutter_Flag == HIGH && Solenoid_Flag == LOW && millis() - when_timer_started > shutter_lag )
        {
          Serial.println("solenoid on");
          turn_On_Solenoid();
        }

        if (Shutter_Flag == HIGH && Solenoid_Flag == HIGH && millis() > Solenoid_On_duration)
        {
          Serial.println("solenoid off");
          turn_OFF_Solenoid();
        }

        if ( (millis() - when_timer_started) >= interval_before_FLASH)
        { 
          Serial.println("flash on");
          turn_On_Flash ();
          if (Shutter_Flag == HIGH && Solenoid_Flag == LOW && Flash_Flag == HIGH && millis() > Flash_On_Duration) 
          {
            Serial.println("flash off");
            turn_OFF_Flash ();
          }
        }
      }// close while

      turn_OFF_Shutter ();
      Run_Completed = millis();
      printTimerResults ();

      break;
    }
  }// close switch

} // close loop



void turn_On_Shutter (){                    //This function opens the camera shutter. 
  digitalWrite (AutoFocus, HIGH);
  digitalWrite (Shutter, HIGH);
  Shutter_Flag = true;//remember when we toggled it
  Shutter_timer_ON = millis ();
}// end turn_On_Shutter

void turn_OFF_Shutter ()
{                    //This function closes the camera shutter. 
  digitalWrite (Shutter, LOW);
  digitalWrite (AutoFocus, LOW);
  Shutter_Flag = false; //remember when we toggled it
  Shutter_timer_OFF = millis ();
}// end turn_On_Shutter

void turn_On_Flash ()
{   
  digitalWrite(Flash,HIGH);
  Flash_Flag = true;
  Flash_timer_ON = millis();
}// close turn_on_Flash

void turn_OFF_Flash ()
{   
  digitalWrite(Flash, LOW);
  Flash_Flag = false;
  Flash_timer_OFF = millis();//remember when we toggled it
}// end of turn_OFF_Flash 

void turn_On_Solenoid ()// create a single drop 
{
  digitalWrite (Solenoid, HIGH);
  Solenoid_Flag = true;
  Solenoid_timer_ON = millis ();
}// end of turn_On_Solenoid

void turn_OFF_Solenoid ()// create a single drop 
{
  digitalWrite (Solenoid, LOW);
  Solenoid_Flag = false;
  Solenoid_timer_OFF = millis ();
}// end of turn_On_Solenoid

void printTimerResults ()
{
  Serial.print("Timing start at:  ");
  Serial.print("\t");
  Serial.println(when_timer_started);
  Serial.println();
  Serial.print("Shutter open at: ");
  Serial.print("\t");
  if(Shutter_Flag == HIGH)
  {
    Serial.print("Shutter: ");
    Serial.print("\t");
    Serial.println("On");
  }
  Serial.println(Shutter_timer_ON);
  Serial.print("Solenoid activated at: ");// 
  Serial.print("\t");
  Serial.println(Solenoid_timer_ON);
  Serial.print("Solenoid stoped at   : ");
  Serial.print("\t");
  Serial.println(Solenoid_timer_OFF);
  Serial.println();
  Serial.print("Flash ON at          : ");
  Serial.print("\t");
  Serial.println(Flash_timer_ON);
  Serial.print("Flash OFF at         : ");
  Serial.print("\t");
  Serial.println(Flash_timer_OFF);
  Serial.print("Shutter closed at     : ");
  Serial.print("\t");  
  Serial.println(Shutter_timer_OFF);
  Serial.print("Run completed at      : ");
  Serial.print("\t");
  Serial.println(Run_Completed);
}