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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. /*
  2. * ticks.cpp
  3. *
  4. * OpenChrono BB speed measurement device.
  5. *
  6. * Copyright (c) 2022 Thomas Buck <thomas@xythobuz.de>
  7. *
  8. * OpenChrono is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation, either version 3 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * OpenChrono is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with OpenChrono. If not, see <https://www.gnu.org/licenses/>.
  20. *
  21. * Some notes about time calculations:
  22. * We have Timer1 running with 16MHz
  23. * which gives us a tick period of 62.5ns.
  24. *
  25. * The distance of the sensors is given in mm
  26. * in SENSOR_DISTANCE (eg. 70mm).
  27. *
  28. * period_in_s = 1 / F_CPU
  29. * period_in_s = 62.5 / 1000 / 1000 / 1000;
  30. * dist_in_m = SENSOR_DISTANCE * 0.1 * 0.01
  31. * travel_time_in_s = ticks * period_in_s;
  32. * speed = dist_in_m / travel_time_in_s;
  33. *
  34. * period_in_s = 0.0000000625
  35. * dist_in_m = 0.07m
  36. * ticks = 2000
  37. * travel_time_in_s = 0.000125
  38. * speed = 560 m/s
  39. *
  40. * speed = (SENSOR_DISTANCE / 1000) / (ticks * 62.5 / 1000 / 1000 / 1000)
  41. * speed = SENSOR_DISTANCE / (ticks * 62.5 / 1000 / 1000)
  42. * speed = SENSOR_DISTANCE / (ticks * 1000 / F_CPU)
  43. *
  44. * Because we can at max measure 0xFFFF ticks
  45. * this gives us a slowest speed we can measure.
  46. * 0xFFFF = 65535 ticks
  47. * speed = SENSOR_DISTANCE / (65535 * 1000 / F_CPU)
  48. * so we can measure from 17m/s (61km/h, approx. 0.03J @ 0.2g)
  49. * up to ridulous 1120000m/s (4032000km/h)
  50. *
  51. * with a prescaler of 8, we can measure from 2.14m/s to 140000m/s
  52. * with a prescaler of 64, we can measure from 0.27m/s to 17500m/s
  53. */
  54. #include <Arduino.h>
  55. #include "ticks.h"
  56. #include "config.h"
  57. uint16_t tick_history[HISTORY_BUFFER] = DEBUG_TICK_DATA;
  58. uint8_t tick_count = DEBUG_TICK_COUNT;
  59. void tick_new_value(uint16_t ticks) {
  60. // store new value in history buffer
  61. if (tick_count < HISTORY_BUFFER) {
  62. tick_history[tick_count] = ticks;
  63. tick_count++;
  64. } else {
  65. for (uint8_t i = 0; i < HISTORY_BUFFER - 1; i++) {
  66. tick_history[i] = tick_history[i + 1];
  67. }
  68. tick_history[HISTORY_BUFFER - 1] = ticks;
  69. }
  70. }
  71. uint16_t tick_average() {
  72. if (tick_count == 0) {
  73. return 0;
  74. }
  75. uint64_t sum = 0;
  76. for (uint8_t i = 0; i < tick_count; i++) {
  77. sum += tick_history[i];
  78. }
  79. sum /= (uint64_t)tick_count;
  80. return (uint16_t)sum;
  81. }
  82. uint16_t tick_max() {
  83. if (tick_count == 0) {
  84. return 0;
  85. }
  86. uint16_t cmp = 0;
  87. for (uint8_t i = 0; i < tick_count; i++) {
  88. if (tick_history[i] > cmp) {
  89. cmp = tick_history[i];
  90. }
  91. }
  92. return cmp;
  93. }
  94. uint16_t tick_min() {
  95. if (tick_count == 0) {
  96. return 0;
  97. }
  98. uint16_t cmp = 0xFFFF;
  99. for (uint8_t i = 0; i < tick_count; i++) {
  100. if (tick_history[i] < cmp) {
  101. cmp = tick_history[i];
  102. }
  103. }
  104. return cmp;
  105. }
  106. double tick_to_metric(uint16_t ticks) {
  107. // v = d / t
  108. double period = 1000.0 / ((double)(F_CPU / TIMER_PRESCALER));
  109. double time = period * (double)ticks;
  110. double speed = (double)SENSOR_DISTANCE / time;
  111. return speed;
  112. }
  113. double metric_to_imperial(double speed) {
  114. // convert m/s to f/s
  115. speed *= 3.28084;
  116. return speed;
  117. }
  118. double metric_to_joules(double speed, double mass) {
  119. // e = 0.5 * m * v^2
  120. double energy = 0.5 * mass * speed * speed / 1000.0;
  121. return energy;
  122. }