Browse Source

add openchrono page

Thomas Buck 2 years ago
parent
commit
bb46834c71
100 changed files with 658 additions and 0 deletions
  1. 658
    0
      input/projects/openchrono.md
  2. BIN
      static/img/OpenChrono_LiPo_bb.png
  3. BIN
      static/img/OpenChrono_LiPo_bb_small.png
  4. BIN
      static/img/OpenChrono_LiPo_schem.png
  5. BIN
      static/img/OpenChrono_LiPo_schem_small.png
  6. BIN
      static/img/OpenChrono_bb.png
  7. BIN
      static/img/OpenChrono_bb_small.png
  8. BIN
      static/img/OpenChrono_schem.png
  9. BIN
      static/img/OpenChrono_schem_small.png
  10. BIN
      static/img/airsoft_silencers.jpg
  11. BIN
      static/img/airsoft_silencers_small.jpg
  12. BIN
      static/img/chrono_complete_1.jpg
  13. BIN
      static/img/chrono_complete_1_small.jpg
  14. BIN
      static/img/chrono_complete_2.jpg
  15. BIN
      static/img/chrono_complete_2_small.jpg
  16. BIN
      static/img/chrono_complete_3.jpg
  17. BIN
      static/img/chrono_complete_3_small.jpg
  18. BIN
      static/img/chrono_done_1.jpg
  19. BIN
      static/img/chrono_done_1_small.jpg
  20. BIN
      static/img/chrono_done_2.jpg
  21. BIN
      static/img/chrono_done_2_small.jpg
  22. BIN
      static/img/chrono_insert_1.jpg
  23. BIN
      static/img/chrono_insert_1_small.jpg
  24. BIN
      static/img/chrono_insert_2.jpg
  25. BIN
      static/img/chrono_insert_2_small.jpg
  26. BIN
      static/img/chrono_insert_3.jpg
  27. BIN
      static/img/chrono_insert_3_small.jpg
  28. BIN
      static/img/chrono_lipo_1.jpg
  29. BIN
      static/img/chrono_lipo_1_small.jpg
  30. BIN
      static/img/chrono_lipo_2.jpg
  31. BIN
      static/img/chrono_lipo_2_small.jpg
  32. BIN
      static/img/chrono_lipo_3.jpg
  33. BIN
      static/img/chrono_lipo_3_small.jpg
  34. BIN
      static/img/chrono_lipo_4.jpg
  35. BIN
      static/img/chrono_lipo_4_small.jpg
  36. BIN
      static/img/chrono_lipo_5.jpg
  37. BIN
      static/img/chrono_lipo_5_small.jpg
  38. BIN
      static/img/chrono_lipo_6.jpg
  39. BIN
      static/img/chrono_lipo_6_small.jpg
  40. BIN
      static/img/chrono_lipo_7.jpg
  41. BIN
      static/img/chrono_lipo_7_small.jpg
  42. BIN
      static/img/chrono_lipo_r_1.jpg
  43. BIN
      static/img/chrono_lipo_r_1_small.jpg
  44. BIN
      static/img/chrono_m11.jpg
  45. BIN
      static/img/chrono_m11_measurement_1.jpg
  46. BIN
      static/img/chrono_m11_measurement_10.jpg
  47. BIN
      static/img/chrono_m11_measurement_10_small.jpg
  48. BIN
      static/img/chrono_m11_measurement_11.jpg
  49. BIN
      static/img/chrono_m11_measurement_11_small.jpg
  50. BIN
      static/img/chrono_m11_measurement_12.jpg
  51. BIN
      static/img/chrono_m11_measurement_12_small.jpg
  52. BIN
      static/img/chrono_m11_measurement_13.jpg
  53. BIN
      static/img/chrono_m11_measurement_13_small.jpg
  54. BIN
      static/img/chrono_m11_measurement_14.jpg
  55. BIN
      static/img/chrono_m11_measurement_14_small.jpg
  56. BIN
      static/img/chrono_m11_measurement_15.jpg
  57. BIN
      static/img/chrono_m11_measurement_15_small.jpg
  58. BIN
      static/img/chrono_m11_measurement_16.jpg
  59. BIN
      static/img/chrono_m11_measurement_16_small.jpg
  60. BIN
      static/img/chrono_m11_measurement_17.jpg
  61. BIN
      static/img/chrono_m11_measurement_17_small.jpg
  62. BIN
      static/img/chrono_m11_measurement_18.jpg
  63. BIN
      static/img/chrono_m11_measurement_18_small.jpg
  64. BIN
      static/img/chrono_m11_measurement_19.jpg
  65. BIN
      static/img/chrono_m11_measurement_19_small.jpg
  66. BIN
      static/img/chrono_m11_measurement_1_small.jpg
  67. BIN
      static/img/chrono_m11_measurement_2.jpg
  68. BIN
      static/img/chrono_m11_measurement_20.jpg
  69. BIN
      static/img/chrono_m11_measurement_20_small.jpg
  70. BIN
      static/img/chrono_m11_measurement_21.jpg
  71. BIN
      static/img/chrono_m11_measurement_21_small.jpg
  72. BIN
      static/img/chrono_m11_measurement_22.jpg
  73. BIN
      static/img/chrono_m11_measurement_22_small.jpg
  74. BIN
      static/img/chrono_m11_measurement_23.jpg
  75. BIN
      static/img/chrono_m11_measurement_23_small.jpg
  76. BIN
      static/img/chrono_m11_measurement_24.jpg
  77. BIN
      static/img/chrono_m11_measurement_24_small.jpg
  78. BIN
      static/img/chrono_m11_measurement_25.jpg
  79. BIN
      static/img/chrono_m11_measurement_25_small.jpg
  80. BIN
      static/img/chrono_m11_measurement_26.jpg
  81. BIN
      static/img/chrono_m11_measurement_26_small.jpg
  82. BIN
      static/img/chrono_m11_measurement_2_small.jpg
  83. BIN
      static/img/chrono_m11_measurement_3.jpg
  84. BIN
      static/img/chrono_m11_measurement_3_small.jpg
  85. BIN
      static/img/chrono_m11_measurement_4.jpg
  86. BIN
      static/img/chrono_m11_measurement_4_small.jpg
  87. BIN
      static/img/chrono_m11_measurement_5.jpg
  88. BIN
      static/img/chrono_m11_measurement_5_small.jpg
  89. BIN
      static/img/chrono_m11_measurement_6.jpg
  90. BIN
      static/img/chrono_m11_measurement_6_small.jpg
  91. BIN
      static/img/chrono_m11_measurement_7.jpg
  92. BIN
      static/img/chrono_m11_measurement_7_small.jpg
  93. BIN
      static/img/chrono_m11_measurement_8.jpg
  94. BIN
      static/img/chrono_m11_measurement_8_small.jpg
  95. BIN
      static/img/chrono_m11_measurement_9.jpg
  96. BIN
      static/img/chrono_m11_measurement_9_small.jpg
  97. BIN
      static/img/chrono_m11_small.jpg
  98. BIN
      static/img/chrono_m11_test.mp4
  99. BIN
      static/img/chrono_m11_test_poster.png
  100. 0
    0
      static/img/chrono_m11_test_thumb.png

