Arduino stepper motor speed control with xbox 360 controller

xbox-panr

Recently I have been working on controlling my time lapse motion control rig with a standard xbox 360 controller, I have written this brief post to give pointers to anyone else who may be trying to accomplish anything similar. Here is a quick video of my work in progress, unfortunately the motors are rather loud due to the relatively cheap drivers, but as this is only for timelapse noise is not a problem.

xbox pan tilt from Steven Brace on Vimeo.

Controlling multiple stepper motors simultaneously can be challenging using the arduino platform. Recently I made a panning, tilting and sliding camera mount for timelapse photography, I had some trouble adapting my code to allow me to move all three axes at once. Previously I had been moving one axis at a time, this was adequate for shoot-move-shoot operation, but I was interested in being able to control all axes concurrently for live motion control.

I spent some time getting an xbox controller communicating with my rig, from my research it would seem that it is not feasible to connect the xbox controller directly to the arduino. I used a processing LINK sketch on my PC to read the input from the controller and send it using serial to the Arduino. I adapted code from Matthew Spinks to read the state of the controller and send it to the arduino over serial. I had to modify his code a little to rescale the outputs and add control for an extra axis, this was fairly straightforward. He also has a sketch for the arduino, to receive the serial information, I used a little bit of this, but mainly wrote my own. Here is a video from matthew spinks where he explains his project.

http://www.youtube.com/watch?v=U-pQrnn8-Ao

I found it was more difficult than I expected to drive two steppers simultaneously, previously I had been simply switching the stepping output and waiting a set amount of time before switching again to control the motor. This approach did not work with more than one motor because the delay command I had been using, to set the time between switching the step output, blocked the processor from doing anything else for the duration of the delay. I looked in to using timers to prevent blocking, but the arduino only has 3 hardware timers. To be able to use more than 3 motors at the same time some clever handling of the timers would be necessary. Luckily there is a library which deals with all of these problems for you, and also allows for much more complex stepper control, AccellStepper. From the AccelStepper site:

