Using Stepper Motors to Pan & Tilt Mirror

Hey everyone,

First time poster, but I’ve been reading and learning from the forums for a couple years now. Appreciate any feedback in advance.

I’ve got a mirror mounted to one stepper motor for tilt control, and that whole assembly is mounted to another for panning. (It’s taken out of one of those stage lighting scanners). The end goal is to have the motors moving the mirror so that a laser shown directly onto the mirror reflects off and moves in a circle, as smoothly as possible. The original stage light can do this with ease through DMX and external software or control hardware, but I’ve taken the steppers/mirror assembly out and am replacing the brains, essentially, with an Uno and the HW to make a few very simple circle patterns.

I’m driving the two steppers with an Arduino Uno along with the Adafruit Motor Shield V2.3. Vin jumper pulled and using an external and separate 12V DC power supply for the motors/shield.

I’ve got the multi-stepper example program, slightly modified, from the Accel Stepper Library working pretty well. I’m able to smoothly control both steppers at different speeds and directions, etc. I’m having trouble, however, making the correct circle pattern with the mirror/reflected laser. I know that all I need to do is make one stepper move 90 degrees out of phase from the other, but I can’t figure out a good way to do this. Essentially one needs to be sweeping a sine wave, while the other a consine.

Here’s the code I’m currently using. Like I said, it’s 90% the example provided with the library, but does the trick. Thanks for any feedback!

// Shows how to run three Steppers at once with varying speeds
//
// Requires the Adafruit_Motorshield v2 library 
//   https://github.com/adafruit/Adafruit_Motor_Shield_V2_Library
// And AccelStepper with AFMotor support 
//   https://github.com/adafruit/AccelStepper

// This tutorial is for Adafruit Motorshield v2 only!
// Will not work with v1 shields

#include <AccelStepper.h>
#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_MS_PWMServoDriver.h"


Adafruit_MotorShield AFMSbot(0x60); // Default address, no jumpers, single shield

// Connect two steppers with 200 steps per revolution (1.8 degree)
// to the shield
Adafruit_StepperMotor *myStepper1 = AFMSbot.getStepper(200, 1);
Adafruit_StepperMotor *myStepper2 = AFMSbot.getStepper(200, 2);



// you can change these to DOUBLE or INTERLEAVE or MICROSTEP!
// wrappers for the first motor!
void forwardstep1() {  
  myStepper1->onestep(FORWARD, MICROSTEP);
}
void backwardstep1() {  
  myStepper1->onestep(BACKWARD, MICROSTEP);
}
// wrappers for the second motor!
void forwardstep2() {  
  myStepper2->onestep(FORWARD, MICROSTEP);
}
void backwardstep2() {  
  myStepper2->onestep(BACKWARD, MICROSTEP);
}


// Now we'll wrap the 2 steppers in an AccelStepper object
AccelStepper stepper1(forwardstep1, backwardstep1);
AccelStepper stepper2(forwardstep2, backwardstep2);


void setup()
{  
  AFMSbot.begin(); // Start the motor shield

   
  stepper1.setMaxSpeed(400.0);
  stepper1.setAcceleration(100.0);
  stepper1.moveTo(40 * 8);
    
  stepper2.setMaxSpeed(400.0);
  stepper2.setAcceleration(100.0);
  stepper2.moveTo(40 * 8);
  
  
}

void loop()
{
    // Change direction at the limits
    if (stepper1.distanceToGo() == 0)
	stepper1.moveTo(-stepper1.currentPosition());

    if (stepper2.distanceToGo() == 0)
	stepper2.moveTo(-stepper2.currentPosition());
        
    stepper1.run();
    stepper2.run();
  
}

I would put a (Sin() +1) * MAX_MOTION table in PROGMEM. The "+1" is to avoid negative numbers. The length of the table is N. For the Sin() positions SinCounter=0; For the Cos() positions CosCounter = N/4;

Move to: Sin(SinCounter),Sin(CosCounter)
SinCounter = (SinCounter+1)%N;
CosCounter = (CosCounter+1)%N;

Repeat for as long as you want the mirror to move in a circle. If you want the display to look like a circle instead of a point moving in a circle you will need to draw the circle at least 30 times per second. Keeping N low will help but too low and you get a polygon.

Bresenham’s algorithm and generalizations of it are used for drawing lines, arcs, circles and other regular shapes using steppers. If you look around you can find code in just about any computer language.

First one up on google.