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.
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.
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.
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!
#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();
}
}
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.
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.
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.
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.
#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.
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:
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.
I've never worked with states before so I have no clue what to do =(, my searches on the net has lead nowhere. Is it part of another library? Discovered something called finished state machine.
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.
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.)
I've been experimenting with the example code you gave me and I think I've learned quite a bit, I'm still a bit unsure about defining states but... anyway, I'm getting an error trying to compile the code. I get the "expected primary-expression before ")" token" at the swith (state) line.
#include <AccelStepper.h>
AccelStepper stepper1(AccelStepper::FULL2WIRE, 2, 3);
enum state {
PARKING, SLOW_FORWARDS, FAST_FORWARDS, REVERSE };
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);
switch (state)
{
case PARKING:
if(sensorValue < 1000)
{
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();
}
You should take a look at my statemachine library found here: http://playground.arduino.cc/Code/SMlib
It gives cleaner code than using swtich statements and also has some other benefits.
When working with the concept of statemachines you should always draw a state diagram in order to model the problem and its solution. It is clear from this state diagram that you never go back to the Parked state. Is this intentional? Otherwise change the state following Reverse from Slow to Parked.
Here is the code, it compiles fine but i was not able to test it with a motor. The state diagram is attached.
#include <AccelStepper.h>
#include <SM.h>
SM Controller(Parked);
AccelStepper stepper1(AccelStepper::FULL2WIRE, 2, 3);
void setup()
{
stepper1.setMaxSpeed(3000.0);
stepper1.setAcceleration(7000.0);
stepper1.moveTo(5800);
}
void loop(){
EXEC(Controller);
stepper1.run();
}//loop()
State Parked(){//wait for sensor to be activated
stepper1.setCurrentPosition(0); // this also stops the motor
if(analogRead(A3)<1000) Controller.Set(SlowH, SlowB);
}//Parked()
State SlowH(){// start moving forward at slow speed
stepper1.moveTo(2500);
stepper1.setSpeed(200);
}//SlowH()
State SlowB(){//check remainng distance while moving
if(stepper1.distanceToGo() == 0) Controller.Set(FastH, FastB);
}//SlowB()
State FastH(){
stepper1.moveTo(5800);
stepper1.setSpeed(400);
}//FastH()
State FastB(){
if(stepper1.distanceToGo() == 0) Controller.Set(ReverseH, ReverseB);
}//FastB
State ReverseH(){
stepper1.moveTo(0);
stepper1.setSpeed(400);
}//ReverseH()
State ReverseB(){
if(stepper1.distanceToGo() == 0) Controller.Set(SlowH, SlowB);
}//ReverseB()
I dont know what sensor you are using (or why you are using an analog input for that matter) or in which configuration so i just copied the code from your example.
The last line in the "parked" state (which i suppose you are reffering to) means:
State Parked(){//wait for sensor to be activated
stepper1.setCurrentPosition(0); // this also stops the motor
//if sensor is activated change state to slow:
if(analogRead(A3)<1000) Controller.Set(SlowH, SlowB);
}//Parked()
If i misunderstood your example just change the condition in the parenthesis of the if statement.
As i mentioned before, the way you described the workings there is no returning to the parked state. Look at the state diagram. If you want to change that, make a new state diagram before changing the code...
I'm glad you liked my library, feel free to spread the knowledge