Necessary tools and machines

Apps and online services

About this project

The Background:

Have you ever wondered about how sound editing software can cut or boost the base in a recording? Or how sound-canceling headphones work? Or how civil engineers can design buildings and avoid the resonant frequencies of earthquakes? Well, the answer to all of those questions originates with one man: Joseph Fourier. Fourier figured out how to mathematically brake a complex wave down into its component sine waves, allowing each to be edited or observed individually. The general idea (without getting into the calculus behind it) is that you take the wave and wrap it around a circle so that it draws a type of flower. You then gradually increase the frequency at which you wind the wave around that circle, watching the shapes that the graph draws change. You do this until you find a frequency that draws something that looks like a heart shape. When you find that, it means that the frequency at which you are winding the wave around the circle is the same as the frequency of one of the component sine waves in the parent wave you are analyzing. I decided to make a physical representation of that process of finding the component sine waves.

The Project:

The idea that we (Henry Haggart and I) came up with is to have a rotating circle of phosphorescent paper which you can control the speed of under a linear actuator with a blue laser attached to it. The idea is that the linear actuator with the laser would trace a sine wave as you altered the speed at which the circle turned to try and find where they matched and you started to draw hearts instead of flowers. This could be easily achieved by driving two separate stepper motors and using the input from a rotary encoder to change the speed at which the base circle rotates. The rest of the physical design was relatively rudimentary, as we only needed a way to suspend the laser above the base circle on a custom fabricated linear actuator which we laser cut from acrylic.

Explaining the Code:

Programming this device, while it wasn’t excessively hard, did present some unexpected challenges for me. Firstly, I had never worked with Arduino and steppers, and so did not think about the mechanics of the setSpeed function. What the speed does is just add a different delay between steps in the program. This was a problem for us, as every time the delay changed in the sine wave generator code, it would also change the speed of the base circle. As it was getting dangerously close to exhibition time, the quick fix was to simply run the two motors off of two different boards. This was a way to make the code much more readable and (more importantly) debuggable. Later on, however, I learned about a way to run the two codes together on the same Arduino without having the delay in the sine function effect the delay in the base circle.

The millis() function in the Arduino IDE is a timer function, so its value counts at a constant rate no matter the delays that you may have in your code. What this does is looks for when millis() has counted up a certain increment (value or your base circle speed) and when that condition is met, it takes one step forward with the base stepper motor.

Code

Arduino 1 : Sine WaveArduino

doubleti;doubleinp;doublecosine;doublenn;doublepi=3.1415926535;intsinSpeed=126;// How fast the arm is moving back and forth#include<AFMotor.h>AF_Steppermotor(200,2);// 200 steps per rotationvoidsetup(){Serial.begin(9600);Serial.println("Stepper test!");}voidloop(){Moto1();}voidMoto1(){Serial.println("Moto1 init");/*With the rack and pinion gears I printed, it is 400 steps from the center of the circle to the edge. Change entries in "@@" marked lines to half the number of steps.*/intin=-200;//@@while(in<200){//@@doublecosine=cos((in*pi)/400);doublenn=abs(cosine);motor.setSpeed((nn+0.1)*sinSpeed);motor.step(1,FORWARD,DOUBLE);in++;}in=-200;//@@while(in<200){//@@doublecosine=cos((in*pi)/400);doublenn=abs(cosine);motor.setSpeed((nn+0.1)*sinSpeed);motor.step(1,BACKWARD,DOUBLE);in++;}}

Arduino : Dual runArduino

Use this code to run the entire machine off of one shield. This is at the risk of putting too much strain on the motor shield.

//Need to download the AFMotor library.#include<AFMotor.h>#define pinA A0#define pinB A2AF_Steppermotor2(200,1);AF_Steppermotor(200,2);longpreviousMillis=0;intlLim=1;intuLim=75;// Set max speeddoubleti;doubleinp;doublecosine;doublenn;doublepi=3.1415926535;intsinSpeed=126;/* How fast the sin wave is going. This is not on the same scale as the motor speeds. In my case, 126 matched up with 16 to draw a cardioid. */intvalue=0;intaState;intaLastState;voidsetup(){Serial.begin(9600);Serial.println("program initiated...");pinMode(pinA,INPUT);pinMode(pinB,INPUT);Serial.begin(9600);aLastState=digitalRead(pinA);}voidloop(){aState=digitalRead(pinA);if(aState!=aLastState){if(digitalRead(pinB)!=aState){value++;}else{value--;}Serial.print("Position: ");Serial.println(value);}aLastState=aState;intin=-200;while(in<200){doublecosine=cos((in*pi)/400);doublenn=abs(cosine);motor.setSpeed((nn+0.1)*sinSpeed);motor.step(1,FORWARD,DOUBLE);in++;}in=-200;while(in<200){doublecosine=cos((in*pi)/400);doublenn=abs(cosine);motor.setSpeed((nn+0.1)*sinSpeed);motor.step(1,BACKWARD,DOUBLE);in++;}if(value<lLim){value=0;}if(value>uLim){value=uLim;}if((millis()-previousMillis)>=value){motor2.step(1,FORWARD,DOUBLE);previousMillis=millis();}}