Jump to content

Otro detector de rayos


flamberge
 Compartir

Publicaciones recomendadas

Hola

estimulado por el diseño que presento Dandon en un post anterior, decidí intentar un diseño propio. Este es el resultado:

Es en principio similar al de Dandon en que un Arduino con una fotoresistencia CdS y un circuito divisor de voltaje se encarga de medir la luminosidad ambiente. Pero ahí terminan los similitudes.

1.- El detector dispone de una pequeña pantalla (display) LCD que se encarga de entregar la información. El usuario efectúa al inicio una calibración de la luz ambiental, define un valor umbral por medio de un encoder giratorio, y luego pone el equipo en función de espera para registrar aumentos de luminosidad ambiental ( léase rayos o cualquier cosa que incremente la luminosidad ambiental) y tomar las fotos.

2.- Por medio de un switch de tres polos se pone el equipo en "calibración", "Umbral", o "Detección". Como este switch solo conecta en cada posición uno de dos cables a tierra, se pueden sustituir con dos botones. La posición "deteccion" central del switch es cuando ninguno de ambos cables de señal esta conectado a tierra,. Equivale a no apretar ningún botón.

este es el esquema fritzing:

 

49856231183_605c7a7555_c.jpg

 

3.- El display LCD es el típico 16x2 basado en el chip Hitachi HD4478 que cuestan algo menos que dos euros en ebay. En este caso ademas le puse una interfaz I2C ( otro euro y medio) porque la conexión al arduino usando I2C se reduce a solo dos cables, mas los dos de V+ y tierra.

4.- El encoder es uno rotatorio también común y corriente. Los optocopladores son idénticos a los que muestra Dandon en su diseño, los EL817.

Realmente el circuito no tiene ninguna dificultad. La resistencia divisora del sensor es 1K, y las de los optos son de 470R.

 

 

El aparato funciona asÏ:

 

El usuario efectúa al principio una calibración de luz ambiental moviendo el switch de tres posiciones (eventualmente manteniendo presionado un botón)
a la posición "Cal". El display muestra la palabra "CALIBRANDO" y el arduino mide la lectura ambiente y la registra como un valor entero en el  rango 0 a 1023.

Se pone luego el switch en la posición "Enc" (o manteniendo presionado otro boton) y el display mostrará la palabra "Encoder: " seguida de un valor
entero definido rotando el encoder. En la segunda fila se mantiene mostrando el valor medido de luz ambiental determinada en el paso anterior de calibración.

Con ello se establece un valor para el umbral de disparo, resultante de la suma del máximo de luz ambiental calibrada,
mas el valor fijado con el encoder.

De esta forma  se asegura que el disparo ocurra solo ante aumentos de luz significativos por sobre la luminosidad ambiental. Lo "significativo" lo decide el usuario con el encoder.

Con el switch en la posición central "Det" ( o no oprimiendo ningún botón) el Arduino funcionará comparando los niveles de luminosidad con el valor umbral.
En la primera fila del display mostrará el valor umbral seguido entre paréntesis por el valor que gatilló el ultimo disparo.
Si aun no se ha hecho ningún disparo, el valor medido de disparo muestra (0). En la segunda fila mostrará en valor calibrado ambiental
Esta vista permite tener todos los parámetros de funcionamiento del aparato a la vista para evaluación y registro.

Cuando el valor de luminosidad ambiente aumenta por sobre el umbral se producirá el disparo. El display mostrará durante dos segundos la palabra "DISPARO"
seguido del número secuencial de éste y en segunda fila el valor de luminosidad que gatilló el disparo.

Abajo las fotos del diseño funcionando. En lugar del conector para la Nikon puse un par de LEDs a tierra. Así se puede verificar el igual de bien el funcionamiento

 

 

Switch en posición de calibración:

49856772911_42528616de_c.jpg

 

 

Switch en posición "Enc". Se aprecia el valor puesto con el encoder,  debajo se ve el valor de luz ambiental registrado en el paso anterior de calibración:

49856772701_34b17408c1_c.jpg

 

 

Un aspecto mas general del circuito en posición de detección, en el momento de un disparo. El display muestra el número del disparo (445, bastante alto porque con la luz artificial se mantuvo disparando mientras tomaba las fotos) y el valor de lectura de luz que lo provocó. Esto se muestra sólo por dos segundos, luego vuelve al aspecto que muestro abajo:

49857074712_07e13253fa_c.jpg

 

Finalmente el aspecto del display con el switch en posición  de detección esperando disparar. Se ve el valor de umbral que se decidió usar, luego entre paréntesis el valor que gatilló el  disparo previo, y abajo el valor calibrado de la luz ambiental de base. Esto permite visualizar todos los parámetros, anotarlos y aplicar ajustes al umbral si se requiere.

49856772631_b88959821a_c.jpg

 

Y aquí está el sketch. Estoy absolutamente seguro que hay muchas formas de mejorarlo, yo lo hice a lo bruto con mis escasos conocimientos  autodidactas y sacando ideas de aquí y allá. Bienvenida cualquier corrección que quieran hacerle.

 

/*
Copyright 2020  Dr. Jaime Fischer C.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files
(the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

Detector de rayos con calibracion de luz ambiental y determinacion de umbral de disparo con encoder

 
*/


#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2); //Crear el objeto lcd en dirección 0x27 de 16 columnas x 2 filas


// estas constantes no cambian:

const int Pinsensor = A0;         // pin del sensor
const int Pinumbral = 10;         // pin del interruptor en posicion indicador de valor de umbral, o boton
const int Pincalibracion = 9;     // pin del interruptor en posicion de calibracion, o boton
const int Pindisparo = 8;         // pin al optoacoplador
const int encoder0PinA = 11;      // pin para el encoder
const int encoder0PinB = 12;      // pin para el encoder

// estas variables cambian:

int sensorMin = 1023;        // valor minimo del sensor para efectos de calibracion
int sensorMax = 0;           // valor maximo del sensor para efectos de calibracion
int sensorValue = 0;         // valor medido por el sensor
int umbraldisp = 0;          // umbral para disparar
int numero = 1;              // numero de disparos
int sensorValueDisp = 0;     // valor del sensor al momento del disparo

// las variables que siguen son para el encoder:

int val;
int encoder0Pos = 0;
int encoder0PinALast = LOW;
int n = LOW;

void setup() {

  lcd.init();                      // inicializa el lcd
  lcd.clear();
  lcd.backlight();
  lcd.setCursor(0, 0);


  // configura los pines de ambos interruptores como entradas polarizadas en alta y el de disparo como salida:

  pinMode(Pinumbral, INPUT_PULLUP);
  pinMode(Pincalibracion, INPUT_PULLUP);
  pinMode(Pindisparo, OUTPUT);

  // configura pines para el encoder polarizados en alta:

  pinMode (encoder0PinA, INPUT_PULLUP);
  pinMode (encoder0PinB, INPUT_PULLUP);

}

void loop() {            

  digitalWrite(Pindisparo, LOW);   // se asegura que el pin de disparo este en LOW

 

  // mientras se mantiene presionado el botón o el interruptor en "Cal", lee valores de luz ambiental y registra esas lecturas en rango maximo y minimo:

  while (digitalRead(Pincalibracion) == LOW) {
    calibrate();

  }


  // mientras se mantenga presionado boton o el interruptor en "Enc" muestra en el LCD los valores de umbral y luz maxima ambiental calibrada:

  while (digitalRead(Pinumbral) == LOW) {
    encod();
  }

 

  umbraldisp = sensorMax + encoder0Pos;          // establece umbral del disparo = lectura ambiente maxima (0-1023) + valor del encoder
  sensorValue = analogRead(Pinsensor);           // midiendo luminosidad ( esperando aumento )
  lcd.setCursor(0, 0);
  lcd.print("Umbral:");
  lcd.print(umbraldisp);
  lcd.print("(");
  lcd.print(sensorValueDisp);
    lcd.print(")");
  lcd.setCursor(0, 1);
lcd.print("Ambiente:");

 lcd.print(sensorMax);

  if (sensorValue > umbraldisp)                  // comprueba si el valor medido del sensor está por sobre el valor umbral. Si es asi:

  {
    digitalWrite(Pindisparo, HIGH);              // inicia disparo
    sensorValueDisp = sensorValue;               // registra el valor medido de luz ambiental al momento el disparo
    lcd.clear();
    lcd.setCursor(0, 0);                        // Notifica disparo en LCD y muestra el numero secuencial del dispar y el valor de luminosidad al momento del disparo  
    lcd.print("DISPARO ");                      
    lcd.print(numero);
    lcd.print("   ");
    lcd.setCursor(0, 1);  
    lcd.print("Valor lum: ");  
    lcd.print(sensorValueDisp);
   
 

    delay (300) ;                               // mantiene disparo durante 300 milisegundos para asegurar reacción de la cámara

    digitalWrite(Pindisparo, LOW);              // finaliza disparo

    delay (2000);                               // espera dos segundos para mostrar display

  lcd.clear();
    numero++;                                   // aumenta conteo disparos

  }
}


