|Software apps and online services:|
|Hand tools and fabrication machines:|
Because ammo counters are cool and range finders are also pretty cool and Nerf is cool – mix them together and its ice cold.
This would give me the display needed for the range in CM and a clear display for the ammo counter itself.
- Make a device that can measure distance from the barrel of a Nerf gun.
- That can also count down remaining ammo in a clear way.
- Make it modular.
First its best to wire up the battery and the Powerboost 500, for instructions on this refer to my previous project.
Next job is to solder the Pi Zero 40 pin header onto the Pi itself – see here for an introduction into soldering.
Next you’ll want to put the Pi Zero together with the Case purchased from above, this is pretty simple, you can then put the Rainbow Hat on top.
The hat and the proximity sensor
Next grab the veroboard, snap the male header from above into 2 parts of nine and solder them into either side of the board as such, with the top resistor being a 1k and the lower one being a 2k, this will attach to the GND pin and form the voltage divider as per the tutorial on modmypi:
You will then want to drill the gap between the resistor in the area marked below so that it will function correctly, using the veroboard cutter listed above:
Once both ends have headers and the resistors are soldered in attach the jumper cables to the sensors and plug the cables into the headers on the side of the resistors making sure that the wires are as such:
Now to save Pins, we will wire GND and VCC to share the same lines on both sensors, solder in wires as such:
While the hat has a number of breakout pins on it it does not have pinouts for GPIO 23 and 24 which are needed for the ultrasonic range sensor as per the above tutorial so I soldered in direct to the pins using this pinout (soldered from the underside is easiest).
The top 4 wires there go to the breakouts on the Rainbow Hat from the Proximity Sensor, the bottom 2 go to the pins direct on the Pi mentioned above:
When all is connected up it should look something like this:
Now go to the awesome PiBakery and configure this and burn to an SD Card:
Hook the Pi up to Ethernet using a USB hub from the parts section with a KB/Mouse put the SD in and power it up!
Once it has configured and rebooted, log in and run through the following tutorials/installations:
Now go to your IDE of choice and download the following test scripts:
Run the range finder python code and point it somewhere within a few meters:
Now load the proximity sensor test and move the sensor around and it will output the ambient light and distance.
The range finder is simple enough, I want it to run and simply measure the distance in CM from the barrel every couple of seconds or so, nothing complex in the functionality here.
As for the ammo counter, I pondered ways to get it to read the ammo in the magazine dynamically but I could not think of a way to get this done – if someone has an idea for accomplishing this it would be awesome – please let me know if you manage to improve this project.
In lieu of this function I came up with the idea that the ammo per magazine being used should be set manually and then ‘loaded’, as shots are fired this will count down eventually to zero, then when changing magazine the user hits the ‘reload’ button on the hat and the ammo per magazine amount is loaded again.
When manually changing the ammo per magazine by another button on the hat it will show the ammo selection for a second and then return to the current ammo residing in the inserted magazine – there will be a video linked below that will show this clearer.
Now the sensors are checked to be working we can get onto the code for the shot detector (make sure the following scripts go into your home folder):
Code for the range finder can be found under attachments.
Code for the ammo counter is again under attachments.
Now we need to configure /etc/rc.local to launch the scripts on boot, also found under the attachments of this project.
Save, reboot and watch as the Rainbow Hat lights up!
Now its time to attach it all to the modulus-compatible barrel of the Retaliator, being that the electronics will be on the barrel only this will mean it can be connected or disconnected to or from any modulus Nerf gun.
I ran cable ties through the tiny slits just below the top rail:
I used blu-tak to hole the PCB, the ultrasonic sensor and the proximity sensor in place (for temporary positioning/testing, Sugru can be used later for a more permanent solution):
The proximity sensor needs to be angled as such so it does not pick up on the proximity of the end of the barrel itself, but will still pick up shots as they leave the barrel.
Wrap the cable ties around the veroboard, the Powerboost, the battery and the Raspberry Pi/Hat assembly itself and pull the ties tight – it is probably best to tighten this one at at a time using hands to hold them in place (4 cable ties were enough to reach around the barrel for each loop):
Now cut off the loose ends of the cable ties and check the stability of the construction and attach to the Nerf gun of choice (mine being the Recon MKII):
Here is a YouTube video showing the device in action.
In the video you can see the following:
- Me switching the device on and the range sensor eventually measuring the range to the door in the background.
- I then set the number of rounds per magazine being used to 2.
- I then load the Nerf up and fire off a round and the counter responds accordingly.
- I then hit the ‘reload’ button to simulate a new mag with 1 Nerf dart in it.
- Next part of the video I switch the device on and show it actively measuring the distance to the door as I get closer / further away from it.
- I fire off the 2 darts in the current mag and put in a new mag with 6 rounds, as the default mag size was set to 6 when I hit reload the LED’s reflect this.
- I then fire off the remaining 6 rounds and the LED’s count down 1 per shot.
So it works quite nicely I think and the aesthetic design lands somewhere between Half-Life 2 and Metro Last Light, with some Titanfall sprinkled on.
The next logical step would be to find a way to actively and automatically measure the number of rounds in an inserted magazine and reset accordingly; I am hoping that someone has found or will find a solution to this and improve my design or use this as a jumping point for an entirely better project – please do let me know I would love to see this idea be improved upon as mine is rather, rustic.
Let me know if I’ve missed anything in this guide or if you want some more info and I shall provide it!
Ammo Counter CodePython
#!/usr/bin/env python #imports import sys,os import colorsys import time import rainbowhat import time import Adafruit_VCNL40xx vcnl = Adafruit_VCNL40xx.VCNL4010() #the class used for counting the shots up/down and resetting class adjustShots(object): def __init__(self, shotsN): self.shotsN = shotsN def changeAmmo(self, shotsN): self.shotsN = shotsN return self.shotsN def showAmmo(self): return self.shotsN def plusShots(self): if self.shotsN < 20: self.shotsN = self.shotsN + 1 else: self.shotsN = (-0) return self.shotsN def minusShots(self): if not self.shotsN < 0: self.shotsN = self.shotsN - 1 return self.shotsN #here we set the number of shots that are currently in the magazine (0 is -1 here as the counter works by 0 indexing) shotsMag = adjustShots(-1) #here we set the default number of shots per magazine that will be used (as above 11 will count as 12 due to 0 indexing) shotsPerMag = adjustShots(11) #display function for the leds def display_message(message): rainbowhat.display.print_str(message) rainbowhat.display.show() #this is the code that handles showing the number of leds at the top, first 7 being red, next 7 orange and final 7 green for a total of- #21 possible shots, the code here also sets the colour 'below' it for empty shots, so you will see orange shots remaining below green shots etc. #(check the youtube video linked in the guide on my site for how this works) def display_shots(shot_count): if shot_count <= 6: for x in range(7): if x <= shot_count: rainbowhat.rainbow.set_pixel(x, 50, 0, 0, brightness=0.1) rainbowhat.rainbow.show() else: rainbowhat.rainbow.set_pixel(x, 0, 0, 0, brightness=0.1) rainbowhat.rainbow.show() if shot_count > 6 and shot_count < 14: for x in range(7): shot_count_2 = shot_count - 7 if x <= shot_count_2: rainbowhat.rainbow.set_pixel(x, 200, 50, 0, brightness=0.1) rainbowhat.rainbow.show() else: rainbowhat.rainbow.set_pixel(x, 50, 0, 0, brightness=0.1) rainbowhat.rainbow.show() if shot_count > 13: for x in range(7): shot_count_3 = shot_count - 14 if x <= shot_count_3: rainbowhat.rainbow.set_pixel(x, 0, 50, 0, brightness=0.1) rainbowhat.rainbow.show() else: rainbowhat.rainbow.set_pixel(x, 200, 50, 0, brightness=0.1) rainbowhat.rainbow.show() display_shots(shotsMag.showAmmo()) #the 'A' button will cleanly shut the device down @rainbowhat.touch.A.press() def press_a(channel): os.system("sudo shutdown now") pass #the 'B' button will count the number of shots per mag up +1, looping back around to 1 once it reaches 21 @rainbowhat.touch.B.press() def press_b(channel): shotsPerMag.plusShots() display_shots(shotsPerMag.showAmmo()) time.sleep(1) display_shots(shotsMag.showAmmo()) pass #the 'C' button initiates a 'reload', so when you put a mag in or reload it will reset the leds to show remaining ammo in the current mag @rainbowhat.touch.C.press() def press_c(channel): shotsMag.changeAmmo(shotsPerMag.showAmmo()) print (shotsMag.showAmmo()) display_shots(shotsMag.showAmmo()) pass #loop for detecting proximity - proximity decreasing when a shot passes the sensor indicating a shot and calling the class- #for the current magazine to minus one shot try: while True: proximity = vcnl.read_proximity() if proximity > 2540: display_shots(shotsMag.minusShots()) print (shotsMag.showAmmo()) time.sleep(1) except KeyboardInterrupt: pass
Range Finder CodePython
#!/usr/bin/env python #general imports import time import colorsys import rainbowhat import RPi.GPIO as GPIO import time #setup for the GPIO GPIO.setmode(GPIO.BCM) TRIG = 23 ECHO = 24 GPIO.setup(TRIG,GPIO.OUT) GPIO.setup(ECHO,GPIO.IN) #loop for measuring distance, this fires out a pulse and measures time to return, it then converts to an int to remove decimals and- #finally to a string to be sent to the led readout on the lower part of the rainbow hat try: while True: #print "Distance Measurement In Progress" GPIO.output(TRIG, False) #print "Waiting For Sensor To Settle" time.sleep(2) GPIO.output(TRIG, True) time.sleep(0.00001) GPIO.output(TRIG, False) while GPIO.input(ECHO)==0: pulse_start = time.time() while GPIO.input(ECHO)==1: pulse_end = time.time() pulse_duration = pulse_end - pulse_start distance = pulse_duration * 17150 distance = int(distance) distance = str(distance) print "Distance:",distance,"cm" rainbowhat.display.clear() rainbowhat.display.print_str(distance) rainbowhat.display.show() #time.sleep(1) except KeyboardInterrupt: pass #cleanup code for exiting rainbowhat.display.clear() rainbowhat.display.show() GPIO.cleanup()
#!/bin/sh -e # # rc.local # # This script is executed at the end of each multiuser runlevel. # Make sure that the script will "exit 0" on success or any other # value on error. # # In order to enable or disable this script just change the execution # bits. # # By default this script does nothing. # Print the IP address _IP=$(hostname -I) || true if [ "$_IP" ]; then printf "My IP address is %s\n" "$_IP" fi sudo python /home/pi/nerfpi.py & sudo python /home/pi/nerfpi_range.py & exit 0
Did you replicate this project? Share it!I made one
Love this project? Think it could be improved? Tell us what you think!