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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 |
#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)") ; */ } |