Arduino for Nerf: Ballistic Chronograph




Introduction: Arduino for Nerf: Ballistic Chronograph

Arduino is an amazing tool for Makers, and as I got back into Nerf and started modding, I began to wonder what I could do with Arduindo to help determine the effect of modifications. Take a look at any older Nerf video and you will find a kid firing darts on their lawn over a tape measure. Take a look at any recent Nerf video, and you will see them shooting darts through an expensive ballistic chronograph. Why not apply Arduino to help us with Nerf mods, both in measuring performance and in controlling operation?

Using this project to measure dart speed as an example, I looked at the effect of removing the air restrictor and adding a stronger spring to a thrift-store Modulus Modulator. Either mod by itself equated to 20 to 25% improvement. Together, however, an exponential increase of almost 80%!

The cover photo is just a teaser example of a chrongraph integrated with a barrel attachment and display. We will first focus on detection portion and get the readings on a serial console. And yes, this poor old unmodified thrift-store Recon is shooting a miserable 40 fps. Once we know what we are starting with we can start modding to see the effects . ..

There are already a number of cool projects like this out there. My goal for this one was to make it fundamental enough to understand and easy enough for a beginner to accomplish. You'll have to judge if I succeeded, or let me know how to make it better.

Step 1: How Does It Work?

There are a number of methods to measure the speed of an object. We want easy, reliable, and inexpensive. My choice is an infrared emitter detector pair. The microcontroller will sense when an object enters the beam, and when the object leaves the beam. If we know the length of the object, and measure the time it takes, we have all the ingredients needed calculate velocity.

The photo transistor works as a switch, but instead of a signal being applied to the base to allow current to flow from the collector to the emitter, light is applied. The dark cover means only infrared light will work. We are using a small resistor to pull-up the signal to 5 volts, so when the IR light is detected, current flows through the transistor, allowing the signal to fall toward 0 volts. It is a bit counter intuitive, but it works. Learn more about how transistors work at

Step 2: Parts and Tools

To start with, we just want to wire something up to test it on the bench. Later, we can integrate it into a stand-alone solution ready for the battlefield.



Step 3: Let's Begin . . .

The photo transistor is the dark package.

The short leg is the collector. We are going to attach the sensor wire and a 10K ohm pull-up resistor to it.

  • Select a jumper wire with a color other than black or red (orange in the photo looks red).
  • Cut one end off near the terminal and strip about 1/2" of insulation off.
  • Twist the sensor wire with the 10K resistor around the short leg and solder them together.
  • Slide a piece of heat shrink over the wire and resistor, leaving the resistor leg sticking out, and shrink.

Step 4:

Lets switch over to the IR emitter.

We are going to attach a 100 ohm current-limiting resistor to the anode, or plus side.

  • Twist the 100 ohm resistor around the anode (long) leg and solder in place.
  • Take a black jumper wire, and cut both ends off so it is about 6" in length (use regular wire if you have it).
  • Strip 1/2" off both ends.
  • Wrap one end of the black wire around the cathode (short) lead and solder it in place.
  • Cover the exposed leads of the emitter with heat shrink (leave the resistor end out).

Step 5:

We are going to combine ground and power lines to the IR LED starting with the black ground wire.

  • Take a black 12" jumper and cut one end off near the terminal.
  • Strip off 1/2" of insulation.
  • Place a small piece of heat shrink on the 6" black lead before soldering.
  • Twist it together with the 6" black wire from the IR LED and solder to the emitter (short) leg of the transistor.

Combine a 6" red wire and 12" red wire to the 10K resistor:

  • Strip and tin both ends of the red wire.
  • Take a red jumper wire and cut both ends off so it is about 6" in length (use regular wire if you have it).
  • Strip 1/2" off both ends.
  • Take a red 12" jumper wire and cut one end off near the terminal.
  • Cover exposed metal with heat shrink.

Step 6:

We are going to finish this end of the harness by connecting the 6" wires to the IR emitter, starting with black

  • Place a piece of heat shrink on the black 6" wire and solder to the short leg (cathode) of the LED.
  • Slide the heat shrink up and heat.

And now the power side (red):

  • Place a piece of heat shrink on the red 6" wire and solder it to the 100 ohm resistor.
  • slide the head shrink up and heat.

Step 7:

Time to test out your work. Make the following connections to your Arduino board:

  • Red wire to 5V.
  • Black wire to GND.
  • Color wire to A0.

If you are new to Arduino, learn how to download, install, and set up the IDE here:

If you are using the IstyBitsy, see for setup, and solder wires to the correct pins.

Attach your Arduino and launch the Arduino IDE

  • [Tools] -> [Board] -> Select the flavour of Arduino you are using.
  • [Tools] -> [Port] -> Select the port (usually the highest number).
  • [File] -> [Examples] -> [Analog] -> [AnalogReadSerial]
  • Upload to your board.
  • Click the "Serial Monitor" icon in the right corner.

