Arduino Blaster

This project isn’t my original design, but rather my attempt to get a project running for a coworker; a project he found online and built per the online information, but which didn’t work. The project was the electronics for a Star Wars replica blaster. I did not build / customize the actual blaster shell, but rather corrected the electrical and code issues for the electronics. The actual pistol was modified by my coworker, Angel, who can be found on Instagram.

History

Angel heard me discussing the Arduino microcontroller with another coworker, and asked me how much I knew about it. I’m admittedly only considered intermediate with the Arduino, having only learned the C language used by Arduino back in 2015 while working at Parallax Inc. My experiences are more with other CPUs and microcontrollers, but overall, I am an experienced programmer in multiple languages. Angel asked me if I could help him get his project working and explained to me that he had wired everything up according to the information found online, but it wasn’t working. Although I hadn’t touched an Arduino in 3 years, I offered to help him. And so, the adventure begins…

Disclaimer

Please understand that I mean no judgement or disrespect to the original author of the project, however, as built, the original project did not function, and significant changes were required in order to get the original project working and clean up the code. The original author may at some point update the project linked in this article, so some things may be fixed by the time you read this article. This article outlines how things were at the time of post and what I did to get things running. I will link to the original project and video as I go through the original version of the project, since that is how I got involved. I also fixed several bugs and added some features to the original program. Perhaps the original author of this project will see this and find something useful. I did enjoy doing some debugging again after several years.

The Original Project

Originally, I was sent a link to the following YouTube video. This video described the electronics for a Star Wars replica blaster that you could build using an Arduino Nano microcontroller. The original project page can be found in the Resources below.

As you can see in the video, the blogger describe a blaster that has the following features:

  • Microcontroller (Arduino Nano)
  • Target Display (OLED)
  • Ammo Counter (OLED)
  • DFPlayer (MP3 Player)
  • WS2812B Strips (Not visible in the video)

First Impressions

Watching the video, three things stood out to me immediately. The first was that the project was not very responsive when pushing the button. As the blogger pressed the button fast, many presses were not processed and he had to press it again. I’m guessing this is due to the Arduino being busy driving the displays, WS2812 strip and playing the sound.

The second thing I noticed was that, as he was pressing the fire button and the ammo count was going down, every time he got to the 10th count, the number would decrement by 2. For example, if you watch the video, when he reaches 40, on the next press the counter goes to 38. When he reaches 30, the next press goes to 28 and so on. Finally, the LED strip isn’t visible in the video, so I can’t tell what it’s supposed to be doing.

Wiring Diagram & Code

Original Fritzing Diagram from Blogger

Looking at the code, I noticed that, while there are two OLED displays, they are connected to different sets of pins. The reason this stood out to me is that I2C devices, such as these displays, are designed to share their pins so you can fit multiple devices on the same bus. In this project one display was connected to the hardware I2C pins (A4 & A5), while the other was connected to two other pins that were set up to use a software I2C driver (9 & 10). By sharing the same pins, I2C devices can save I/O pins and require less drivers.

Original Parts List

Looking at the blogger’s parts list, here’s what is listed and what I actually used. Links are in red.

Since the 64×32 OLED wasn’t available, I used a 128×64, which was exactly double the resolution. On power-up, Angel’s build had a working Ammo Count display, but no Target display and no sound. Although the code showed support for the Serial Monitor, that didn’t seem to be working either. I surmised this may be because one or more pins were in conflict.

Troubleshooting

The first thing I decided to do in helping Angel to figure out what was wrong with his project was to download the demo programs for each piece of hardware used. Typically, when I’m working on a project that has multiple peripherals or hardware connected, I will write a test program for each piece of hardware. This allows you to test the individual pieces of hardware and rule out the hardware as the issue. Basically, if the test programs all work for each device, but not the main program, then you know it’s a code issue.