AccelStepper significantly improves on the standard Arduino Stepper library in several ways:

  • Supports acceleration and deceleration
  • Supports multiple simultaneous steppers, with independent concurrent stepping on each stepper
  • API functions never delay() or block
  • Supports 2, 3 and 4 wire steppers, plus 3 and 4 wire half steppers.
  • Supports alternate stepping functions to enable support of AFMotor (https://github.com/adafruit/Adafruit-Motor-Shield-library)
  • Supports stepper drivers such as the Sparkfun EasyDriver (based on 3967 driver chip)
  • Very slow speeds are supported
  • Extensive API
  • Subclass support

AccelStepper essentially takes care of all the hard work and allows simple velocity or positional control of stepper motors. You can either carry out point to point moves with set velocities and accelerations or you can set the motor velocities manually. Here is a short demo of the accelstepper library being used to control two motors:

At the moment my goal is to be able to drive the rig into a position using the xbox controller, then using one of the buttons on the controller save this position. I will be able to set a start-point and an end-point like this and then record a time lapse between them at a user selected speed. I am pretty close but there still seem to be a few bugs in my code. Hopefully I will be able to iron out these problems soon.

#include 
 
AccelStepper Stepper3(AccelStepper::DRIVER, 8, 7);
AccelStepper Stepper2(AccelStepper::DRIVER, 12, 11);
AccelStepper Stepper1(AccelStepper::DRIVER, 10, 9);
 
void SetPosition (long x, long y, long z);
 
void setup()
{
  Serial.begin(9600);
  Stepper1.setMaxSpeed(100000);
  Stepper1.setAcceleration(200);
  Stepper1.setSpeed(0);       
  Stepper2.setMaxSpeed(100000);
  Stepper2.setAcceleration(200);
  Stepper2.setSpeed(0); 
  Stepper3.setMaxSpeed(100000);
  Stepper3.setAcceleration(200);
  Stepper3.setSpeed(0); 
 
 
}
void loop()
{  
       long x = 0L;
       long y = 0L;
       long z = 0L;
      
       int TiltSpeed = 0;
       int PanSpeed = 0;
       int SlideSpeed = 0;
       int IncomingByte = 0;
 
       char go;
       char CachePositions;
 
       Stepper1.runSpeed();
       Stepper2.runSpeed();
       Stepper3.runSpeed();
 
       while (Serial.available() > 5)
       {
              IncomingByte = Serial.read();
              if (IncomingByte=='#')
              {
                     TiltSpeed=Serial.read();
                     PanSpeed=Serial.read();
                     SlideSpeed=Serial.read();
 
                     CachePositions=Serial.read();
                     go=Serial.read();
 
                     if (CachePositions=='H')
                     {
                           x = Stepper1.currentPosition();
                           y = Stepper2.currentPosition();
                           z = Stepper3.currentPosition();
                     }
 
                     if (go=='H')
                     {
                           SetPosition(x, y, z);
                     }
 
 
                     SetSpeed(&Stepper1, TiltSpeed);
                     SetSpeed(&Stepper2, PanSpeed);
                     SetSpeed(&Stepper3, SlideSpeed);
              }
       }
}
 
void SetSpeed(AccelStepper* pStepper, long MotorSpeed)
{
       if (MotorSpeed >= 128)
       {
              MotorSpeed = MotorSpeed - 256;
       }
 
       if (abs(MotorSpeed) < 11)
       {
              pStepper->setSpeed(0);
              //(*pStepper).setSpeed(0);
       }
       else
       {
              pStepper->setSpeed(MotorSpeed*150);
       }
}
 
void SetPosition(long x, long y, long z)
{
       Stepper1.moveTo(x);
       Stepper2.moveTo(y);
       Stepper3.moveTo(z);
 
       while (abs(x - Stepper1.currentPosition()) > 0)
       {
              Stepper1.run();
              Stepper2.run();
              Stepper3.run();
       }
}

5 Replies to “Arduino stepper motor speed control with xbox 360 controller”

  1. Hi Steve, I am trying to find someone who can put together a basic stepper motor controller and driver package.
    I’m not proficient in circuit making and programming so would be unable to build this myself.
    I will be using a std NEMA 23 stepper motor bipolar spec. I would need to switch motor on/off , change rotation, and control speed down to zero.
    The motor will always run at a very slow speed but must have smooth steps….micro stepping??
    Power supply will be 12v dc battery.
    I can supply further complete details if you would be interested in making this.
    If you cannot help with this then perhaps you may know where I can get this made.
    Best regards
    John Grkinic.

  2. Hi Steve, I´m Giovanni from Venezuela. I´m trying to do a Panorama Head just with Arduino and 2 stepper motors. COulkd you please provide me the basic schematic to connect it and the code to mode the pan and til movements.

    The project will have an LCD display with 5 buttons to go up, dlown, left, right and select button.

    Is just a simple application to make a 360 horizointal degrees stopping each 15 degree take the picture and continue until make the complete 360 degrees.

    Just I´m photographer with electronic limitations and also now in Venezuela is very hard to reach foreing currency to purchase hardware. This will be a very simple project.

    My email is partgio@hotmail.com

    Thanks for all and all the best.

    If you can send to me the mechanism of your project to move the pan and tilt will be grat to implement a same schema.

    All the best,

    Bye

  3. Hi Steve, Im building a rework station with arduino mega2560 + ramps 1.4 using marlin firmware. I have a problem, i want to use xbox controller to control stepper motors and i don’t find anywhere how to use xbox controller with marlin firmware. I can use your sketch to control stepper motors?
    Do you have experience with this?

  4. Good morning,

    Firstly, my project I am wanting to undertake is this:

    Control my 3 axis milling machine via my wired XBOX controller.

    I bought the following items, but at present, haven’t got the motors to turn:

    1 x 36V 3 way power supply
    3 x Stepper motor controllers like in your video
    3 x Minebea Matsushita Bipolar motors with 4 wires, RED, YELLOW, ORANGE & BLUE (I have no idea what is A and A- and B & B- are on these wires, but I have had each motor connected to a breadboard, and know which the coils are, and have had them move via a 9v battery)
    1 x MACH3 Breakout board
    MACH3 CNC Software, all plugins installed and configured.
    1 x Official USB wired XBOX 360 controller.

    I have just ordered a pack of 5 x H Bridge units, I read somewhere that these were also needed?

    I have had all the stuff wired up, and MACH3 installed and working, can get the XYZ motions to work on software via keyboard and controller, motors are under power as they can no longer be turned by hand, but I can’t get them to work via MACH3 software,

    I am not a programmer, and need a very easy solution, if one exists?

    Can an Arduino UNO unit be setup easy for me to move X Y Z via my XBOX controller?

    Hope you can help

    Nick

Leave a Reply

Your email address will not be published. Required fields are marked *