Fotografía impacto de gotas

Objetivo del sketch
Se pretende fotografiar el impacto de una gota en su caída con el rebote en el agua de la anterior.
Para ello se dispone de una válvula eléctrica, que controla el tamaño de las gotas y su espaciado
El flash debe coincidir con el momento del impacto de las gotas
La cámara se abre al principio del proceso y se cierra al final

Descripción del hardware
Mediante las salidas de Arduino 1 R3 y través de transistores TIP126 se activan:
salida1 = la cámara en modo bulb
salida2 = una válvula eléctrica que deja caer las gotas de agua
salida3 = dispara el flash

Secuencia de acción
Al tiempo Cam_in dispara la cámara.
Al tiempo V1 se abre la válvula por el tiempo TG
Se esperan dG2 milisegundos a activar la válvula por segunda vez
Se esperan dF milisegundos para disparar el flash, está activado durante Flash_t
Se esperan dCam milisegundos para cerrar la cámara en Cam_t (= Cam_in + V1 + TG*2 + dG + dF + Flash_t + dCam)

Tipos de variables
Variables fijas
Cam_in, dispara la cámara
V1, abre la valvula por primera vez
Flash_t, es el tiempo que está activado el flash
dCam, tiempo de espera para cerrar la cámara

Variables ajustables con el encoder rotativo
TG, es el tiempo que está abierta la válvula y asi regular su tamaño
dG2, retraso para soltar la segunda gota
dF, retraso para disparar el flash

Variables calculadas
V2, = V1 + TG + dG2, tiempo en el que se abre la válvula por segunda vez
Flash_in = V2 + TG + dF, tiempo en el que se dispara el flash
Cam_t = V1 + TG*2 + dG2 + dF + Flash_t + dCam, tiempo en el que se cierra la cámara

Problema a solucionar

Con algunas combinaciones de TG, dG2 y dF no activa el flash, se salta el buche de disparo.

Me gustaría quitar la doble pulsación para el disparo. He probado con ezButton, pero no lo he conseguido, aunque si me funciona el tutorial.

Incluyo el sketch
/*
FUENTES:
Iniciar secuencia con varios temporizadores - #3 by system
Cacteres del display LCD: Arduino pantallas LCD caracteres especiales. Eñe, acentos. español.
https://www.instructables.com/Casos-Con-Switch-Case/
Salida a Excel: https://www.youtube.com/watch?v=b1D_MJvfXIg
Comunicación puerto serie: Comunicación de Arduino con puerto serie

Conexiones display LCD 20 x 4
. Banco a GND
. Verde a VCC
. Gris a SDA
. Violeta a SCL

. En el display se indican con ":" las variables modificables con el encoder
. con "=" las variales fijas en el sketch

Solo tres variables modificables: TG, dG2 y dF
*/

byte salida1 = 4; // asigna el pin 4 para el salida1 = Cámara
byte salida2 = 5; // asigna el pin 5 para el salida3 = Válvula
byte salida3 = 6; // asigna el pin 6 para el salida2 = Flash
byte pulsador = 10;
byte NuevoEstado = HIGH;
byte ViejoEstado = HIGH; // Recuerdo estado en 1 porque es pulsador Pull-up
bool inicio = false;
byte disparo = LOW;

unsigned long T0;
unsigned long Cam_in = 25; // Inicio Cámara
unsigned long Cam_t = 1500; // Timpo de exposición se calcula como la suma de Cam_in + V1 + TG2 + dG + dF + Flash_t + dCam
unsigned long TG = 150; // Tamaño gotas
unsigned long dG2 = 50; // Tiempo de separación entre gotas
unsigned long V1 = 110; // Apertura Valvula 1
unsigned long V2 = V1 + TG + dG2; // Apertura Valvula 2
unsigned long dF = 30; // Tiempo de espera del flash
unsigned long Flash_in = 50; // Inicio Flash se calcula como la suma de V1 + TG
2 + dG
unsigned long Flash_t = 80; // Duración flash
unsigned long dCam = 200; // Tiempo de espera para cerrar el obturdor
int N_img; // #### Poner el número a mano al principio ####