void calibrate() {                             //  calibracion
  lcd.setCursor(0, 0);

  lcd.print("CALIBRANDO                      ");   // informa calibracion efectuandose

  // lee el sensor:
  sensorValue = analogRead(Pinsensor);

  // registra valor maximo del sensor:

  if (sensorValue > sensorMax) {
    sensorMax = sensorValue;

  }

  // registra valor minimo del sensor:

  if (sensorValue < sensorMin) {
    sensorMin = sensorValue;

  }
}


void encod() {    // determina valor umbral con encoder

  n = digitalRead(encoder0PinA);
  if ((encoder0PinALast == LOW) && (n == HIGH)) {
    if (digitalRead(encoder0PinB) == LOW) {
      encoder0Pos--;
    } else {
      encoder0Pos++;
    }

    lcd.setCursor(0, 0);
    lcd.print("Encoder:");
    lcd.print(encoder0Pos);
    lcd.print("                  ");
    delay(10);       
              
  }

  encoder0PinALast = n;

 

}

 

(edité el sketch para hacerlo mas comprensible).

Finalmente, este diseño no hace nada que el de Dandon no pueda hacer. Solo que este es mas elegante y amigable, la contrapartida es que ocupa mas espacio y es un par de euros mas caro. Además mejoré la parte de calibración y umbral para hacerla mas transparente al usuario y para poder manipular esto en forma mas precisa con referencias objetivas, numéricas.

Eventualmente con la experiencia y el uso espero tal vez poder determinar un valor constante universal para agregar a la calibración inicial que asegure un disparo ante cualquier situación de ocurrencia de rayos y me voy a evitar el encoder. Pero eso será otra historia.

 

 

saludos a todos.

 

Editado por flamberge
Enlace al comentario
Compartir en otros sitios web

hace 1 hora, Rabla dijo:

:bravo:

Pues ahora vengo yo a tocar un poco las narices ;):D

Ya que te quedan E/S libres, le montas una barrera laser, una infrarroja, disparo por sonido y le programas un intervalómetro y ya te queda un multidisparador 'de categoría'

Saludos

Estoy por incorporar esto al mío de barrera láser y sonido...

Enlace al comentario
Compartir en otros sitios web

¡Fantástico! Y @Rabla me ha quitado las palabras de las teclas :D

Hay por ahí un proyecto "Photoduino" que no sé si puede dar algunas ideas...

Creo que no tengo ningún encoder, pero miraré a ver. Si no, también se puede apañar con dos pulsadores para + y -.

Desde luego, tener la pantalla le da un plus de calidad y facilidad de uso. No me había atrevido a experimentar con ello, pero vista tu versión igual me lanzo... ... por cierto, no sé si conocéis estas pantallitas OLED:

https://www.amazon.es/MakerHawk-pantalla-pulgadas-SSD1306-Controlador/dp/B07BDFXFRK/ref=sr_1_17?dchild=1&keywords=MakerHawk&qid=1588672162&sr=8-17

Son minúsculas, pero se ven de miedo. Pedí un par y precisamente pensaba en cómo acoplarlas a algún proyecto de estos. Aú no he hecho más que cargar  un sketch de demos, pero creo que es perfecto para integrarlo en una caja pequeña.  Por el tamaño son ideales, además no necesitan iluminación posterior y ya son I2C.

Enlace al comentario
Compartir en otros sitios web

  • Moderadores
hace 24 minutos, Dandon dijo:

Si no, también se puede apañar con dos pulsadores para + y -.

O con tres, +, - y ok

Y para no ocupar demasiadas entradas digitales, puedes utilizar una analógica donde cada botón tiene un divisor de tensión (distinto) de forma que se sabe cual es el botón pulsado por la tensión leída en la entrada

Saludos

  • Like 1
Enlace al comentario
Compartir en otros sitios web

hace 7 horas, Dandon dijo:

Creo que no tengo ningún encoder, pero miraré a ver. Si no, también se puede apañar con dos pulsadores para + y -.

Hola

Para los que no tienen encoder, se puede usar un potenciómetro en el rango de unos 10K para que cumpla una función similar.

Me explico: la idea de usar un encoder es que puedes girarlo determinado valores muy precisos. Con un potenciómetro es algo mas difícil pero igual se puede:

Fundamento: si se conecta un potenciómetro con sus pines laterales a tierra y a 5v, y luego el del medio a una entrada analógica del arduino, se hace un divisor de voltaje. El arduino mide en ese pin el voltaje en forma analógica y luego lo transforma en un valor entero en el rango de 0 a 1023.

Hasta aquí todo bien. Pero a veces ese rango es mucho o muy poco para establecer el valor que se quiere. Por eso hay una función "map" en el código, que permite remapear el valor del potenciómetro en el rango que uno quiera. En este caso reduje el rango a valores enteros entre  0 y 100.

 

Si alguien quiere modificar el rango, solo tiene que modificar esta linea del sketch:

 

mapeopot = map(potread, 0, 1023, 0, 100);   // reduce rango original del pot a un rango de enteros entre 0 a 100

y aquí modificar el xxx con el valor que se quiera como rango:

mapeopot = map(potread, 0, 1023, 0, xxx);   // poner en "xxx" el valor requerido

 

este es el fritzing de la variante con potenciómetro. Noten que va conectado a tierra, a 5v y el pin del medio a entrada analógica A1:

 

 

49859858231_5f2da203fc_c.jpg

 

 

Y este es el sketch:


/*

 Copyright 2020  Dr. Jaime Fischer C.
  Permission is hereby granted, free of charge, to any person obtaining
  a copy of this software and associated documentation files
  (the "Software"), to deal in the Software without restriction,
  including without limitation the rights to use, copy, modify, merge,
  publish, distribute, sublicense, and/or sell copies of the Software,
  and to permit persons to whom the Software is furnished to do so,
  subject to the following conditions:
  The above copyright notice and this permission notice shall be
  included in all copies or substantial portions of the Software.
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  SOFTWARE.

 

  DETECTOR DE RAYOS CON CALIBRACION DE LUZ AMBIENTAL Y UMBRAL DE DISPARO CON POTENCIOMETRO

*/


#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2); //Crear el objeto lcd en dirección 0x27 de 16 columnas x 2 filas


// estas constantes no cambian:

const int Pinsensor = A0;         // pin del sensor
const int Pinpot = A1;            // pin del potenciometro regulador de umbral
const int Pinumbral = 10;         // pin del interruptor en posicion indicador de valor de umbral
const int Pincalibracion = 9;     // pin del interruptor en posicion de calibracion
const int Pindisparo = 8;         // pin al optoacoplador

 

// estas variables cambian:

int sensorMin = 1023;        // valor minimo del sensor para efectos de calibracion
int sensorMax = 0;           // valor maximo del sensor para efectos de calibracion
int sensorValue = 0;         // valor medido por el sensor
int umbraldisp = 0;          // umbral para disparar
int calibrarmax = 1023;      // maxima lectura teorica de pot
int calibrarmin = 0;         // minima lectura teorica de pot
int potread = 0;             // valor del pot
int mapeopot = 0;            // mapeo del valor del pot
int numero = 0;              // numero de disparos
int sensorValueDisp = 0;     // valor del sensor al momento del disparo

