Stepper: Stopping at center position

Hello,

I am using Arduino UNO, NEMA34 stepper motor, CL86T driver and nRF24L01 for communication from remote. I am using Accel library. This motor is being used to operate a oscillating arm. I am facing following problems.
a. I want to stop the arm at center position when off signal is received. It starts properly as per code but doesn't stop at center position.
b. When off signal is passed, it doesn't stops after completing a single cycle but it stops after four cycles.

Please find my code and guide me.

#include <AccelStepper.h>
#include <nRF24L01.h>
#include <RF24.h>

RF24 radio(9, 10); // CE, CSN

int x , i , m, ang , arm_sp , AC; // ang = Angle, arm_sp = Arm Speed, AC = Arm On/Off Control, 
int n = 12;
int a[12] ;
int A[12] ;

AccelStepper stepper(1, 7, 6);

const byte address[6] = {'1' , 'S' , '0' , '1', '1'};

void setup()
{
//  Serial.begin(9600);
  radio.begin();
  radio.openReadingPipe(0, address);
  radio.setAutoAck(false);
  radio.setDataRate(RF24_250KBPS);
  radio.setPALevel(RF24_PA_LOW);
  radio.startListening();
  for (int i = 0; i < n; i++)
  {
    a[i] = 0;
  }
}

void loop()
{
  Data_recieve(a, n);
  arm();
}

void Data_recieve(int x[], int n)
{
  int c = 0;
  while (c < n)
  {
    if (radio.available())
    {
      radio.read( A, sizeof(A));
      for (int i = 0; i < 1; i++)
      {
        x[i] = A[i];
      }
      break;
    }
  }
}

void arm()
{
  {
    AC = A[5];
    if ( AC == 1)
    {
      ang = A[2];
      arm_sp = A[7];

      ang = map( ang , 0 , 860 , 70 , 140 ); // mapping angle with Pot value. Pot max value is 860.
      arm_sp = map(arm_sp, 0, 860, 100, 10000); // mapping arm speed with Pot value. Pot max value is 860.

      int ang1 = ang * 20; // to include gear ratio

      stepper.setMaxSpeed(arm_sp); // change of speed by pot setting.
      stepper.setAcceleration(arm_sp); // Set Acceleration
      stepper.currentPosition();
      
      stepper.setMaxSpeed(arm_sp); // change the speed by pot setting.
      stepper.setAcceleration(arm_sp); // Set Acceleration

      stepper.moveTo(ang1/2); // Run in CCW to half angle value with set speed and acceleration/deceleration:
      while (stepper.currentPosition() != (ang1/2)) // Full speed up to half of angle
        stepper.run();
      stepper.runToPosition();
      Serial.println(stepper.currentPosition());
      delay(1000);


      stepper.moveTo(-ang1); // Reverse direction to CW and run full angle value
      while (stepper.currentPosition() != (-ang1)) // Full speed up to angle in reverse direction
        stepper.run();
      stepper.runToPosition();
      Serial.println(stepper.currentPosition());
      delay(2000);

      stepper.moveTo(ang1/2); // Reverse direction to CCW and run to half angle value
      while (stepper.currentPosition() != (ang1/2)) // Full speed up to half of angle
        stepper.run();
      stepper.runToPosition();
      Serial.println(stepper.currentPosition());
      delay(2000);
      AC = A[5];
      Serial.println(AC);
      if ( AC == 0) {
        stepper.stop();
      }
}
  }
}

You use the same parameter as motor speed and acceleration? Is it what you intended?

What the sense of calling

without storing the return value? Do you know what this method for?

Where from the radio data arrives? What's this a device? PC or arduino? Do you have a code of transmitter?

  1. Yes, it is intended
  2. I am new to Accel library. Not aware of it.
  3. I am using a self developed remote to control three motor. Yes. It is working fine. I am receiving all values properly.

Please point to the code lines where you doing that

Added "stop". but no effect

it doesn't return motor to the "center", it knowns nothing about where the center is.
Please answer my question in post #4