#include <LiquidCrystal_I2C.h> // Incluimos la libreria del LCD
#include <Encoder.h>
#include <Bounce2.h> // Instalada Bounce2.5 para encoder

LiquidCrystal_I2C lcd(0x27, 20, 4); // I2C address 0x27, 20 column and 4 rows

#define ENCODER_SW 9 // Cable Verde ### para encoder
#define ENCODER_CLK 2 // Cable Naranja ### para encoder
#define ENCODER_DT 3 // Cable Amarillo Azul a (+) y marrón a GND ### para encoder

#define CANTIDAD_DE_VAIRABLES 3

#define minTG 50 // ### para encoder
#define maxTG 500 // ### para encoder
#define mindG2 25 // ### para encoder
#define maxdG2 400 // ### para encoder
#define mindF 25 // ### para encoder
#define maxdF 280 // ### para encoder
#define DEBUG(a) Serial.println(a);

Encoder myEnc(ENCODER_CLK, ENCODER_DT); // ### para encoder
Bounce pulsadorEncoder; // ### para encoder

int variableActiva = 0; // ### para encoder

void setup(){
pinMode (salida1, OUTPUT); // declara el pin4 como salida
pinMode (salida2, OUTPUT); // declara el pin5 como salida
pinMode (salida3, OUTPUT); // declara el pin6 como salida
pinMode (pulsador, INPUT); // declaro pulsador en pin9 como entrada
pinMode(7, INPUT_PULLUP); // Válvula manual
T0= millis();

lcd.init(); // initialize the lcd
lcd.backlight();

pulsadorEncoder.attach(ENCODER_SW, INPUT_PULLUP); // para encoder
pulsadorEncoder.interval(10); // para encoder
Serial.begin(9600); // para encoder y puerto serie
}