void setup() {

  lcd.init();                      // inicializa el lcd
  lcd.clear();
  lcd.backlight();
  lcd.setCursor(0, 0);

  // configura los pines de ambos interruptores como entradas polarizadas en alta y el de disparo como salida

  pinMode(Pinumbral, INPUT_PULLUP);
  pinMode(Pincalibracion, INPUT_PULLUP);
  pinMode(Pindisparo, OUTPUT); 

 Serial.begin (9600);


}

void loop() {                      // bucle principal:

 

  digitalWrite(Pindisparo, LOW);   // se asegura que el pin de disparo este en LOW


  //Muestra numero de disparo, luminsidad a la que disparó,
  //valor luminosidad ambiental y valor umbral:

  lcd.setCursor(0, 0);
  lcd.print("N.Disp:");
  lcd.print (numero);
  lcd.print(" (");
  lcd.print(sensorValueDisp);
  lcd.print(")");
  lcd.setCursor(0, 1);
  lcd.print("Amb:");
  lcd.print(sensorMax);
  lcd.print(" Umb:");
  lcd.print(umbraldisp);


  // mientras se mantiene presionado el botón calibracion, lee valores de luz ambiental y registra esas lecturas en rango maximo y minimo:

  while (digitalRead(Pincalibracion) == LOW) {
    calibrate();

  }


  // mientras se mantenga presionado boton "Pot" el display muestra en el LCD los valores de umbral y luz maxima ambiental calibrada:

  while (digitalRead(Pinumbral) == LOW) {
    poten();
  }

 

  umbraldisp = sensorMax + mapeopot;          // establece umbral del disparo = lectura ambiente maxima (0-1023) + valor mapeado del pot (0-100).
  sensorValue = analogRead(Pinsensor);        // midiendo luminosidad ( esperando aumento )

  if (sensorValue > umbraldisp)               // decide si el valor medido del sensor está por sobre el valor umbral. Si es asi:

  {

    digitalWrite(Pindisparo, HIGH);             // inicia disparo
    sensorValueDisp = sensorValue;              // registra valor de luminosidad que provocó disparo
    lcd.clear();
    lcd.setCursor(4, 0);                        // Notifica disparo en LCD
    lcd.print("DISPARO");

Serial.print ("DISPARO: ");
     Serial.print (numero);
     Serial.print ("  Lumin:");
     Serial.print ( sensorValueDisp );
     Serial.print ( "  Ambiente:" );
     Serial.print (sensorMax);
     Serial.print ("  Umbral:");
     Serial.print (umbraldisp);
  Serial.println();
    delay (300) ;                               // mantiene disparo durante 300 milisegundos para asegurar reacción de la cámara

    digitalWrite(Pindisparo, LOW);              // finaliza disparo

    numero++;                                   // aumenta conteo numero de disparos


  }

}  // fin bucle principal

void calibrate() {          // bucle de calibración

  lcd.clear();
  lcd.setCursor(4, 0);
  lcd.print("CALIBRANDO");             // informa calibracion efectuandose

  // lee el sensor:
  sensorValue = analogRead(Pinsensor);

  // registra valor maximo del sensor:

  if (sensorValue > sensorMax) {
    sensorMax = sensorValue;
  }

  // registra valor minimo del sensor:

  if (sensorValue < sensorMin) {
    sensorMin = sensorValue;
  }
  delay(100);
}

void poten() {         // bucle de potenciometro

  potread = analogRead(Pinpot);               // lectura del potenciometro de umbral transformando de 0 a 5 volts a enteros de 0 a 1023
  mapeopot = map(potread, 0, 1023, 0, 100);   // reduce rango original del pot a un rango de enteros entre 0 a 100
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Pot:");
  lcd.print(mapeopot);
  lcd.setCursor(0, 1);
  lcd.print("Ambiente:");
  lcd.print(sensorMax);

  delay (100);
}

 

 

 

Ojo, aproveché este sketch  para incorporar otros dos cambios:

 

1.- . Resulta que me di cuenta que es ridículo mostrar cualquier información los escasos segundos que el display muestra la información de disparo. Máxime cuando en ese momento puede ocurrir un rayo que no se va a registrar.

Por eso modifiqué el sketch. Ahora al momento del disparo muestra unicamente  la palabra "DISPARO" y sólo durante los 300 milisegundos que mantiene los contactos para la cámara cerrados.

Luego durante la detección muestra los valores del numero de disparos, entre paréntesis  la luminosidad que gatilló el último disparo, y abajo los valores de luminosidad ambiental calibrada y el del umbral establecido.

 

Esta es la vista actual en posición Det:

49857848632_ac20a7a448_c.jpg

 

2.- Además, por si alguien conecta el arduino a un PC y quiere registrar los datos,  agregué la característica que ante cada disparo envía los datos por protocolo serial al PC. Este es un pantallazo de mi MacBook registrando los eventos:

49859965391_72ddfc8444_c.jpg

 

 

 

Aquí está además el sketch para la variante con encoder incorporando estos cambios:

 

/*
  Copyright 2020  Dr. Jaime Fischer C.
  Permission is hereby granted, free of charge, to any person obtaining
  a copy of this software and associated documentation files
  (the "Software"), to deal in the Software without restriction,
  including without limitation the rights to use, copy, modify, merge,
  publish, distribute, sublicense, and/or sell copies of the Software,
  and to permit persons to whom the Software is furnished to do so,
  subject to the following conditions:
  The above copyright notice and this permission notice shall be
  included in all copies or substantial portions of the Software.
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  SOFTWARE.

  DETECTOR DE RAYOS CON CALIBRACION DE LUZ AMBIENTAL Y UMBRAL DE DISPARO CON ENCODER
 
*/

#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2); //Crear el objeto lcd en dirección 0x27 de 16 columnas x 2 filas

// estas constantes no cambian:

const int Pinsensor = A0;         // pin del sensor
const int Pinumbral = 10;         // pin del interruptor en posicion indicador de valor de umbral, o boton
const int Pincalibracion = 9;     // pin del interruptor en posicion de calibracion, o boton
const int Pindisparo = 8;         // pin al optoacoplador
const int encoder0PinA = 11;      // pin para el encoder
const int encoder0PinB = 12;      // pin para el encoder

// estas variables cambian:

int sensorMin = 1023;        // valor minimo del sensor para efectos de calibracion
int sensorMax = 0;           // valor maximo del sensor para efectos de calibracion
int sensorValue = 0;         // valor medido por el sensor
int umbraldisp = 0;          // umbral para disparar
int numero = 0;              // numero de disparos
int sensorValueDisp = 0;     // valor del sensor al momento del disparo

// las variables que siguen son para el encoder:

int val;
int encoder0Pos = 0;
int encoder0PinALast = LOW;
int n = LOW;

void setup() {

  lcd.init();                      // inicializa el lcd
  lcd.clear();
  lcd.backlight();
  lcd.setCursor(0, 0);

  // configura los pines de ambos interruptores como entradas polarizadas en alta y el de disparo como salida:

  pinMode(Pinumbral, INPUT_PULLUP);
  pinMode(Pincalibracion, INPUT_PULLUP);
  pinMode(Pindisparo, OUTPUT);

  // configura pines para el encoder polarizados en alta:

  pinMode (encoder0PinA, INPUT_PULLUP);
  pinMode (encoder0PinB, INPUT_PULLUP);

}

