El detector de huecos no registra proyectiles de alta velocidad

-1

Estoy tratando de construir un crono de pistola ASG basado en un detector de brechas. Conecté con éxito dos detectores de espacio a Arduino Uno, escribí un programa, que mide el tiempo entre dos picos de voltaje (en cada detector de espacio) y los conecté a un perfil de aluminio, de manera que el proyectil ASG debe cruzar las corrientes de infrarrojos de los detectores de espacio (el proyectil ASG tiene 6 mm de diámetro, el perfil tiene alrededor de 8-9 mm de espacio en el interior, el detector se coloca exactamente en el centro, verticalmente.

La configuración se ve como la siguiente (sin el perfil):

Ahora,cuandocolocoelproyectileneseperfil,Arduinonotacorrectamentedospicos(decadadetector)ymideeltiempoentreellos.PerocuandodispareelproyectildesdelalentapistolaASGbasadaenlaprimavera,nopasanada.

Misospechaesqueeltiempo,cuandoelproyectilcubreelflujodeIRestancorto,eldetectornotienetiemposuficienteparaelevarelvoltajey,porlotanto,Arduinonoregistraningúncambio.

Laparteprincipaldelcódigofuenteseveasí:

#include"Display.h"
#include "Keypad.h"
#include "Menu.h"
#include "EnableInterrupt.h"

// Global variables -----------------------------------------------------------

LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
Display display(lcd, 16, 2);
Keypad keypad;

BaseMenuItem * mainItems[] = 
{
  new ActionMenuItem("\x01 Pomiar FPS", 1),
};

MainMenu mainMenu(display, mainItems, sizeof(mainItems) / sizeof(BaseMenuItem *));

// *** FPS measurement ***

unsigned long fpsStart;
unsigned long fpsEnd;
int fpsMode = 0;

// Global functions -----------------------------------------------------------

void detector1Up()
{
  fpsStart = micros();
  fpsMode = 1;

  disableInterrupt(A1);
  enableInterrupt(A2, detector2Up, RISING);  
}

void detector2Up()
{
  fpsEnd = micros();
  fpsMode = 2;
  disableInterrupt(A2);
}

void fpsDisplay(long ms)
{
  lcd.clear();

  lcd.setCursor(0, 0);
  lcd.print("ms: ");
  lcd.print(ms);
}

void fpsDisplayMissedError()
{
  lcd.clear();

  lcd.print(" *** Error *** ");
  lcd.setCursor(0, 1);
  lcd.print("Missed 2 sensor");
}

void fpsMeasurement()
{
  fpsMode = 0;
  enableInterrupt(A1, detector1Up, RISING);

  fpsDisplay(0);

  bool finish = false;
  while (!finish)
  {
    if (fpsMode == 1)
    {
      // Checking if particle missed second sensor

      unsigned long now = micros();
      if (now > fpsStart && now - fpsStart > 1000000)
      {
        // If second passed after first measurement, assume, that
        // particle missed second sensor

        // Stop waiting for second sensor
        disableInterrupt(A2);

        fpsDisplayMissedError();

        // Restart measurement
        fpsMode = 0;
        enableInterrupt(A1, detector1Up, RISING);
      }
    }    

    if (fpsMode == 2)
    {
      // Checking if measurement was made

      if (fpsEnd > fpsStart)
      {
        unsigned long timeDist = fpsEnd - fpsStart;
        fpsDisplay(timeDist);

        Serial.print("Measured time: ");
        Serial.print(timeDist);
        Serial.print("\n");
      }

      fpsMode = 0;
      enableInterrupt(A1, detector1Up, RISING);
    }
    else
    {
      // Waiting for keypress - exiting mode

      int key = keypad.ReadKey();
      if (key != KEY_NONE)
        finish = true;
    }
  }

  disableInterrupt(A1);
  disableInterrupt(A2);
}

void setup()
{
  Serial.begin(9600);
  while (!Serial);

  // (...)

  delay(2000);
  mainMenu.Show();
}

void loop()
{
  int key = keypad.ReadKey();
  int result = mainMenu.Action(key);
  if (result == 1)
  {
    fpsMeasurement();
    mainMenu.Show();
  }
}

¿Cómo puedo mejorar el hardware o el software para registrar la partícula y así poder medir su velocidad?

Editar:

Para evitar discusiones demasiado grandes en los comentarios, proporcionaré toda la información solicitada aquí:

@PlasmaHH: el detector de huecos usa (supongo) un diodo IR y un detector IR en el otro lado. Cuando se conecta a Arduino, proporciona baja tensión sin obstáculos y alta tensión en obstáculos entre el diodo y el detector. No tengo valores aquí, pero por lo que recuerdo, los valores eran 31-32 sin obstáculos y alrededor de 800 cuando había obstáculos (Arduino escala el voltaje de 0 ~ 5V a 0 ~ 1023).

@JRE: Los esquemas del detector están [en la página de la tienda del detector] (dejando el enlace si se necesita más información) 2 .

Primerplanodelpropiodetector:

@OllinLanthrop:Estoesraro,laBúsquedadeimágenesdeGoogleen"Perfil de aluminio" devuelve exactamente lo que he usado. Pero para mayor claridad, estoy usando la siguiente pieza de aluminio:

Taladreagujerosendoslugaresenelperfil,demodoquelavigadeldetectorpaseexactamenteatravésdelperfilylosagujerosesténcentradosverticalmenteenelperfil.Esperoquelaimagentedémásinformaciónsobremicompilación.Además,elproyectilde"caída" debería tener más sentido ahora.

También, un cronógrafo de pistola (o cronógrafo) es un dispositivo que mide la velocidad del proyectil. El comercial se parece a lo siguiente:

    
pregunta Spook

2 respuestas

7

Mirando el esquema del detector, veo un pullup de 10k en el fototransistor, y un capacitor "104" (100nF) a tierra, para filtrar el ruido.

La constante de tiempo de este filtro RC es demasiado lenta para detectar un proyectil volador.

Solución simple: desoldar el condensador! Si aún no pulsa, use un pullup más bajo como 1k para una velocidad adicional, y aumente la corriente del LED en consecuencia.

La hoja de datos del detector debe mencionar su velocidad y las corrientes máximas.

En cuanto al código, deberías usar interrupciones de cambio de pin que serán tanto más simples como más precisas. Todo lo que tienes que hacer es:

  • Cuando el "detector 1" vea el proyectil, tome el valor del temporizador y guárdelo en una variable
  • Cuando el "detector 2" vea el proyectil, tome el valor del temporizador y reste el valor previamente almacenado.

Puedes usar "micros ()" en lugar de un temporizador si eres realmente perezoso.

EDIT

Los documentos para micros ():

  

Devuelve el número de microsegundos desde que la placa Arduino comenzó a ejecutar el programa actual. Este número se desbordará (volverá a cero), después de aproximadamente 70 minutos. En las placas Arduino de 16 MHz (por ejemplo, Duemilanove y Nano), esta función tiene una resolución de cuatro microsegundos (es decir, el valor devuelto siempre es un múltiplo de cuatro). En las placas Arduino de 8 MHz (por ejemplo, la LilyPad), esta función tiene una resolución de ocho microsegundos.

Supongo que tu UNO corre a 16 Mhz. Entonces 800µs son 12800 ciclos, lo cual es suficiente.

Si usa un temporizador adecuado con una velocidad de reloj de 16 Mhz, obtendrá una precisión excelente.

Si usas micros () con su redondeo idiota a 4 relojes, obtendrás 4 veces peor precisión, pero aún así está bien.

Lo importante es evitar la interrupción de jitter y otras fuentes de jitter. Por lo tanto, si hace todo lo que está en el software utilizando una interrupción de cambio de pin, debe asegurarse de que ninguna otra interrupción de prioridad más alta pueda bloquearla (como los temporizadores de arduino, serial o lo que sea) y, por supuesto, no hacer nada que pueda tomar una cantidad de tiempo variable en tu interrupción.

Ahora, la forma habitual de hacer esto es usar un temporizador en modo de captura. El hardware se activará en el pin que especifique y capturará el valor del temporizador en ejecución en un registro, ENTONCES provocará una interrupción que puede leer el valor capturado. En este caso, ya que el valor ha sido capturado con la mayor precisión por el hardware, no importa si la interrupción que lo leerá tendrá fluctuación. Hay un ejemplo aquí .

    
respondido por el peufeu
2

Sería útil publicar un esquema de su proyecto junto con los números de parte reales.

Al revisar tu boceto, estás inhabilitando y deshabilitando innecesariamente las interrupciones. Cualquier latencia en su programa podría hacer que se pierda un evento como resultado.

Mi recomendación es que simplemente habilites las interrupciones, las dejes habilitadas y uses la máquina de tu estado para determinar el estado de detección.

También asegúrese de que los bucles de espera en el código principal que están monitoreando la máquina de estado no afecten los recursos del procesador.

Idealmente, esto debería implementarse con temporizadores de hardware, ya que una simple captura de micros (), por ejemplo, puede llamar a docenas de líneas de código de ensamblaje, introduciendo así una latencia significativa durante una interrupción. Recuerde que la velocidad ASG puede ser fácilmente de 400 fps. Si sus sensores están separados por un pie, esto le otorga menos de 2.5 milisegundos para procesar una interrupción.

Si sospecha que el detector no está atrapando el vuelo del proyectil ASG, simplemente cree un programa de prueba con un detector que informe si / cuando se produjo la interrupción.

Editar:

Al observar el esquema del PE que agregó a su pregunta, recomendaría quitar el condensador que se encuentra entre la entrada negativa y la conexión a tierra. El límite ralentizará la respuesta del PE, que es lo contrario de lo que necesita.

    
respondido por el Glenn W9IQ

Lea otras preguntas en las etiquetas