void loop(){
Cam_t = V1 + TG*2 + dG2 + dF + Flash_t + dCam;
V2 = V1 + TG + dG2;
Flash_in = V2 + TG + dF;

lcd.setCursor(2,0); // Línea 0 (Nº caracter, Nº Línea)
lcd.print("TG :");
lcd.setCursor(6,0);
lcd.print(TG);
if (TG < 100){
lcd.setCursor(8,0);
lcd.print(" ");
}

lcd.setCursor(12,0);
lcd.print("Ct=");
lcd.setCursor(16,0);
lcd.print(Cam_t);
if (Cam_t < 1000){
lcd.setCursor(19,0);
lcd.print(" ");
}

lcd.setCursor(2,1); // Línea 1 / 1
lcd.print("dG2:");
lcd.setCursor(6,1);
lcd.print(dG2);
if (dG2 < 100){
lcd.setCursor(8,1);
lcd.print(" ");
}

lcd.setCursor(12,1); // Línea 1 / 2
lcd.print("V1=");
lcd.setCursor(16,1);
lcd.print(V1);

lcd.setCursor(2,2); // Línea 2
lcd.print("dF :");
lcd.setCursor(6,2);
lcd.print(dF);
if (dF < 100){
lcd.setCursor(8,2);
lcd.print(" ");
}

lcd.setCursor(12,2);
lcd.print("V2=");
lcd.setCursor(16,2);
lcd.print(V2);
if (V2 < 1000){
lcd.setCursor(19,2);
lcd.print(" ");
}

lcd.setCursor(2,3); // Línea 3
lcd.print("Fin=");
lcd.setCursor(6,3);
lcd.print(Flash_in);
if (Flash_in < 1000){
lcd.setCursor(9,3);
lcd.print(" "); // Imprime espacio
}
lcd.setCursor(12,3);
lcd.print("N =");
lcd.setCursor(16,3);
lcd.print(N_img);

// ### para encoder
pulsadorEncoder.update();
if (pulsadorEncoder.fallingEdge()) {
variableActiva = (variableActiva + 1) % CANTIDAD_DE_VAIRABLES;
switch (variableActiva) {
case 0:
lcd.setCursor(1,2);// (Nº caracter, Nº Línea)
lcd.write(" "); // Imprime espacio, borra de dF
lcd.setCursor(1,0);
lcd.write(126); // Imprime flecha derecha TG

            break;
        case 1:                
            lcd.setCursor(1,0);
            lcd.write(" ");         // Imprime espacio, borra flecha de TG
            lcd.setCursor(1,1);
            lcd.write(126);         // Imprime flecha de dD2
            break;            
        case 2:
            lcd.setCursor(1,1);
            lcd.write(" ");         // Imprime espacio, borra flecha de dG2
            lcd.setCursor(1,2);
            lcd.write(126);         // Imprime flecha de dF 
            break;           
     
  }
}
long cambio = myEnc.readAndReset();     //    #####  Cambio de valores con encoder  #####
if (cambio) {
    switch (variableActiva) {                                        
        case 0:
            TG += cambio;
            if (TG < minTG) {
                TG = minTG;
            }
            if (TG > maxTG) {
                TG = maxTG;
            }
            break;
        case 1:
            dG2 += cambio;
            if (dG2 < mindG2) {
                dG2 = mindG2;
            }
            if (dG2 > maxdG2) {
                dG2 = maxdG2;
            }
             break;      
         case 2:
            dF += cambio;
            if (dF < mindF) {
                dF = mindF;
            }
            if (dF > maxdF) {
                dF = maxdF;
            }
            break;                   
  }
}

// ### FINAL encoder ###

// #### Secuencia de disparo ####

NuevoEstado = digitalRead(pulsador); // cambio el estado del pulsador?
if (NuevoEstado != ViejoEstado) { // pulsador debe estar con un borne a gnd y el otro a pin 9 y una r de 10k cuyo
ViejoEstado = NuevoEstado;
delay(25); // 25 mseg para asegurar rebotes (Antes era 50)

if (NuevoEstado == LOW) {         // pulsador esta cerrado cuando esta en 0
 disparo = !disparo;
  if (disparo)
  inicio = true;
}

}
if (disparo) {
if (inicio) { // otro borne esta conectado a 5V
T0 = millis();
inicio = false;

Serial.print("N img: "); // ### Imprime variables en Excel ###
Serial.print(",");
Serial.print(N_img++);
Serial.print(",");
Serial.print(",");
Serial.print("TG: ");
Serial.print(",");
Serial.print(TG);
Serial.print(",");
Serial.print("dG2: ");
Serial.print(",");
Serial.print(dG2);
Serial.print(",");
Serial.print("dF: ");
Serial.print(",");
Serial.print(dF);
Serial.println();
}

if ( millis()-T0 >= Cam_in && millis()-T0 < Cam_t) { // Activa salida 1 *** Disparo cámara ***
digitalWrite(salida1,HIGH);
} else
if (millis()-T0 >= Cam_t){
digitalWrite(salida1,LOW); // Desactiva salida 1
}

if (millis()-T0 >= V1 && millis()-T0 < V1 + TG){
digitalWrite(salida2,HIGH); // Activa salida 2 *** Primera gota ***
} else
if (millis()-T0 >= V1 + TG){
digitalWrite(salida2,LOW); // Desactiva salida 2
}

if(millis()-T0 >= V2 && millis()-T0 < V2 + TG){
digitalWrite(salida2,HIGH); // Activa salida 2 *** Segunda gota ***
} else
if (millis()-T0 >= V2 + TG){
digitalWrite(salida2,LOW); // Desactiva salida 2
}

if(millis()-T0 >= Flash_in && millis()-T0 < Flash_in + Flash_t){ // *** Disparo flash ***
digitalWrite(salida3,HIGH); // Activa salida 3
} else
if (millis()-T0 > Flash_in + Flash_t){
digitalWrite(salida3,LOW); // Desactiva salida 3
}
}
}

escribe o pega el código aquí

Moderador
Como he visto tu segundo mensaje y se trata de un doble posteo cierro este y seguimos en el que dejo a continuación

Nunca repitas el mismo tema.
insiste, y ten paciencia.
siempre postea usando etiquetas para códigos/errores.
Lee las normas del foro por favor.