void loop() {

  digitalWrite(Pindisparo, LOW);   // se asegura que el pin de disparo este en LOW

  // mientras se mantiene presionado el botón o el interruptor en "Cal", lee valores de luz ambiental y registra esas lecturas en rango maximo y minimo:

  while (digitalRead(Pincalibracion) == LOW) {
    calibrate();
  }

  // mientras se mantenga presionado boton o el interruptor en "Enc" muestra en el LCD los valores de umbral y luz maxima ambiental calibrada:

  while (digitalRead(Pinumbral) == LOW) {
    encod();
  }

  umbraldisp = sensorMax + encoder0Pos;          // establece umbral del disparo = lectura ambiente maxima (0-1023) + valor del encoder
  sensorValue = analogRead(Pinsensor);           // midiendo luminosidad ( esperando aumento )
  lcd.setCursor(0, 0);
  lcd.print("N.Disp:");
  lcd.print (numero);
  lcd.print(" (");
  lcd.print(sensorValueDisp);
  lcd.print(")");
  lcd.setCursor(0, 1);
  lcd.print("Amb:");
  lcd.print(sensorMax);
  lcd.print(" Umb:");
  lcd.print(umbraldisp);

  if (sensorValue > umbraldisp)                  // comprueba si el valor medido del sensor está por sobre el valor umbral. Si es asi:

  {
    digitalWrite(Pindisparo, HIGH);              // inicia disparo
    numero++;
    sensorValueDisp = sensorValue;               // registra el valor medido de luz ambiental al momento el disparo
    lcd.clear();
    lcd.setCursor(4, 0);                        // Notifica disparo en LCD y muestra el numero secuencial del dispar y el valor de luminosidad al momento del disparo
    lcd.print("DISPARO");
    delay (300) ;                               // mantiene disparo durante 300 milisegundos para asegurar reacción de la cámara

    digitalWrite(Pindisparo, LOW);              // finaliza disparo

    delay (700);                               // espera dos segundos para mostrar display

    lcd.clear();
    // aumenta conteo disparos
  }
}

void calibrate() {                             //  calibracion
  lcd.setCursor(0, 0);

  lcd.print("CALIBRANDO                      ");   // informa calibracion efectuandose
  sensorMin = 1023;                               // valor minimo del sensor para efectos de calibracion
  sensorMax = 0;                                  // valor maximo del sensor para efectos de calibracion

  // lee el sensor:
  sensorValue = analogRead(Pinsensor);

  // registra valor maximo del sensor:

  if (sensorValue > sensorMax) {
    sensorMax = sensorValue;
  }

  // registra valor minimo del sensor:

  if (sensorValue < sensorMin) {
    sensorMin = sensorValue;
  }
}

void encod() {    // determina valor umbral con encoder

  n = digitalRead(encoder0PinA);
  if ((encoder0PinALast == LOW) && (n == HIGH)) {
    if (digitalRead(encoder0PinB) == LOW) {
      encoder0Pos--;
    } else {
      encoder0Pos++;
    }

    lcd.setCursor(0, 0);
    lcd.print("Encoder:");
    lcd.print(encoder0Pos);
    lcd.print("                  ");
    delay(10);
  }

  encoder0PinALast = n;

}

 

 

 

saludos a todos

 

Enlace al comentario
Compartir en otros sitios web

  • Moderadores
hace 18 horas, flamberge dijo:

Eventualmente con la experiencia y el uso espero tal vez poder determinar un valor constante universal para agregar a la calibración inicial que asegure un disparo ante cualquier situación de ocurrencia de rayos y me voy a evitar el encoder. Pero eso será otra historia.

Estaba leyendo y se me ocurre lo siguiente (desde mi desconocimiento tormentoso)

Creo que no se necesita realizar una calibración del disparador, puesto que el sensor puede ir midiendo continuamente la luz ambiente y por tanto se adecuará a dicha luz, únicamente se sería necesario introducir el incremento sobre el ambiente para definir el umbral de disparo

Por otro lado, viendo la programación, en la subrutina de calibración:

void calibrate() {                             //  calibracion
  lcd.setCursor(0, 0);
  lcd.print("CALIBRANDO                      ");   // informa calibracion efectuandose
  // lee el sensor:
  sensorValue = analogRead(Pinsensor);
  // registra valor maximo del sensor:
  if (sensorValue > sensorMax) {
    sensorMax = sensorValue;
  }
  // registra valor minimo del sensor:
  if (sensorValue < sensorMin) {
    sensorMin = sensorValue;
  }
}
 

Por un lado veo que la variable "sensorMin" no se utiliza en ninguna otra parte, por lo que entiendo que no es necesario asignar valor a ésta 

Por otro lado la variable utilizada es "sensorMax" que se utiliza para registrar el valor de calibración

Esta calibración por lo que veo solo se hace si el valor medido en ese momento es superir a "sensorMax"
if (sensorValue > sensorMax) {
    sensorMax = sensorValue;
  }

Es decir solo cambia el valor de calibración si el valor registrado "sensorValue" es mayor que el registrado anteriormente "sensorMax", por lo que si la luz ambiente disminuye (se oscurece el cielo) como la Resistencia de la fotorresistencia (Rf) será mayor, el valor registrado por el arduino será menor y no se podrá calibrar puesto que "sensorMax" solo se resetea al inicio del programa (por lo que abría que resetear)

Saludos

P.D. Espero no haberme equivocado

Enlace al comentario
Compartir en otros sitios web

  • Moderadores

Por otro lado se me estaba ocurriendo que por la no linealidad y 'lentitud' de respuesta de la fotoresistencia igual era mas conveniente utilizar un fotodiodo.

 

Saludos

P.D. puede parecer que estoy en plan 'toca narices', pero nada mas lejos de mi intención, la cual es intentar aportar ideas que se me ocurren (aunque igual alguna de ellas es disparatada)

Enlace al comentario
Compartir en otros sitios web

Hola

 

No, no estas equivocado :D

Respecto de lo primero:

Efectivamente se podría hacer un valor basal flotante que se vaya modificando solo. Y determinar sólo el valor umbral por sobre el que dispare. Y este además también se podría fijar

El problema que podría ocurrir es que con el arduino ejecutando 16 millones de instrucciones por segundo y reseteando su basal continuamente, pudiera ser que el aumento de luminosidad producido por un rayo sea tan lento en comparación a la velocidad del arduino,  que este se vaya reseteando a medida que la luminosidad aumenta y nunca alcance a un delta entre una medición y la siguiente como para que dispare. No lo sé.

Buena pregunta...Quien es mas rápido...¿arduino o rayo? Valdría la pena probar.

 

Respecto a la calibración:

Originalmente tomé esta calibración de un sketch donde se definían las variables sensorMin = 1023 y sensorMax = 0 al comienzo del sketch. Eso lo mantuve

Así es como entendí que funciona: cuando se mide un valor ambiente durante la calibración, si este valor es mayor a sensorMax, fija el valor sensorMax ese valor medido.

