Better Stepper motor control

Hi there,

I am working on an inverted pendulum project and it is a kind of moving cart driven by a (stepper) motor setup. I have an UNO, a NEMA 17, A4988 driver and IMU as a sensor. At the moment, I am really struggling with the control the stepper using AccelStepper.

// Include the AccelStepper Library
#include <AccelStepper.h>

// Define pin connections
const int dirPin = 2;
const int stepPin = 3;

// Define motor interface type
#define motorInterfaceType 1

// Creates an instance
AccelStepper stepper(motorInterfaceType, stepPin, dirPin);
int steps =200; //steps to move

void setup() {
	// set the maximum speed, acceleration
	stepper.setMaxSpeed(2500);
	stepper.setAcceleration(50000);
	stepper.setSpeed(1000);
}

void move_stepper(int value){

  if (stepper.distanceToGo() == 0) {
	  stepper.moveTo(value);
    } else {
      stepper.run();
    }
}

void loop() {
  move_stepper(steps);
  steps = -1*steps; // Change direction once the motor reaches target position
}

First of all, above is the code I run for testing. Basically, it is just running 200 steps forward and backward. It works well as I expected. By running this, I can see the cart can make the pendulum swing. So, I believe the torque/speed generated by the system is capable to perform the task (balancing the pole).

But when I tried to control the motor with sensor's reading...

#include <AccelStepper.h>

// Define pin connections
const int dirPin = 2;
const int stepPin = 3;

// Define motor interface type
#define motorInterfaceType 1

// Creates an instance
AccelStepper stepper(motorInterfaceType, stepPin, dirPin);

int steps =200; //steps to move

void setup() {
  Serial.begin(9600);
  //stepper setup
  stepper.setMaxSpeed(2500);
  stepper.setAcceleration(90000);
  stepper.setSpeed(1000);
}

void move_stepper(int value){

  if (stepper.distanceToGo() == 0) {
	  stepper.moveTo(value);
    } else {
      stepper.run();
    }
}

void loop() {

  u := readingFromSensors; //degree at the moment

  if (u>10){
    move_stepper(steps);
  }
  if (u<-10) {
    move_stepper(-1*steps);
  }
}

Let u be the reading from my sensor. What I intended to do is just moving the cart 200 steps forward if the pole inclines 10 degree to the right while 200 steps backward if it inclines to the left. (I totally understand this should not be good enough to balance the pole well.) But even with a simple case like that, the stepper is not moving as I intended to do. It is actually moving less than 200 steps and totally out of control.

May I know how should I modify my move stepper function? Also, for those had experience doing similar projects, any advice is welcome :slight_smile:

Thank you!

I do not try to follow your logic, but I can assure you a stepper motor cannot move a fractional step as you are trying to do with a "float" value. Steppers move in whole, complete steps.

Your move_stepper() ignores the value if the stepper is still moving.

I am sorry to confuse you but I am sure that the actual code I tested is "int" already. The above "float" was a typo and corrected.

But even with "int" the motor does not move as I intended.

But I think it should complete 200 steps firstly anyway, before moving another 200 steps. What I should I write if it is still moving?

Write whatever you want while it is moving, but to the best of my knowledge you cannot do anything because the step() method is a blocking function. It does not return until the motor has completed stepping the specified number of steps. The speed and number of steps defines how long it will take.

My puzzle is really why it works very well when I just tell it to move back and forth, while it doesn't when I tell it to move base on some control outputs (calculated based on readings), given the same "move_stepper" function

To achieve the control, how would you suggest writing my moving control?

I believe it is doing what you tell it to do within the best of its capability. Print out what you are sending it to validate the commands are correct. Simply stated it is doing what you told it to do, not what you thought you told it to do.

Thanks for reply. I am getting familiar with the AccelStepper. As far as I know, runSpeed() can only run at a constant speed while run() can incorporate acceleration to achieve a higer max speed. However, it requires a setup of moveTo or move, which is kindly of positional control.

I would like to know is it possible to implement something like "runAcceleration()" regardless of the steps to move.

What should that function do?

AccelStepper accelerates to the given speed, then runs at that speed until it decelerates to zero. The deceleration phase can be omitted by giving a new target position before deceleration starts.

Basically I just wanted the move motor "faster" or intended to increase the upper limit while performing the general setSpeed situation like:

stepper.setSpeed(a big number);
stepper.runSpeed();

Will it help when applying a timer interrupt to the runSpeed function?

Why would you define a "upper limit" if then you want to exceed it?

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.