Stepper motor move faster in one direction than the other

Hey Arduino people!

I am having trouble with making a stepper motor move at equal speeds in both directions. I have an RC transmitter and receiver successfully moving the stepper motor back and forwards. However, one direction does not move as fast as the other. when moving the joystick left it has 5 speeds, which is correct. However, moving the joystick to the right it only has the first three of those 5 speeds I've told it to do. I checked the pulses and having the joystick in the center is sending 1490, full left stick sends 892, full right stick sends 2091. I have fiddled around with changing pulse width to higher and lower values but the problem persists. I am pretty new to coding and don't exactly know what's going on. Any help would be wonderful
Thanks :slight_smile:

//Define Pins
#define RCPin 2
#define DIR 17
#define STEP 16


//Set up time variables for Stepper motor
unsigned long previousMotorTime = millis();
long MotorInterval;
volatile long StartTime = 0;
volatile long CurrentTime = 0;

//Set up time variables for RC Read
volatile long Pulses = 0;
int PulseWidth = 0;


void setup() {
  Serial.begin(9600);

  //RC Read Setup
  pinMode(RCPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(RCPin), PulseTimer, CHANGE); 

  pinMode(DIR, OUTPUT);
  pinMode(STEP, OUTPUT);



}


void loop() {
  digitalWrite(STEP, LOW);

  //Only save HIGH pulse lengths
  if (Pulses < 2000){
    PulseWidth = Pulses;
  }

  //Stepper motor speed, bigger MotorInterval is a slower speed.
  if (PulseWidth >= 1400 && PulseWidth <= 1600){
    digitalWrite(STEP, LOW); //Motor doesn't move if the joystick is near the midpoint
  }
  else if (PulseWidth < 1400){
    digitalWrite(DIR, LOW);
    MotorInterval = map(PulseWidth, 1000, 1400, 1, 5); //map the RC signal to the motor speed in reverse when the joystick is pulled down
  }
  else if (PulseWidth > 1600){
    digitalWrite(DIR, HIGH);
    MotorInterval = map(PulseWidth, 1600, 2000, 5, 1); //map the RC signal to the motor speed when the joystick is pushed forward.
  }

  //check if the MotorInterval time has elapsed and step the motor.
  unsigned long currentMotorTime = millis(); 
  if (currentMotorTime - previousMotorTime > MotorInterval){
    digitalWrite(STEP, HIGH);
    previousMotorTime = currentMotorTime;
  }
}

//Function to measure the length of the pulses from the remote control
void PulseTimer(){
  CurrentTime = micros();
  if (CurrentTime > StartTime){
    Pulses = CurrentTime - StartTime;
    StartTime = CurrentTime;
  }
}

Schematics and links to datasheets, please. Words and code give no clue, and the crystal ball is on vacation.
What's the observed difference in speed?

I think here you should be toggling the STEP pin HIGH (if its LOW) and LOW (if its HIGH).
You are setting it LOW every scan.

Regards,

Gareth

But, does the motor move the same distance in both directions and does it always return to the same beginning position?

Thanks for the quick reply, I tried changing it from 'HIGH' to 'LOW' but the motor doesn't work at all. I am probably understanding this wrong and I sadly lack the knowledge to write the code to do that. I am following this person's tutorial on it https://www.theboredrobot.com/post/controlling-a-stepper-motor-with-a-remote-control-and-arduino

Here is the link to the tutoiral I am following: https://www.theboredrobot.com/post/controlling-a-stepper-motor-with-a-remote-control-and-arduino

The observed speed in one direction moves nearly twice the speed as the other direction. Each side should have 5 controllable speeds, the first three speeds on both sides match. But one side goes the extra 2 speeds while the other is stuck at speed 3.

Sorry about my lack of info, this is my first Arduino project :((

The motor will keep moving in the direction the stick is held until I return the stick on the transmitter to the middle, which is good as that's what I am wanting!

Have you verified the pulse length with an oscilloscope to be sure the pulse length are the same for however you move the stick?

It won't, you need to toggle it. Try this ...

You'll need to remove the first line in your loop ( digitalWrite(STEP, LOW); )

I have added your new code in place of the old however I get an error

(exit status 1
Compilation error: 'MotorOutput' was not declared in this scope)

I think the declaration of MotorOutput needs to be placed at the start somewhere but I do not know how.

MotorInterval = map(PulseWidth, 1600, 2000, 5, 1); 

Could you be going outside the mapped value and going to zero instead of 1? I'd double check your measured output with some serial debugging.

Yes I tried adjusting the PulseWidth values up and down and nothing different was perceivably happening to the motors speed in either directions

There's a lot of crap out there so such videos are not analysed.

Okey. What about the reply from @ Paul_KD7HB?

Use Serial.print and serial monitor to know what values are in use.

Ah yes, sorry ... under

long MotorInterval;

add

int MotorOutput = 0;

 if (PulseWidth >= 1400 && PulseWidth <= 1600){
    digitalWrite(STEP, LOW); //Motor doesn't move if the joystick is near the midpoint
  }
  else if (PulseWidth < 1400){
    digitalWrite(DIR, LOW);
    MotorInterval = map(PulseWidth, 1000, 1400, 1, 5); //map the RC signal to the motor speed in reverse when the joystick is pulled down
  }
  else if (PulseWidth > 1600){
    digitalWrite(DIR, HIGH);
    MotorInterval = map(PulseWidth, 1600, 2000, 5, 1); //map the RC signal to the motor speed when the joystick is pushed forward.
  }

I am a little concerned with the time spent for mapping and the tight timing with 1 and 2 milliseconds.

What do you see if you reverse the checking order? Are the missing times switched around? This will give a clue as to whether the issue is with the timing of the if/ifelse ladder.

 if (PulseWidth >= 1400 && PulseWidth <= 1600){
    digitalWrite(STEP, LOW); //Motor doesn't move if the joystick is near the midpoint
  }
 else if (PulseWidth > 1600){
    digitalWrite(DIR, HIGH);
    MotorInterval = map(PulseWidth, 1600, 2000, 5, 1); //map the RC signal to the motor speed when the joystick is pushed forward.
  }
  else if (PulseWidth < 1400){
    digitalWrite(DIR, LOW);
    MotorInterval = map(PulseWidth, 1000, 1400, 1, 5); //map the RC signal to the motor speed in reverse when the joystick is pulled down
  }

Added it now! The code does compile however the same issue is occurring. Additionally, the RPM appears to be slightly lower than before on both directions

With it reversed the motor is still slower when moving the stick right, (clockwise movement for the stepper)

Then your pulses are not symmetrical, high time is not equal to low time. A scope will show if true.

I do not own an oscilloscope so I cannot do that suggestion sadly.
I used a Serial.print and the serial monitor to check those values, which are from 892-2091.

I thought the issue was that the full range of speeds available in the two directions was not the same, but that for the speeds that you had, the rates were equivalent in each direction.

Can you please characterize the nature of the problem with a bit more detail.