I tried to correct it


      stepper.moveTo(ang1/2); // Run in CCW to half angle value with set speed and acceleration/deceleration:
      while (stepper.currentPosition() != (ang1/2)) // Full speed up to half of angle
        stepper.run();
      stepper.runToPosition();
      Serial.println(stepper.currentPosition());
      delay(1000);


      stepper.moveTo(-ang1); // Reverse direction to CW and run full angle value
      while (stepper.currentPosition() != (-ang1)) // Full speed up to angle in reverse direction 
        stepper.run();
      stepper.runToPosition();
      Serial.println(stepper.currentPosition());
      delay(2000);

      stepper.moveTo(ang1/2); // Reverse direction to CCW and run to half angle value
      while (stepper.currentPosition() != (ang1/2)) // Full speed up to half of angle
        stepper.run();
      stepper.runToPosition();
      Serial.println(stepper.currentPosition());
      delay(2000);
      AC = A[5];
      Serial.println(AC);
      if ( AC == 0) {
        stepper.stop();
      }

Did you succeed in it?

No, It didn't. When you switch on power, it starts with mid and goes to extreme end (half angle) and then after completion of cycle, it stops at extreme end. Now, if I again start it, it starts from extreme end and goes to another extreme end.

rather than duplicate code to run the stepper, i suggest writing a sub-function to run the stepper to a position specified as an argument. that function can be used to move the stepper from side to side, as well as position it in the middle ... as well as do other things

... maybe that function is simply runToPosition()

i'm not familiar with AccelStepper and the functions, but do you need to invoke both run() and runToPosition()?

also, suggest to test the motor function using the Serial monitor and only add the radio part after motor stuff works properly

finally, why is arm_sp passed to both setMaxSpeed() and setAcceleration()?

Some of your logic seems wrong.
This code:

Sets the arm_sp to a number between 100 and 10000. Then sets the stepper max speed to that value. The default max speed is 1. The values you are using are huge. Can the stepper actually produce that speed?

Thanks for your guidance and sorry for delayed responce.
I changed code. Now it works as desired but as per your above guidance motor runs quite slow if I map 860 to 1000. With 860 to 10000, I am getting the required speed. I would like to have your comments on it. What is wrong? Changed code is given below. I also want to run it on constant speed then accelarating and deaccelarating it.

void arm()
{
  {
    AC = A[5];
    if ( AC == 1)
    {
      ang = A[2];
      arm_sp = A[7];
      stepper.setCurrentPosition(0);
      ang = map( ang , 0 , 860 , 80 , 140 ); // mapping angle with Pot value. Pot max value is 860.
      arm_sp = map(arm_sp, 0, 860, 0, 10000); // mapping arm speed with Pot value. Pot max value is 860.

      int ang1 = ang * 20; // to include gear ratio

      stepper.setSpeed(arm_sp); // change the speed by pot setting.
      stepper.setAcceleration(arm_sp); // Set Acceleration

      stepper.moveTo(ang1); // Run in CCW to half angle value with set speed and acceleration/deceleration:
      while (stepper.currentPosition() != (ang1)) 
        stepper.run();

      stepper.moveTo(-ang1); // Reverse direction to CW and run full angle value
      while (stepper.currentPosition() != (-ang1)) 
        stepper.run();

      stepper.moveTo(0);
      while (stepper.currentPosition() != 0)
      {
        stepper.run();
      }
    }
  }
}

Thanks for your response.
a. Will work on function
b. I want to run it with max speed and max accelaration.

what are those values? why not define them as Constants and set there values once in setup()

why read them from the command line?

If your motor really can handle 10,000 steps per second then that's fine. The step angle of your motor is 1.8 degree so it does 1 full turn in 200 steps.
200 steps for a full turn and 10,000 steps per second means 50 full turns per second. That's 3000rpm. I can't see a max speed in the spec for the motor but that seems high to me.

You can't set the acceleration and speed to the same value if you're using the max speed.
If your motor is already at the max speed then it can't accelerate.

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