This instructable was created in fulfillment of the project requirement of the Makecourse at the University of South Florida (www.makecourse.com)
So before we get started, this is my project, and therefore the components I used are arbitrary (diodes, transistors, solenoid, power source, etc.) but are optimized to the performance. After building, the code was further optimized to meet the shortcomings of the components.
What you will need:
- Access to a 3D printer
- Box (20cm length, 12 cm width, and 7cm height; these are not set in stone but it is suggested not to go under these dimensions)
- Push/Pull Solenoid
- 2 decent Servos
- Distance sensor (I used a sonar sensor, however in hindsight I should have used an IR sensor)
- Push Button
- Slide Switch
- 9V battery
- External power source (usually a laptop charger)
- Jumper wires
- Arduino Uno
- Resistor (1K - 10K preferably)
- Transistor (TIP120)
- Diode (MUR460)
- Optional: Soldering supplies, Spray paint, electrical tape.
After 3D printing all of the above parts, and gathering a box close to those dimensions, we will begin assembly.
- We're going to need to cut the lid of the box up. Whichever short side you consider the back, go up 66mm and cut a rectangle 100 cm to the front with a 20cm width. This allows the monster to move up and down freely.
- Next cut holes for your connectors & buttons.
- This next part is a little tricky, and we must wire the servos in to the Arduino before mounting the support to them. The program initializes the servos at specific angles in order to work in their domain and work together. Just turning on the Arduino sets the servos at the correct angles in which to mount. Mount the servos to the part named "cannon lift", and then the servos to the lid while the Arduino is on. This ensures the servos are in the correct position even if the Arduino is off and the lift is moved at a different angle.
- The Solenoid is to be mounted to the flat region of the halfpipe. I mounted mine so that the edge of the solenoid was flush with the flat piece.
- One thing that is experimental is the mounting of the ball holder. What I used was, in fact, the end of a roll of scotch tape. I mounted it where the ball was just in reach of the throw of the solenoid and screwed it in from the sides.
- Now the halfpipe must go on the lift. make sure the bottom edge of the halfpipe is flat on the edge of the holder. I super glued mine to the holder and it hasn't moved in hundreds of trial runs.
- The distance sensor is mounted flush with the front of the lid, giving a gap of about 7cm to the actual ball location (the code fixes this discontinuity).
- I mounted my slide switch on the back of the lid, with simple solid core wires. The trick I used was putting the wires in the little holes, and bending them into L's. Then take your soldering iron and press it up against the wire, causing it to seep slowly into the plastic lid.
So, referencing the wiring diagram, wire the Arduino as shown. It may be a little confusing, but I think it is good enough since the software I was using to make it nicer keeps crashing on me. (circuits.io)
The external power source I used was a 16V - 4.5A output. This provided enough force to the ping pong ball to land in a cup of max distance 2 feet away. Other power sources may yield different results.
Make sure the servo you put on the left is the one connected to pin 6 of the Arduino, and the servo you put on the right is connected to pin 5. This ensures that the servos will move together.
Pretty straight forward.
The Actual Code
I have attached a video, and the actual code for further insight if the next few paragraphs don't explain everything in detail.
So my code is pretty straightforward, initializing variables, pins, outputs and inputs.
Let me take you through a loop in my code.
The loop starts with an if statement, saying if the button is pressed, a variable is formed. That variable then starts the while loop (If you may not have noticed, I like while loops best).
Once the while loop starts, everything else happens. The Arduino waits one second and then measures an initial distance. Then a for-loop starts.
The for-loop takes a measurement, decides if its close enough to the initial distance, and if it is it sums it, and does this 10 times. There is an if statement in there that combats a misread distance if the initial distance didn't pick up the cup, in which case the user can press the button again, and it will exit the while loop and go back to standby mode.
After the for-loop is finished it takes the sum of the distances, divides it by 11 to get an average, then converts the centimeter distance into meters. This is essential for projectile dynamics.
This distance is called R in the code, and as you'll notice it is restated as it is put through a quadratic equation. This is the offset equation. It is empirical and was determined through testing max and min distances several times. The coefficients are predetermined and are optimized for my set up.
After finding the distance to use for the dynamics, we plug in our value of R into the max distance equation (solved for theta), to get an angle. This is the angle in which both servos have to go to in order for the ball to go in the cup.
- The servos make the launcher angle 45 degrees, which is the angle of maximum distance. There is an if statement that if the distance measured is larger than 60cm, the servos don't move and it fires at 45 degrees. This grants that the machine will try even if it cannot reach it, it might bounce in.
The servos move in opposite rotation, so one is adding angle, and one is subtracting angle to get to the same spot. The next while loop does just this, and delays every angle change by 100 milliseconds to ensure a smooth transition.
Once in position, it activates the solenoid for a very short burst as to not get it too hot, and then deactivates it. The servos then move back to the original position in a smooth manner. Every variable is reset and then it returns to standby mode.