A useless machine, in essence, is a device that turns itself off after being turned on. A video of a conventional useless machine is below.
(Frivolous Engineering, YouTube)
While a conventional useless machine is certainly fun, I believe it could be more fun with six more toggle switches. I intend to make a Superfluously Useless Machine. How will I make a useless machine with seven switches? Well, that is the question at the heart of this project. There are many examples of useless machines with multiple switches; I am intentionally ignoring those. I want this device to be entirely of my design. My machine will be made of parts I already have on hand.
The arm mechanism must reposition itself in a useless machine with multiple switches before toggling a switch. The arm mechanism repositions itself either linearly or rotationally. Rotational repositioning is easiest, given the parts at my disposal. Linear movement requires a gantry, carriage, and some sort of linear actuator (belt, screw, etc.), i.e., parts that I can not easily manufacture or parts I must buy. On the other hand, rotational positioning can be accomplished with 3D-printed parts and electronic components, which I already have.
A rotational mechanism will be used to position the arm. This, then, begs the question: How will the arm be rotated? Why, of course, a servomotor (servo) will perform that function admirably. Thus, I searched my supplies for a servo. Unfortunately, I found no working servos. I, then, endeavored to make one. The basic components of the type of servo that would work best in my machine are a motor and an encoder (usually some sort of potentiometer). My first servo design consisted of a 5-volt geared DC motor connected directly to the potentiometer via a coupler. I programmed an Arduino to control the servo. Upon testing the servo, I determined the DC motor could not make an effective motor due to the motor's gears' backlash and the motor's relatively coarse controllability. I did try my hand at PID control, but I had only developed the P part before I determined there was a better motor. I used a 28BYJ stepper motor in my second servo design. With 2048 steps per revolution, this stepper motor provided more control than the DC motor. This new servo performed exceptionally well using the same basic design as the first homemade servo (motor output coupled directly to potentiometer input).
When the motor was coupled directly to the potentiometer, the servo worked. However, a useless machine with such an arrangement would be unnecessarily tall. So, lest the final product be dramatically tall, a new servo design was needed. Simply put, the potentiometer was rotated 180 degrees (upside down compared to its previous orientation) and connected via gears to the stepper motor. This third homemade servo performed equally well compared to its predecessor. Below is a video of the new servo rotating between consecutively smaller angles before ending in the middle (the blue marks line up when the servo is in the middle position).
This stepper-motor-servo has a suitable sweep for the Superfluously Useless Machine and will be used in the final product. The servo is controlled with an Arduino running the Stepper.h library (the stepper motor could be controlled without a library, but using one makes control much simpler). In the final product, the stepper motor's gear will have a carriage that holds the arm and its motor on top of it. Usually, when controlling a servo with an Arduino, degrees are used to tell the servo where to rotate. In essence, that is what I am doing. However, instead of transforming the potentiometer output into degrees (0–360), I will leave the potentiometer output as is (i.e., a range from 0 to 1023). I then need to determine which angle each toggle switch is positioned.
Firstly, I designed a prototype with one toggle switch—essentially, a conventional useless machine. The main purpose of this prototype was to hammer out proper dimensions. The servo is included in this prototype even though there is only one switch; this was done to ensure the servo can reliably move to a designated angle. The axis about which the toggling arm rotates is directly under the toggle switch. Thus, the arm needs to rotate about 90 degrees to toggle the switch. To rotate between the toggle switch and an out-of-the-way resting position, the arm must have some sort of limit switch. The toggle switch serves as one limit, and a button will serve as the other. Simply put, the arm will rotate from rest, toggle the switch, rotate the other way, and press down on the button. Of course, the motor, arm, and button must be mounted to the servo. Thus, a motor mount was designed. This motor mount has a gear on the bottom, holes for motor aligning, threaded inserts for motor mounting, and an indexed spot for the button. The arm is connected to the mount by virtue of being connected to the motor. A CAD assembly of the motor mount and servo is below (note: the threaded inserts and electrical wires are not modeled). In the image below, the potentiometer is the grey and orange component at the bottom back; the stepper motor is in the bottom front, the motor mount is on the top of the stepper, meshing with the gear connected to the potentiometer; and the motor (yellow) and arm are fastened to the mount.
I designed a rudimentary test stand to ensure correct dimensions and to test the concept. The motor mount will be mounted to this stand. This stand will mount a single toggle switch, essentially creating a conventional useless machine. Initially, I neglected to take into account bending forces, so the initial test stand worked only when I held it firmly. The next iteration solved this by the addition of stringers put in places to best counter the bending forces. A video of the first test stand is directly below. Below that is a video of the second (note the extra supports to counteract the bending forces).
To further ensure the concept, I designed a toggle switch mount that would connect to the existing motor mount. Instead of one toggle switch, this new part would have three. Thus creating a useless machine with three toggle switches. The toggle switches were placed 45 degrees apart on the arc described by the arm as the stepper motor rotates. Thus, each toggle switch is in the same position relative to the motor and arm when the stepper motor rotates to the toggle switch's defined angle. A video of the useless machine with the new toggle switch mount is below.
This three-switch useless machine worked flawlessly, so the final product with seven toggle switches was designed. The final product used the same basic dimensions hammered out with the test stand. However, all electronics, wires, and mechanical parts would fit inside the final product, so it would appear to be a simple box with seven toggle switches in a semi-circle (there will be a small flap that is open only when the arm moves to un-toggle a switch). The majority of the final product will be 3D-printed, except for the walls of the box; the walls will be wood panels slotted into and fastened to the 3D-printed frame. A video of the working final product is below.
Designing the mechanical parts is only half the battle. The Superfluously Useless Machine needed code to work. I used an Arduino and two driver boards to control this device (stepper motor and DC motor drivers; the DC motor driver's 5V buck converter is used to power the stepper motor driver and Arduino). All the electronics are powered by 9 volts from the wall (a battery could be used, but there is no space for it inside the machine). The Arduino is the veritable brain of the operation. All inputs are fed into the "brain," and the brain decides what to do with them. Each toggle switch has a defined angle, and essentially, the Arduino checks each toggle switch repeatedly to determine if it needs to be un-toggled. The stepper motor then rotates the arm to the switch's position, and the arm toggles it. The Arduino checks each toggle switch even if the arm is already in transit to a toggled switch. Thus, the Arduino will always try to toggle the closest switch. The Arduino cares about one switch at a time. Once it has toggled the closest switch, then it begins to care about the next closest one. The code, with annotations, is below.
Superfluously Useless Machine Code
#include <Stepper.h> //stepper motor library
const int stepsPerRev = 2048; //stepper motor has 2048 steps per revolution
const int encoder = A0; //Potentiometer input
const int limitSwitch = 6; //Button used to home the arm
const int toggles[7] = {9,7,8,A5,12,A3,A4}; //Array of the toggle switch input pins
const int toggleAngles[7] = {214,323,436,536,653,773,890}; //Array of the toggle switch angles (potentiometer input values). Each angle's index lines up directly with the correct switch pin in the array above.
const int motorPin1 = 11; //DC motor control pins
const int motorPin2 = 10;
int targetAngle = 302; //Home angle for the servo
int minAngle = 0;
int maxAngle = 1000;
int angle; //Current position of the servo
int closestAng = 0; //Used in the function that finds the closest un-toggled switch
int closestPin = 0;
int angleDiff = 1023;
bool togglable = LOW;
Stepper stepper = Stepper(stepsPerRev, 2, 4, 3, 5); //initializes the stepper motor
void setup() {
pinMode(limitSwitch, INPUT_PULLUP); //initializing all the pins
pinMode(motorPin1, OUTPUT);
pinMode(motorPin2, OUTPUT);
stepper.setSpeed(10);
for (int i = 0; i < 7; i++){
pinMode(toggles[i], INPUT_PULLUP);
}
moveTo(214); //Move to both the furthest left and right pin
moveTo(890);
Serial.begin(9600);
}
void loop() {
angle = analogRead(encoder); //determine servo angle
// Serial.println(angle);
unToggle();
if (angle < targetAngle){ //moves to the target angle
stepper.step(1);
}
if (angle > targetAngle){
stepper.step(-1);
}
}
void moveTo(int servAngle){ //moves to a specific angle. cannot be stopped.
angle = analogRead(encoder);
targetAngle = servAngle;
while (angle != servAngle){
angle = analogRead(encoder);
if (angle < servAngle){
stepper.step(1);
}
if (angle > servAngle){
stepper.step(-1);
}
}
}
void unToggle(){ //determines where the closes toggled switch is and sets the corresponding angle as the target. Once it has reached the correct angle it will move the arm to un-toggle the offending switch.
angle = analogRead(encoder);
closestAng = 490;
for (int i = 0; i < 7; i++){
if (digitalRead(toggles[i])==LOW){
if (abs(angle-toggleAngles[i]) < angleDiff){
angleDiff = abs(angle-toggleAngles[i]);
closestAng = toggleAngles[i];
}
togglable = HIGH;
}
}
targetAngle = closestAng;
angleDiff = 1023;
for (int i = 0; i< 7; i++){
if (angle == closestAng && togglable == HIGH && closestAng == toggleAngles[i]){
closestPin = toggles[i];
delay(100);
while (digitalRead(closestPin) == LOW){
analogWrite(motorPin2, 0);
analogWrite(motorPin1, 1000);
}
while (digitalRead(limitSwitch) == HIGH){
analogWrite(motorPin2, 100);
analogWrite(motorPin1, 0);
}
analogWrite(motorPin2, 0);
analogWrite(motorPin1, 0);
togglable = LOW;
}
}
if (togglable == LOW){
targetAngle = 536;
}
}