Fotografía impacto gotas 2

He subido estos comentarios y el sketch hace uno días, pero al no recibir ningún comentario he supuesto que algo no había hecho bien, por eso vuelvo a subirlo. He añadido una tabla de datos

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 una tabla donde se ve que algunas combinaciones no activan la salida 3 (cuando NO aparece Fl=ON), que es la del flash. Agradecería que me ayuden a solucionar ese problema

|Columna 1 | Columna 2 | Columna 3 | Columna 4 | E | F | G | H | I | J | K|

|--- | --- | --- | --- | --- | --- | --- | --- | --- | --- | ---|

|N img | TG | dG2 | V2 | V2_off | dF | Flash_in | Cam_t | | | |

|1 | 150 | 50 | 310 | 460 | 30 | 490 | 770 | | | |
|2 | 154 | 50 | 314 | 468 | 30 | 498 | 778 | | | |
|3 | 158 | 50 | 318 | 476 | 30 | 506 | 786 | Fl=ON | | |
|4 | 162 | 50 | 322 | 484 | 30 | 514 | 794 | Fl=ON | | |
|5 | 166 | 50 | 326 | 492 | 30 | 522 | 802 | Fl=ON | | |
|6 | 170 | 50 | 330 | 500 | 30 | 530 | 810 | Fl=ON | | |
|7 | 174 | 50 | 334 | 508 | 30 | 538 | 818 | Fl=ON | | |
|8 | 178 | 50 | 338 | 516 | 30 | 546 | 826 | Fl=ON | | |
|9 | 182 | 50 | 342 | 524 | 30 | 554 | 834 | Fl=ON | | |
|10 | 186 | 50 | 346 | 532 | 30 | 562 | 842 | Fl=ON | | |
|11 | 190 | 50 | 350 | 540 | 30 | 570 | 850 | Fl=ON | | |
|12 | 194 | 50 | 354 | 548 | 30 | 578 | 858 | Fl=ON | | |
|13 | 198 | 50 | 358 | 556 | 30 | 586 | 866 | Fl=ON | | |
|14 | 202 | 50 | 362 | 564 | 30 | 594 | 874 | | | |
|15 | 206 | 50 | 366 | 572 | 30 | 602 | 882 | | | |
|16 | 210 | 50 | 370 | 580 | 30 | 610 | 890 | | | |
|17 | 214 | 50 | 374 | 588 | 30 | 618 | 898 | | | |
|18 | 218 | 50 | 378 | 596 | 30 | 626 | 906 | Fl=ON | | |
|19 | 222 | 50 | 382 | 604 | 30 | 634 | 914 | Fl=ON | | |
|20 | 226 | 50 | 386 | 612 | 30 | 642 | 922 | Fl=ON | | |
|21 | 230 | 50 | 390 | 620 | 30 | 650 | 930 | Fl=ON | | |
|22 | 234 | 50 | 394 | 628 | 30 | 658 | 938 | Fl=ON | | |
|23 | 238 | 50 | 398 | 636 | 30 | 666 | 946 | Fl=ON | | |
|24 | 242 | 50 | 402 | 644 | 30 | 674 | 954 | Fl=ON | | |
|25 | 246 | 50 | 406 | 652 | 30 | 682 | 962 | Fl=ON | | |

/* 
FUENTES:
  https://forum.arduino.cc/t/iniciar-secuencia-con-varios-temporizadores/251858/3
  Cacteres del display LCD: http://kio4.com/arduino/31pantallaA_LCD.htm
  https://www.instructables.com/Casos-Con-Switch-Case/
  Salida a Excel: https://www.youtube.com/watch?v=b1D_MJvfXIg 
  Comunicación puerto serie: https://www.luisllamas.es/arduino-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 + TG*2 + 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 = 1;                      //                                            #### 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

  Serial.println();  
   Serial.print("N img:");    
   Serial.print("   TG:");
   Serial.print("   dG2:");
   Serial.print("   V2:");
   Serial.print("   V2_off:");
   Serial.print("   dF:");
   Serial.print("  Flash_in:");
   Serial.print("  Cam_t:");
   }

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;  
                            
  /*//                                       ### Imprime variables en Excel ###
   Serial.println();  
   Serial.print("N img: ");  
   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(" V2: ");
   Serial.print(",");
   Serial.print(V2);
   Serial.print(",");
   Serial.print("dF: ");
   Serial.print(",");
   Serial.print(dF);