if (sensorValue > sensorMax) {
    sensorMax = sensorValue;

Evidentemente, cualquier cosa que se mida va a ser de un valor mayor a 0. Con eso bastaría para establecer el valor de luminosidad ambiental de base.

El problema ocurre cuando quieres recalibrar de nuevo, esta vez porque notas una luminosidad ambiente menor. Pero si ya fijaste el valor sensorMax a un valor, digamos 500 en una calibración previa, si la luminosidad actual es menor que ese valor, digamos 400,  el comando de calibración de arriba ahora no hace nada.

por eso cuando no se cumple la condición:

if (sensorValue > sensorMax)

actúa este otro paso:

if (sensorValue < sensorMin) {
    sensorMin = sensorValue;

Como sensorMin está definido en 1023 al comienzo,  cualquier valor va a ser menor a ese y se establece ahora un nuevo valor sensorMin como el de luz ambiental.

Aquí tenía dos problemas:

- Tener que escribir comandos para usar ya sea el valor sensorMin o sensorMax para usarlo como luminosidad de base, según sea el caso.

- Aún logrando usar ya sea sensorMin o sensorMax como referencia,  si en una nueva calibración resulta que el sensor mide por ejemplo un valor ambiental de 450, este valor es inferior a sensorMax, pero mayor a sensorMin. Aquí no se cumple ninguna de las condiciones de arriba y la recalibración simplemente no se realiza. Lo que mencionas ocurría por el primer caso ya que usaba sólo sensorMax como referencia.

Me aburrí de tomar caldo de cabeza y simplemente reescribí los valores iniciales al comienzo de la subrutina. De esta forma cada vez que ejecuta la calibración parte con  valores sensorMax = 0 y sensorMin = 1023. Con eso resolví el problema  y no me preocupé por depurar mas.

Evidentemente lo que se necesita es eliminar la definición de variable sensorMin y dejar la subrutina de calibración así:

 

void calibrate() {                             //  calibracion
 

lcd.setCursor(0, 0);

lcd.print("CALIBRANDO      "); 

sensorMax = analogRead(sensorPin);

}

 

Y eso sería toda la subrutina de calibración. :D

 

saludos

Enlace al comentario
Compartir en otros sitios web

hace 26 minutos, Rabla dijo:

Por otro lado se me estaba ocurriendo que por la no linealidad y 'lentitud' de respuesta de la fotoresistencia igual era mas conveniente utilizar un fotodiodo.

 

Saludos

P.D. puede parecer que estoy en plan 'toca narices', pero nada mas lejos de mi intención, la cual es intentar aportar ideas que se me ocurren (aunque igual alguna de ellas es disparatada)

Hola

 

Si, no hay duda que la respuesta de un fotodiodo es muchísimo mas rápida. El problema es que no entrega valores y eso dificultaría cualquier tipo de calibración. Es todo o nada.

En realidad siempre había desdeñado las fotoresistencias para este tipo de aplicaciones. Fue sólo la imagen de Dandon mostrando un rayo que tomó, lo que me convenció la viabilidad de usarlas. Tanto por la rápida reacción como por haber discriminado el rayo con ese nivel de luminosidad ambiente, ya que no estaba tan oscuro.

Mi otro detector de rayos, mucho mas antiguo, usa un fototransistor.

Y yo al menos creo que cualquier aporte o idea son bienvenidos.

 

saludos

Enlace al comentario
Compartir en otros sitios web

Hola

 

Ok, hechas las tareas :D

 

Incluí las sugerencias de Rabla sobre la calibración al sketch. Ahora no hay sensorMax o sensorMin, hay  una sola variable que se define con la calibración y se llama "ambiente". Además, ambos sketch ahora los fijé para partir con un valor inicial de umbral sobre 900 para que el arduino no comience a disparar desde el inicio, previo a la calibración y fjacion del valor del pot o encoder.

 

Sketch para potenciómetro. Parte con valor de luminosidad de ambiente fijado en 950 y valor del potenciómetro en 40:

 

/*
  Copyright 2020  Dr. Jaime Fischer C.
  Permission is hereby granted, free of charge, to any person obtaining
  a copy of this software and associated documentation files
  (the "Software"), to deal in the Software without restriction,
  including without limitation the rights to use, copy, modify, merge,
  publish, distribute, sublicense, and/or sell copies of the Software,
  and to permit persons to whom the Software is furnished to do so,
  subject to the following conditions:
  The above copyright notice and this permission notice shall be
  included in all copies or substantial portions of the Software.
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  SOFTWARE.

  DETECTOR DE RAYOS CON CALIBRACION DE LUZ AMBIENTAL Y UMBRAL DE DISPARO CON POTENCIOMETRO

*/


#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2); //Crear el objeto lcd en dirección 0x27 de 16 columnas x 2 filas


// estas constantes no cambian:

const int Pinsensor = A0;         // pin del sensor
const int Pinpot = A1;            // pin del potenciometro regulador de umbral
const int Pinumbral = 10;         // pin del interruptor en posicion indicador de valor de umbral
const int Pincalibracion = 9;     // pin del interruptor en posicion de calibracion
const int Pindisparo = 8;         // pin al optoacoplador

 

// estas variables cambian:

int sensorValue = 0;         // valor medido por el sensor
int umbraldisp = 0;          // umbral para disparar
int ambiente = 950;      // valor de luminosidad obtenido en calibración. Parte en 950 para que no dispare antes de calibrar. En cuanto se calibre cambia a valor medido real
int potread = 0;                // valor del pot
int mapeopot = 40;            // mapeo del valor del pot. Parte en 40. En cuanto se ponga el switch en "Pot" este valor cambiará a la posición real actual del potenciometro
int numero = 0;                // numero de disparos
int sensorValueDisp = 0;     // valor del sensor al momento del disparo

void setup() {

  lcd.init();                      // inicializa el lcd
  lcd.clear();
  lcd.backlight();
  lcd.setCursor(0, 0);

  // configura los pines de ambos interruptores como entradas polarizadas en alta y el de disparo como salida

  pinMode(Pinumbral, INPUT_PULLUP);
  pinMode(Pincalibracion, INPUT_PULLUP);
  pinMode(Pindisparo, OUTPUT);
  Serial.begin (9600);
}

void loop() {                      // bucle principal:

 

  digitalWrite(Pindisparo, LOW);   // se asegura que el pin de disparo este en LOW


  //Muestra numero de disparo, luminsidad a la que disparó,
  //valor luminosidad ambiental y valor umbral:

  lcd.setCursor(0, 0);
  lcd.print("N.Disp:");
  lcd.print (numero);
  lcd.print(" (");
  lcd.print(sensorValueDisp);
  lcd.print(")");
  lcd.setCursor(0, 1);
  lcd.print("Amb:");
  lcd.print(ambiente);
  lcd.print(" Umb:");
  lcd.print(umbraldisp);


  // mientras se mantiene presionado el botón calibración, lee valor de luz ambiental y lo registra en la variable "ambiente"

  while (digitalRead(Pincalibracion) == LOW) {
    calibrate();

  }


  // mientras se mantenga presionado boton "Pot" el display muestra en el LCD los valores de potenciometro  y de luz ambiental calibrada:

  while (digitalRead(Pinumbral) == LOW) {
    poten();
  }

 

  umbraldisp = ambiente + mapeopot;          // establece umbral del disparo = lectura ambiente maxima (0-1023) + valor mapeado del pot (0-100).
  sensorValue = analogRead(Pinsensor);        // midiendo luminosidad ( esperando aumento )

  if (sensorValue > umbraldisp)               // decide si el valor medido del sensor está por sobre el valor umbral. Si es asi:

  {

    digitalWrite(Pindisparo, HIGH);             // inicia disparo

    numero++;                                                // aumenta numero de disparos
    sensorValueDisp = sensorValue;          // registra valor de luminosidad que provocó disparo
    lcd.clear();
    lcd.setCursor(4, 0);                                // Notifica disparo en LCD
    lcd.print("DISPARO");
     Serial.print ("DISPARO: ");                   // envía informacion por serial
     Serial.print (numero);
     Serial.print ("  Lumin:");
     Serial.print ( sensorValueDisp );
     Serial.print ( "  Ambiente:" );
     Serial.print (ambiente);
     Serial.print ("  Umbral:");
     Serial.print (umbraldisp);
  Serial.println();
    delay (300) ;                                              // mantiene disparo durante 300 milisegundos para asegurar reacción de la cámara

    digitalWrite(Pindisparo, LOW);              // finaliza disparo

 


  }

}  // fin bucle principal

void calibrate() {                                                     //  bucle de calibracion
  lcd.setCursor(0, 0);

  lcd.print("CALIBRANDO                      ");           
  ambiente = analogRead(Pinsensor);

 

}

void poten() {                                                         // bucle de potenciometro

  potread = analogRead(Pinpot);                        // lectura del potenciometro de umbral transformando de 0 a 5 volts a enteros de 0 a 1023
  mapeopot = map(potread, 0, 1023, 0, 100);   // reduce rango original del pot a un rango de enteros entre 0 a 100
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Pot:");
  lcd.print(mapeopot);
  lcd.setCursor(0, 1);
  lcd.print("Ambiente:");
  lcd.print(ambiente);

  delay (100);
}

 

 

 

Sketch para el diseño con encoder. Parte con valor para ambiente fijado en 950 y encoder en 40:

 

/*
  Copyright 2020  Dr. Jaime Fischer C.
  Permission is hereby granted, free of charge, to any person obtaining
  a copy of this software and associated documentation files
  (the "Software"), to deal in the Software without restriction,
  including without limitation the rights to use, copy, modify, merge,
  publish, distribute, sublicense, and/or sell copies of the Software,
  and to permit persons to whom the Software is furnished to do so,
  subject to the following conditions:
  The above copyright notice and this permission notice shall be
  included in all copies or substantial portions of the Software.
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  SOFTWARE.

  DETECTOR DE RAYOS CON CALIBRACION DE LUZ AMBIENTAL Y UMBRAL DE DISPARO CON ENCODER
 
*/

#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2); //Crear el objeto lcd en dirección 0x27 de 16 columnas x 2 filas

// estas constantes no cambian:

const int Pinsensor = A0;              // pin del sensor
const int Pinumbral = 10;              // pin del interruptor en posicion indicador de valor de umbral, o boton
const int Pincalibracion = 9;         // pin del interruptor en posicion de calibracion, o boton
const int Pindisparo = 8;               // pin al optoacoplador
const int encoder0PinA = 11;      // pin para el encoder
const int encoder0PinB = 12;      // pin para el encoder

// estas variables cambian:

int ambiente = 950;                    // valor del sensor obtenido en calibracion. Parte en 950 para que el arduino no dispare. En cuanto se calibre cambia a valor medido real
int sensorValue = 0;                   // valor medido por el sensor
int umbraldisp = 0;                    // umbral para disparar
int numero = 0;                          // numero de disparos
int sensorValueDisp = 0;         // valor del sensor al momento del disparo

// las variables que siguen son para el encoder:

int val;
int encoder0Pos = 40;                  // se parte con un valor de 40. Se modifica con el encoder
int encoder0PinALast = LOW;
int n = LOW;

void setup() {

  lcd.init();                      // inicializa el lcd
  lcd.clear();
  lcd.backlight();
  lcd.setCursor(0, 0);

  // configura los pines de ambos interruptores como entradas polarizadas en alta y el de disparo como salida:

  pinMode(Pinumbral, INPUT_PULLUP);
  pinMode(Pincalibracion, INPUT_PULLUP);
  pinMode(Pindisparo, OUTPUT);

  // configura pines para el encoder polarizados en alta:

  pinMode (encoder0PinA, INPUT_PULLUP);
  pinMode (encoder0PinB, INPUT_PULLUP);
    Serial.begin (9600);

}

void loop() {

  digitalWrite(Pindisparo, LOW);   // se asegura que el pin de disparo este en LOW

  // mientras se mantiene presionado el botón o el interruptor en "Cal", lee valor de luz ambiental y lo registra en variable "ambiente"

  while (digitalRead(Pincalibracion) == LOW) {
    calibrate();
  }

  // mientras se mantenga presionado boton o el interruptor en "Enc", muestra en el LCD el valor del encoder  y  de luz ambiental calibrada:

  while (digitalRead(Pinumbral) == LOW) {
    encod();
  }

  umbraldisp = ambiente + encoder0Pos;          // establece umbral del disparo = lectura ambiente maxima (0-1023) + valor del encoder
  sensorValue = analogRead(Pinsensor);           // midiendo luminosidad ( esperando aumento )
  lcd.setCursor(0, 0);
  lcd.print("N.Disp:");
  lcd.print (numero);
  lcd.print(" (");
  lcd.print(sensorValueDisp);
  lcd.print(")");
  lcd.setCursor(0, 1);
  lcd.print("Amb:");
  lcd.print(ambiente);
  lcd.print(" Umb:");
  lcd.print(umbraldisp);

  if (sensorValue > umbraldisp)                      // comprueba si el valor medido del sensor está por sobre el valor umbral. Si es asi:

  {
    digitalWrite(Pindisparo, HIGH);                  // inicia disparo
    numero++;
    sensorValueDisp = sensorValue;               // registra el valor medido de luz ambiental al momento el disparo
    lcd.clear();
    lcd.setCursor(4, 0);                                      // Notifica disparo en LCD
    lcd.print("DISPARO");
     Serial.print ("DISPARO: ");                         // envía informacion por serial
     Serial.print (numero);
     Serial.print ("  Lumin:");
     Serial.print ( sensorValueDisp );
     Serial.print ( "  Ambiente:" );
     Serial.print (ambiente);
     Serial.print (" Umbral:");
     Serial.print (umbraldisp);
  Serial.println();
    delay (300) ;                                                 // mantiene disparo durante 300 milisegundos para asegurar reacción de la cámara

    digitalWrite(Pindisparo, LOW);                 // finaliza disparo

    lcd.clear();
  }
}

void calibrate() {                                                             //  bucle calibración
  lcd.setCursor(0, 0);

  lcd.print("CALIBRANDO                      "); 
  ambiente = analogRead(Pinsensor);

 
}

void encod() {                                                                   // bucle encoder

  n = digitalRead(encoder0PinA);
  if ((encoder0PinALast == LOW) && (n == HIGH)) {
    if (digitalRead(encoder0PinB) == LOW) {
      encoder0Pos--;
    } else {
      encoder0Pos++;
    }

    lcd.setCursor(0, 0);
    lcd.print("Encoder:");
    lcd.print(encoder0Pos);
    lcd.print("                  ");
    delay(10);
  }

  encoder0PinALast = n;

}

 

 

saludos a todos.

Editado por flamberge
Enlace al comentario
Compartir en otros sitios web

  • Moderadores
hace 12 horas, flamberge dijo:

El problema que podría ocurrir es que con el arduino ejecutando 16 millones de instrucciones por segundo y reseteando su basal continuamente, pudiera ser que el aumento de luminosidad producido por un rayo sea tan lento en comparación a la velocidad del arduino,  que este se vaya reseteando a medida que la luminosidad aumenta y nunca alcance a un delta entre una medición y la siguiente como para que dispare. No lo sé.

Efectivamente y fallo mío al escribir " ir midiendo continuamente la luz ambiente" que debería haber puesto 'periodicamente', puesto que si lo hiciera continuamente podría darse el caso de una medición durante un rayo (o inicio de este) lo que podría llevar a engaño al aparato

Esta medición 'periódica' se podría llevar a cabo mediante un contador de iteraciones o mediante un 'cronómetro' de forma que se diera un intervalo entre calibración y calibración, incluso para minimizar que el aparato entre en calibración en los próximos rayos (porque el tiempo de calibración se esté agotando) cuando se dispare la cámara se pone el 'cronómetro' a cero.

Por ejemplo, se me ocurre lo siguiente (para insertar dentro de tu código)

 

const int PeriodoCalibra = 600000;   //Define el intervalo de tiempo entre calibraciones ( por ejemplo 10 min = 600000 ms)
unsigned long TiempoCalibra = 0;     //contiene la ‘hora’ en la que se ha realizado la calibración

 

 

void setup() {

 

calibrate();      //hace la primera calibración cuando arranca el sistema
TiempoCalibra = millis();       // inicializa el ‘reloj’ de calibracion

}

 


void loop() {
  digitalWrite(Pindisparo, LOW);   // se asegura que el pin de disparo este en LOW


   if(millis() > TiempoCalibra + PeriodoCalibra){      //si se ha excedido el periodo calibración se autocalibra
        calibrate ();
        TiempoCalibra = millis();      
// inicializa el ‘reloj’ de calibracion
    }

 

  // mientras se mantenga presionado boton o el interruptor en "Enc", muestra en el LCD el valor del encoder  y  de luz ambiental calibrada:
  while (digitalRead(Pinumbral) == LOW) {
    encod();
  }
  umbraldisp = ambiente + encoder0Pos;          // establece umbral del disparo = lectura ambiente maxima (0-1023) + valor del encoder
  sensorValue = analogRead(Pinsensor);           // midiendo luminosidad ( esperando aumento )
  lcd.setCursor(0, 0);
  lcd.print("N.Disp:");
  lcd.print (numero);
  lcd.print(" (");
  lcd.print(sensorValueDisp);
  lcd.print(")");
  lcd.setCursor(0, 1);
  lcd.print("Amb:");
  lcd.print(ambiente);
  lcd.print(" Umb:");
  lcd.print(umbraldisp);
  if (sensorValue > umbraldisp)                      // comprueba si el valor medido del sensor está por sobre el valor umbral. Si es asi:
  {
    digitalWrite(Pindisparo, HIGH);                  // inicia disparo
    numero++;
    sensorValueDisp = sensorValue;               // registra el valor medido de luz ambiental al momento el disparo
    lcd.clear();
    lcd.setCursor(4, 0);                                      // Notifica disparo en LCD
    lcd.print("DISPARO");
     Serial.print ("DISPARO: ");                         // envía informacion por serial
     Serial.print (numero);
     Serial.print ("  Lumin:");
     Serial.print ( sensorValueDisp );
     Serial.print ( "  Ambiente:" );
     Serial.print (ambiente);
     Serial.print (" Umbral:");
     Serial.print (umbraldisp);
  Serial.println();
    delay (300) ;                                                 // mantiene disparo durante 300 milisegundos para asegurar reacción de la cámara
    digitalWrite(Pindisparo, LOW);                 // finaliza disparo
    TiempoCalibra = millis();       // inicializa el ‘reloj’ de calibración para minimizar riesgo de calibración en los próximos rayos
    lcd.clear();
  }
}
 

Saludos

 

 

Enlace al comentario
Compartir en otros sitios web

  • Moderadores

con permiso:

He intentado 'agilizar' el programa minimizando las escrituras en pantalla (LCD) escribiendo en ella solo cuando hay cambio de parámetros que mostrar:

Escribo solo los 'bloques' que he modificado

 

void setup() {

 

calibrate();      //hace la primera calibración cuando arranca el sistema

TiempoCalibra = millis();       // inicializa el ‘reloj’ de calibración

 

// Al arranque del sistema muestra disparos 0

  lcd.setCursor(0, 0);
  lcd.print("N.Disp:");
  lcd.print (0);
 

 

}

 

 

 

void loop() {

  digitalWrite(Pindisparo, LOW);   // se asegura que el pin de disparo este en LOW

   if(millis() > TiempoCalibra + PeriodoCalibra){      //si se ha excedido el periodo calibración se autocalibra
        calibrate ();
        TiempoCalibra = millis();       // inicializa el ‘reloj’ de calibración

               //Escribo en pantalla los datos de calibración

         lcd.setCursor(0, 1);
         lcd.print("Amb:");
        lcd.print(ambiente);

        lcd.setCursor(9, 1);
        lcd.print("Umb:");
        lcd.print(umbraldisp);

 

    }

 

  // mientras se mantenga presionado boton o el interruptor en "Enc", muestra en el LCD el valor del encoder  y  de luz ambiental calibrada:

  while (digitalRead(Pinumbral) == LOW) {
    encoded();

    umbraldisp = ambiente + encoder0Pos;          // establece umbral del disparo = lectura ambiente maxima (0-1023) + valor del encoger (Paso aquí el establecimiento del umbral)

        //Escribo en pantalla el nuevo umbral de disparo

        lcd.setCursor(9, 1);    //tambien se podríar ir a 13,1 y omitir la escritura de “Umb”
        lcd.print("Umb:");
        lcd.print(umbraldisp);

  }

   sensorValue = analogRead(Pinsensor);           // midiendo luminosidad ( esperando aumento )
                      //quito de aquí las escrituras en pantalla para agilizar

  if (sensorValue > umbraldisp)                      // comprueba si el valor medido del sensor está por sobre el valor umbral. Si es asi:

  {
    digitalWrite(Pindisparo, HIGH);                  // inicia disparo
    numero++;
    sensorValueDisp = sensorValue;               // registra el valor medido de luz ambiental al momento el disparo

          //escribo en pantalla los datos de disparo

     lcd.setCursor(0, 0);

     lcd.print("DISPARO         ");     // Notifica disparo en LCD
 

     Serial.print ("DISPARO: ");                         // envía informacion por serial
     Serial.print (numero);
     Serial.print ("  Lumin:");
     Serial.print ( sensorValueDisp );
     Serial.print ( "  Ambiente:" );
     Serial.print (ambiente);
     Serial.print (" Umbral:");
     Serial.print (umbraldisp);
     Serial.println();
    delay (300) ;                                                 // mantiene disparo durante 300 milisegundos para asegurar reacción de la cámara

    digitalWrite(Pindisparo, LOW);                 // finaliza disparo

    TiempoCalibra = millis();       // inicializa el ‘reloj’ de calibración para minimizar riesgo de calibración en los próximos rayos

          //Establece los valores de la primera línea

  lcd.setCursor(0, 0);
  lcd.print("N.Disp:");
  lcd.print (numero);
  lcd.print(" (");
  lcd.print(sensorValueDisp);
  lcd.print(")");

  }
}

 

Puesto que no lo he llevado a la práctica, habría que repasarlo porque seguro hay gazapos

 

Saludos

 

 

Enlace al comentario
Compartir en otros sitios web

  • Moderadores
hace 13 horas, flamberge dijo:

Si, no hay duda que la respuesta de un fotodiodo es muchísimo mas rápida. El problema es que no entrega valores y eso dificultaría cualquier tipo de calibración. Es todo o nada.

Si no recuerdo mal, la corriente de polarización inversa de un fotodiodo es proporcional a la cantidad de luz recibida

Saludos

Enlace al comentario
Compartir en otros sitios web

Qué barbaridad, estoy anonadado con el jugo que le podéis sacar a estas cosas.:1ok: Yo con el Arduino y la electrónica estoy como el que acaba de pasar de hacer fotos "mira y dispara" con el móvil y está descubriendo el mundo reflex. Tengo ciertas nociones que se remontan a mi infancia con el Aypetronic (bueno, luego he trasteado un poquito más, jeje) y he desempolvado mis escuetos conocimientos de C, pero me manejo a nivel de aficionado básico. Casi me arrepiento de haber montado ya el detector. (bueno, funciona, que es lo principal)... ¡habrá que hacer una V2.0 con todas vuestras ideas! O mejor esperar a que le pongáis gráficos 3D, sonido 5.1 de los truenos y barra y friegue :D

 

Enlace al comentario
Compartir en otros sitios web

Lo que no entiendo en el esquema Fritzing porque esta separado el autofoco y el disparo? que no se trabaja en forma manual? que seria lo mas lógico para mi..delo contrario el Af se volvería un poco loco.........bueno algún día lo comprobare:=):=):=):=):=)