I found demo programs for the NeoPixels, OLED displays and the DFPlayer Mini. Once the I/O pins were updated, I downloaded and ran the various programs only to find that NeoPixels worked, as did the Ammo Count OLED, however the Target OLED and the DFPlayer Mini were still unresponsive.

The DFPlayer Mini was set to use pins 2, 1 (RX, TX), but pin 1 is the default TX port for communication between the Arduino and the host PC. On Uno, Nano, Mini, and Mega, pins 0 and 1 are used for communication with the computer. Connecting anything to these pins can interfere with that communication, including causing failed uploads to the board. The code was making use of the Serial Monitor, so this was a reasonable assumption.

In any event, I changed these pins to 10, 11 (RX, TX), which were used by the DFRobot example code for the DFPlayer Mini. I also noted that in the wiring diagram on the DFRobot website, the TX pin had a 1K resistor in series, so that was added. Once these changes were made, the DFPlayer Mini started working, as did the Serial Monitor.

Display Changes

For the new display, I updated the display library references to reflect the correct display resolution. The old reference was commented out.

//64x32 Scop display on pins 4 & 5 (native SDA SCL pins)
//U8G2_SSD1306_64X32_1F_1_HW_I2C u8g3(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
U8G2_SSD1306_128X64_NONAME_2_HW_I2C u8g3(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);

The “target” OLED had been set to use pins 9, 10 (clock, data), but pin 10 was now in use by the DFPlayer Mini. The target OLED pins were changed to 9, 8 (clock, data) and the display started working, although it was definitely not displaying correctly, since the resolution was different, throwing off the coordinates for the graphics. There were also some artifacts outside the configured display window (see photo above).

I decided to rewrite the target display code that draws the display to expand it to the larger display. Of course, the display I was using had 16 yellow rows and the rest were blue, which made things look a bit funny. The results are shown below. Had I written the original display code myself, I would have turned the yellow pixels into a single bar graph and moved the rest into the blue area, but in this case I just wanted to get things working.

Over time as I corrected issues and updated code, I also made some minor adjustments to make things work with my Angel’s replica. The original demo only had two functions; KILL and STUN, so I updated the display to show the current mode. Angel’s display was also horizontal, not vertical, so I modified the code to draw the ammo count horizontally. As more modes were added (20 in total), I changed the code to display the current mode number (1-20). I could have named each mode, however, real-estate on the display was at a premium already.

Sound Updates

Once I got the sound working, Angel was then having issues with the correct sound being played off his microSD card. In looking at the library used, it seemed like the sounds had to be put on the microSD card in the order they were called by number using the DFPlayerMini_Fast library.

As I mentioned earlier, I changed the pins used by the DFPlayer Mini to the ones used by their demo. That’s when I realized that the demo used the DFRobotDFPlayerMini library, so I switched to that, which required changing the relevant lines of code from:

myMP3.playFromMP3Folder(0001);

For the DFRobot library, these were changed to:

myMP3.play(13);

They were still hard-coded, but would work.

I think one of the biggest limitations I saw in the DFPlayer Mini was that you could not access files by filename. Files could only be accessed by number, further convoluted by the fact that these numbers didn’t necessarily apply to the visual order of the files on the microSD card, which are often displayed on a PC in alphabetical order. Instead, the order in which the files were copied to the microSD card was the numerical order.

From their own website: “NOTE: The order you copy the mp3 into micro SD card will affect the order mp3 played , which means play(1) function will play the first mp3 copied into micro SD card.” [sic]

This limitation means that if you need to replace a sound on the memory card, it may alter your numeric references to the files. This could result in having to change the references in the code. It also means that, even if someone has the same sounds as you do on their SD card, they may not be using the same numeric references for the exact same code. I find this frustrating, but manageable.

The way I manage it is instead of copying the files to the SD Card all at once, which often puts them in the order they appear on the screen, I dragged them over one at a time, ensuring that the numerical order was as I intended, which in this project means that each number corresponds to the “mode” it is assigned to. More on this in the “upgrades” section.