*/
   //                                   Impresión puerto serie
   Serial.println();  
   //Serial.print("N img:");   
   Serial.print("-- "); 
   Serial.print(N_img++);
   //Serial.print("  TG:");
   Serial.print(" --  ");
   Serial.print(TG);
   //Serial.print("  dG2:");
   Serial.print(" -- ");
   Serial.print(dG2);
   //Serial.print("  V2:");
   Serial.print(" -- ");
   Serial.print(V2);
   //Serial.print("  V2_off:");
   Serial.print(" -- ");
   Serial.print( V2 + TG);
   //Serial.print("  dF:");
   Serial.print(" --   ");
   Serial.print(dF);
   //Serial.print(" Flash_in:");
   Serial.print(" -- ");
   Serial.print(Flash_in);
   //Serial.print("  Cam_t:");
   Serial.print("  --  ");
   Serial.print(Cam_t);
     
  }  
  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
      Serial.print("  --  Fl=ON");
    } else 
   if (millis()-T0 > Flash_in + Flash_t){
       digitalWrite(salida3,LOW);                         // Desactiva salida 3          
    }
   }
  } 
 
escribe o pega el código aquí

:warning:

He trasladado su tema de una categoría de idioma inglés del foro a la categoría International > Español .

En adelante por favor usar la categoría apropiada a la lengua en que queráis publicar. Esto es importante para el uso responsable del foro, y esta explicado aquí la guía "How to get the best out of this forum".
Este guía contiene mucha información útil. Por favor leer.

De antemano, muchas gracias por cooperar.

Muchas gracias, no me había dado cuenta del error.

Intenta poniendo esta instrucción después de la impresión serie (antes del if que controla el disparo de la cámara) y aumentando la velocidad de comunicación serial de 9600 a 115200 (no olvides hacer también el cambio en el monitor del IDE).


He hecho una sencilla reorganización de código para poder entenderlo mejor. Sin cambios funcionales, salvo dos correcciones menores. No incluye el cambio que te he sugerido antes.



void loop() {
  actualizarVariables();
  actualizarLCD();
  procesarEncoder();
  procesarDisparo();
}

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

void actualizarLCD() {
  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);
}

void procesarEncoder() {
  //                                        ### para encoder
  pulsadorEncoder.update();
  if (pulsadorEncoder.fell()) { //fallingEdge es obsoleta
    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 (usar ' en lugar de ")
        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 = limitar(TG + cambio, minTG, maxTG);
        break;
      case 1:
        dG2 = limitar(dG2 + cambio, mindG2, maxdG2);
        break;
      case 2:
        dF = limitar(dF + cambio, mindF, maxdF);
        break;
    }
  }
}
//                                             ### FINAL encoder ###

//                                         #### Secuencia de disparo ####
void procesarDisparo() {
  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(); // <<--- esto debería ir después de impresionPuertoSerie();
      inicio = false;
      //    impresionExcel();
      impresionPuertoSerie();
    }
    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
      Serial.print("  --  Fl=ON");
    } else if (millis() - T0 > Flash_in + Flash_t) {
      digitalWrite(salida3, LOW);                        // Desactiva salida 3
    }
  }
}

