Pages: [1] 2   Go Down
Author Topic: I want my stepper motor to switch speed while traveling  (Read 694 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 15
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I have this project I'm working on where I'll need the speed of the stepper motor to change set speed at a certain distance, I just can't figure out a way to do it. I'm using arduino UNO and a stepper motor, this is the current code.

#include <AccelStepper.h>

AccelStepper stepper1(AccelStepper::FULL4WIRE, 0, 1, 2, 3);

void setup() {
stepper1.setMaxSpeed(200.0); stepper1.setAcceleration(400.0); stepper1.moveTo(5000);

}

void loop() { // Change direction at the limits if (stepper1.distanceToGo() == 0) stepper1.moveTo(-stepper1.currentPosition()); stepper1.run();

What I want it to do basically is to first moveTo2500 at the current speed 200 then after 2500 I want it to increase speed to 400. After it has moved 5000 it turns and moves back to position but that's implemented already.

I've searched around on the net but haven't found anything and decided to try here.

Thank you.
« Last Edit: October 23, 2013, 06:22:53 am by PZ2332 » Logged

UK
Offline Offline
Faraday Member
**
Karma: 47
Posts: 3615
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I imagine you should break up your instruction into two chunks - the first 2500 at one speed and the second 2500 at the other speed?

...R
Logged

UK
Offline Offline
Shannon Member
****
Karma: 184
Posts: 11183
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It depends whether you want to do the movement synchronously (i.e. with your code blocking until teach movement is complete) or asynchronously. For blocking, can't you just call setSpeed() to set the initial speed and then call runSpeedToPosition() to move to the first position, and then call setSpeed() and runSpeedToPosition() again to move to the second position? If you want to do it asynchronously it would be similar but you'd need to call runSpeed() repeatedly and monitor the progress to your target position yourself.

That's how it seems to me, anyway, judging by the API documentation.
Logged

I only provide help via the forum - please do not contact me for private consultancy.

Offline Offline
Newbie
*
Karma: 0
Posts: 15
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for the help!

I'll try your advice and report my results, the non blocking code seems to be what I'm after.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 15
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I've gotten stuck again and I wasn't sure about making a new topic or not, so decided to use my old one.

I'm trying to implement a way for my stepper motor to move into home position before starting the loop, I've set up an IR LED that is supposed to work like this, the motor moves backwards until the IR LED breaks then the loop starts running.
There's something wrong in the code though that I haven't been able to figure out.

Here it is!

Code:
#include <AccelStepper.h>


// Define some steppers and the pins the will use
AccelStepper stepper1(AccelStepper::FULL2WIRE, 2, 3);


const int reset = 4;
int buttonState = 0;
int sensorPin = A3;
int sensorValue = 0;

void softReset() // Restarts program from beginning but does not reset the peripherals and registers
{
asm volatile ("  jmp 0"); 
}

void setup()

   
    pinMode(reset, INPUT);
    stepper1.setMaxSpeed(30000.0);
    stepper1.setAcceleration(20000.0);
    stepper1.moveTo(8000);
  sensorValue = analogRead(sensorPin);
if (sensorValue < 150)

  stepper1.moveTo(20000);
  stepper1.setMaxSpeed(500.0);
  stepper1.run();
}
  else if (sensorValue >150)
  {
    stepper1.setCurrentPosition(0);
stepper1.moveTo(-8000);
  }
   
}



void loop()

{
 
 
    buttonState = digitalRead(reset);
    if (buttonState == LOW)
    {   
   
    softReset(); 


  }
sensorValue = analogRead(sensorPin);
if (sensorValue < 150)

  stepper1.moveTo(20000);
  stepper1.setMaxSpeed(1000.0);
  stepper1.run();
}
  else if (sensorValue >150)
  {
    stepper1.setCurrentPosition(0);
 

    // Change direction at the limits
    if (stepper1.distanceToGo() == 0)
   
    {
     stepper1.moveTo(-stepper1.currentPosition());   
    }
     else if (stepper1.distanceToGo() == 2000)
     {
  stepper1.setMaxSpeed(40000);
}


stepper1.run();


 


  }
}
Logged

Offline Offline
God Member
*****
Karma: 7
Posts: 647
"In this house, we obey the Laws of Thermodynamics" Homer J. Simpson
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
What I want it to do basically is to first moveTo2500 at the current speed 200 then after 2500 I want it to increase speed to 400.

The title of your post includes "not acceleration wise".

You seem to be trying to instantly double the step speed of your stepper motor. Whether not you can do this will depend on the torque your stepper generates and the mass of the object it is moving. In reality the stepper motor does have to accelerate the mass, if the mass is too large for the motor it will skip.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 15
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I changed the title, It was unclear and you are correct. I did manage to get it to move the way I want, but I hit another obstacle  smiley
Logged

UK
Offline Offline
Shannon Member
****
Karma: 184
Posts: 11183
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

There's something wrong in the code though that I haven't been able to figure out.

Does it compile? Does it detect the sensor state correctly? What is it doing wrong?
Logged

I only provide help via the forum - please do not contact me for private consultancy.

Offline Offline
Newbie
*
Karma: 0
Posts: 15
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It compiles, the wrong part is that it doesn't go to the loop of moving forward and backwards, when I go against the sensor it stops for around one second, then it keeps going till it moved all the steps. After that it stops.
Logged