+ 658
- 0
input/projects/openchrono.md View File

1
+title: OpenChrono
2
+description: Airsoft Chronograph and Tracer Unit made with Arduino and 3D Printing
3
+parent: projects
4
+git: https://git.xythobuz.de/thomas/OpenChrono
5
+github: https://github.com/xythobuz/OpenChrono
6
+date: 2022-06-26
7
+comments: true
8
+---
9
+
10
+Over the past years I've been kinda getting into gas-driven Airsoft guns.
11
+They are interesting from a technical perspective and they are fun toys, as well! 😊
12
+
13
+Of course it didn't take much time for me to get some ideas on how to combine this with my other interests.
14
+So I decided to build a chronograph that can measure the speed and energy of BBs shot out of an Airsoft gun.
15
+Two infrared light-barriers detect when a BB passes so an Arduino can measure the speed and display it on an OLED display.
16
+
17
+The project was great fun.
18
+It combines different aspects of making, like 3D printing, electronics, low-level microcontroller code and shooting stuff! 🤣
19
+
20
+<!--%
21
+lightgallery([
22
+    [ "img/chrono_m11.jpg", "OpenChrono on M11 Airsoft gun" ],
23
+    [ "img/chrono_m11_measurement_4.jpg", "Graph of first M11 magazine" ],
24
+    [ "img/chrono_complete_1.jpg", "Front view of completed unit" ],
25
+    [ "img/chrono_complete_2.jpg", "Back view of completed unit" ],
26
+    [ "img/chrono_complete_3.jpg", "Top view of unit without adapter" ],
27
+])
28
+%-->
29
+
30
+The housing for OpenChrono is 3D printed and was designed in OpenSCAD.
31
+
32
+<!--%
33
+lightgallery([
34
+    [ "img/openchrono_open.png", "Inside view of 3D model" ],
35
+    [ "img/openchrono_closed.png", "Assembled 3D model" ],
36
+    [ "img/openchrono_lipo.png", "LiPo compartment in 3D model" ],
37
+])
38
+%-->
39
+
40
+As usual the project is released as free and open-source software / hardware.
41
+You can find everything you need to build it yourself in [the git repository](https://git.xythobuz.de/thomas/OpenChrono)!
42
+
43
+### Table Of Contents
44
+
45
+ * [Prototype](openchrono.html#prototype)
46
+ * [Mounting Options](openchrono.html#mounting_options)
47
+ * [Test Results](openchrono.html#test_results)
48
+ * [Build Guide](openchrono.html#build_guide)
49
+ * [Firmware](openchrono.html#firmware)
50
+ * [Possible Future Improvements](openchrono.html#possible_future_improvements)
51
+ * [Potential Other Uses](openchrono.html#potential_other_uses)
52
+ * [Links](openchrono.html#links)
53
+ * [License](openchrono.html#license)
54
+ * [More Pictures](openchrono.html#more_pictures)
55
+
56
+## Prototype
57
+<a class="anchor" name="prototype"></a>
58
+
59
+Because the optical sensing is dependent on environment conditions I decided to not do any breadboard prototyping and immediately went ahead and designed a case to test with.
60
+In this initial attempt I used an Arduino Nano, an SSD1306 128x64 OLED LCD and an AA-battery holder, all of which I still had left from other projects.
61
+For the IR phototransistor and LED I had to order some parts on eBay.
62
+This got me the [SFH 309 FA-5](https://www.osram.com/ecat/Radial%20T1%20SFH%20309%20FA/com/en/class_pim_web_catalog_103489/prd_pim_device_2219658/) as well as some no-name 940nm IR LEDs.
63
+
64
+<!--%
65
+lightgallery([
66
+    [ "img/chrono_proto_1.jpg", "First Prototype and some notes" ],
67
+    [ "img/chrono_proto_2.jpg", "First Prototype (sensors missing)" ],
68
+    [ "img/chrono_proto_3.jpg", "First Prototype, front" ],
69
+    [ "img/chrono_proto_4.jpg", "First Prototype, back" ],
70
+])
71
+%-->
72
+
73
+The circuit to connect the phototransistors to the Arduino is pretty simple.
74
+You can find [details here](https://www.electronics-notes.com/articles/electronic_components/transistor/phototransistor-circuits-applications.php).
75
+Signal processing with the Arduino is quick and easy when we have a binary signal available from the sensors, so the phototransistors are used in switch-mode.
76
+To achieve this, proper resistor values need to be selected.
77
+The current passed by the transistors is dependent on the amount of light hitting it, which is difficult for me to calculate, so I determined the proper values experimentally.
78
+
79
+<!--%
80
+lightgallery([
81
+    [ "img/chrono_proto_5.jpg", "Prototype with potis" ],
82
+    [ "img/chrono_proto_6.jpg", "Potis and dispaly with data" ],
83
+    [ "img/chrono_proto_7.jpg", "Batteries and potis" ],
84
+    [ "img/chrono_proto_8.jpg", "Scope measurement setup" ],
85
+    [ "img/chrono_proto_9.jpg", "Closer look at phototransistor" ],
86
+    [ "img/chrono_scope.bmp", "Scope view of falling BB" ],
87
+])
88
+%-->
89
+
90
+To do this I added external potis outside the case instead of resistors.
91
+You can also see a scope screenshot of both sensors triggering with a BB falling through the device.
92
+
93
+The resistor value for the IR LEDs needs to be low enough that the transistors properly switch to a low-value when the light beam is uninterrupted.
94
+This was the case for me at around 50Ω to 100Ω, depending on the supply voltage.
95
+I think it makes sense to drive the LEDs at their current limit, so ~20mA.
96
+
97
+Also the pull-up resistors for the transistors need their value to be low enough to quickly drive the signal to near supply voltage when the BB interrupts the light beam.
98
+A value of 1kΩ seems to work well there.
99
+
100
+## Mounting Options
101
+<a class="anchor" name="mounting_options"></a>
102
+
103
+Unfortunately the OpenChrono IR photo-sensing is a bit constrained in regards to the path of the BB.
104
+The sensors are only 3mm wide, and the BBs are 6mm wide commonly.
105
+So there can not be much deviation of the position of the BB in the light beam, otherwise the beam would not be fully interrupted and the speed measurement can not work.
106
+So we can not just add a big hole in the front of the unit which the user shoots through free-hand, like with standard commercial chronographs.
107
+We need to make sure the gun barrel is centered well in line with the sensor axis.
108
+
109
+I already did some experiments in the past with [3D-printed silencer imitations](https://www.printables.com/model/230609-asg-m11-silencer-handgrip) for airsoft use.
110
+So printing matching threaded adapters was not completely new to me.
111
+
112
+<!--%
113
+lightgallery([
114
+    [ "img/airsoft_silencers.jpg", "Silencers and adapters I printed in the past" ],
115
+])
116
+%-->
117
+
118
+In my first prototype I printed a matching thread into the body of the device itself, split into two halves.
119
+This was not a great idea, when screwing both halves back together the threads did not align well enough to screw something in the top.
120
+
121
+So I slightly re-designed it, making the threaded adapter plate a separate part that screws onto the body of the device.
122
+In this way it can also more easily be fitted to different guns.
123
+For my M11 I had to also add an extension plate because it has some length of barrel sticking out past the threaded part.
124
+
125
+<!--%
126
+lightgallery([
127
+    [ "img/chrono_threads_m14.jpg", "Adapter for default 14mm thread" ],
128
+    [ "img/chrono_threads_mac11.jpg", "Threaded adapter for Mac11" ],
129
+])
130
+%-->
131
+
132
+The 3D models are made using the [OpenSCAD threads library by Dan Kirshner](https://dkprojects.net/openscad-threads/).
133
+
134
+<!--%
135
+lightgallery([
136
+    [ "img/openchrono_m14.png", "Adapter for default 14mm thread" ],
137
+    [ "img/openchrono_m11.png", "Threaded adapter for Mac11" ],
138
+    [ "img/openchrono_1911.png", "Threaded adapter for 1911" ],
139
+])
140
+%-->
141
+
142
+## Test Results
143
+<a class="anchor" name="test_results"></a>
144
+
145
+Attaching the whole unit to a airsoft gun barrel turned out to be a bit tricky.
146
+
147
+The first gun I wanted to test with is a full-metal TM 1911 clone with a gas blowback system.
148
+The repetition imparts a big impulse on any barrel attachment, big enough to break my self-made silencer adapters in the past after a single-digit number of shots.
149
+Of course OpenChrono is much heavier than a plastic silencer imitation, so predictably it broke after only three test shots, even though I supported the weight with my hand.
150
+Additionally the impulse in combination with the inertia of the AA batteries caused the supply voltage to cut out in the moment of shooting.
151
+So no usable measurements could be obtained.
152
+
153
+<!--%
154
+lightgallery([
155
+    [ "img/chrono_threads_1911.jpg", "Broken threaded adapter for 1911" ],
156
+])
157
+%-->
158
+
159
+For the second test run I tried to use a non-blowback ASG Ingram M11 Co2 gun.
160
+Besides some unrelated problems with the magazines it worked relatively well.
161
+Even without blowback the impulse on firing is still big enough to cut out the AA battery power.
162
+But this time it was easily possible to hold the batteries in place by hand while shooting, avoiding the problem.
163
+The measurement results looked mostly realistic, ranging from nearly zero with an empty gas capsule, up to ~1.5J with a full one, which roughly matches the specs of the gun (which hopefully was to be expected, as it is completely unmodified).
164
+With one magazine I got some faulty readings, counting a single shot multiple times with ridiculously high velocities.
165
+I suspect this was caused by oil droplets from a maintenance capsule that was in the magazine previously.
166
+But because of the aforementioned magazine problems I was only able to shoot about 20 BBs for this test.
167
+
168
+<!--%
169
+lightgallery([
170
+    [ "img/chrono_m11.jpg", "OpenChrono on M11 Airsoft gun" ],
171
+    [ "img/chrono_m11_test.mp4", "video/mp4", "img/chrono_m11_test_thumb.png", "img/chrono_m11_test_poster.png", "Video of magazine shot through M11" ],
172
+])
173
+%-->
174
+
175
+To be able to properly measure anything I next redesigned the hardware to use a soldered-in LiPo battery that won't disconnect on firing.
176
+For the next test with the M11 I went through about 200 shots or more without seeing a single false measurement.
177
+
178
+<!--%
179
+lightgallery([
180
+    [ "img/chrono_m11_measurement_1.jpg", "Data for last shot of first magazine" ],
181
+    [ "img/chrono_m11_measurement_4.jpg", "Graph of first magazine" ],
182
+    [ "img/chrono_m11_measurement_7.jpg", "Graph of later magazine" ],
183
+    [ "img/chrono_m11_measurement_23.jpg", "Graph of later magazine" ],
184
+])
185
+%-->
186
+
187
+The results are interesting, you can see the behaviour of the Co2 capsule well.
188
+With the first shots with a fresh capsule the speed is about 105m/s, which is 1.39J at 0.25g BB weight.
189
+The speed then reduces with each shot and goes back up again when waiting long enough between shots, as the capsule slowly heats up again.
190
+With the last couple of shots I took only 0.23J were left.
191
+
192
+I also want to continue testing with the blowback 1911.
193
+But I first need to get a metal threaded adapter that can withstand the forces.
194
+A female printed thread should do much better than my first test run.
195
+
196
+## Build Guide
197
+<a class="anchor" name="build_guide"></a>
198
+
199
+Also take a look at [the "Hardware" section of the README.md](https://git.xythobuz.de/thomas/OpenChrono/src/branch/master/README.md#hardware).
200
+You can find detailed parts lists, schematic and wiring plan there as well.
201
+
202
+Before starting the build you need to acquire the following parts.
203
+
204
+<!--%
205
+tableHelper([ "align-right", "align-right", "align-right monospaced", "align-left" ],
206
+    [ "Description", "Type", "Count", "Link" ], [
207
+        [ "Arduino Nano", "", "1x", "<a href=\"https://store.arduino.cc/products/arduino-nano\">Arduino Store</a>, <a href=\"https://www.aliexpress.com/item/1005002998391675.html\">AliExpress</a>" ],
208
+        [ "LCD 128x64 I2C", "SSD1306 0.96\"", "1x", "<a href=\"https://www.aliexpress.com/item/32638662748.html\">AliExpress</a>, <a href=\"https://www.ebay.de/itm/353351582659\">eBay.de</a>" ],
209
+        [ "Slide Switch", "", "1x", "<a href=\"https://www.aliexpress.com/item/32765155281.html\">AliExpress</a>, <a href=\"https://www.ebay.de/itm/334211625913\">eBay.de</a>" ],
210
+        [ "IR Phototransistor", "<a href=\"https://www.osram.com/ecat/Radial%20T1%20SFH%20309%20FA/com/en/class_pim_web_catalog_103489/prd_pim_device_2219658/\">SFH 309 FA</a>-5", "2x", "<a href=\"https://www.reichelt.de/de/de/fototransistor-npn-730-1120nm-24-tht-3mm-sfh-309-fa-p60553.html\">Reichelt</a>, <a href=\"https://www.ebay.de/itm/353899814039\">eBay.de</a>" ],
211
+        [ "IR LED 3mm", "940nm", "2x", "<a href=\"https://www.aliexpress.com/item/32660252297.html\">AliExpress</a>, <a href=\"https://www.ebay.de/itm/321558979835?var=510446659784\">eBay.de</a>" ],
212
+        [ "LiPo Battery", "600mAh", "1x", "<a href=\"https://www.aliexpress.com/item/1005004340664249.html\">AliExpress</a>, <a href=\"https://www.ebay.de/itm/193560287247\">eBay.de</a>" ],
213
+        [ "Charging Module", "TP4056", "1x", "<a href=\"https://www.aliexpress.com/item/32930640893.html\">AliExpress</a>, <a href=\"https://www.ebay.de/itm/154034193943?var=454147761245\">eBay.de</a>" ],
214
+        [ "Resistor SMD", "4kΩ, 0603", "1x", "<a href=\"https://www.ebay.de/itm/373651719055?var=642713852109\">eBay.de</a>" ],
215
+        [ "Resistor", "1kΩ", "2x", "<a href=\"https://www.ebay.de/itm/352540072577\">eBay.de</a>" ],
216
+        [ "Resistor", "50Ω", "1x", "<a href=\"https://www.ebay.de/itm/372813822157?var=642490601730\">eBay.de</a>" ],
217
+        [ "Screws (Display)", "M2 10mm", "4x", "<a href=\"https://www.ebay.de/itm/261298209327?var=560230293993\">eBay.de</a>" ],
218
+        [ "Screws (Switch)", "M2.5 10mm", "2x", "<a href=\"https://www.ebay.de/itm/261298209327?var=560230293999\">eBay.de</a>" ],
219
+        [ "Screws (Body)", "M3 16mm", "8x", "<a href=\"https://www.ebay.de/itm/261298209327?var=560230294009\">eBay.de</a>" ],
220
+        [ "Screws (Lid)", "M3 <= 6mm", "4x", "<a href=\"https://www.ebay.de/itm/261298209327?var=560230294003\">eBay.de</a>" ],
221
+        [ "Heatmelt Insert", "M3 <= 10mm", "8x", "<a href=\"https://www.ebay.de/itm/184650202586?var=692369947868\">eBay.de</a>" ],
222
+    ]
223
+)
224
+%-->
225
+
226
+For the UV tracer option you also need the following parts.
227
+
228
+<!--%
229
+tableHelper([ "align-right", "align-right", "align-right monospaced", "align-left" ],
230
+    [ "Description", "Type", "Count", "Link" ], [
231
+        [ "UV LED 3mm", "", "2x", "<a href=\"https://www.ebay.de/itm/373071970513\">eBay.de</a>" ],
232
+        [ "Resistor", "50Ω", "1x", "<a href=\"https://www.ebay.de/itm/372813822157?var=642490601730\">eBay.de</a>" ],
233
+    ]
234
+)
235
+%-->
236
+
237
+Next you need to generate the STL files with [OpenSCAD](https://openscad.org/) using [the script in the repository](https://git.xythobuz.de/thomas/OpenChrono/src/branch/master/hardware/openchrono.scad).
238
+You can set `include_uv_leds` to `true` or `false` in there.
239
+At the bottom, comment out the proper parts you need to print.
240
+Besides the `left_half`, you need to select the proper `right_half_xxx` depending on your power source.
241
+For LiPo battery use, also print the `lipo_lid`.
242
+Then select the proper threaded adapter for your gun.
243
+You will most likely need to print either `thread_profile_m14_cw` or `thread_profile_m14_ccw` for standard 14mm diameter, 1mm pitch threads.
244
+Other thread profiles can be added easily.
245
+
246
+Print the parts, remove supports and do some sanding as needed.
247
+Then put in the heat-melt inserts.
248
+I recommend using a spare thick soldering iron tip.
249
+Also I put in a small grub screw and place it at the bottom of the insert.
250
+This way, any plastic that gets pushed down will not clog the thread.
251
+Push them in, use a hard flat surface to align them with the printed part, let it cool and remove the grub screw.
252
+
253
+<!--%
254
+lightgallery([
255
+    [ "img/chrono_insert_1.jpg", "Heat-melt insert with grub screw" ],
256
+    [ "img/chrono_insert_2.jpg", "Heat-melt insert on soldering iron" ],
257
+    [ "img/chrono_insert_3.jpg", "Putting in heat-melt insert" ],
258
+])
259
+%-->
260
+
261
+To connect all the parts I recommend using a thin stranded wire.
262
+I used the cores of an old ethernet cable.
263
+First solder wires with enough length to the OLED display and power switch.
264
+Feed these through the printed `left_half` before screwing on both parts from the outside.
265
+
266
+<!--%
267
+lightgallery([
268
+    [ "img/chrono_wiring_4.jpg", "Wiring of power switch" ],
269
+    [ "img/chrono_wiring_5.jpg", "Wiring of OLED display" ],
270
+])
271
+%-->
272
+
273
+On the inside of the `left_half` you should next add the IR LEDs and phototransistors (and UV LEDs, if needed).
274
+Pre-bend the wires of the parts to a 90 degree shape that fits the slots in the parts.
275
+If you'd like, add some heat-shrink tubing to insulate agains potential shorts.
276
+
277
+Next use a small amount of hotglue to fix the LEDs and transistors into their respective slots.
278
+
279
+You need to take care to align the phototransistors and the LEDs properly.
280
+They need to look at each other as straight as possible.
281
+If there is too much deviation, and you maybe also have a resistor that limits the LED current too much, the transistor will not switch properly!
282
+
283
+<!--%
284
+lightgallery([
285
+    [ "img/OpenChrono_LiPo_bb.png", "LiPo 'Breadboard' wiring plan" ],
286
+    [ "img/OpenChrono_LiPo_schem.png", "LiPo Schematics" ],
287
+])
288
+%-->
289
+
290
+Connect the LEDs in series, as shown on the schematics.
291
+For ease of soldering place the resistor in between the two IR LEDs.
292
+To connect the IR LEDs to the Arduino, feed two wires through their canal in the `left_half` to bring them over to the other side.
293
+
294
+For the UV LED option, you can simply route the wires along the existing channels for the IR LED wires.
295
+Only fitting the additional resistor in can be a little bit tricky.
296
+
297
+Do the same for the phototransistors.
298
+I recommend connecting both of their Emitters, as well as all the other Ground connections (battery, OLED display, phototransistors, LEDs) together in one spot, wrapping their connection point in heat-shrink tubing.
299
+For the pull-up resistors of the phototransistors, I soldered them on top over the Arduino to the +5V pad, with heat-shrink tubing to prevent any shorts.
300
+I think this is the most space efficient solution.
301
+
302
+Also beware to not leave too long dangling wires.
303
+This will make later putting both halves together difficult.
304
+
305
+You should be able to build all this with 0.25W THT resistors and everything can fit if you take care to not use up too much space.
306
+If you can I recommend using SMT parts to greatly ease assembly.
307
+But just to make sure it can be done, I used THT parts.
308
+
309
+Now everything should be connected to the Arduino.
310
+As the final step for the left half, solder two wires to +5V and GND of the Arduino respectively and leave them dangling for maybe 10mm or more.
311
+This will later connect to the right half.
312
+
313
+<!--%
314
+lightgallery([
315
+    [ "img/chrono_wiring_1.jpg", "Wiring below Arduino" ],
316
+    [ "img/chrono_wiring_2.jpg", "Arduino and phototransistors" ],
317
+    [ "img/chrono_wiring_3.jpg", "IR LEDs and Arduino" ],
318
+])
319
+%-->
320
+
321
+Next we're going to prepare the right half.
322
+
323
+**Beware:** If you use the TP4056 LiPo charger board, they normally come with the charge current set to 1A with a 1.2kΩ resistor on position R3.
324
+You need to put in a higher valued resistor instead, otherwise the small battery will be charged with far too much current and the charger will get very hot.
325
+I recommend 4kΩ or more.
326
+See [this page](https://www.best-microcontroller-projects.com/tp4056.html#TP4056_Current_Programming_Resistor) and [this video](https://www.youtube.com/watch?v=M88e1r8nvYk) for more info.
327
+
328
+<!--%
329
+lightgallery([
330
+    [ "img/chrono_lipo_r_1.jpg", "Swapping the current resistor" ],
331
+])
332
+%-->
333
+
334
+Next either solder the battery directly to the proper charging board pads, or, if you have it, use the connector that's probably already fitted to your battery, like I did.
335
+Also connect two wires to the OUT+ and OUT- pads, and feed them through the hole next to the charger board hole.
336
+Now first see if the board properly fits into its slot.
337
+If that is the case take it out again, put some dabs of hotglue in the hole, and push the board back in.
338
+You should be able to easily remove hotglue in the USB connector area while it is still warm.
339
+Then secure the board with some more glue on the sides and on top.
340
+This should hold the board firmly in place even when pushing in a USB connector!
341
+
342
+<!--%
343
+lightgallery([
344
+    [ "img/chrono_lipo_3.jpg", "LiPo charger prepared" ],
345
+    [ "img/chrono_lipo_6.jpg", "LiPo compartment of device" ],
346
+    [ "img/chrono_lipo_7.jpg", "LiPo battery in device" ],
347
+])
348
+%-->
349
+
350
+**Beware:** If you are using the LiPo charger make sure to _always_ keep the power switch in the off position while having a charging USB cable connected.
351
+
352
+Turn the right half to the inside and cut the power supply wires to an appropriate length.
353
+Then solder them to the power supply wires of the Arduino, insulating with some heat-shrink tubing.
354
+
355
+To flash the firmware onto your Arduino please also take a look at [the "Software" section of the README.md](https://git.xythobuz.de/thomas/OpenChrono/src/branch/master/README.md#software).
356
+
357
+**Beware:** _Always_ leave the power switch in the off position when connecting a USB cable to flash the Arduino.
358
+
359
+Finally screw both halves together, put in the battery and turn your device on.
360
+Test it by dropping a BB through the device (but beware, depending on your firmware setting this may be too low a speed to measure properly).
361
+
362
+<!--%
363
+lightgallery([
364
+    [ "img/chrono_done_1.jpg", "LiPo battery compartment lid" ],
365
+    [ "img/chrono_done_2.jpg", "Front of unit with USB charging port" ],
366
+])
367
+%-->
368
+
369
+Attach the threaded adapter for your gun and in turn attach all this to your airsoft gun.
370
+For the first tests, I recommend supporting the weight of the device from below with your hand, depending on how your gun works and if the excess weight may damage the mechanism.
371
+Also be careful for the first test shots!
372
+If for some reason the hole through the device is not perfectly aligned with your gun barrel, the BB may skip off from the side walls and come out of the front in unpredictable directions.
373
+In that case, you will not hit what you are aiming at!
374
+So beware of your environment, wear proper safety gear and start out with a short distance to your bullet stop, increasing only slowly as you are sure everything works as expected.
375
+
376
+## Firmware
377
+<a class="anchor" name="firmware"></a>
378
+
379
+To achieve high measurement accuracy I used some of the hardware features of the AtMega328p MCU included in standard Arduinos.
380
+
381
+To measure the impulses I'm using the two available external interrupts, INT0 and INT1.
382
+They are connected to the phototransistors and usually are on a low level when the LED shines on them as no BB passes through.
383
+When the BB passes the transistor the interrupt pins are pulled high.
384
+
385
+So I'm triggering them on rising edges and measure the current time in the interrupt routines and set a flag.
386
+
387
+<pre class="sh_cpp">
388
+void interrupt_init() {
389
+    // trigger both on rising edge
390
+    EICRA = (1 << ISC00) | (1 << ISC01);
391
+    EICRA |= (1 << ISC10) | (1 << ISC11);
392
+
393
+    // enable interrupts
394
+    EIMSK = (1 << INT0) | (1 << INT1);
395
+}
396
+
397
+/*
398
+ * this is supposed to be the "input" sensor,
399
+ * the one that triggers first on firing.
400
+ */
401
+ISR(INT0_vect) {
402
+    time_a = timer_get();
403
+    trigger_a = 1;
404
+}
405
+
406
+/*
407
+ * this is supposed to be the "output" sensor,
408
+ * the one that triggers after the other sensor.
409
+ */
410
+ISR(INT1_vect) {
411
+    time_b = timer_get();
412
+    trigger_b = 1;
413
+
414
+    // we now need to turn on the UV led
415
+    // and make sure it will only be on shortly!
416
+    timer_start();
417
+    digitalWrite(UV_LED_PIN, HIGH);
418
+}
419
+</pre>
420
+
421
+For `timer_get()` and `timer_start()` I'm using another feature of AVR MCUs, their internal Timers.
422
+The 328p has three timers.
423
+Timer0 and Timer2 are 8bit, but Timer0 is already used by the Arduino framework to keep track of the passed milliseconds.
424
+Timer1 is 16bit and can therefore count for the longest time, so I'm using that to measure the speed of the BBs.
425
+
426
+To keep the interrupt routines as short and as equal-length as possible, I'm running the Timer1 all the time.
427
+It simply counts from 0x0000 to 0xFFFF and on overflow rolls back to the beginning.
428
+The clock source prescaler determines the maximum and minimum possible measurement speeds.
429
+When the external interrupts fire, they simply record the current value of Timer1.
430
+Later when both have fired and the UI code is not busy, both stored timer values will be used to calculate the time it took for the BB to travel the distance between the measurements.
431
+
432
+<pre class="sh_cpp">
433
+static void timer1_init() {
434
+    // normal mode
435
+    TCCR1A = 0;
436
+
437
+    // prescaler
438
+#if TIMER_PRESCALER == 1
439
+    TCCR1B = (1 << CS10);
440
+#elif TIMER_PRESCALER == 8
441
+    TCCR1B = (1 << CS11);
442
+#elif TIMER_PRESCALER == 64
443
+    TCCR1B = (1 << CS11) | (1 << CS10);
444
+#elif TIMER_PRESCALER == 256
445
+    TCCR1B = (1 << CS12);
446
+#elif TIMER_PRESCALER == 1024
447
+    TCCR1B = (1 << CS12) | (1 << CS10);
448
+#else
449
+#error Invalid Prescaler for Timer1
450
+#endif
451
+}
452
+
453
+uint16_t timer_get() {
454
+    return TCNT1;
455
+}
456
+
457
+// ...
458
+
459
+void calculate(uint16_t a, uint16_t b) {
460
+    uint16_t ticks = 0;
461
+
462
+    if (b >= a) {
463
+        // simple case - just return difference
464
+        ticks = b - a;
465
+    } else {
466
+        // the timer overflowed between measurements!
467
+        int32_t tmp = ((int32_t)b) - ((int32_t)a);
468
+        tmp += 0x10000;
469
+        ticks = (uint16_t)tmp;
470
+    }
471
+
472
+    // ...
473
+}
474
+</pre>
475
+
476
+From this the speed and (given the BB weight) the energy can be calculated easily.
477
+
478
+<pre class="sh_cpp">
479
+double tick_to_metric(uint16_t ticks) {
480
+    // v = d / t
481
+    double period = 1000.0 / ((double)(F_CPU / TIMER_PRESCALER));
482
+    double time = period * (double)ticks;
483
+    double speed = (double)SENSOR_DISTANCE / time;
484
+    return speed;
485
+}
486
+
487
+double metric_to_imperial(double speed) {
488
+    // convert m/s to f/s
489
+    speed *= 3.28084;
490
+    return speed;
491
+}
492
+
493
+double metric_to_joules(double speed, double mass) {
494
+    // e = 0.5 * m * v^2
495
+    double energy = 0.5 * mass * speed * speed / 1000.0;
496
+    return energy;
497
+}
498
+</pre>
499
+
500
+Timer2 is used for the tracer feature, to turn on the UV LEDs only for as long as needed.
501
+This could enable a future improvement where the UV LEDs could be pulsed with a far higher current to achieve more light output.
502
+To pulse the LEDs I'm only connecting the timer to a clock source when the LEDs have been turned on, with an initial value of the timer that determines how long it will take to count up to 0xFF.
503
+Then in the overflow interrupt I'm turning off both the LEDs and the Timer again.
504
+
505
+<pre class="sh_cpp">
506
+static void timer2_init() {
507
+    // normal mode, no clock source
508
+    TCCR2A = 0;
509
+    TCCR2B = 0;
510
+
511
+    // enable overflow interrupt
512
+    TIMSK2 = (1 << TOIE2);
513
+}
514
+
515
+void timer_start() {
516
+    /*
517
+     * the distance between the second IR sensor
518
+     * and the UV LEDs is 7.5mm.
519
+     * Our bullet will travel with a speed of
520
+     * ~10m/s up to ~300m/s approximately.
521
+     * So it will move the 7.5mm in
522
+     * 750us to 25us respectively.
523
+     * So it makes sense to keep the UV LED
524
+     * on for 1ms.
525
+     *
526
+     * We reach exactly 1ms when counting to 250
527
+     * with a prescaler of 64 at 16MHz.
528
+     *
529
+     * If you __really__ want to increase the brightness
530
+     * of the tracer, reduce the pulse length here.
531
+     * Then you can also reduce the UV LED resistor for
532
+     * higher currents, according to the datasheet of
533
+     * your UV LED.
534
+     * Make sure to keep within 40mA the AVR GPIO can provide.
535
+     * Otherwise you need to add a transistor for switching.
536
+     */
537
+    const static uint8_t pulse_length = 250;
538
+
539
+    // initial value we count up from
540
+    TCNT2 = 0xFF - pulse_length;
541
+
542
+    // prescaler 64
543
+    TCCR2B = (1 << CS22);
544
+}
545
+
546
+ISR(TIMER2_OVF_vect) {
547
+    // turn off UV LED
548
+    digitalWrite(UV_LED_PIN, LOW);
549
+
550
+    // and also stop timer
551
+    TCCR2B = 0;
552
+}
553
+</pre>
554
+
555
+In the main-loop I'm simply updating the LCD to show the measured values.
556
+This is very easy to implement using the great [u8g2 library](https://github.com/olikraus/u8g2).
557
+
558
+If you're interested I recommend taking a look at [the code](https://git.xythobuz.de/thomas/OpenChrono/src/branch/master/firmware/OpenChrono).
559
+I think it should be relatively easy to understand and well commented 😅
560
+
561
+## Possible Future Improvements
562
+<a class="anchor" name="possible_future_improvements"></a>
563
+
564
+As usual I was mostly using parts that I already had.
565
+That explains some strange design decisions, like using cylindrical screws for the battery compartment lid, which honestly look and feel ugly and stand out from the device.
566
+
567
+I'm sure it is also possible to make better use of the space inside the device and make wiring much easier that way.
568
+
569
+Also the tracer feature has been kind of an afterthought.
570
+I have no real use for it and have not really tested it.
571
+So I'm not sure how well it will work in practice under different conditions.
572
+I also don't think it's realistic to take this bulky device onto a field, but who knows, I'm not really into that.
573
+
574
+To be quite honest, I'm happy with the device as it is now.
575
+But I'm always open to feedback and pull requests of course 😉
576
+
577
+## Potential Other Uses
578
+<a class="anchor" name="potential_other_uses"></a>
579
+
580
+One thing I'd like to talk about is using this device for measuring other things besides Airsoft BBs.
581
+It is definitely feasible to use OpenChrono to measure the speed of air rifle pellets, and this is something I would be interested in as well.
582
+Unfortunately my air rifle does not have a threaded barrel, so attaching the device with proper alignment will be difficult.
583
+
584
+Speaking from a measurement perspective, the phototransistors and the Arduino are easily able to measure higher speeds.
585
+500m/s or more should be no problem.
586
+So it is possible to measure much faster projectiles, like real bullets for example.
587
+Beware however about the 3D printed housing.
588
+I'm not sure if it would be able to survive either the pressures involved or the impulse of firing.
589
+This could maybe partly be fixed by adding depressurization holes to the device.
590
+All the hot gases coming out of a real gun will probably also be problematic, both for the plastic and for the optical measurement method.
591
+
592
+But all this is not something I can or want to test, and I also do not recommend you do it, either! 👮
593
+
594
+## Links
595
+<a class="anchor" name="links"></a>
596
+
597
+You can find [all the source code and design files for OpenChrono](https://git.xythobuz.de/thomas/OpenChrono) on my [Gitea instance](https://git.xythobuz.de).
598
+The project is also [mirrored on GitHub](https://github.com/xythobuz/OpenChrono).
599
+
600
+If you decide to build it yourself I would be interested in any kind of feedback!
601
+
602
+## License
603
+<a class="anchor" name="license"></a>
604
+
605
+OpenChrono is licensed under the [GNU General Public License](https://www.gnu.org/licenses/gpl-3.0.en.html).
606
+
607
+    Copyright (c) 2022 Thomas Buck <thomas@xythobuz.de>
608
+
609
+    OpenChrono is free software: you can redistribute it and/or modify
610
+    it under the terms of the GNU General Public License as published by
611
+    the Free Software Foundation, either version 3 of the License, or
612
+    (at your option) any later version.
613
+
614
+    OpenChrono is distributed in the hope that it will be useful,
615
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
616
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
617
+    GNU General Public License for more details.
618
+
619
+    You should have received a copy of the GNU General Public License
620
+    along with OpenChrono.  If not, see <https://www.gnu.org/licenses/>.
621
+
622
+## More Pictures
623
+<a class="anchor" name="more_pictures"></a>
624
+
625
+Here are some more photographs I didn't use above.
626
+
627
+<!--%
628
+lightgallery([
629
+    [ "img/OpenChrono_bb.png", "AA 'Breadboard' wiring plan" ],
630
+    [ "img/OpenChrono_schem.png", "AA Schematics" ],
631
+    [ "img/chrono_lipo_1.jpg", "Battery and charger on their own" ],
632
+    [ "img/chrono_lipo_2.jpg", "Fitting test of charger and LiPo" ],
633
+    [ "img/chrono_lipo_4.jpg", "LiPo charger with cable" ],
634
+    [ "img/chrono_lipo_5.jpg", "Glued-in LiPo charger" ],
635
+    [ "img/chrono_m11_measurement_2.jpg", "Minimum for first magazine" ],
636
+    [ "img/chrono_m11_measurement_3.jpg", "Maximum for first magazine" ],
637
+    [ "img/chrono_m11_measurement_5.jpg", "" ],
638
+    [ "img/chrono_m11_measurement_6.jpg", "" ],
639
+    [ "img/chrono_m11_measurement_8.jpg", "" ],
640
+    [ "img/chrono_m11_measurement_9.jpg", "" ],
641
+    [ "img/chrono_m11_measurement_10.jpg", "" ],
642
+    [ "img/chrono_m11_measurement_11.jpg", "" ],
643
+    [ "img/chrono_m11_measurement_12.jpg", "" ],
644
+    [ "img/chrono_m11_measurement_13.jpg", "" ],
645
+    [ "img/chrono_m11_measurement_14.jpg", "Graph of later magazine" ],
646
+    [ "img/chrono_m11_measurement_15.jpg", "" ],
647
+    [ "img/chrono_m11_measurement_16.jpg", "" ],
648
+    [ "img/chrono_m11_measurement_17.jpg", "" ],
649
+    [ "img/chrono_m11_measurement_18.jpg", "" ],
650
+    [ "img/chrono_m11_measurement_19.jpg", "Graph of later magazine" ],
651
+    [ "img/chrono_m11_measurement_20.jpg", "" ],
652
+    [ "img/chrono_m11_measurement_21.jpg", "" ],
653
+    [ "img/chrono_m11_measurement_22.jpg", "" ],
654
+    [ "img/chrono_m11_measurement_24.jpg", "" ],
655
+    [ "img/chrono_m11_measurement_25.jpg", "" ],
656
+    [ "img/chrono_m11_measurement_26.jpg", "" ],
657
+])
658
+%-->

BIN
static/img/OpenChrono_LiPo_bb.png View File


BIN
static/img/OpenChrono_LiPo_bb_small.png View File


BIN
static/img/OpenChrono_LiPo_schem.png View File


BIN
static/img/OpenChrono_LiPo_schem_small.png View File


BIN
static/img/OpenChrono_bb.png View File


BIN
static/img/OpenChrono_bb_small.png View File


BIN
static/img/OpenChrono_schem.png View File


BIN
static/img/OpenChrono_schem_small.png View File


BIN
static/img/airsoft_silencers.jpg View File


BIN
static/img/airsoft_silencers_small.jpg View File


BIN
static/img/chrono_complete_1.jpg View File


BIN
static/img/chrono_complete_1_small.jpg View File


BIN
static/img/chrono_complete_2.jpg View File


BIN
static/img/chrono_complete_2_small.jpg View File


BIN
static/img/chrono_complete_3.jpg View File


BIN
static/img/chrono_complete_3_small.jpg View File


BIN
static/img/chrono_done_1.jpg View File


BIN
static/img/chrono_done_1_small.jpg View File


BIN
static/img/chrono_done_2.jpg View File


BIN
static/img/chrono_done_2_small.jpg View File


BIN
static/img/chrono_insert_1.jpg View File


BIN
static/img/chrono_insert_1_small.jpg View File


BIN
static/img/chrono_insert_2.jpg View File


BIN
static/img/chrono_insert_2_small.jpg View File


BIN
static/img/chrono_insert_3.jpg View File


BIN
static/img/chrono_insert_3_small.jpg View File


BIN
static/img/chrono_lipo_1.jpg View File


BIN
static/img/chrono_lipo_1_small.jpg View File


BIN
static/img/chrono_lipo_2.jpg View File


BIN
static/img/chrono_lipo_2_small.jpg View File


BIN
static/img/chrono_lipo_3.jpg View File


BIN
static/img/chrono_lipo_3_small.jpg View File


BIN
static/img/chrono_lipo_4.jpg View File


BIN
static/img/chrono_lipo_4_small.jpg View File


BIN
static/img/chrono_lipo_5.jpg View File


BIN
static/img/chrono_lipo_5_small.jpg View File


BIN
static/img/chrono_lipo_6.jpg View File


BIN
static/img/chrono_lipo_6_small.jpg View File


BIN
static/img/chrono_lipo_7.jpg View File


BIN
static/img/chrono_lipo_7_small.jpg View File


BIN
static/img/chrono_lipo_r_1.jpg View File


BIN
static/img/chrono_lipo_r_1_small.jpg View File


BIN
static/img/chrono_m11.jpg View File


BIN
static/img/chrono_m11_measurement_1.jpg View File


BIN
static/img/chrono_m11_measurement_10.jpg View File


BIN
static/img/chrono_m11_measurement_10_small.jpg View File


BIN
static/img/chrono_m11_measurement_11.jpg View File


BIN
static/img/chrono_m11_measurement_11_small.jpg View File


BIN
static/img/chrono_m11_measurement_12.jpg View File


BIN
static/img/chrono_m11_measurement_12_small.jpg View File


BIN
static/img/chrono_m11_measurement_13.jpg View File


BIN
static/img/chrono_m11_measurement_13_small.jpg View File


BIN
static/img/chrono_m11_measurement_14.jpg View File


BIN
static/img/chrono_m11_measurement_14_small.jpg View File


BIN
static/img/chrono_m11_measurement_15.jpg View File


BIN
static/img/chrono_m11_measurement_15_small.jpg View File


BIN
static/img/chrono_m11_measurement_16.jpg View File


BIN
static/img/chrono_m11_measurement_16_small.jpg View File


BIN
static/img/chrono_m11_measurement_17.jpg View File


BIN
static/img/chrono_m11_measurement_17_small.jpg View File


BIN
static/img/chrono_m11_measurement_18.jpg View File


BIN
static/img/chrono_m11_measurement_18_small.jpg View File


BIN
static/img/chrono_m11_measurement_19.jpg View File


BIN
static/img/chrono_m11_measurement_19_small.jpg View File


BIN
static/img/chrono_m11_measurement_1_small.jpg View File


BIN
static/img/chrono_m11_measurement_2.jpg View File


BIN
static/img/chrono_m11_measurement_20.jpg View File


BIN
static/img/chrono_m11_measurement_20_small.jpg View File


BIN
static/img/chrono_m11_measurement_21.jpg View File


BIN
static/img/chrono_m11_measurement_21_small.jpg View File


BIN
static/img/chrono_m11_measurement_22.jpg View File


BIN
static/img/chrono_m11_measurement_22_small.jpg View File


BIN
static/img/chrono_m11_measurement_23.jpg View File


BIN
static/img/chrono_m11_measurement_23_small.jpg View File


BIN
static/img/chrono_m11_measurement_24.jpg View File


BIN
static/img/chrono_m11_measurement_24_small.jpg View File


BIN
static/img/chrono_m11_measurement_25.jpg View File


BIN
static/img/chrono_m11_measurement_25_small.jpg View File


BIN
static/img/chrono_m11_measurement_26.jpg View File


BIN
static/img/chrono_m11_measurement_26_small.jpg View File


BIN
static/img/chrono_m11_measurement_2_small.jpg View File


BIN
static/img/chrono_m11_measurement_3.jpg View File


BIN
static/img/chrono_m11_measurement_3_small.jpg View File


BIN
static/img/chrono_m11_measurement_4.jpg View File


BIN
static/img/chrono_m11_measurement_4_small.jpg View File


BIN
static/img/chrono_m11_measurement_5.jpg View File


BIN
static/img/chrono_m11_measurement_5_small.jpg View File


BIN
static/img/chrono_m11_measurement_6.jpg View File


BIN
static/img/chrono_m11_measurement_6_small.jpg View File


BIN
static/img/chrono_m11_measurement_7.jpg View File


BIN
static/img/chrono_m11_measurement_7_small.jpg View File


BIN
static/img/chrono_m11_measurement_8.jpg View File


BIN
static/img/chrono_m11_measurement_8_small.jpg View File


BIN
static/img/chrono_m11_measurement_9.jpg View File


BIN
static/img/chrono_m11_measurement_9_small.jpg View File


BIN
static/img/chrono_m11_small.jpg View File


BIN
static/img/chrono_m11_test.mp4 View File


BIN
static/img/chrono_m11_test_poster.png View File


+ 0
- 0
static/img/chrono_m11_test_thumb.png View File


Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save