Skip to content

Commit

Permalink
Merge branch 'release/1.1.3'
Browse files Browse the repository at this point in the history
  • Loading branch information
laurb9 committed Nov 15, 2017
2 parents e015090 + 18a7cd4 commit a12bd12
Show file tree
Hide file tree
Showing 12 changed files with 146 additions and 82 deletions.
12 changes: 9 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ This is suggested wiring for running the examples unmodified. All the pins below
- 100uF capacitor between GND - VMOT
- Make sure to set the max current on the driver board to the motor limit (see below).
- Have a motor power supply that can deliver that current.
- Make sure the motor power supply is within the range supported by the driver board.
- Make sure the motor power supply voltage is within the range supported by the driver board.

Set Max Current
===============
Expand Down Expand Up @@ -86,8 +86,14 @@ stepper motor like the seconds hand of a watch:
#include "A4988.h"

// using a 200-step motor (most common)
// pins used are DIR, STEP, MS1, MS2, MS3 in that order
A4988 stepper(200, 8, 9, 10, 11, 12);
#define MOTOR_STEPS 200
// configure the pins connected
#define DIR 8
#define STEP 9
#define MS1 10
#define MS2 11
#define MS3 12
A4988 stepper(MOTOR_STEPS, DIR, STEP, MS1, MS2, MS3);