With any luck, you are seeing a stream of values coming in. These are 10-bit analog values so will range from 0 to 1023. Point the IR LED toward the transisor and verify you see a change:

  • When the photo transistor is exposed to light, it allows current to pass and the signal will drop towards 0.
  • When the photo transistor does not see IR, it stops the current flow allowing the signal to go high.

If you are not getting expected changes, here are some things to check:

  • Are the jumpers connected to the correct pins (5V, GND, A0)?
  • Is the IR LED on?
    • It should be slightly warm to the touch.
    • A cheap cell phone camera will show IR light nicely.
    • If it is not on, it is likely wired backward.

Step 8:

Time to install the sensor rig into something usable. This can be:

  • A short section of 3/4" PCV pipe.
  • Barrel of a Nerf blaster.
  • A removable Nerf blaster barrel attachment.

The one big trick I have learned the hard way is that the both the dart and the plastic will reflect IR light, giving spurious values as the dart passes by. The way to avoid this is to spray flat or matte black inside the barrel to absorb the scattered light.

  • Drill a hole large enough for the LED and transistor through the middle of the tube on both side.
  • Hot glue the transistor and LED so they are pointing directly at each other.
  • Reconnect to the Arduino and test as in the previous step.
  • Using a dart, ensure that the values are well above half (>700) with the dart present, and well below half (<300) with the dart removed.
  • Check the alignment if you are not getting good values. The phone camera can show if the IR is hitting the transistor.

Step 9:

Time for a program to calculate velocity. The analog reading is great for testing and troubleshooting, but when we are looking for darts at full speed, we only need to see when the signal crosses the half-way point, which is where interrupts come in. For Arduino, there are two types of interrupts, hardware interrupts (on pins 2 & 3 only) that can detect rising or falling edges, and pin-change interrupts that works on any pin but requires us to figure out what happened. By doing a quick digitalRead() on the pin when the interrupt occurs, we can decipher if the dart is there or not, and thus whether it is entering or exiting. The difference in time between the entry and exit and the length of the dart give us the data needed to calculate velocity.

Note: This method is only valid if the darts are the same length. If you use modified darts ("Stephans"), you will either need to change the dart length in the program, or add a second emitter/detector pair at a specific distance. The farther apart, the more accurate the timing will be.

If you want to dig deeper into how interrupts work and how to use them, check out

You should be able to copy and paste this code into the Arduino IDE, or download and open the attached file.

int sensorPin = A0;        // must be pin A0 to A5 for interrupt PCINT1_vect signal
int shot_count = 0;
long time1_us = 0;         // dart enters gate
long time2_us = 0;         // dart exits gate
long interval_us;          // flight time between entrance and exit
float dartLength_mm = 72;  // mm
float speed_fps = 0;       // feet per second
float speed_mps = 0;       // meters per second
float speed_mph = 0;       // miles per hour
float ave_fps = 0;         // average feet per second
bool flag = false;         // dart exits gate