UK
Offline Offline
Shannon Member
****
Karma: 184
Posts: 11183
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Delete the softReset() function and the code calling it. You do NOT need or want to reset the Arduino.

Any place where you have two blank lines together, delete one of them.

Any place where you have a blank line before a { or } or after a {, delete it.

Run the Tools / Autoformat command to correct the indentation on your code.

Initialise the Serial port in setup() and add print statements to loop() to confirm that the sketch is reading the sensor value correctly and that it is taking the action you intend in response to that value. This will show you where the problem is.
Logged

I only provide help via the forum - please do not contact me for private consultancy.

Offline Offline
Newbie
*
Karma: 0
Posts: 15
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The sketch is reading the sensor correctly, but it isn't taking the action I want it to. I want it to move backwards till it hits the switch, then stops till it reads a button press. The motor doesn't move at all though. I'm not sure what to do.

Code:
#include <AccelStepper.h>

AccelStepper stepper1(AccelStepper::FULL2WIRE, 2, 3);

int buttonState = 0;

void setup()
{  
  Serial.begin(9600);
  stepper1.setMaxSpeed(3000.0);
  stepper1.setAcceleration(7000.0);
  stepper1.moveTo(5800);
}

void loop()

{
  int sensorValue = analogRead(A3);
  Serial.println(sensorValue);
  if (sensorValue < 1000)
  {
    stepper1.setCurrentPosition(0);
  }
  if (stepper1.distanceToGo() == 0)
  {
    stepper1.moveTo(-stepper1.currentPosition());
    digitalWrite(startScan, HIGH);   // turn the LED on (HIGH is the voltage level)
    delay(100);
    digitalWrite(startScan, LOW);    
  }
  else if (stepper1.distanceToGo() == 2000)
  {
    stepper1.setMaxSpeed(4000);
  }
  stepper1.run();
}

It ignores my call to move to 5800 and I think that is what is messing it up.
« Last Edit: November 05, 2013, 04:31:04 am by PZ2332 » Logged

UK
Offline Offline
Shannon Member
****
Karma: 184
Posts: 11183
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm not sure what the problem is, but the way you're using the stepper motor API assumes that the library does what you expect - some of those methods have subtleties that aren't obvious and it would be easy for them to have unexpected side effects. You aren't really controlling what happens and when, either, so you could be inadvertantly running the wrong logic at the wrong time.

I can see two approaches to take.

First approach is to implement your sketch as a state machine. This fits the way the AcelStepper is designed to work since it is obviously designed with non-blocking operation in mind. The simplest way to do this is to define your states as integer values and then use a switch / case statement to execute the logic appropriate to the current state. For example you could define your states as enum States { PARKING, SLOW_FORWARDS, FAST_FORWARDS, REVERSING }; and then use a switch to do whatever is appropriate to the current state:

Code:
switch(state)
{
case PARKING:
    if(parkingSensorTriggered())
    {
        stepper1.setCurrentPosition(0); // this also stops the motor
        // start moving forward at slow speed
        stepper1.moveTo(2500);
        stepper1.setSpeed(200);
        state = SLOW_FORWARDS;
    }
    break;
case SLOW_FORWARDS:
    if(stepper1.distanceToGo() == 0)
    {
        stepper1.moveTo(5800);
        stepper1.setSpeed(400);
        state = FAST_FORWARDS;       
    }
    break;
case FAST_FORWARDS:
    if(stepper1.distanceToGo() == 0)
    {
        stepper1.moveTo(0);
        stepper1.setSpeed(400);
        state = REVERSE;       
    }
    break;
case REVERSE:
    if(stepper1.distanceToGo() == 0)
    {
        stepper1.moveTo(2500);
        stepper1.setSpeed(200);
        state = SLOW_FORWARDS;       
    }
    break;
}
stepper1.run();

This would treat the slow and fast parts of the movement as separate operations which I expect means the stepper driver will slow and stop at 2500. If you want it to be a continuous movement then at the start of SLOW_FORWARD you would command a movement to 5800 and set MaxSpeed to 200; at the start of FAST_FORWARD you would just change MaxSpeed to 400.
Logged

I only provide help via the forum - please do not contact me for private consultancy.

Offline Offline
Newbie
*
Karma: 0
Posts: 15
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I've never worked with states before so I have no clue what to do smiley-cry, my searches on the net has lead nowhere. Is it part of another library? Discovered something called finished state machine.
Logged

UK
Offline Offline
Faraday Member
**
Karma: 47
Posts: 3615
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

A state machine is just a mental concept.

Think about it in human terms. When you are reading this you are probably not in the "in bed" state and when you are asleep at night you are probably in the "in bed" state.

Imagine that you leave a note inside the hall door that says "gone to bed" before you climb the stairs. When you come downstairs in the morning you turn the note over so it says "not in bed".

In Arduino terms the equivalent of the note is a variable (perhaps called "inBed") which the program sets to true or false as appropriate.

...R
« Last Edit: November 06, 2013, 07:13:17 am by Robin2 » Logged

UK
Offline Offline
Shannon Member
****
Karma: 184
Posts: 11183
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Is it part of another library?

No, it's just a variable that you set to a value to record what state you're in, so that you can perform the logic that needs to be performed in that state. The snippet I posted was supposed to demonstrate the concept.

(The term you were looking for is finite state machine.)
Logged

I only provide help via the forum - please do not contact me for private consultancy.

Pages: [1] 2   Go Up
Jump to: