Pololu A4988 driver + Arduino + Smooth driving

Hi everyone,
I have some questions to you.
I bought Pololu A4988 stepper driver WITHOUT voltage regulator version.
I have Arduino Uno and 1.8 degree/200 steps stepper motor.
I want to drive my motor with that driver but it should be in microstep such as 1/16.

My plan is like so :

  1. turn 45 degree and wait 2 seconds
  2. then turn again 45 degree and wait 2 seconds more. these will go on until to finish 360 degree
    but these 45 degree steps should be smooth start and finish(I think it’s calling like “ramp”).
    another problem is : I want to drive with 12 V , 1.2 A battery, so energy saving is very important. but when I make a delay between 45 degree steps it still spends energy. so this is about giving a hold torque functionality to the stepper but I don’t want this function (I’m not sure but it is chopping , right ? ) . so I enable active and passive with EN pin but is it right way ? should I se different way ?

normally ; RESET and SLEEP pins connect to each other in Pololu driver.

I need a exact code from you specially that delay and smooth start/end process.

Sorry for my bad english.
I wish you can help
Thanks

Hello.

I don’t think it is reasonable to expect someone to write exactly the code to do what you are describing. You try starting with the code for Arduino in this guide.

Yes, enable lets you turn on and off the output FETs, so that is what you want for saving a little power when you don’t need holding torque. A very detailed description of the driver is available in the A4988 datasheet.

- Ryan

I used the decrDude documentation that RyanTM referenced above, plus another decrDude post with code and even a Arduino shield posted here https://forum.pololu.com/t/a4988-dev-board/3822/1 to write and test a program for you. It took only an hour to adapt the decrDude code and I tested it on my version of his shield.

There are parameters to tweak the speed of the motor and the ramp speeds. These are inside of setup() and loop() and are timeBetweenStepsInMicroSec and rampspeed.

The code from decrDude starts with #define statements to assign the pins on the Arduino that command the A4988. They now have the values needed to use a shield that he has developed and will (or would, before) sell you if you’d like.

Try it. It may be just what you need. To others, you might want to examine the code as a learning tool.

It works for me with both Arduino 0022 and 1.0 but no promises that it will work for you. Use at your own risk. I am not a teacher or lawyer and I don’t even play one on TV.

// This "sketch" by jed on https://forum.pololu.com from one
// posted by decrDude at https://forum.pololu.com/t/a4988-dev-board/3822/1
// also using the guide decrDude posted at
// https://forum.pololu.com/t/a4983-and-a4988-getting-started-guide/2789/1

// I've said it before and I'll repeat it: MANY thanks to 
// decrDude for his help teaching the rest of us how to use
// steppers, Pololu controller boards, and the Arduino
// together. 

// jed's changes:
// Special code to move 45 degrees at a time, wait 2 seconds,
// move another 45 degrees

#define stepPin 3 
#define dirPin 2 
#define enablePin 7
#define MicroStep1Pin 6
#define MicroStep2Pin 5
#define MicroStep3Pin 4

#define numMsInOneSec 1000
#define numMicroSecInOneMs 1000
#define stepPulseWidthInMicroSec 2
#define setupTimeInMicroSec 1

#define inputBufferSize 128

int  serialCharIn;             
char serialInString[inputBufferSize];  
int  serialInIndex  = 0;

unsigned long timeBetweenInputPollsInMicroSec = ( (unsigned long)(numMsInOneSec /4) * numMicroSecInOneMs ); // 250 = 1/4th of a second
unsigned long timeBetweenStepsInMicroSec = (1 * numMicroSecInOneMs);

unsigned long loopCheck = 0;

boolean lineReady = false;
boolean successfullyParsed = false;
boolean currentDirection = false;
boolean shouldStep = true;

boolean speedChanged = true;

void setCurrentDirection(boolean dir)
{
  if(dir == false)
  {
      digitalWrite(dirPin, LOW);
  } else {
      digitalWrite(dirPin, HIGH);
  }
  currentDirection = dir;
  delayMicroseconds(setupTimeInMicroSec);
}

void changeDirection()
{
  setCurrentDirection(!currentDirection);
}

void enableStepper(int isEnabled)
{
  if(isEnabled)
  {
      digitalWrite(enablePin, LOW); // enable HIGH = stepper driver OFF
  } else {
      digitalWrite(enablePin, HIGH); // enable HIGH = stepper driver OFF
  }
  // wait a few microseconds for the enable to take effect 
  // (That isn't in the spec sheet I just added it for sanity.) 
  delayMicroseconds(2);
}

void takeSingleStep()
{
    digitalWrite(stepPin, LOW);
    delayMicroseconds(stepPulseWidthInMicroSec); 
    digitalWrite(stepPin, HIGH); 
    delayMicroseconds(stepPulseWidthInMicroSec); 
    digitalWrite(stepPin, LOW);
}

void setFullStep()
{
  digitalWrite(MicroStep1Pin, LOW);
  digitalWrite(MicroStep2Pin, LOW);
  digitalWrite(MicroStep3Pin, LOW);
  delayMicroseconds(setupTimeInMicroSec);
}