saludos

 

Enlace al comentario
Compartir en otros sitios web

Qué barbaridad, estoy anonadado con el jugo que le podéis sacar a estas cosas.:1ok: Yo con el Arduino y la electrónica estoy como el que acaba de pasar de hacer fotos "mira y dispara" con el móvil y está descubriendo el mundo reflex. Tengo ciertas nociones que se remontan a mi infancia con el Aypetronic (bueno, luego he trasteado un poquito más, jeje) y he desempolvado mis escuetos conocimientos de C, pero me manejo a nivel de aficionado básico. Casi me arrepiento de haber montado ya el detector. (bueno, funciona, que es lo principal)... ¡habrá que hacer una V2.0 con todas vuestras ideas! O mejor esperar a que le pongáis gráficos 3D, sonido 5.1 de los truenos y barra y friegue :D

 

Enlace al comentario
Compartir en otros sitios web

  • Moderadores
hace 1 hora, Dandon dijo:

he desempolvado mis escuetos conocimientos de C,

Pues si has programado lo tienes chupao, sabes estructurar una programación que es lo importante. Luego traducirlo al 'idioma' correspondiente solo es cuestión de buscar en el 'diccionario' (google)

Saludos

  • Like 1
Enlace al comentario
Compartir en otros sitios web

hace 10 horas, Rabla dijo:

