Um die Geschwindigkeit von Pfeilen oder Projektilen bestimmen zu können, habe ich mir auf Arduino-Basis einen Geschwindigkeitsmesser gebaut. Dieser basiert auf 2 Laserlichtschranken. Fällt die Intensität an der Eingangs-Photodiode (Typ SFH-203) unter einen bestimmten Wert (konkret 95% des Ausgangswerts), so wird die Zeitmessung gestartet. Gestoppt wird diese, wenn die Intensität an der Ausgangs-Photodiode wieder unter diese 95%-Schwelle fällt. Die Flugzeit t zwischen den beiden Lichtschranken wird dann am 16 x 2 Display in µs angegeben. Aus dem Abstand s der beiden Laserlichtschranken und der Zeit t ergibt sich für die Geschwindigkeit des Projektils v = s/t.
Um den Aufbau flexibler zu gestalten verwendete ich Matador-Holzbausteine. So lassen sich etwa beide Lichtschranken einfach von der Basis trennen, wenn man diese etwa an besonderer Position anbringen möchte/muss. Die beiden Lasermodule sind für 3V ausgelegt. Dadurch kann man sie direkt in Serie an den 5V-Pin des Arduino anschließen. Damit die Lichtschranken auch auf kleine Projektile reagiert, habe ich die Eingänge zu den beiden Photodioden mittels Lochblenden verkleinert. Betrieben wird der Geschwindigkeitsmesser mittels zweier 18650 Liion-Zellen.








Arduino-Code:
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x27 for a 16 chars and 2 line display. ACHTUNG: Adresse kann auch 0x3F sein !!!
// Anschlüsse:
// GND - GND
// VCC - 5V
// SDA - ANALOG Pin 4
// SCL - ANALOG pin 5
unsigned long time_start;
unsigned long time_end;
unsigned long time;
int PD_start; // value of the start-Photodiode
int PD_end; // value of the end-Photodiode
int Werte[100];
long start;
int i;
float velocity; // velocity of the projectile
float multiplier; // multiplier of the PD-value to start or finish the measurement
float distance; // distance between the two PDs
// settings for faster analogread:
// ADPS2 ADPS1 ADPS0 Division factor
// 0 0 0 1 nicht schneller als 2
// 0 0 1 2
// 0 1 0 4
// 0 1 1 8
// 1 0 0 16
// 1 0 1 32
// 1 1 0 64
// 1 1 1 128 (Standard)
#define FASTADC 1
// defines for setting and clearing register bits
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
// ===========================
// ======= SETUP =========
// ===========================
void setup()
{
Serial.begin(9600);
#if FASTADC
/*
// set prescale to 32
sbi(ADCSRA,ADPS2) ; // ADPS2 auf 1 gesetzt
cbi(ADCSRA,ADPS1) ; // ADPS1 auf 0 gesetzt
sbi(ADCSRA,ADPS0) ; // ADPS0 auf 1 gesetzt
*/
// set prescale to 8
cbi(ADCSRA,ADPS2) ; // ADPS2 auf 0 gesetzt
sbi(ADCSRA,ADPS1) ; // ADPS1 auf 1 gesetzt
sbi(ADCSRA,ADPS0) ; // ADPS0 auf 1 gesetzt
#endif
lcd.begin(); // initialize the lcd
lcd.backlight();
lcd.setCursor(0,0);
lcd.print("Geschwindigkeits");
lcd.setCursor(0,1);
lcd.print("messer");
delay(3000);
lcd.setCursor(0,0);
lcd.print(" ");
lcd.setCursor(0,1);
lcd.print(" ");
multiplier = 0.95; // the PD-values have to be 5% lower than the values without projectile to start and finish the measurement
distance = 0.258; // distance in meters between the two PDs
Serial.print(analogRead(A0));
Serial.print(" ");
Serial.println(analogRead(A1));
delay(100);
PD_start = analogRead(A0); // measuring the brightness of the starting-PD without projectile
delay(20);
PD_end = analogRead(A1); // measuring the brightness of the ending-PD without projectile
delay(20);
Serial.print("PD-start: ");
Serial.print(PD_start);
Serial.print(" , PD-end: ");
Serial.println(PD_end);
lcd.setCursor(0,0);
lcd.print("PD1: ");
lcd.print(PD_start);
lcd.setCursor(0,1);
lcd.print("PD2: ");
lcd.print(PD_end);
delay(5000);
lcd.setCursor(0,0);
lcd.print("ready for shoot");
lcd.setCursor(0,1);
lcd.print("... ");
delay(40);
}
// ===========================
// ======= LOOP =========
// ===========================
void loop()
{
while(analogRead(A0) > PD_start * multiplier)
{
// waiting for the projectile
}
time_start = micros(); // start-time in µs
while(analogRead(A1) > PD_end * multiplier)
{
// waiting for the projectile
}
time_end = micros(); // end-time in µs
time = time_end - time_start; // flight-time in µs
//time = 123456;
/*
Serial.print("Time: ");
Serial.println(time);
*/
velocity = distance * 1000000 / time; // velocity of the projectile in m/s
lcd.setCursor(0,0);
lcd.print(" ");
lcd.setCursor(0,1);
lcd.print(" ");
lcd.setCursor(0,0);
lcd.print("t = ");
lcd.setCursor(4,0);
lcd.print(time);
lcd.print(" us");
lcd.setCursor(0,1);
lcd.print("v = ");
lcd.setCursor(4,1);
lcd.print(velocity, 2);
lcd.print(" m/s");
delay(10);
// test for fast-analogread
/*
Serial.print("ADCTEST: ") ;
start = micros();
for (i = 0 ; i < 100 ; i++)
Werte[i] = analogRead(A0);
//delay(16);
Serial.print(micros() - start);
Serial.println(" microsec (100 calls)") ;
*/
}
