Friday, August 21, 2015

Stepper Motor Player

I took some stepper motors out of some old printers to play with. Newer printers seem to use DC motors, but I love finding steppers because they make such nice sounds. I spent a while on this project just figuring out how to get the steppers to work and some different options for

programming them. I used a couple Easy Stepper drivers, one for each motor, and used the provided sketch to get them spinning at different speeds. I spliced an old wall wart (rated 9V, 200mA, tho when I measure it I get ~15V. Let it be known I know nothing about electricity and fear the outlet but this wart works and does not seem to get too hot), I think from a baby monitor, into the rails of the breadboard as the motors need their own stronger power source independent from the Arduino.
Eventually I wanted to be able to dynamically control the speed of the motors and switch between the two. I found that they cannot be on simultaneously at least using the functions provided in the Easy Stepper sketch because they involve a blocking action, meaning rather than being set to turn on and just staying that way like a DC motor these are instructed to move a certain number of steps for a certain duration of time, which blocks anything else from happening during that duration. One possibility I didn't look at yet is setting the duration to 1 and alternating the two motors to simulate simultaneous motor activity. For a future experiment! Anyway I configured a potentiometer and set the motor speed to a scaled down version of the pot value (potentiometer / 4000), then added a button to toggle between the two motors. To find the acceptable range for the pot value I hard coded different speed values and found everything from .01 - .26 worked well.
Wow I made a Fritzing! 9V was actually AC power source but I
couldn't find that in fritzing.
It took a long time, almost a year over many experiments, in fact, to find a good way to make the vibrations of the motors resonate well. Cardboard boxes are okay, wood not very good, and a cardboard tube I thought would amplify it did almost nothing. Finally I tried a big styrofoam box and the sound is pretty amazing. Put a mic under the box and the multiple harmonics ring out loudly.
I love microtones and harmonics so this is turning out to be a really fun instrument to play and so easy to play that you can really focus on listening while you play it.
Here is what I've recorded so far. They are each long, but it's no pop music.

And here's the source code:
#define DIR_PIN_A 2
#define STEP_PIN_A 3
#define DIR_PIN_B 4
#define STEP_PIN_B 5
#define POT_PIN A0
#define BUTTON A1
boolean whichMotor = true;
int buttonState = 0;
double speedA, speedB;
void setup() { 
  pinMode(DIR_PIN_A, OUTPUT); 
  pinMode(STEP_PIN_A, OUTPUT); 
  pinMode(DIR_PIN_B, OUTPUT); 
  pinMode(STEP_PIN_B, OUTPUT); 
  pinMode(POT_PIN, INPUT);
  pinMode(BUTTON, INPUT_PULLUP);
  Serial.begin(9600);
} 

void loop(){ 
  changePot();
}

void changePot() {
  float setPot = analogRead(POT_PIN);
  setPot /= 4000;
  Serial.print("pot: ");
  Serial.println(setPot);
  buttonState = digitalRead(BUTTON);
  if(buttonState == LOW) {
    whichMotor = !whichMotor;
    delay(200);  //debounce
  }
  if(whichMotor) {
    rotateDeg('A',20,setPot);
  } else {
    rotateDeg('B',20,setPot);
  }
//delay(100);
}

void rotateDeg(char motor, float deg, float speed){ 
  //rotate a specific number of degrees (negitive for reverse movement)
  //speed is any number from .01 -> 1 with 1 being fastest - Slower is stronger
  int dir = (deg > 0)? HIGH:LOW;
  if(motor == 'A') {
    digitalWrite(DIR_PIN_A,dir); 
  } 
  else {
    digitalWrite(DIR_PIN_B,dir); 
  }
  int steps = abs(deg)*(1/0.225);
  float usDelay = (1/speed) * 70;

  for(int i=0; i < steps; i++){ 
    if(motor == 'A') {
      digitalWrite(STEP_PIN_A, HIGH); 
      delayMicroseconds(usDelay); 

      digitalWrite(STEP_PIN_A, LOW); 
      delayMicroseconds(usDelay); 
    } 
    else {
      digitalWrite(STEP_PIN_B, HIGH); 
      delayMicroseconds(usDelay); 

      digitalWrite(STEP_PIN_B, LOW); 
      delayMicroseconds(usDelay); 
    }
  } 
}

No comments :