Rehosted from my personal blog.
In my ongoing campaign to become a living GUNDAM, after I finished the S.A.G.A. (Superior Assault Gauntlet Apparatus) project for my forearms, I decided the next body part I would weaponize would be my deltads (shoulders lol). I wanted to create a shoulder cannon that could target and fire automatically, like Marvel's War Machine.
Problem was, the only things I had ever programmed in were MATLAB and Arduino, both for very simple applications. In order to create a cannon that could auto-target, I needed something with more computational power. So I enrolled in ENGI 301 to learn Python and take the next step forward in programming.
Before going for the full shoulder cannon right away, I chose to create a stationary defense turret first, to keep things simple. Well, simpler.
Thinking back, it was probably suicidal to try and do a full computer vision application for my first project, but you best believe I pulled it off! It was a 9-day sprint of skipping class and sleep, but it worked and I can't wait to share the process in this article below.
I used a Raspberry Pi instead of the Pocketbeagle because of its faster processor and larger RAM, more documentation, and it being more useful on my resume. Also, the USB ports on my computer are very glitchy and often disconnect at random times, so I wanted to connect to the Pi with Wi-Fi instead, to avoid this issue. Went out and bought a starter kit.
Like the Pocketbeagle, the Raspberry OS, Raspbian, is also based on Debian Linux, which meant that most of the things we learned in class could be mapped directly over. The above picture was me installing Raspbian from a microSD card.
I had very little space in my dorm, but I made the most of it by borrowing a TV to use as a monitor, and laying a plank on a crate to use as a table. There's a dumbbell weighing everything down haha.
After downloading and getting various dependencies using sudo apt-get update
and upgrade
, and downloading OpenCV via pip
install, I had to compile it using make -j4
. This took close to 48 hours. I initially thought the Pi was throttling its processing speeds from excessive heat, so I put a bag of ice underneath it XD.
But after a little more research it turned out that I had too much RAM allocated to the GPU, and not enough to the CPU. I also needed to have the swap size set to 1024 kB but hadn't changed it from its default 100. Compiling would advance one or two lines per attempt, then the Pi would hang and I would reboot it. This went on over and over through the 48 hours.
Words cannot express how happy I was after OpenCV FINALLY finished building. This was the night of Sunday the 10th, to give an idea of the time deficit I was running on.
After spending some time in Python and OpenCV (and many YouTube tutorials), I was able to get the Pi to read and manipulate video from the camera. Here is a good demonstration of the targeting method I decided to use. Using a specified HSV color range, the program would block or 'mask' out anything not in the range, and the remaining colored patches would be target zones for my cannon.
The program first finds the coordinates of the centroid of the color mass and the x- and y- distances from the center of the camera frame. Based on this, it would issue servo commands to turn the camera and cannon on two axes until the target was within a certain distance from the center. During debugging, I had the camera feed displayed on my computer via remote access, and I superimposed some lines over it to act as a targeting guide.
After getting fairly reliable results from just the camera alone, it was time to add some servos into the game, to able to actually move the cannon. To do this, I bought a Servo Controller Pi Hat, designed to plug right into the Pi's header pins. The 16 pairs of male headers on the far end of the picture can control up to 16 servos from this one board. I trimmed most of them to make space, though. I'll explain why later.
I destroyed the barrel connector and removed the capacitor and screw terminal to make some more space in the z-direction. I re-mounted the capacitor upside-down underneath, so it would sit sandwiched between the Pi and Pi hat.
I used a permaproto breadboard and buck converters to make a power management board. This let me power the Pi and servo controller from a 3S Lipo battery instead of having it plugged into a wall adapter. The wall adapter could only output 2 amps, most of which was consumed by the Pi, which meant I actually needed a second battery pack to power the servos and servo controller. With this setup, though, current was no longer an issue.
Here are the Pi and servo controller stacked on some nylon standoffs and bolted to a 3D-printed plate. Notice how the servo cables are connected underneath the Hat through the use of 90 degree male header pins! This would allow me to trim all the remaining header pins sticking out of the top, and mount a third circuit board above them with very little clearance. I was trying to go as compact as possible, because I didn't want my enclosure to be too big. Also it was a fun challenge.
Here are the servos turning. Nothing too interesting, but it's part of the documentation
Ok, now with a mostly working electronics loom, it was time to design some physical components. Even with some, back-of-the-envelope calculations, I had no way of really knowing whether the servos would be powerful enough to turn a heavy cannon. Especially since most of my components were scrounged from parts bins at the OEDK, where they might have been previously damaged without my knowledge. The only way to be sure was to physically test everything.
In addition, I needed to figure out how I would mount all my electronics, camera,, motors, and battery in the cannon.
Sketching takes so long T_T
Here was a early CAD model I made. It was really rough and had a lot of wasted space (I'll come back and stick an image of the finalized CAD in too), but it allowed me to visualize how to best arrange and assemble components.
I used the laser cutter to make an enclosure / base for the cannon. There are vents and holes for switches, plugs, and displays to sit though.
Gluing and clamping da box.
Here I am adding body filler to hide some of the finger joints on the edges. Necessary? Nah. This is 100% me flexing because I can.
I designed some bearing mounts and decided to decorate them a bit. This is Baki, an anime character whose name I stole and made into an acronym for this project.
A rough mockup so far. I was able to get the 'negative film' effect by painting the wood black before laser etching it.
I had counted on the OEDK having a turntable, but I couldn't find one in the part bins in the lobby. Had a mild panic attack until I looked on a whim and found one on top of the bolt shelf. I had to stand on a swivel chair to find it - like a real life easter egg!
Turntable mounted to a 3D-printed cannon platform, and the two bearing mounts bolted to flanges on its side. I found the bearings in the oedk. The gray gear on the bottom bolts into the black piece and has a square taper to be able to transmit torque. Looking good
I found some gears (in TinkerCAD, of all places) printed them, and epoxied them to my servo horns.
The launching mechanism I designed involves using flywheels to launch Nerf Rival rounds, like a baseball pitching machine. So I put together a flywheel cage in Solidworks, as well as an shaft and gear to slot into the bearings. It'd be bad engineering to have the loads mounted directly to the servo horns and spindles, hence the presence of a parallel shaft and gear trains at all. There are two 180-sized hobby motors wound for launching Nerf balls and its high torque requirements. These things draw up to 22 amps at stall!
The gears mesh beautifully. I was really happy about that, since because I found the gears as STLs, I couldn't use them in my Solidworks assembly. Instead, I used a thin cylinder with a diameter averaged between the gears' major and minor diameters as an approximation, and it worked out!
Here is everything so far hooked up and actuating.
Next up was to figure out how to arrange my components to fit inside the box. As you can see, there were a lot of flat circuit boards that had a lot of area but not much height. This was an inefficient use of space, so I decided I wanted to stack the power management board (bottom left) on top of the blue servo controller one.
While the Pi and Pi hat were designed to have standoff holes that lined up, the permproto boards weren't, so I had to cut one down and make a custom mounting plate to be able to get everything to play nice together. Routing wires between layers of circuit boards was pretty complicated. I made sure to leave enough slack so that I could 'unfold' the boards and make modifications if need be.
Here are all three boards (five if you count the 3D-printed ones) stacked! I added some colored jumper wires to the top board too. They don't do anything but add to the a e s t h e t i c.
Remember how I mentioned my 12V motors required a ton of current? Because of that, I'm using two CSD18531Q5A MOSFETs to be able to control those from Raspberry Pi's puny 5V GPIO pins. I set them up in a V-shape, and those together with the blocky power converter make the whole board look like a V-engine. I like cars a lot. Also, I epoxied some dowels under the MOSFET pins to protect them from getting hit and snapping.
Also, I don't think I've seen many other people doing this, so I thought I'd share here: Whenever I do MOSFET builds, I like putting the pulldown resistor across the top of the FET like above. If you keep your wire bends super tight and clean, once it's soldered it'll never move. And it looks cool as hell.
Here is my switching area. The green circuit board is a voltmeter, the piece above that with 6 black wires is my charging port, and the two switches in the right corner switch on the main and auxiliary circuits. However, when I was testing for continuity, I noticed that the voltage after the switches was only 10.2 volts, when a fully charged 3S battery is 12.6 volts. There was obviously some parasitic resistance inside the switches, meaning my motors couldn't get their full 12V and really go wild. This was a problem.
To fix this, I added another MOSFET board in the switch area. The main switches now only control on/off logic, they are no longer part of the main power supply 'line'. Ideally I'd find some better switches, but I was out of time.
This area was really messy because I literally made up all the connections here as I went along. I soldered everything without testing and luckily it all worked on the first go-around. All the JST connectors are so I don't need to cut and splice in replacement parts if I ever need to swap anything out.
As the rotating mechanism was mounted on the lid of the box, and the horizontal rotation servo on the inside of the box, it was difficult to get a perfect gear mesh by just jamming the lid on. I came up with a pretty clever solution.
I mounted the servo on a bracket, and cut slots into the floor of the box so that the bracket could slide.
The process would be to (1) slide the servo out of alignment as (2) the lid and its gear were put on, and then to (3) slide the servo back into place to mesh with the now secured top gear. The 'feet' on the bottom of the casing allows the bolts to protrude beneath the bottom of the box proper.
Finally, it was time to mount the camera! I used a Logitech C920 webcam for this project. I left this task until last, because I was pretty sure I wanted to disassemble the camera and rehouse the electronics in a smaller enclosure. I didn't want to take it apart too early in the build and have it sit around exposed to potential damage.
Well all that caution ended up being pointless because I just hacked away at the case with a dremel and flush cutters until I had the circuit board extracted. There was a very nice disassembly guide on iFixit, but the OEDK didn't have any screwdrivers small enough >:(
Test mounting the camera on a piece of cardboard. The webcam has these 4 cool blue LEDs that make the cannon look really menacing.
After that, I painted the flywheel cage black, replaced the cardboard strip with a 3D-printed ledge, and epoxied everything together. The top of the camera PCB gets physically locked in by the rear edge of the barrel, and the rubber band is there to secure the bottom end as the epoxy cures. On my computer screen is the camera / barrel view, as well as an anime girl playing guitar apparently.
Complete 'business end' subassembly with camera mount epoxied to the cage, camera epoxied to its mount, motors screwed in using M2 screws, flywheels painted gold and pressed onto the motor splines, and an additional cosmetic piece to fit over the barrel. It looks like a spaceship. The drop of hot glue was only there temporarily, until the epoxy cured. I cleaned it off afterwards.
All internals installed, LEDs on! I velcroed the Lipo battery to the floor of the box so it wouldn't rattle around. It was simpler than building another enclosure for it and bolting it to the walls. I have zip ties to keep the wiring relatively tidy, and a spiral cable to sheathe the wires leaving the box and running to the cannon itself.
Another shot of the internals. It really does look clean. Also, I left a hole in the left wall of the box for an HDMI cable. Just in case I want to use the Pi as a computer still, and watch youtube or something.
The top half of the project. I painted the gears gold as well, and it with the wood looking gold-ish I think paired really well with the black paint job.
Fully assembled, magazine not inserted.
Fully assembled, magazine inserted.
Testing servo movement. The movement speed was throttled for actual tracking, due to the Raspberry Pi lagging under the heavy OpenCV RAM requirements.
The program wouldn't realize in time when a target was already in its sights. It would continuously overshoot and reverse to try and overcompensate for rotating too far, and the solution to that was to slow the servos so the program had more time to react.
Testing tracking with full assembly. I have the HSV range set to target a can of Monster I had. (One of many I had over the course of this build).
*cue Wild West staredown music*
Successful tracking trial #1
Successful tracking trial #2
I should mention that at the time of writing, b.a.k.i. does not fire. The code for it to fire does not yet physically (virtually?) exist. That is intentional. The OEDK has gotten upset with me in the past before for building Nerf blasters in their facilities. Therefore, I am waiting until I have b.a.k.i. built to a degree that it can run indefinitely without OEDK maintenance before I add in the last lines of code to enable full functionality. All of the hardware (all three motors and wheels, MOSFETs, and Zener diodes) are installed and ready.
______________________________________________________________
Operation Instructions:
1. Toggle main (bottom) switch to power on Raspberry Pi (baki.py will execute on boot)
2. Duck and Cover
2.1 Alternatively, stay out of the camera's range
2.1.2 Use the IP Address listed on the LCD display to log into the Raspberry Pi via VNC Viewer
2.1.3 Recalibrate target color using trackbar_test.py (run from command line or from Thonny IDE)
2.1.4 Reboot to run baki.py on boot with new colors to target.
______________________________________________________________
Next Steps:
As project b.a.k.i. is a stepping stone project for the full-spec Project B.A.K.I., the things I learned here will definitely be carried forward. Improvements I am hoping to make for the full shoulder cannon are:
- Rotating barrels
- Optional joystick override control (via Wii Nunchuk and SPI)
- Remote keyboard access for another user to operate cannon as it sits on my shoulder
- Instead of a 7-round magazine, implement a tank of Nerf balls and a blower air delivery system for sustained fire
- Brushless motors to drive flywheels (higher performance, and I want experience using ESCs)
- Preprogrammed firing patterns
- Add a third degree of freedom by having the turret ride on a sliding stage up and down my back
- Addition of Real-time Clock to Raspberry Pi
- Optimize OpenCV further to reduce lag
- Introduce better cooling system to be able to further overclock Pi
Just to name a few.
______________________________________________________________
Conclusion (what is this, a high school English paper??)
This project definitely taught me a lot! By setting the bar high and rising to meet it, I learned much more than I would have by doing a safer project. I'm absolutely ecstatic about how everything turned out, and would like to thank Dr. Welsh for all his help and staying late hours to help the class.
Comments