Initial Build

As I started my own full build to debug and test, I created my own Fritzing diagram to assist me and make it easy to make changes. I updated the Fritzing diagram as I made each change and this is where I ended up, with a revised build of this project. I also shared this information with Angel so he could update a second build on a breadboard I gave him, so he could test my changes without having to unsolder his original project, at least not until we were done.

Original V1.0 code converted to run on my hardware (V1.1). No other changes made.

Initial Changes

The first thing I did after getting things working as they should was to go through the code and try to understand what the programmer was doing along the way. Some things made sense, while others had me a bit confused. Here are some of my findings and subsequent changes.

The first change I made to the code was to disable the many Serial.println statements, which were sending what I assume to be debugging information to the console, but which serve only to slow things down in a project like this. When I use debugging statements in a project, I always comment them out before releasing the code, unless it’s a demo making use of the code. In just this clip of code there were three such statements. I may have missed some in the initial run.

I also noticed that some of these statements were very limited in their use, but taking up code space and execution time nonetheless. On line 139 you can see the code is sending out serially, the value of count1. This variable is declared and then incremented and sent out in this one routine. It seems to print to the console the total number of times that the fire button was pressed. This may be useful during development or debugging, but serves no purpose in the end code, except to bloat it and make it run slower.

In my first impressions, I mentioned that the ammo counter had a bug in it. To solve the counter issue, where it was counting down by two on every 10th count, I looked at the code to see how the counter was being decremented. What I noticed is that since there are 5 blocks and an ammo count of 50, every 10 shots a block is removed. While looking at the section that removes the blocks, I noticed that the counter is decremented when a block is removed.

The problem is that the way the code is written, once a block is removed, the code then drops into the next block conditional section decrementing the code a second time. This happens every time the code moves from one condition block to another. See lines 166 and 177. You may notice as you continue that I switched to a “dark” theme with the IDE. Less eye-strain.

So the solution was to simply remove (comment out) the code that decrements the ammo count from the sections that remove the blocks, and simply decrement the ammo counter once in the Ammo Bar section. Now, the ammo count is decremented each time you press fire, unless the count is already zero (lines 509-512).

Another thing I ran into was the routine that drives the NeoPixel strip. If you look at lines 142-143 and 148-149, you’ll see that when the colorWipe function is called, four parameters are passed to it. The R, G and B color values, and the delay value.

However, when you look at the colorWipe function line 313, you see that the SpeedDelay is specified as an integer. Yet just above that routine, line 312, there is an attempt to set it to a decimal value, despite it being declared as an integer. This means, not only is the value invalid (must be a whole number), but since the declaration is outside the function, I don’t believe it is ever executed (set) anyway. Normally it would be declared as a float (floating point) variable.

Upgrades

Once the original code was working the way it was described, certain enhancements were made to the original project, expanding on the functionality. For starters, Angel’s build did not use NeoPixels, but instead he wanted a laser to trigger on / off. So I added a laser to my circuit. The Arduino cannot drive the laser directly, so a 2N2222 NPN transistor was used to drive the laser (see the revised build below). A 1K resistor was used to drive the base of the transistor. If you don’t connect the transistor or laser, it won’t affect anything. These parts are optional.

And, while the original build had two modes, Angel had twenty different sounds to implement, so eighteen additional modes were added. This was done by copying and pasting each sub and then updating the functional call and parameters, including the sound to play and color values.

For each mode I asked him to provide the SFX and the intended color of the RGB LEDs. Then, I made it so that there were twenty entry points for these modes. Each plays the intended SFX for that mode, turns the laser on, calls the NeoPixel update subroutine with the correct parameters, then turns the laser off.