void impresionPuertoSerie() {
  //                                   Impresión puerto serie
  Serial.println();
  //Serial.print("N img:");
  Serial.print("-- ");
  Serial.print(N_img++);
  //Serial.print("  TG:");
  Serial.print(" --  ");
  Serial.print(TG);
  //Serial.print("  dG2:");
  Serial.print(" -- ");
  Serial.print(dG2);
  //Serial.print("  V2:");
  Serial.print(" -- ");
  Serial.print(V2);
  //Serial.print("  V2_off:");
  Serial.print(" -- ");
  Serial.print( V2 + TG);
  //Serial.print("  dF:");
  Serial.print(" --   ");
  Serial.print(dF);
  //Serial.print(" Flash_in:");
  Serial.print(" -- ");
  Serial.print(Flash_in);
  //Serial.print("  Cam_t:");
  Serial.print("  --  ");
  Serial.print(Cam_t);

}
void impresionExcel() {
  //                                       ### Imprime variables en Excel ###
  Serial.println();
  Serial.print("N img: ");
  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(" V2: ");
  Serial.print(",");
  Serial.print(V2);
  Serial.print(",");
  Serial.print("dF: ");
  Serial.print(",");
  Serial.print(dF);
}

int limitar( int valor, int minimo, int maximo) {
  if (valor < minimo)
    valor = minimo;
  else if (valor > maximo)
    valor = maximo;
  return valor;
//  return (min(max(valor, minimo), maximo); // forma directa
}

Muchas gracias por sus interesantes comentarios.
He probado con varios valores de velocidad de comunicación del puerto serie.
También he adaptado el sketch según sus sugerencias.
Pero desafortunadamente ninguno de los cambios ha producido cambios en el comportamiento de la salida 3. La tabla de resultados con el sketch rehecho y varias velocidades es la misma en todos los casos.
¿Alguna otra sugerencia?

Estoy intentando ver lo mismo en algo simulado y se muestra bastante bien.
Dime que te parece.
Vi que hay un error con tus sistema de mostrar la flecha. Yo lo corregí.
Tmb he simplificado el código.

Muchas gracias Surbyte.
Muy interesante el simulador, no lo conocía.
Sus correcciones han mejorado considerablemente la respuesta del sketch, ahora se producen muchos menos fallos en la salida 3.
Gracias

Estimado Surbyte, analizando más detenidamente el funcionamiento del sketch, he visto que en el display LCD algunas variables no borran el último dígito cuando sus valores pasan de cuatro cifras y tres. Así, aunque el valor sea de tres dígitos, permanece la última cifra de cuando tenía cuatro. Esto pasa para Cam_t (Ct) y V2. No obstante Flash_in (Fin) lo hace perfectamente.
Muchas gracias

En el código de @Surbyte cambia todas las ocurrencias de %3ld y %2ld por %4ld en las líneas que imprimen en la lcd.
De ese modo los números quedan alineados a la derecha y con 4 dígitos de longitud, rellenando con espacios delante si hace falta.

Muchas gracias MaximoEsfuerzo por su consejo sobre los espacios en el LCD, ahora funciona perfectamene.
Lo que sigo sin entender es por qué ciertas combinaciones de valores de las variables no producen la activación del flash (salida3). Si el condicional vale para la mayoría de los valores, como es que para otros no.
Envío otra tabla de datos.

Columna 1 Columna 2 Columna 3 Columna 4 E
Salida 3
N img: TG: dG2: dF: Flash
1 126 50 30
2 126 50 30 Fl=ON
3 130 50 30 Fl=ON
4 134 50 30 Fl=ON
5 138 50 30 Fl=ON
6 142 50 30 Fl=ON
7 146 50 30
8 150 50 30
9 154 50 30
10 158 50 30
11 162 50 30
12 166 50 30 Fl=ON
13 170 50 30 Fl=ON
14 174 50 30 Fl=ON
15 178 50 30 Fl=ON

H eseguido probando el funcionamiento del sketch y analizando los fallos.
Ahora incluyo las acciones de las salidas 2 y 3. La salida 2 debe activarse dos veces, V1 y V2. La salida 3 debe activar el flash Fl. En la siguiente tabla se indican los ajustes con el encoder y las respuestas de las salidas.