void setup() {
// Set target motor RPM to 1RPM and microstepping to 1 (full step mode)
Expand Down
21 changes: 15 additions & 6 deletions examples/AccelTest/AccelTest.ino
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Using accelerated motion ("linear speed")
* Using accelerated motion ("linear speed") in nonblocking mode
*
* Copyright (C)2015-2017 Laurentiu Badea
*
Expand All @@ -10,7 +10,12 @@

// Motor steps per revolution. Most steppers are 200 steps or 1.8 degrees/step
#define MOTOR_STEPS 200
// Target RPM for cruise speed
#define RPM 120
// Acceleration and deceleration values are always in FULL steps / s^2
#define MOTOR_ACCEL 2000
#define MOTOR_DECEL 1000

// Microstepping mode. If you hardwired it to save pins, set to the same value here.
#define MICROSTEPS 16

Expand Down Expand Up @@ -44,7 +49,7 @@ DRV8834 stepper(MOTOR_STEPS, DIR, STEP, ENABLE, M0, M1);
// #define M1 11
// #define TRQ0 6
// #define TRQ1 7
// DRV8880 stepper(MOTORS_STEPS, DIR, STEP, ENABLE, M0, M1, TRQ0, TRQ1);
// DRV8880 stepper(MOTOR_STEPS, DIR, STEP, ENABLE, M0, M1, TRQ0, TRQ1);

// #include "BasicStepperDriver.h" // generic
// BasicStepperDriver stepper(DIR, STEP);
Expand All @@ -58,13 +63,17 @@ void setup() {
// stepper.setCurrent(100);

/*
* LINEAR_SPEED profile needs the acceleration and deceleration values
* in full steps / s^2.
* Set LINEAR_SPEED (accelerated) profile.
*/
stepper.setSpeedProfile(stepper.LINEAR_SPEED, 2000, 1000);
stepper.setSpeedProfile(stepper.LINEAR_SPEED, MOTOR_ACCEL, MOTOR_DECEL);

Serial.println("START");
stepper.startRotate(360);
/*
* Using non-blocking mode to print out the step intervals.
* We could have just as easily replace everything below this line with
* stepper.rotate(360);
*/
stepper.startRotate(360);
}

void loop() {
Expand Down
2 changes: 1 addition & 1 deletion examples/BasicStepperDriver/BasicStepperDriver.ino
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ void loop() {
/*
* Moving motor to original position using steps
*/
stepper.move(-200*MICROSTEPS);
stepper.move(-MOTOR_STEPS*MICROSTEPS);

// pause and allow the motor to be moved by hand
// stepper.disable();
Expand Down
2 changes: 1 addition & 1 deletion examples/ClockStepper/ClockStepper.ino
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ DRV8834 stepper(MOTOR_STEPS, DIR, STEP, ENABLE, M0, M1);
// #define M1 11
// #define TRQ0 6
// #define TRQ1 7
// DRV8880 stepper(MOTORS_STEPS, DIR, STEP, ENABLE, M0, M1, TRQ0, TRQ1);
// DRV8880 stepper(MOTOR_STEPS, DIR, STEP, ENABLE, M0, M1, TRQ0, TRQ1);

// #include "BasicStepperDriver.h" // generic
// BasicStepperDriver stepper(DIR, STEP);
Expand Down
47 changes: 24 additions & 23 deletions examples/MicroStepping/MicroStepping.ino
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* Microstepping demo
*
* This requires that M0, M1 be connected in addition to STEP,DIR
* This requires that microstep control pins be connected in addition to STEP,DIR
*
* Copyright (C)2015 Laurentiu Badea
*
Expand Down Expand Up @@ -44,55 +44,56 @@ DRV8834 stepper(MOTOR_STEPS, DIR, STEP, ENABLE, M0, M1);
// #define M1 11
// #define TRQ0 6
// #define TRQ1 7
// DRV8880 stepper(MOTORS_STEPS, DIR, STEP, ENABLE, M0, M1, TRQ0, TRQ1);
// DRV8880 stepper(MOTOR_STEPS, DIR, STEP, ENABLE, M0, M1, TRQ0, TRQ1);

// #include "BasicStepperDriver.h" // generic
// BasicStepperDriver stepper(DIR, STEP);

void setup() {
/*
* Set target motor RPM.
* Too high will result in a high pitched whine and the motor does not move.
*/
stepper.begin(RPM);
stepper.enable();

// set current level (for DRV8880 only). Valid percent values are 25, 50, 75 or 100.
// set current level (for DRV8880 only).
// Valid percent values are 25, 50, 75 or 100.
// stepper.setCurrent(100);
}

void loop() {
delay(1000);

/*
* Moving motor at full speed is simple:
* Moving motor in full step mode is simple:
*/
stepper.setMicrostep(1); // make sure we are in full speed mode
stepper.setMicrostep(1); // Set microstep mode to 1:1

// these two are equivalent: 180 degrees is 100 steps in full speed mode
stepper.move(100);
stepper.rotate(180);
// One complete revolution is 360°
stepper.rotate(360); // forward revolution
stepper.rotate(-360); // reverse revolution

// one full reverse rotation
stepper.move(-100);
stepper.rotate(-180);
// One complete revolution is also MOTOR_STEPS steps in full step mode
stepper.move(MOTOR_STEPS); // forward revolution
stepper.move(-MOTOR_STEPS); // reverse revolution

/*
* Microstepping mode: 1,2,4,8,16 or 32(DRV8834 only)
* Microstepping mode: 1, 2, 4, 8, 16 or 32 (where supported by driver)
* Mode 1 is full speed.
* Mode 32 is 32 microsteps per step.
* The motor should rotate just as fast (set RPM),
* but movement precision is increased.
* The motor should rotate just as fast (at the set RPM),
* but movement precision is increased, which may become visually apparent at lower RPMs.
*/
stepper.setMicrostep(8);
stepper.setMicrostep(8); // Set microstep mode to 1:8

// 180 degrees now takes 100 * 8 microsteps
stepper.move(100*8);
stepper.rotate(180);

// as you can see, using degrees is easier
stepper.move(-100*8);
stepper.rotate(-180);
// In 1:8 microstepping mode, one revolution takes 8 times as many microsteps
stepper.move(8 * MOTOR_STEPS); // forward revolution
stepper.move(-8 * MOTOR_STEPS); // reverse revolution

// One complete revolution is still 360° regardless of microstepping mode
// rotate() is easier to use than move() when no need to land on precise microstep position
stepper.rotate(360);
stepper.rotate(-360);

delay(5000);
}
14 changes: 12 additions & 2 deletions examples/MultiAxis/MultiAxis.ino
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,15 @@
*/
#include <Arduino.h>
#include "BasicStepperDriver.h"
#include "MultiDriver.h"
#include "SyncDriver.h"

// Motor steps per revolution. Most steppers are 200 steps or 1.8 degrees/step
#define MOTOR_STEPS 200
// Target RPM for X axis motor
#define MOTOR_X_RPM 30
// Target RPM for Y axis motor
#define MOTOR_Y_RPM 90

// X motor
#define DIR_X 8
Expand All @@ -33,14 +38,19 @@
BasicStepperDriver stepperX(MOTOR_STEPS, DIR_X, STEP_X);
BasicStepperDriver stepperY(MOTOR_STEPS, DIR_Y, STEP_Y);

// Pick one of the two controllers below
// each motor moves independently, trajectory is a hockey stick
// MultiDriver controller(stepperX, stepperY);
// OR
// synchronized move, trajectory is a straight line
SyncDriver controller(stepperX, stepperY);

void setup() {
/*
* Set target motors RPM.
*/
stepperX.begin(30, MICROSTEPS);
stepperY.begin(90, MICROSTEPS);
stepperX.begin(MOTOR_X_RPM, MICROSTEPS);
stepperY.begin(MOTOR_Y_RPM, MICROSTEPS);
}

void loop() {
Expand Down
5 changes: 3 additions & 2 deletions examples/NonBlocking/NonBlocking.ino
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,9 @@ void setup() {
Serial.println("START");

// set the motor to move continuously for a reasonable time to hit the stopper
stepper.startMove(20000); // 20000 full steps = 100 full rotations
// stepper.startRotate(36000); // 36000 degrees = 100 rotations
// let's say 100 complete revolutions (arbitrary number)
stepper.startMove(100 * MOTOR_STEPS * MICROSTEPS); // in microsteps
// stepper.startRotate(100 * 360); // or in degrees
}

void loop() {
Expand Down
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name=StepperDriver
version=1.1.2
version=1.1.3
author=Laurentiu Badea
maintainer=Laurentiu Badea
sentence=A4988, DRV8825 and generic two-pin stepper motor driver library.
Expand Down
51 changes: 25 additions & 26 deletions src/BasicStepperDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,12 @@ short BasicStepperDriver::setMicrostep(short microsteps){
* accel and decel are given in [full steps/s^2]
*/
void BasicStepperDriver::setSpeedProfile(Mode mode, short accel, short decel){
this->mode = mode;
this->accel = accel;
this->decel = decel;
profile.mode = mode;
profile.accel = accel;
profile.decel = decel;
}
void BasicStepperDriver::setSpeedProfile(struct Profile profile){
this->profile = profile;
}

/*
Expand Down Expand Up @@ -113,23 +116,25 @@ void BasicStepperDriver::startMove(long steps){
} else {
// set up new move
dir_state = (steps >= 0) ? HIGH : LOW;
last_action_end = 0;
steps_remaining = abs(steps);
step_count = 0;
switch (mode){
rest = 0;
switch (profile.mode){
case LINEAR_SPEED:
// speed is in [steps/s]
speed = rpm * motor_steps / 60;
// how many steps from 0 to target rpm
steps_to_cruise = speed * speed * microsteps / (2 * accel);
steps_to_cruise = speed * speed * microsteps / (2 * profile.accel);
// how many steps are needed from target rpm to a full stop
steps_to_brake = steps_to_cruise * accel / decel;
steps_to_brake = steps_to_cruise * profile.accel / profile.decel;
if (steps_remaining < steps_to_cruise + steps_to_brake){
// cannot reach max speed, will need to brake early
steps_to_cruise = steps_remaining * decel / (accel + decel);
steps_to_cruise = steps_remaining * profile.decel / (profile.accel + profile.decel);
steps_to_brake = steps_remaining - steps_to_cruise;
}
// Initial pulse (c0) including error correction factor 0.676 [us]
step_pulse = (1e+6)*0.676*sqrt(2.0f/(accel*microsteps));
step_pulse = (1e+6)*0.676*sqrt(2.0f/(profile.accel*microsteps));
break;

case CONSTANT_SPEED:
Expand Down Expand Up @@ -172,7 +177,7 @@ void BasicStepperDriver::startBrake(void){
break;

case ACCELERATING:
steps_remaining = step_count * accel / decel;
steps_remaining = step_count * profile.accel / profile.decel;
break;

default:
Expand All @@ -190,12 +195,12 @@ void BasicStepperDriver::stop(void){
*/
long BasicStepperDriver::getTimeForMove(long steps){
long t;
switch (mode){
switch (profile.mode){
case LINEAR_SPEED:
startMove(steps);
t = sqrt(2 * steps_to_cruise / accel) +
t = sqrt(2 * steps_to_cruise / profile.accel) +
(steps_remaining - steps_to_cruise - steps_to_brake) * STEP_PULSE(rpm, motor_steps, microsteps) +
sqrt(2 * steps_to_brake / decel);
sqrt(2 * steps_to_brake / profile.decel);
break;
case CONSTANT_SPEED:
default:
Expand Down Expand Up @@ -223,22 +228,16 @@ void BasicStepperDriver::startRotate(double deg){
* calculate the interval til the next pulse
*/
void BasicStepperDriver::calcStepPulse(void){
// remainder to be fed into successive steps to increase accuracy (Atmel DOC8017)
static long rest;

if (steps_remaining <= 0){ // this should not happen, but avoids strange calculations
return;
}

steps_remaining--;
step_count++;

if (mode == LINEAR_SPEED){
if (profile.mode == LINEAR_SPEED){
switch (getCurrentState()){
case ACCELERATING:
if (step_count == 1){ // first step, initialize rest
rest = 0;
}
step_pulse = step_pulse - (2*step_pulse+rest)/(4*step_count+1);
rest = (step_count < steps_to_cruise) ? (2*step_pulse+rest) % (4*step_count+1) : 0;
break;
Expand All @@ -258,10 +257,8 @@ void BasicStepperDriver::calcStepPulse(void){
* Toggle step and return time until next change is needed (micros)
*/
long BasicStepperDriver::nextAction(void){
static unsigned long next_action_time = 0;
long next_action_interval = 0;
if (steps_remaining > 0){
microWaitUntil(next_action_time);
delayMicros(next_action_interval, last_action_end);
/*
* DIR pin is sampled on rising STEP edge, so it is set first
*/
Expand All @@ -273,19 +270,21 @@ long BasicStepperDriver::nextAction(void){
m = micros() - m;
// We should pull HIGH for 1-2us (step_high_min)
if (m < step_high_min){ // fast MCPU or CONSTANT_SPEED
DELAY_MICROS(step_high_min-m);
delayMicros(step_high_min-m);
m = step_high_min;
};
digitalWrite(step_pin, LOW);
// account for calcStepPulse() execution time
next_action_interval = pulse - m;
// account for calcStepPulse() execution time; sets ceiling for max rpm on slower MCUs
last_action_end = micros();
next_action_interval = (pulse > m) ? pulse - m : 1;
} else {
// end of move
last_action_end = 0;
next_action_interval = 0;
}
next_action_time = micros() + next_action_interval;
return next_action_interval;
}

enum BasicStepperDriver::State BasicStepperDriver::getCurrentState(void){
enum State state;
if (steps_remaining <= 0){
Expand Down
Loading

0 comments on commit a12bd12

Please sign in to comment.