Line 382 checks to make sure there is ammo and which mode we’re in. Line 383 plays the specified SFX. Line 384 turns the laser on. Lines 385 through 393 animate the NeoPixel by lighting up the WS2812 LEDs using the parameters being passed, with various delays in between. These delays animate the display so that it more closely appears to react to the SFX. Finally, line 394 turns the laser off.

Revised Build

This build reflects all the changes I made to the code and hardware for the upgrades. As you can see, I migrated to one of my more robust development boards, despite not using the Arduino UNO for this project. The extra components on the breadboard reflect the addition of the laser, and include a 2N2222 transistor and a 1K resistor.

Rather than revise the Fritzing diagram, I simply started over with it, keeping the old one for reference to the fixed code, before the enhancements. Below is a video demo of my build with the aforementioned upgrades.

V1.5 Code Running Demo

Angel’s Hardware Build

Before I ever got involved with this project, Angel had already purchased an air pistol to be converted for the Star Wars Replica Blaster. This replica is built on a T4E TR 50 – .50 CAL PISTOL REVOLVER.

It was modified and painted and ready to support his electronics build. These photos are of the teardown of the TR 50. You can see all the various parts that made up the inside of this pistol. I was impressed when I saw what Angel did with this air pistol. I’m also impressed that he was able to fit the electronics inside of what was a functional airsoft type pistol. This kind of hardware hacking is not an area I am good at. I can do prototypes and standard type enclosures, but when it comes to modifying real-world items to look like their movie counterparts, I don’t have that much talent or experience.

These photos show the completed Blaster, both before and after power-up. Originally the working ammo display was oriented wrong for the way it was mounted on Angel’s Blaster. So the code was updated to display it sideways. This involved more than just changing the orientation of the display. The ammo blocks had to be drawn using landscape coordinates. This involved a rewrite of that section. The scope display was small enough to fit inside the scope and looks pretty cool. This was the first version.

Angel’s Part 2 Update Video

After some testing of the original build and some thought about the power source, Angel revised the Blaster a bit and these photos are of the revised build. The internal Arduino Nano can be reprogrammed via the USB port, which is accessible on the right side of the cylinder. Additionally, the microSD card for the DF Player Mini is accessible just behind the left side of the cylinder. An additional speaker was added and a rechargeable battery was placed in the handle of the Blaster. This battery can be charged by plugging a USB cable directly into the bottom of the handle.

Final Thoughts

While working on this project I was reminded of the limitations of a single-tasking MCU like the Arduino. Despite being able to run some tasks in the background, the Arduino can only really do one thing at a time, meaning, while it is updating the displays and playing sound, it’s not really able to process other things. This resulted in a very sluggish response and not being able to depress the trigger again until each fire sequence was fully completed. This is the same issue as the original blogger’s project.

That said, I was inspired to design my own blaster replica. When I worked at Parallax, I was asked several times to recreate props from movies, TV and even video games, such as my Counterstrike Bomb replica, which I am going to recreate at some point. I was working on a Sci-Fi pulse rifle with someone, but when I left CA, I no longer had access to the hardware, so it kind of went the wayside.

I am in the planning stages of a new Star Wars Blaster replica using the P8X32A. With 8 cores and the ability to play SFX directly from the SD card, the P8X32A can run the NeoPixels, SFX and other routines concurrently, making it a much more responsive platform for this particular application. Once I get that project started, I will link it in the Resources section. I zipped up ALL the versions of the code I saved so you can see the various changes I made from the original V1.0 through the final V1.5 code.

Unfortunately, I cannot include the SFX files I used. These are copyrighted and unable to be distributed, though I know there are some sites that have them available. Please do not ask for me for the SFX files.

Resources

Original Project Page

Angel’s (coworker) Instagram Page

Discuss this project on Savage///Chats


Arduino Blaster by Chris Savage is licensed under CC BY 4.0

PLEASE FEEL FREE TO LEAVE YOUR COMMENTS, QUESTIONS, SUGGESTIONS OR FEEDBACK ON THIS POST.

Leave a Reply