Columna 1 Columna 2 Columna 3 Columna 4 E F G
N img: TG: dG2: dF:
1 65 50 30 V1=ON V2=ON Fl=ON
2 65 50 30 V1=ON V2=ON Fl=ON
3 65 282 30 V1=ON V2=ON Fl=ON
4 65 308 30 V1=ON Fl=ON
5 65 318 30 V1=ON Fl=ON
6 65 326 30 V1=ON
7 65 330 30 V1=ON
8 65 334 30 V1=ON
9 65 342 30 V1=ON
10 65 350 30 V1=ON
11 65 358 30 V1=ON V2=ON
12 65 370 30 V1=ON V2=ON Fl=ON
13 65 382 30 V1=ON V2=ON Fl=ON
14 65 382 30 V1=ON V2=ON Fl=ON
15 65 350 134 V1=ON
16 65 358 134 V1=ON V2=ON
17 65 358 118 V1=ON V2=ON
18 65 358 98 V1=ON V2=ON Fl=ON
19 65 358 98 V1=ON V2=ON Fl=ON
20 65 358 78 V1=ON V2=ON Fl=ON
21 65 358 66 V1=ON V2=ON Fl=ON
22 65 358 54 V1=ON V2=ON Fl=ON
23 65 358 106 V1=ON V2=ON Fl=ON
24 65 358 114 V1=ON V2=ON
25 65 358 122 V1=ON V2=ON
26 65 358 130 V1=ON V2=ON

Debemos entender que las que no dicen FI=ON son las que no funcionan.
Probando 6.

No, cuando funcionan es ON.
Si no pone nada, no funcionan.

Disculpa Surbyte. Estamos diciendo lo mismo.

No pasa nada, nos estamos entendiendo.
El encoder simulado no funciona bien o yo no lo entiendo. No para de girar solo.
En mi caso no lo puedo detener.
Me incrementa todo al tal punto que no puedo fijar ningun valor.

En mi caso el encoder funciona bien.
Pulsando en una "flechita" aumenta los valores, pulsando en la otra los disminuye y pulsando en el eje cambia la línea seleccionada.

Lo que no entiendo es como funciona el código. :man_facepalming:t2:

O sea, no entiendo cuáles son los pasos para reproducir el error.

1 Like

En teoria los que no ha indicado con ON son los que no funcionan.
O sea fijando los valores indicados, la salida no hace lo que debe.

Como no he podido resolver los fallos del sketch con el encoder lo he adaptado a entrada de valores mediante potenciómetro. Pero ahora nunca se activan las salidas. Podrían ayudarme con los condicionales o los millis()
Subo el sketch modificado
Gracias

/*
  FUENTES: 
  Cacteres del display LCD: http://kio4.com/arduino/31pantallaA_LCD.htm
  Salida a Excel: https://www.youtube.com/watch?v=b1D_MJvfXIg
  Varios temporizadores: https://forum.arduino.cc/t/iniciar-secuencia-con-varios-temporizadores/251858/3
  Comunicación puerto serie: https://www.luisllamas.es/arduino-puerto-serie/
  Convertir string en entero: https://youtu.be/84P4rPQogo0?si=5FE5RyHeDjGBV_yB
  Potenciómetro: https://programarfacil.com/blog/arduino-blog/el-potenciometro-y-arduino/
  ezButton: https://arduinogetstarted.com/tutorials/arduino-button-library

  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

  Prueba para quitar el sistema de rebote ezButton.
  Conseguido: solo leer el pulsador y un delay(100)
*/
byte salida1  = 4;          // asigna el pin 4 para el salida1 = Cámara
byte salida2  = 7;          // asigna el pin 7 para el salida2 = Válvula
byte salida3  = 6;          // asigna el pin 6 para el salida3 = Flash
byte pulsador = 10;

unsigned long T0 = millis();
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 + TG*2 + dG + dF + Flash_t + dCam
unsigned long TG = 65;              // Tamaño gotas
unsigned long dG2 = 250;             // 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 = 130;              // 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

long N_img = 1;          // Número de imagen, aunque se puede cambiar via puerto serie

int FB1;                // Variable para evitar múltiples ciclos de disparo para valores altos de TG  
int FB2;                // Variable para evitar múltiples ciclos de disparo para valores altos de dG2
int FB3;                // Variable para evitar múltiples ciclos de disparo para valores altos de Cam