Esta medición 'periódica' se podría llevar a cabo mediante un contador de iteraciones o mediante un 'cronómetro' de forma que se diera un intervalo entre calibración y calibración, incluso para minimizar que el aparato entre en calibración en los próximos rayos (porque el tiempo de calibración se esté agotando) cuando se dispare la cámara se pone el 'cronómetro' a cero.

Por ejemplo, se me ocurre lo siguiente (para insertar dentro de tu código)

 

const int PeriodoCalibra = 600000;   //Define el intervalo de tiempo entre calibraciones ( por ejemplo 10 min = 600000 ms)
unsigned long TiempoCalibra = 0;     //contiene la ‘hora’ en la que se ha realizado la calibración 

  

....................

 

 

Hola

 

estuve probando el código, y encontré entraba en un loop de calibraciones sucesivas durante algo de 30 segundos.

 

Lo depuré y probando con otros valores y verificando en el monitor serial encontré que la constante:

const int PeriodoCalibra = 600000;   //Define el intervalo de tiempo entre calibraciones ( por ejemplo 10 min = 600000 ms)

hacía un rollover como sobre un valor de 30000 y mostraba luego otro valor, segun lo que pusiera  a veces negativo.

lo cambié a una variable long, que es de lo poco que conozco que permite números mas grandes: esta vez con una duración de 5 minutos:

long PeriodoCalibra= 300000;     

y el valor se mantuvo y funciona sin problemas. Ahora se recalibra en forma automática cada 5 minutos.

 

Ahora voy a ver de que manera evito tanta reescritura en pantalla

saludos y gracias

 

 

