Useless Box Project:
In this Digi-DIY I will be covering the creation of my Useless box. Our previous box was no longer working and I decided that it needed an update from its ATMEGA328P-PU chip to an Arduino Nano for additional program-ability and ease of use.
I started by researching the useless box and trying to find any other DIY or How-To tutorials. I got a lot of inspiration from Vagelis Chantzis. This helped me get the basics for my project.
For this DIY guide I am covering my Useless Box build so you too can make this fun project. This project was a good learning project for me, and as you will see there were some adjustments along the way. Like with many projects, there were some problems that crept up on me.
Problems like…
Mounting the servo motors: I didn’t see any good way to mount the servo motors as is. Since the arms were going to be constantly pressing against objects, I decided that hot glue was not going to cut it. Over time, it will tear itself away from a flat surface due to torque. I went ahead and used OnShape to sketch up a unique bracket for both servo motors. You can see the plans below.
Power problems: I was having some issues with my 6v of power. The Arduino Nano needs at least 7-12 volts to rectify it down to 5v internally for its 5v pin. Since I was feeding it 6 volts, it could not properly get 5 volts out. This under powered my servo motors and nothing worked. For a work around, I created a custom power cable to feed into the Micro-USB port, as it does not rectify that power. Alternatively, you can just use a 6 AA battery pack, which will bring you up to 9 volts.
For a general build process, I started with getting the board soldered together and working. Once I got the board working with sample code I made the box. After I had working servo motors and a box, I sketched out the arm lengths for their travel distance. I then sketched up the arms in OnShape and 3D printed them out. If you do not have a 3D printer available you can also make similar shapes out of wood. After final assembly I had to work the power kinks out.
Arduino Nano: (1050-1001-ND)
I chose the Arduino Nano because of its small size and ease to program. I planned for a small board footprint and the full-size Arduino Uno was a little too big for what I wanted.
Board Choice: (1528-1195-ND)
When planning my board layout (parts list below) I started with a full-size breadboard, but then I had too much space left over. Keeping with my idea of a small footprint, I ended up cutting the full-size board in half for a smaller board. I did this with a small Dremel and cutting wheel. There is a half size breadboard that would be perfect for this (part number above). It will fit the small size of the Arduino Nano and still has enough room for all the other components. I am sure if you wanted to go smaller, you could.
Wiring: (BKWK-3-ND)
There are many types of wires you can use on your breadboard. I chose to use ‘Hook Up Wires’ because they are already sized for breadboards, colored, and pre-stripped.
Servo Motors: (1528-1084-ND)
I decided to use the 5v high torque servo motors because it fit the Arduino Nano power output and lifts the heavy oak hard-wood I used for my box. If you go with a light weight material such as plastic or balsa wood, you will have no trouble using a regular servo motor. However, make sure you are getting a positional rotation motor and not a continuous rotation motor.
Servo Motor Pinout:
Power In: Red
Ground: Brown
Control: Yellow
Capacitors: (399-6602-ND)
The original plans I was looking at went with two 100uF capacitors to help offset the current draw of the servo motors.
Header Pins: (S9258-ND)
Since the Servo motors have a 3-pin female connecter on them, it’s a lot easier to put some header pins on the board to connect them.
USB A (Male) to Micro B (Male) Cable: WM14083-ND
I cut the USB A (Male) part off of this cable and wired the positive and negative wires to the 9 Volt Snap Battery Connector to make a custom power cable. This cable connects to the battery pack and into the Micro B (Male) portion of the Arduino Nano. The reason I did this was to bypass the internal rectifier on the Nano which did not correctly change the 6 volts from the battery pack to 5 volts for the 5v power pin. The range you would need is between 7 and 12v to properly rectify it down to 5v internally.
If you use the 6 AA battery pack, you shouldn’t have to do this. Just hookup the pack to Vin and Ground.
9 Volt Snap Battery Connector: 36-232-ND
I chose to use this due to being able to quickly connect or disconnect the AA power pack.
Four Slot Battery Holder for AA: BH24AASF-ND
I chose this part because it holds the four AA batteries needed to power the Arduino Nano up to 6 volts. If you use a 6 battery AA holder (BH26AASF-ND) this would output 9 volts, which should rectify, with the Vin input pin, down to 5 volts properly.
Single Pole Double Throw switch: (EG2350-ND)
I used a switch from the previous box, but if I had to get another one, I would choose the (EG2350-ND).
ON/OFF Rocker Switch: (EG5619-ND)
If you wanted to put in an On/Off power switch to save on your battery, you can put this in between your battery pack and Vin pin.
10kΩ resistor: (CF14JT10K0CT-ND)
This resistor is to bias the signal from your SPDT switch. This lets your board know when to move the switch and door arms.
Soldering Iron: (243-1267-ND)
Solder: (473-1128-ND)
Wire Stripper: (K598-ND)
Pliers: (K633-ND)
Box Dimensions:
The box dimensions are entirely up to you. I am putting what I have down to give you an idea of what I was working with. The only think you need to keep in mind is the travel distance from the switch to the edge of the box lid. If the switch is too far away, you need an increasingly long switch arm to get to it. This can create travel problems inside the box.
(2x) 7” x 5 ½” (End Pieces)
(3x) 12” x 5 ½” (Walls + Bottom)
(1x) 5 ½“ x 5” (Top 1, Lid)
(1x) 5 ½” x 6 ¾” (Top 2, Fixed)
Box Information:
Wood: I used Oak for my box, but lighter wood is easier on the servo motors.
Construction: This was a large box for the small components inside. If you plan your box, you can easily go smaller in size.
Other Parts:
2 x Small hinges (Screw into box end first, then lid.)
4 x small ½” Screws (Length depends on thickness of material you are using.)
12 x 2” Screws (Pre-drill wood with drill-bit equal in size to the core of screw to prevent wood from splitting)
Drill
Drill Bits (Standard pack from the store will work. Wood and plastic are soft and easily drilled)
Sandpaper (Start rough: 40-50, then medium: 100, then finish with a fine paper: 220-240)
Pencil
Wood Chisel (Optional, as I had to chisel out an area for my switch to sit in the wood)
Door arm:
I used OnShape to create a 3D printable door arm for my project. You can see the design “here.”
Custom door bracket:
I used OnShape to create a 3D printable door arm bracket for my project. You can see the design “here.”
Switch arm:
I used OnShape to create a 3D printable switch arm for my project. You can see the design “here.”
Custom switch arm bracket:
I used OnShape to create a 3D printable switch arm bracket for my project. You can see the design “here.”
Schematic:
Code:
#include <Servo.h>
Servo doorServo;
Servo fingerServo;
int swPin = 2; // Switch on pin 2
int pos = 0; // Sets initial arm positions.
int selectedMove = 0; // Move selector
void setup() {
pinMode(swPin, INPUT); // Sets pin 2 as input.
doorServo.attach(9); // Sets door servo on Pin 9
fingerServo.attach(10); // Sets finger servo on Pin 10
doorServo.write(0); // Sets door to position
fingerServo.write(80); // Sets finger to position
}
void loop() { // If the switch is on, move door and finger to switch it off
if (digitalRead(swPin) == HIGH) {
if (selectedMove > 9) { // If greater than 9 count, reset to 0.
selectedMove = 0; // ^
}
if (selectedMove == 0) { // If count = 0 then perform this function / Same logic for the following.
simpleClose();
}
else if (selectedMove == 1) {
simpleClose();
}
else if (selectedMove == 2) {
simpleClose2();
}
else if (selectedMove == 3) {
crazydoor();
}
else if (selectedMove == 4) {
slow();
}
else if (selectedMove == 5) {
serious();
}
else if (selectedMove == 6) {
trollClose();
}
else if (selectedMove == 7) {
simpleClose();
}
else if (selectedMove == 8) {
matrix();
}
else if (selectedMove == 9) {
sneak();
}
selectedMove += 1; // Add's 1 to "selectMove" count.
}
}
void simpleClose() {
for (pos = 0; pos < 140; pos += 3) { // Defines starting postition for door
doorServo.write(pos); // Executes starting position for door
delay(20); // Delay before next action
}
for (pos = 0; pos < 200; pos += 4) { // Defines starting position for finger
fingerServo.write(pos); // Executes position position for finger
delay(10); // Delay before next action
}
for (pos = 200; pos >= 0; pos -= 4) { // Defines next position for finger
fingerServo.write(pos); // Executes next position for finger
delay(20); // Delay before next action
}
for (pos = 140; pos >= 0; pos -= 3) { // Defines next position for door
doorServo.write(pos); // Executes next position for door
delay(10); // Delay before next action
}
}
// The following code follows the same schema. Play around with the code to get the correct travel distance. Watch out for doorServo vs. fingerServo, to know which one you are using.
// The following code has extra delays (200+) to make the arms more expresive. Mess with these also to get different timings for movement.
void simpleClose2() {
for (pos = 0; pos < 140; pos += 3) {
doorServo.write(pos);
delay(15);
}
delay(800);
for (pos = 0; pos < 140; pos += 4) {
fingerServo.write(pos);
delay(15);
}
delay(1000);
for (pos = 140; pos < 180; pos += 4) {
fingerServo.write(pos);
delay(15);
}
for (pos = 180; pos >= 0; pos -= 5) {
fingerServo.write(pos);
delay(15);
}
for (pos = 140; pos >= 0; pos -= 3) {
doorServo.write(pos);
delay(15);
}
}
void crazydoor(){
for (pos = 0; pos < 120; pos += 3){
doorServo.write(pos);
delay(15);
}
for (pos = 120; pos >= 0; pos -= 5){
doorServo.write(pos);
delay(15);
}
for (pos = 0; pos < 120; pos += 3){
doorServo.write(pos);
delay(15);
}
for (pos = 120; pos >= 0; pos -= 15){
doorServo.write(pos);
delay(15);
}
delay(700);
for (pos = 0; pos < 120; pos += 3){
doorServo.write(pos);
delay(15);
}
delay(700);
for (pos = 120; pos >= 0; pos -= 5){
doorServo.write(pos);
delay(15);
}
for (pos = 0; pos < 140; pos += 8){
doorServo.write(pos);
delay(15);
}
for (pos = 0; pos < 180; pos += 3){
fingerServo.write(pos);
delay(15);
}
for (pos = 180; pos >= 0; pos -= 3){
fingerServo.write(pos);
delay(15);
}
for (pos = 140; pos >= 0; pos -= 15){
doorServo.write(pos);
delay(15);
}
}
void slow(){
for (pos = 0; pos < 130; pos += 1){
doorServo.write(pos);
delay(100);
}
for (pos = 80; pos < 160; pos += 1){
fingerServo.write(pos);
delay(100);
}
for (pos = 160; pos >= 80; pos -= 1){
fingerServo.write(pos);
delay(100);
}
for (pos = 130; pos >= 0; pos -= 1){
doorServo.write(pos);
delay(100);
}
}
void serious() {
for (pos = 0; pos < 130; pos += 3){
doorServo.write(pos);
delay(15);
}
for (pos = 80; pos < 120; pos += 1){
fingerServo.write(pos);
delay(15);
}
delay(800);
for (pos = 120; pos >= 100; pos -= 3){
doorServo.write(pos);
delay(15);
}
for (pos = 100; pos < 130; pos += 3){
doorServo.write(pos);
delay(15);
}
for (pos = 130; pos >= 90; pos -= 3){
doorServo.write(pos);
delay(15);
}
for (pos = 90; pos < 150; pos += 3){
doorServo.write(pos);
delay(15);
}
fingerServo.write(80);
delay(1000);
for (pos = 80; pos < 160; pos += 4){
fingerServo.write(pos);
delay(15);
}
for (pos = 160; pos >= 80; pos -= 4){
fingerServo.write(pos);
delay(15);
}
for (pos = 150; pos >= 0; pos -= 1){
doorServo.write(pos);
delay(15);
}
}
void trollClose() {
for (pos = 0; pos < 155; pos += 3){
doorServo.write(pos);
delay(15);
}
for (pos = 0; pos < 160; pos += 4){
fingerServo.write(pos);
delay(15);
}
for (pos = 155; pos >= 100; pos -= 3){
doorServo.write(pos);
delay(15);
}
delay(10000);
for (pos = 160; pos >= 0; pos -= 4){
fingerServo.write(pos);
delay(15);
}
for (pos = 100; pos >= 0; pos -= 3){
doorServo.write(pos);
delay(15);
}
}
void matrix(){
for (pos = 0; pos < 120; pos += 3){
doorServo.write(pos);
delay(15);
}
for (pos = 80; pos < 100; pos += 4){
fingerServo.write(pos);
delay(15);
}
for (pos = 100; pos < 160; pos += 1){
fingerServo.write(pos);
delay(30);
}
delay(300);
for (pos = 160; pos >= 0; pos -= 4){
fingerServo.write(pos);
delay(10);
}
for (pos = 120; pos >= 0; pos -= 3){
doorServo.write(pos);
delay(15);
}
}
void sneak(){
for (pos = 0; pos < 100; pos += 1) {
doorServo.write(pos);
delay(30);
}
delay(2000);
for (pos = 80; pos < 100; pos += 1) {
fingerServo.write(pos);
delay(30);
}
delay(500);
for (pos = 100; pos < 120; pos += 4) {
doorServo.write(pos);
delay(15);
}
delay(100);
for (pos = 100; pos < 130; pos += 4) {
fingerServo.write(pos);
delay(15);
}
delay(500);
for (pos = 130; pos >= 100; pos -= 4) {
fingerServo.write(pos);
delay(15);
}
delay(100);
for (pos = 100; pos < 130; pos += 4) {
fingerServo.write(pos);
delay(15);
}
delay(100);
for (pos = 130; pos >= 100; pos -= 4) {
fingerServo.write(pos);
delay(15);
}
delay(100);
for (pos = 100; pos < 160; pos += 4) {
fingerServo.write(pos);
delay(15);
}
for (pos = 160; pos >= 80; pos -= 4) {
fingerServo.write(pos);
delay(15);
}
for (pos = 120; pos >= 0; pos -= 3) {
doorServo.write(pos);
delay(15);
}
}