unsigned long E1;               // Entradas potenciómetros
unsigned long E2;
unsigned long E3;
int P1;

#include <LiquidCrystal_I2C.h>          // Incluimos la libreria del LCD
LiquidCrystal_I2C lcd(0x27, 20, 4);     // I2C address 0x27, 20 column and 4 rows

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 pin 10 como entrada  

  lcd.init();                   // initialize the lcd
  lcd.backlight();  
  Serial.begin(57600);                                //  puerto serie  
    
  }

void loop() {   
E1 = analogRead(A1);     // Entradas analógicas potenciómetros
E2 = analogRead(A2);
E2 = analogRead(A3);
TG = E1/2 + 50;

while(Serial.available() > 0)               // Entrada puerot serie. Asigna Número de imagen opcional
  {
    String entrada = Serial.readStringUntil('\n'); 
    entrada = entrada.substring(0, entrada.length());    
    N_img = entrada.toInt();
    Serial.println(); 
    Serial.print("Nuevo N_img: ");
    Serial.println(N_img);        
    entrada = "";
  }

  char buffer[20];
  Cam_t = V1 + TG * 2 + dG2 + dF + Flash_t + dCam;
  V2 = V1 + TG + dG2;
  Flash_in = V2 + TG + dF;

  lcd.setCursor(1, 0);                           // Línea 0       (Nº caracter, Nº Línea)
  sprintf(buffer, " TG=%4ld   Ct:%4ld", TG, Cam_t );    // Sutituir E1 por TG    
  lcd.print(buffer);

  lcd.setCursor(1, 1);                          // Línea 1
  sprintf(buffer, "dG2=%4ld   V1:%4ld", dG2, V1 );  //  Sustituir TG por dG2
  lcd.print(buffer);

  lcd.setCursor(1, 2);                          // Línea 2
  sprintf(buffer, " dF=%4ld   V2:%4ld", dF, V2 );
  lcd.print(buffer);

  lcd.setCursor(1, 3);                          // Línea 3
  sprintf(buffer, "Fin:%4ld    N:%4ld", Flash_in, N_img );
  lcd.print(buffer);  
  
  //                                         #### Secuencia de disparo ####
   
      P1 = digitalRead(pulsador);
      if (P1 == 0) {
           //                                       Impresión puerto serie
      Serial.print(N_img);
      Serial.print(", ");
      Serial.print(TG);
      Serial.print(", ");
      Serial.print(dG2);
      Serial.print(", ");
      Serial.print(dF);
      Serial.println(", ");
      N_img++;   
      P1 = 1; 
      T0 = millis();                    
        
    
    if ( millis() - T0 >= Cam_in && millis() - T0 < Cam_t && FB3 == 0) { // Activa salida 1           *** Disparo cámara ***
      digitalWrite(salida1, HIGH); 
      Serial.print("Cam=ON, "); 
      FB3 = 1;  
    } else if (millis() - T0 >= Cam_t) {               
      digitalWrite(salida1, LOW);                           // Desactiva salida 1         
    }       
   
    if (millis() - T0 >= V1 && millis() - T0 < V1 + TG && FB1 == 0) {
      digitalWrite(salida2, HIGH);                           // Activa salida 2          *** Primera gota ***
      Serial.print("V1=ON, ");
      FB1 = 1;       
    } else if (millis() - T0 >= V1 + TG) {
      digitalWrite(salida2, LOW);                            // Desactiva salida 2
    }

    if (millis() - T0 >= V2  && millis() - T0 < V2 + TG && FB2 == 0) {
      digitalWrite(salida2, HIGH);                           // Activa salida 2          *** Segunda gota ***
      Serial.print("V2=ON, ");  
      FB2 = 1;     
    } else if (millis() - T0 >= V2 + TG) {
      digitalWrite(salida2, LOW);                            // Desactiva salida 2
    }

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

E1 toma valores entre 0 y 1023, por lo que TG va de 0 a 561. Es correcto?

Por favor publica un diagrama de conexiones; una foto de un diagrama a mano alzada nos ayuda.