hace 4 horas, Dandon dijo:

he desempolvado mis escuetos conocimientos de C, pero me manejo a nivel de aficionado básico

 

 

Hola

 

Quien como tú, que estudiaste C :1ok::D

Lo que es yo, en segundo año de medicina tuve que estudiar Fortran IV. (año 1977 con programas escritos en tarjetas perforadas,  :blush:)

Con eso por lo menos aprendí los fundamentos de programación y pude entender después algo de Basic. Ahora intento comprender la mezcolanza de C/C++ para poder programar mis arduinos.

 

saludos

Enlace al comentario
Compartir en otros sitios web

  • Moderadores
hace 4 minutos, flamberge dijo:

estuve probando el código, y encontré entraba en un loop de calibraciones sucesivas durante algo de 30 segundos.

 

Lo depuré y probando con otros valores y verificando en el monitor serial encontré que la constante:

const int PeriodoCalibra = 600000;   //Define el intervalo de tiempo entre calibraciones ( por ejemplo 10 min = 600000 ms)

hacía un rollover como sobre un valor de 30000 y mostraba luego otro valor, segun lo que pusiera  a veces negativo.

lo cambié a una variable long, que es de lo poco que conozco que permite números mas grandes: esta vez con una duración de 5 minutos:

long PeriodoCalibra= 300000;     

y el valor se mantuvo y funciona sin problemas. Ahora se recalibra en forma automática cada 5 minutos.

 

Ahora voy a ver de que manera evito tanta reescritura en pantalla

:1good::bravo:

Saludos

Enlace al comentario
Compartir en otros sitios web

hace 7 horas, lorete dijo:

Lo que no entiendo en el esquema Fritzing porque esta separado el autofoco y el disparo? que no se trabaja en forma manual? que seria lo mas lógico para mi..delo contrario el Af se volvería un poco loco.........bueno algún día lo comprobare:=):=):=):=):=)

saludos

 

 

Hola

 

En la cámara ambos contactos están separados. Se supone que en una secuencia de disparo normal, al oprimir el botón del obturador primero activas el autofoco y medición de exposición, y posteriormente llegas al nivel de accionar el disparo.

No importa que tan rápido lo hagas, siempre se conectará a tierra primero autofoco/autoexposicion, y luego disparo.

Esto puede tener varias razones, desde por simpleza de construcción y diseño, por lo que se llama "legacy" en ergonomía de controles, o incluso podría ser por un problema del circuito, en que tal vez el potencial del circuito de autofoco/autoexposicion que comparten un cable, no tengan el mismo potencial con respecto de tierra que el circuito y cable de disparo. Así como están hechos, jamás se unen entre sí antes de conectarse a tierra. Incluso los disparadores de cable tienen un switch que conecta en forna secuencial. Por lo menos los que conozco.

Ahora, si los unes en una salida común antes de conectarse a tierra, podría ser que circule corriente de uno al otro si los potenciales no son iguales. Y eso podría dañar algo en la cámara. Hay componentes que no soportan bien las corrientes inversas.

En el fondo, no es mas que desconocimiento del circuito real del interior de la cámara y se trata de recrear el modo mas seguro. Tal vez no pasa nada si se intenta. Pero yo también prefiero irme a la segura. 50 optoacopladores EL817 cuestan en ebay como un euro y medio.

Incluso si se quiere ser mas riguroso, en lugar de una se podrían configurar dos salidas del arduino, una a cada opto por separado. Igual que en el cable de disparo remoto de Nikon. Y en el sketch del arduino programar un retardo en la activación al opto que activa el disparo para que  comience a funcionar un milisegundo después de que se active el que conecta el autofoco/autoexposición.

Y estoy que lo hago. :D

 

El fritzing es mas bien una guía, pero está sujeta a cambios a gusto del usuario. Si quieres usar un solo opto, nada impide que puedes probar.

Y sería interesante que compartas la experienca

 

saludos

Enlace al comentario
Compartir en otros sitios web

Hola

 

Como no tengo nada mas que hacer, estuve entreteniéndome con la idea de Rabla de minimizar el tiempo que pierde el sketch en escribir en el display, y me parece que he logrado algo.

Básicamente se reduce que todas las escrituras al LCD se efectúan solo cuando se cambia el switch (calibracion o encoder) , o al momento de un disparo. Les puse unos marcadores (flags) a las subrutinas para que el  bucle principal los detecte y escriba información solo en esos casos. Si no ocurre nada de eso, el display se mantiene fijo mostrando la información en que quedó.

El bucle principal es sólo esto:

 

void loop() {

 digitalWrite(Pindisparo, LOW);                    // se asegura que el pin de disparo este en LOW

if   ...........................(escribe solo si detecta que el el switch se devolvió de posicion "Enc" a "Det" o de "Cal" a "Det."

if...............................(calibra si transcurren mas de 5 minutos desde la ultima calibración)

while...................(actúa solo si el switch está en Cal)

while...................(actúa solo si el switch está en Enc)

  umbraldisp = ambiente + encoder0Pos;          // establece umbral del disparo = lectura ambiente maxima (0-1023) + valor del encoder
  sensorValue = analogRead(Pinsensor);          // midiendo luminosidad ( esperando aumento )

if .............................(actúa solo si dispara).

}

 

y eso es todo para detectar rayos. No escribe nada en el LCD en este bucle

 

Los demás pasos del programa (disparo, calibración, encoder, etc. ) ocurren solo si las condiciones if o while se cumplen, y se aprovechan esas subrutinas para escribir la información el display.

Aquí el sketch con las modificaciones (para encoder)

 

(editado)

esta vez preferí subirlo como .ino

 

detector_de_rayos_con_encoder.ino

 

Insisto en que esto lo hago a la brutanteque como decimos acá. Seguro hay formas mejores.

Sólo que no se me ocurren al estado actual de mis conocimientos

 

saludos a todos

Editado por flamberge
Enlace al comentario
Compartir en otros sitios web

  • Moderadores
hace 10 horas, flamberge dijo:

Como no tengo nada mas que hacer,

Pues como te veo aburrido y hoy me he levantado malévolo (:whistling:) te propongo un nuevo reto de cara a una ampliación de prestaciones del disparador:

Por un lado, transferir las instrucciones bucle principal (void loop) a una subrutina "DisparoRayo" que contenga las instrucciones para realizar el disparo por rayo y dejar el bucle principal para la ejecución de la 'funcición seleccionada' (DisparoRayo, DisparoLaser, Temporizador, etc..), algo que quede similar a esto:

void loop() {

switch (FuncionSeleccionada){
      case 1:    //Disparador Rayos
          DisparoRayo();   
      break;
      case 2:    //Disparador Laser
           DisparoLaser();   
      break;
      case 3:    //Disparador Sonido
         DisparoSonido();    
      break;
      case 4:    //Intervalometro
          Intervalometro();    
      break;
      case 5:    //etc, etc, etc
          Función5(); 
      break;

      Etc, etc, etc................
    }  //Fin de switch(FuncionSeleccionada)

}

 

Por otro lado, suprimir los switch e introducir dos pulsadores,  BotonMenu y BotonOK, que junto con el selector (encoder) sirva para la selección de la función que queremos (rayo, laser, etc) y la introducción de los parámetros de la función seleccionada

El BotonMenu, estaría en la entrada D2 que dispone de función interrupción, de forma que no harían falta parte las comparaciones ("if" o "while"). Si se presiona BotonMenu en cualquier momento de la ejecución del programa se produce una 'interrupción' y se ejecuta la subrutina asociada a ésta, entrando en el menú correspondiente para la elección de función o parámetros.

Saludos

Editado por Rabla
Enlace al comentario
Compartir en otros sitios web

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Invitado
Responder a este tema...

×   Pegar como texto enriquecido.   Pegar como texto sin formato

  Only 75 emoji are allowed.

×   Tu enlace se ha incrustado automáticamente..   Mostrar como un enlace en su lugar

×   Se ha restaurado el contenido anterior.   Limpiar editor

×   No se pueden pegar imágenes directamente. Carga o inserta imágenes desde la URL.

 Compartir

  • Explorando recientemente

    • No hay usuarios registrados viendo esta página.
×
×
  • Crear nuevo...