uStepper moveToEnd - incorrect result for degrees?

Hello,

I'm brand new to Arduino and stepper motors, so this could very well be me over looking something obvious.

I'm using the uStepper32 with a NEMA23 motor to drive a linear actuator. The total displacement is 388mm and I've measured 1mm of displacement equates to 45deg of rotation from the motor.

I'm using the moveToEnd function to have the motor drive the actuator all the way to one end (until it detects a stall) then all the way to the other (so it covers the full 388mm travel). Then return the "Degrees turned from calling the function, till end was reached", however this is coming back over the serial port at "0.43" ?

I was expecting a value closer to 17460 degree (388 * 45), so this is way off?

Any help here appreciated, links to the relevant places below:

Function: uStepperS32/src/UstepperS32.h at master · uStepper/uStepperS32 · GitHub

uStepper32 data sheet: https://ooznest.co.uk/wp-content/uploads/2023/02/uStepper-S32-Product-Sheet-Feb-22.pdf

Code:

/********************************************************************************************
* 	    	File:  limitDetection.ino                                                         *
*		Version:    2.3.0                                          						    *
*      	Date: 		October 7th, 2023  	                                    			*
*       Author:  Thomas Hørring Olsen                                                       *
*  Description:  Limit Detection Example Sketch!                                            *
*                This example demonstrates how the library can be used to detect hard       *
*                limits in an application, without the use of mechanical endstop switches.  *
*                Stallguard is very sensitive and provides seamless stall detection when 	  *
*				         tuned for the application. It is dependent on speed, current setting		    *
*				         and load conditions amongst others. The encoder stall detection is 		    *
*				         unaffected by most of these but can be a bit less sensitive.				        *
*                                                                                           *
* For more information, check out the documentation:                                        *
*                       http://ustepper.com/docs/usteppers/html/index.html                  *
*                                                                                           *
*  Note.......:  Place the stepper motor on a solid surface where it cannot harm anyone     *
*                during the test.                                                           *
*                                                                                           *
*********************************************************************************************
*	(C) 2023                                                                                  *
*                                                                                           *
*	uStepper ApS                                                                              *
*	www.ustepper.com                                                                          *
*	administration@ustepper.com                                                               *
*                                                                                           *
*	The code contained in this file is released under the following open source license:      *
*                                                                                           *
*			Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International               *
*                                                                                           *
* 	The code in this file is provided without warranty of any kind - use at own risk!       *
* 	neither uStepper ApS nor the author, can be held responsible for any damage             *
* 	caused by the use of the code contained in this file !                                  *
*                                                                                           *
*                                                                                           *
********************************************************************************************/

#include <UstepperS32.h>
UstepperS32 stepper;

#define STEPSPERREV 200 //Number of steps pr revolution. 200 for a 1.8deg motor, 400 for a 0.9deg motor
#define RES (STEPSPERREV *256)/360.0//calculate microstep pr. degree
#define STEPPRMM 25//full step pr. mm for the rail used in the demo
#define MMPRSTEP 1/(STEPPRMM*256)//mm pr. microstep
#define MMPRDEG MMPRSTEP*RES//mm pr. degree
#define STALLSENSITIVITY 2//sensitivity of the stall detection, between -64 and 63 - higher number is less sensitive

// Desired rpm for homing
int16_t rpm = 50;

void setup(){
  stepper.setup(NORMAL, STEPSPERREV); 	//Initialize uStepper S32
  stepper.checkOrientation(30.0);       //Check orientation of motor connector with +/- 30 microsteps movement
  stepper.setMaxAcceleration(2000);		//Use an acceleration of 2000 fullsteps/s^2
  stepper.setMaxVelocity(500);			//Max velocity of 500 fullsteps/s
  stepper.setCurrent(75);
  Serial.begin(9600);
}

void loop() {
  float railLength;
  float cwDirAngle;
  float ccwDirAngle;

  cwDirAngle = stepper.moveToEnd(CW, rpm, STALLSENSITIVITY);      //Reset to CW endpoint
  Serial.println(cwDirAngle);
  //Serial.println(railLength*MMPRDEG);//find end positions and read out the recorded end position
  ccwDirAngle = stepper.moveToEnd(CCW, rpm, STALLSENSITIVITY);    //Go to CCW end
  Serial.println(ccwDirAngle);
  //Serial.println(railLength*MMPRDEG);//find end positions and read out the recorded end position
  
  while(1);
}

The moveToEnd function is defined as follows:

float UstepperS32::moveToEnd(bool dir, float rpm, int8_t threshold, uint32_t timeOut)
{
	uint32_t timeOutStart = micros();
	// Lowest reliable speed for stallguard
	if (rpm < 10.0)
		rpm = 10.0;

	if (dir == CW)
		this->setRPM(abs(rpm));
	else
		this->setRPM(-abs(rpm));

	delay(100);

	this->isStalled();
	// Enable stallguard to detect hardware stop (use driver directly, as to not override user stall settings)
	ptr->driver.enableStallguard(threshold, true, rpm);

	float length = this->encoder.getAngleMoved();

	while (!this->isStalled())
	{
		delay(1);
		if ((micros() - timeOutStart) > (timeOut * 1000))
		{
			break; // TimeOut !! break out and exit
		}
	}
	this->stop();
	ptr->driver.clearStall();

	// Return to normal operation
	ptr->driver.disableStallguard();

	length -= this->encoder.getAngleMoved();
	delay(1000);
	return abs(length);
}

If you dig into the encoder library a bit, it looks like the angle will always be in the range of 0.0 … 360.0.

It would probably be much better/easier if you counted steps taken and then did your own math to convert that to how much rotation. The library really deals in steps.

knowing the threads/cm, wouldn't that many complete revolutions correspond to 1 cm of travel. if the # steps/rev were 200 and there were 10 threads/cm, 2000 steps would travel 1cm

Thanks. Do you know if there's a function to count steps (stepsMoved)?

the function stepper.driver.getPosition() returns the current count of microsteps as an int32_t.

Just call it at the beginning before you try to find the limit and again afterwards and you can figure out how many steps were taken.

Thanks, this helps. However I'm getting numbers that don't align with my expectation.

I'm using a NEMA23 (1.8deg) - so 200 steps / revolution.
Therefore (200*256)/360 = 142 micro-steps/deg.

When I perform a 360 deg rotation on the motor, I'm getting:
stepper.driver.getPosition() = -153600.00
moveAngle(360);
stepper.driver.getPosition() = -165747.00

Difference in steps = 12,147
12,147/142 = 85deg?? Surely this should be 360deg? Therefore is the encoder not reporting steps correctly?

Just realised the error, I was calling the getPosition before the motor had finished turning! Thanks for your help.