void setHalfStep()
{
  digitalWrite(MicroStep1Pin, HIGH);
  digitalWrite(MicroStep2Pin, LOW);
  digitalWrite(MicroStep3Pin, LOW);
  delayMicroseconds(setupTimeInMicroSec);
}

void setQuarterStep()
{
  digitalWrite(MicroStep1Pin, LOW);
  digitalWrite(MicroStep2Pin, HIGH);
  digitalWrite(MicroStep3Pin, LOW);
  delayMicroseconds(setupTimeInMicroSec);  
}

void setEighthStep()
{
  digitalWrite(MicroStep1Pin, HIGH);
  digitalWrite(MicroStep2Pin, HIGH);
  digitalWrite(MicroStep3Pin, LOW);
  delayMicroseconds(setupTimeInMicroSec);  
}

void setSixteenthStep()
{
  digitalWrite(MicroStep1Pin, HIGH);
  digitalWrite(MicroStep2Pin, HIGH);
  digitalWrite(MicroStep3Pin, HIGH);
  delayMicroseconds(setupTimeInMicroSec);  
}

/*  we don't need this code but might need to refer to it
*********** start of commented code
bool makeChangesBasedOnSerial()
{
  boolean output = true;
  String tempString = serialInString;
  String hzStartString = "StepsInHz=";
  if(tempString == "ChangeDirection\n")
  {
    changeDirection();
  } else if (tempString == "EnableStepper\n") {
    enableStepper(true);
  } else if (tempString == "DisableStepper\n") {
    enableStepper(false);
  } else if (tempString == "FullStep\n") {
    setFullStep();
  } else if (tempString == "HalfStep\n") {
    setHalfStep();
  } else if (tempString == "QuarterStep\n") {
    setQuarterStep();
  } else if (tempString == "EighthStep\n") {
    setEighthStep();
  } else if (tempString == "SixteenthStep\n") {
    setSixteenthStep();
  } else if (tempString == "SteppingOn\n") {
    shouldStep = true;
  } else if (tempString == "SteppingOff\n") {
    shouldStep = false;
  } else if (tempString.startsWith( hzStartString ) && tempString.endsWith("\n") ) {
    // must be less than 1,000,000
    String hzstr = tempString.substring(hzStartString.length(), tempString.length() -1);
    char hzCharArray[inputBufferSize];
    hzstr.toCharArray(hzCharArray, inputBufferSize);
//    Serial.println(hzstr);
    long parsed = atol(hzCharArray);
//    Serial.println(parsed);
    if(parsed != 0 && parsed < (numMicroSecInOneMs*numMsInOneSec) )
    {
      timeBetweenStepsInMicroSec = ((unsigned long)numMicroSecInOneMs*numMsInOneSec) / (unsigned long) parsed;
       = true;
    } else {
      output = false;
    }
  } else {
    output = false;
  }
  return output;
}
 *************** end of commented code ************
 */

void setup() 
{
  // We set the enable pin to be an output 
  pinMode(enablePin, OUTPUT); // then we set it HIGH so that the board is disabled until we 
  pinMode(stepPin, OUTPUT); 
  pinMode(dirPin, OUTPUT);
  
  pinMode(MicroStep1Pin, OUTPUT);
  pinMode(MicroStep2Pin, OUTPUT);
  pinMode(MicroStep3Pin, OUTPUT);
  
  // get into a known state. 
  enableStepper(false);
  // we set the direction pin in an arbitrary direction.
  setCurrentDirection(false);
  setSixteenthStep();
  
  enableStepper(true);
 // we set the direction pin in an arbitrary direction. 
  setCurrentDirection(true);
  timeBetweenStepsInMicroSec = (1 * numMicroSecInOneMs); // set speed
//  timeBetweenStepsInMicroSec = (3 * numMicroSecInOneMs); // slower speed
//  timeBetweenStepsInMicroSec = (numMicroSecInOneMs / 2); // faster speed
}


void loop() 
{ 
  int j;
  int loops, ramp;
  int rampspeed=4;  // bigger numbers = quicker ramp
 
 // we need to move 45 degrees until 360 degrees is done
 for (loops=0; loops<(360/45); loops++) {
     enableStepper(true);
// now we ramp up the stepper then move it smoothly
// 200 steps * 16 microstepping = 3,200 / 8 loops = 400
// so will ramp up for 50, speed for 300, ramp down for 50
     for (ramp=0; ramp<50; ramp++) {
       // wait extra time
       delay((50-ramp)/rampspeed);
       takeSingleStep();
       delayMicroseconds(timeBetweenStepsInMicroSec);
       } 
     
    for(j=0; j<200; j++) { 
      takeSingleStep();
      delayMicroseconds(timeBetweenStepsInMicroSec);
      }
    
    for (ramp=0; ramp<50; ramp++) {
      // wait extra time
      delay((ramp+1)/rampspeed);
      takeSingleStep();
      delayMicroseconds(timeBetweenStepsInMicroSec);
      } 
// now disable the stepper and wait two seconds
   enableStepper(false);
   delay(2000);   // in miliseconds
  }
  
  // that's all, folks!
  enableStepper(false);
  delay(8000);  // delay before going again
}