void pciSetup(byte pin){
  *digitalPinToPCMSK(pin) |= bit (digitalPinToPCMSKbit(pin));  // enable pin
  PCIFR  |= bit (digitalPinToPCICRbit(pin)); // clear any outstanding interrupt
  PCICR  |= bit (digitalPinToPCICRbit(pin)); // enable interrupt for the group

void setup() {                  
  // pin setup
  pinMode(sensorPin, INPUT);  // should have external pull-up or use INPUT_PULLUP
  // Open serial coms to console
  Serial.println("Nerf Chronos, waiting for shot . . .");

ISR (PCINT1_vect) { // handle pin change interrupt for A0 to A5 here
  if (digitalRead(sensorPin)) { // HIGH if dart present
    time1_us = micros(); 
  else {                        // LOW when dart exits
    time2_us = micros();
    flag = true;     

void loop() {
  if (flag){ // dart has exited gate
    shot_count += 1;
    interval_us = time2_us - time1_us;
    speed_fps = dartLength_mm / interval_us / 25.4 / 12 * 1E+6;               // feet per second
    speed_mps = dartLength_mm / interval_us / 1000 * 1E+6;                    // meter per second
    speed_mph = dartLength_mm / interval_us / 25.4 / 12 * 1E+6 / 5280 * 3600; // miles per hour  
    Serial.print("Shot #");
    Serial.print("  ");
    Serial.print(" us  ");
    Serial.print(speed_fps, 1);
    Serial.print(" fps  ");
    Serial.print(speed_mps, 1);
    Serial.print(" m/s  ");
    Serial.print(speed_mph, 1);
    Serial.println(" mph  "); 
    flag = false; // reset gate

Testing with your finger should trigger at a few feet per second. Dropping a dart through with gravity should be a little faster.

The pictured data is from an unmodified thrift-store Disruptor shooting a pretty solid 60 fps. Get your blaster out and start collecting data!

Step 10: Going Farther . . .

We have obviously just scratched the surface of what we can do with Arduino and Nerf. Continuing with this project, you can:

  • Add a display to show velocity and shot count..
  • Add a button to reset counter or change settings..
  • Integrate a smaller microcontroller like an Adafruit ItsyBitsy.
  • Battery power for portability.

Going further, you can instrument a number of other parameters to help determine performance:

  • Flywheel speed.
  • Battery voltage.
  • Motor temperature.

And, finally, we could use Arduino to control a number of things:

  • Strobe some LEDs to simulate muzzle flash.
  • Mosfet transistor control of motors.
  • PWM speed control for rate of fire.
  • Single, burst, or auto fire selection.
  • Biometric locks.
  • Phased plasma rifle in the 40 watt range.

And yes, that tired old thrift-store Retaliator in the last picture hit 124 fps with some tweaks. It averages about 100 fps and was summarily banned from the office wars because "it hurts". Knowledge is power . . .

Arduino Contest 2019

Participated in the
Arduino Contest 2019

Be the First to Share


    • Make It Modular: Student Design Challenge

      Make It Modular: Student Design Challenge
    • Home and Garden Contest

      Home and Garden Contest
    • Colors of the Rainbow Contest

      Colors of the Rainbow Contest



    Question 1 year ago

    Hello! I liked your chrono walkthrough & decided to have a go. I've made a setup & am trying to test it on an Arduino MEGA before soldering everything to a Teensy. I'm getting expected readings low (13-16) & high (1013-1016 w/ black dart) from the serial monitor. However when I upload the chrono program, I get nothing on the serial monitor except the initial line of text. Any ideas would be appreciated. Thank you, in advance!


    Answer 1 year ago

    The ISR functions are pretty specific to Atmega328. I would start by putting the detector on an analog pin and outputting AnalogRead() on the serial port. (Sounds like maybe you already did this). Once you are sure you have a good emitter/detector setup, you can start working on measuring duration and such. You don't need to use interrupts, but it helps with such quick events.


    Reply 1 year ago

    Good to know. Yes, I have good reads low & high from the AnalogRead to serial port, so I know the physical & electrical setup is sound. Didn't realize the interrupts were so platform-dependent. Does the code you supplied work with the ItsyBitsy?


    Reply 1 year ago

    This code should work on the 32U4 ItsyBitsy, but not the M0 or M4 ItsyBitsy.


    2 years ago

    great job !!!
    but i have a trouble when i try to meassure my nerf
    number 1 to 4 is with dart and the rest is my finger
    can you help me where is my mistake ?


    Reply 2 years ago

    Seems to be triggering the interrupt but not getting the right timing signal. Are you using an Arduino Uno or a different board?

    Go back to Step 7 and upload the "AnalogReadSerial.ino" sketch. What are the readings with and without a dart in between the sensor.


    Reply 2 years ago

    ha ha ha
    look like my sensor does not work as your instruction
    when it see IR, it high
    when it doesn't, it low to 0

    thank you for your instruction


    Tip 3 years ago

    Вот старенькая и довольно надёжная схема аналогичного устройства.
    Я его собирал и даже использовал несколько лет. Показывает иногда точнее заводских.
    На сайте есть очень подробное описание схемотехники, алгоритма работы, конструкции и методов изготовления всех узлов. Также есть готовые прошивки для повторения прибора. Всё бесплатно.


    Reply 3 years ago

    Looks like a nice implentation of two IR gate chronograph. Google translates:
    Here is an old and quite reliable scheme of a similar device. Http://http: // I collected it and even used it for several years. Sometimes it shows more precisely factory ones. On the site there is a very detailed description of circuit design, algorithm of operation, design and methods of manufacturing all the nodes. There are also ready firmware for repeating the device. Everything is free.


    Reply 3 years ago

    This is quite a decent translation. So I think you can read the articles.
    I hope you will be interested.


    3 years ago

    Written in a way which would allow even someone who has never really worked with arduino before, great starter project. Gonna build one for my airsoft gun.


    Reply 3 years ago

    Air soft and Rival will need two sets of IR emitters and detectors spaced a couple of inches apart since the projectiles are round. I'll add a step and the required code.


    3 years ago

    Awesome hack for Nerf gun. Thank you for sharing.


    3 years ago

    This was a great read and I definitely picked up some super useful tips for working with some of the components you went over. Impressive build! Do you have any video of this behemoth in action?


    Reply 3 years ago

    I added a video!