3D printed Arduino Airsoft Chronograph
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

timing.cpp 2.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. /*
  2. * timing.cpp
  3. *
  4. * OpenChrono BB speed measurement device.
  5. *
  6. * Copyright (c) 2022 Thomas Buck <thomas@xythobuz.de>
  7. *
  8. * Two phototransistors connected to external interrupts 0 and 1.
  9. * Timer1 (16bit) used to count time between triggers.
  10. * Timer2 (8bit) used for timing UV LED pulse.
  11. */
  12. #include <Arduino.h>
  13. #include "timing.h"
  14. #include "config.h"
  15. volatile uint8_t trigger_a = 0, trigger_b = 0;
  16. volatile uint16_t time_a = 0, time_b = 0;
  17. void interrupt_init() {
  18. // trigger both on rising edge
  19. EICRA = (1 << ISC00) | (1 << ISC01);
  20. EICRA |= (1 << ISC10) | (1 << ISC11);
  21. // enable interrupts
  22. EIMSK = (1 << INT0) | (1 << INT1);
  23. }
  24. /*
  25. * this is supposed to be the "input" sensor,
  26. * the one that triggers first on firing.
  27. */
  28. ISR(INT0_vect) {
  29. time_a = timer_get();
  30. trigger_a = 1;
  31. }
  32. /*
  33. * this is supposed to be the "output" sensor,
  34. * the one that triggers after the other sensor.
  35. */
  36. ISR(INT1_vect) {
  37. time_b = timer_get();
  38. trigger_b = 1;
  39. // we now need to turn on the UV led
  40. // and make sure it will only be on shortly!
  41. timer_start();
  42. digitalWrite(UV_LED_PIN, HIGH);
  43. }
  44. // --------------------------------------
  45. static void timer1_init() {
  46. // normal mode
  47. TCCR1A = 0;
  48. // prescaler
  49. #if TIMER_PRESCALER == 1
  50. TCCR1B = (1 << CS10);
  51. #elif TIMER_PRESCALER == 8
  52. TCCR1B = (1 << CS11);
  53. #elif TIMER_PRESCALER == 64
  54. TCCR1B = (1 << CS11) | (1 << CS10);
  55. #elif TIMER_PRESCALER == 256
  56. TCCR1B = (1 << CS12);
  57. #elif TIMER_PRESCALER == 1024
  58. TCCR1B = (1 << CS12) | (1 << CS10);
  59. #else
  60. #error Invalid Prescaler for Timer1
  61. #endif
  62. }
  63. static void timer2_init() {
  64. // normal mode, no clock source
  65. TCCR2A = 0;
  66. TCCR2B = 0;
  67. // enable overflow interrupt
  68. TIMSK2 = (1 << TOIE2);
  69. }
  70. void timer_init() {
  71. timer1_init();
  72. timer2_init();
  73. }
  74. uint16_t timer_get() {
  75. return TCNT1;
  76. }
  77. void timer_start() {
  78. /*
  79. * the distance between the second IR sensor
  80. * and the UV LEDs is 7.5mm.
  81. * Our bullet will travel with a speed of
  82. * ~10m/s up to ~300m/s approximately.
  83. * So it will move the 7.5mm in
  84. * 750us to 25us respectively.
  85. * So it makes sense to keep the UV LED
  86. * on for 1ms.
  87. *
  88. * We reach exactly 1ms when counting to 250
  89. * with a prescaler of 64 at 16MHz.
  90. *
  91. * If you __really__ want to increase the brightness
  92. * of the tracer, reduce the pulse length here.
  93. * Then you can also reduce the UV LED resistor for
  94. * higher currents, according to the datasheet of
  95. * your UV LED.
  96. */
  97. const static uint8_t pulse_length = 250;
  98. // initial value we count up from
  99. TCNT2 = 0xFF - pulse_length;
  100. // prescaler 64
  101. TCCR2B = (1 << CS22);
  102. }
  103. ISR(TIMER2_OVF_vect) {
  104. // turn off UV LED
  105. digitalWrite(UV_LED_PIN, LOW);
  106. // and also stop timer
  107. TCCR2B = 0;
  108. }