Controlling motor position through Serial.parseInt()

3,054 views
Skip to first unread message

anegroo

unread,
Nov 1, 2014, 5:16:45 AM11/1/14
to accels...@googlegroups.com
Hi!
I have trouble with using  Serial.parseint() to define the motor position. I used the ProportionalControl example which  works fine with values of a potmeter. Mapping the analog value I can make a full rotation of the motor so I can position it precisely in between a  360 degrees. Here I have changed the potmeter value with the serial value I sent from the computer, but the motor not moves...

Here is the code:
#include <AccelStepper.h>

// Define a stepper and the pins it will use
AccelStepper stepper(AccelStepper::HALF4WIRE, 8, 9, 10, 11);
// Tested with a 10k linear pot between 5v and GND - works
int val = Serial.parseInt();
void setup()
{
  stepper
.setMaxSpeed(1000);
 
Serial.begin(9600);
}
void loop()
{

if (Serial.available()>0){
val
= Serial.parseInt();
}
 
// Read new position
 
int val = Serial.parseInt();
  stepper
.moveTo(val);
  stepper
.setSpeed(1000);
  stepper
.runSpeedToPosition();
}
I added also the "stepper.run();" before the end, but no change.

This method works well with the normal Arduino stepper library, but I want to use acceleration, and  I need to use  accelstepper...I am new to this library (and in arduino too), I don`t know how to continue. Any help or suggestion would be much appreciated!

Yair Reshef

unread,
Nov 1, 2014, 6:32:12 AM11/1/14
to accels...@googlegroups.com
hey, 

runspeedtoposition() does not implement acceleration. - see the docs 
* put a stepper.run() inside loop()
* place moveTo() and setMaxSpeed() into a serialEvent block outside of loop.  you only need to send these once. 

for info on serialEvent see this tutorial   http://arduino.cc/en/Tutorial/SerialEvent

Yair Reshef

unread,
Nov 1, 2014, 6:54:24 AM11/1/14
to accels...@googlegroups.com
to use your event, this should work (untested)
#include <AccelStepper.h>

// Define a stepper and the pins it will use
AccelStepper stepper(AccelStepper::HALF4WIRE, 8, 9, 10, 11);
// Tested with a 10k linear pot between 5v and GND - works
int val = Serial.parseInt();

void setup() {

  Serial.begin(115200);

}

void loop() {
  stepper.run();
  // if there's any serial available, read it:
  while (Serial.available() > 0) {
    val = Serial.parseInt();

    // look for the newline. That's the end of your
    // sentence:
    if (Serial.read() == '\n') {
      stepper.moveTo(val);
      stepper.setMaxSpeed(1000);
      stepper.setAcceleration(500);
    }
  }
}

Message has been deleted

anegroo

unread,
Nov 1, 2014, 1:53:38 PM11/1/14
to accels...@googlegroups.com
Hi,

 Thank you very much for your suggestion, but unfortunatelly it doesn`t work here, the stepper doesn`t move. Below is the working code with the normal Arduino stepper library.

#include <Stepper.h>

#define STEPS 200

Stepper stepper(STEPS, 8, 9, 10, 11);

int steps = 0;

void setup()

{

  stepper
.setSpeed(100);

 
Serial.begin(115200);


}

 
void loop(){

if (Serial.available()>0){


steps
= Serial.parseInt();

Serial.println(steps);

}

if( steps != 0){

   stepper
.step(steps);

 
}

 steps
=0;

}

As you can see, there is a line " Serial.println(val);" and I can receive every position where the stepper moves. Inserting this  in my first example or your code, also not print any value received through Serial.parseInt. Probably in the code  something blocks the reading or reusing the sent value...

Yair Reshef

unread,
Nov 1, 2014, 4:36:51 PM11/1/14
to accels...@googlegroups.com
i dont know that library
mybe you should ask in general arduino forums
 libraries.

--
You received this message because you are subscribed to the Google Groups "accelstepper" group.
To unsubscribe from this group and stop receiving emails from it, send an email to accelstepper...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
yair99@gmail
050-6301212
tlv, israel

anegroo

unread,
Nov 1, 2014, 4:54:02 PM11/1/14
to accels...@googlegroups.com
Hi Yair,

I`m afraid (in fact I`m sure) that in general arduino forums will not know the accelstepper library... I posted here the example made with the arduino stepper library, to make me understood better. Actually I want to make the same thing with accelstepper. Anyway, thank you for your response. I`m waiting  if someone can help me to find a way...

Sandy Noble

unread,
Nov 1, 2014, 7:23:14 PM11/1/14
to accels...@googlegroups.com
This works ok for me - the Serial.println()s out are just to show that it's doing something (cos I've got no actual motor attached).

Slightly unusual thing about parseInt() is that the "enter" on the end of the number that I type in is interpreted as a 0. So typing 100, and pressing enter results in moving to 100, then the end-of-line character is interpreted as a 0, so it moves back to 0. In the serial monitor, change to "no line ending" at the bottom of the window to avoid this, or you'll need to add some extra logic around handling the numbers in the code itself.



#include <AccelStepper.h>

// Define a stepper and the pins it will use
AccelStepper stepper(AccelStepper::HALF4WIRE, 8, 9, 10, 11);
long steps = 0;

void setup()
  stepper.setMaxSpeed(1000);
  stepper.setAcceleration(1000);
  Serial.begin(9600);
}

void loop(){
  if (Serial.available() > 0) {
    steps = Serial.parseInt();
    Serial.println(steps);
    stepper.moveTo(steps);
    while (stepper.distanceToGo() != 0) {
      Serial.println(stepper.currentPosition());
      stepper.run();
    }
  }
}


anegroo

unread,
Nov 1, 2014, 10:12:16 PM11/1/14
to accels...@googlegroups.com
Hi Sandy!

 It works ! Thank you very much!

 I have another question.  I am  working on a project with arduino in combination with vvvv. I would like to  change  the position of stepper from vvvv interface  through the serial communication in a continuous way, like  a changing analog signal. For example, there is the ProportionalControl example mentioned by me in the first post, where turning left and right a potmeter`s axis  it is changing accordingly and immediately  the motor`s position back and forth. From vvvv I can send the  serial  command, and with simple values your posted code works well. But when I try to send a  range of values (for example from 100 to 200) the motor start to rotate continuously with a constant speed, even if the serial transmission of values ended. The serial transmision has no enough speed for this kind of task? Sorry if it is not clear...my english is too weak.

Thank you!
Message has been deleted

anegroo

unread,
Nov 2, 2014, 5:12:31 AM11/2/14
to accels...@googlegroups.com

I forgot to say, that this kind of continuous monitoring and folowing the position`s value sent through serial communication, also not works wih the standard  stepper library method posted by me in the 4th post.

As I wrote, this kind of control of the stepper`s position works with analog signals, like with a potmeter attached directly to arduino. But in this last case, the values are directly accesible, and it is not involved transcoding and transmitting the signal`s value through the serial port. Maybe exists another way? Or it is a limitation of the  arduino environment? Any help or suggestion would be much appreciated!

anegroo

unread,
Nov 2, 2014, 3:27:01 PM11/2/14
to accels...@googlegroups.com
I have found some bug  in the transcoding process of the floating value in vvvvv.  It was sent ( transcoded as strings) like this: 100101102103104105106...  without spaces.   I modified the encoding method and now the values are sent with spaces:100 101 102 103 104 105 106.... Now it is better: the motor is moving according to the changing values   but often there are impredictable  jumpings, changes in moving direction, and finally the motor begin  to rotate again infinitely. I think the problem is in the way in that the transcoded floating value is interpreted by the arduino sketch. But I`m a visual artist,  not a programmer... I cannot dig in this thing more deeply without help. I use vvvv because it is a way of visual programming. The problem here is no more related to accelstepper library, but to the arduino`s coding language. Anyway, there is some good result, so thank you for your help!

Sandy Noble

unread,
Nov 2, 2014, 4:21:46 PM11/2/14
to accels...@googlegroups.com
Really difficult to say what your issue is, but where there's a physical limit to how fast things can be done (ie with a motor), then it's pretty easy to overload the system with commands. The serial link will buffer a lot of digits so it can take a while for them all to be read, parsed, and acted upon.

Maybe something like below might work to ignore all commands that occur while the motor is already moving. So it'll just discard all messages that occur while it is still moving.

void loop(){
  stepper.run();
  if (Serial.available() > 0) {
    steps = Serial.parseInt();
    
    // only actually set the target if the stepper is stopped
    if (stepper.distanceToGo() == 0) {
      stepper.moveTo(steps);
    }
  }
}

Re your last point, some sort of serial link is the easiest way to communicate with the arduino, afraid it doesn't get any simpler than sending numbers over the serial link. Either way you do it - sampling a pin, or reading numbers off the serial port, you end up with a value, so it doesn't really affect your program structure. Except of course, serial comms is a lot slower than reading a pin


sn

On 2 November 2014 20:27, anegroo <ane...@gmail.com> wrote:
I have found some bug  in the transcoding process of the floating value in vvvvv.  It was sent ( transcoded as strings) like this: 100101102103104105106...  without spaces.   I modified the encoding method and now the values are sent with spaces:100 101 102 103 104 105 106.... Now it is better: the motor is moving according to the changing values   but often there are impredictable  jumpings, changes in moving direction, and finally the motor begin  to rotate again infinitely. I think the problem is in the way in that the transcoded floating value is interpreted by the arduino sketch. But I`m a visual artist,  not a programmer... I cannot dig in this thing more deeply without help. I use vvvv because it is a way of visual programming. The problem here is no more related to accelstepper library, but to the arduino`s coding language. Anyway, there is some good result, so thank you for your help!

--
You received this message because you are subscribed to the Google Groups "accelstepper" group.
To unsubscribe from this group and stop receiving emails from it, send an email to accelstepper...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Sandy Noble

anegroo

unread,
Nov 2, 2014, 6:51:28 PM11/2/14
to accels...@googlegroups.com
Hi Sandy!

Thank you again for your  attention. Your last code works well when the floating value are changing in a linear way very slowly. In HALF4WIRE  mode and with a big value for setAcceleration (10000 or more) for a full rotation of 200*2=400 steps it can not be not below 20 sec to remain in synch, so 20 changing value/sec. In FULL4WIRE mode it can be ~10sec. because of the less steps. This is the limit of the serial or my mega2560`s CPU? Here is the code:
#include <AccelStepper.h>

AccelStepper stepper(AccelStepper::HALF4WIRE, 8, 9, 10, 11);
long steps = 0;
void setup()
{
  stepper.setMaxSpeed(4000);
  stepper.setAcceleration(10000);
  Serial.begin(115200);

}
void loop(){
  stepper.run();
  if (Serial.available() > 0) {
    steps = Serial.parseInt();
// only actually set the target if the stepper is stopped
    if (stepper.distanceToGo() == 0) {
      stepper.moveTo(steps);
    }
  }
}
When I change the floating value fast and randomly the motor begin to behave unpredictable. Changing the value up and down the motor will rotate in the same direction instead of turning back, and sometimes jumps.


Sandy Noble

unread,
Nov 4, 2014, 5:09:03 PM11/4/14
to accels...@googlegroups.com
Not sure what your question is? Maybe if you said what behaviour you're aiming for, then we could offer more specific ideas instead of this general stuff with is a bit woolly. (There's dozens different ways to do any one thing - all of them work, but some are more right than others!)


sn

--
You received this message because you are subscribed to the Google Groups "accelstepper" group.
To unsubscribe from this group and stop receiving emails from it, send an email to accelstepper...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Sandy Noble

anegroo

unread,
Nov 4, 2014, 6:36:20 PM11/4/14
to accels...@googlegroups.com
Sorry,  I know, my english is poor.... In my works I am experimenting the ways to combine some data analyzed by vvvv and  to transmit this to change something in the real world. For example vvvv captures a realtime video, analize the persons motion in the view of camera, calculates the coordonates of moving pixels and I would like this  values to be transmitted through serial to arduino to control in a proportional way the position of an object which could moved phisically by a stepper... If these coordinates are changing fast, now I am not able to control continously and in real time through serial port anything  with my arduino. So my question is: it is possible the transfer of this kind of fast changing data from my computer to control a stepper motor? Thanks.

Sandy Noble

unread,
Nov 5, 2014, 6:37:28 PM11/5/14
to accels...@googlegroups.com
Yep sure that's helpful thanks, question that I have is how to deal with transients.

First way:
1)  Measure, then move to that position, then measure again. So if the pixel is dark, but a second before measurement, it goes bright, then the motor will be sent off to move to the high position, and it might take several seconds to do it. It might be hard to see the connection between the position and the stimulus - it'd always be a little bit behind. This is what you already have, and you'll have seen that it's pretty easy for it to seem out-of-sync with your input values.

Second way:
2) Continuously measure and make small moves. So this is where you measure your value, and only ever move a maximum of one step at a time towards the current value. So a sudden spike will make the motor move a couple of steps higher, but once the spike is over, then it'll stop heading up. 

But if the input value is high for long enough, then the motor will eventually get to that position.

I think the second way is the best, it'll result in a more obvious response to stimulus. The down side is that it might appear more "twitchy" if the input is fairly constant, and you can't really benefit from any of the acceleration features of AccelStepper.

The code below might work (well, it runs, and looks like it works to me, but I don't have a motor attached - hence the printlns!)

#include <AccelStepper.h>

// Define a stepper and the pins it will use
AccelStepper stepper(AccelStepper::HALF4WIRE, 8, 9, 10, 11);
// Somewhere to put the input value
long input = 0;

// how often you want the serial input to be checked.
int measurementInterval = 200;
// when the serial input was last checked.
long lastMeasurementTime = 0L;

void setup()
  stepper.setMaxSpeed(1000);
  stepper.setAcceleration(10000);
  Serial.begin(9600);
  
  // set timeout otherwise parseInt puts in a long pause.
  Serial.setTimeout(10);
}

void loop(){
  // If current time (millis) is higher than the last time
  // a measurement was taken, PLUS the measurement interval.
  if (millis() > (lastMeasurementTime + measurementInterval)) {
    // then read some integers
    input = Serial.parseInt();
    // and if it is NOT zero, set it as the motor target.
    if (input != 0) {
      stepper.moveTo(input);
    }
    Serial.flush();
    lastMeasurementTime = millis();
  }
  
  Serial.print("Input:");
  Serial.print(input);
  Serial.print(", distanceToGo: ");
  Serial.print(stepper.distanceToGo());
  Serial.print(", stepped:");
  Serial.println(stepper.run());
}

It checks for incoming data every 200 milliseconds. You could increase or reduce that if you wanted a more or less responsive system. The process of checking for data on the Serial connection is quite slow, so that's why you wouldn't do it all the time - it would limit how fast your motor could step.

sn



On 4 November 2014 23:36, anegroo <ane...@gmail.com> wrote:
Sorry,  I know, my english is poor.... In my works I am experimenting the ways to combine some data analyzed by vvvv and  to transmit this to change something in the real world. For example vvvv captures a realtime video, analize the persons motion in the view of camera, calculates the coordonates of moving pixels and I would like this  values to be transmitted through serial to arduino to control in a proportional way the position of an object which could moved phisically by a stepper... If these coordinates are changing fast, now I am not able to control continously and in real time through serial port anything  with my arduino. So my question is: it is possible the transfer of this kind of fast changing data from my computer to control a stepper motor? Thanks.

--
You received this message because you are subscribed to the Google Groups "accelstepper" group.
To unsubscribe from this group and stop receiving emails from it, send an email to accelstepper...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Sandy Noble

anegroo

unread,
Nov 6, 2014, 6:42:13 PM11/6/14
to accels...@googlegroups.com
With a little modification  this code works. I only changed the baud rate to 115200, and two values: "int measurementInterval = 5;" and" Serial.setTimeout(5);". This way the rotation isn`t jerky.  Here is a little video I made to show the actual state of the work: video.

As you can see there are four  ways of changing the value. The first one  generates random numbers and the stepper is positioned according it`s value. The second is a manual changing and the stepper follows it pretty well. Only at very high speed looses the sync. The third case is a back and forth changing and at average speed is OK, but at higher speed, below 7-8 sec there are stops in rotation in every cycle. Looks like a stop because of a missing value... In the forth case the value is changed by the motion detectior  but this is yet buggy.

It is interesting that when I changed the value manually there was no stops like in the third case, though the speed often was  higher....

Anyway,  this is something which I can use it under certain circumstances. Thanks You  Sandy for your help!

Sandy Noble

unread,
Nov 6, 2014, 6:55:38 PM11/6/14
to accels...@googlegroups.com
Great little video! I think it's working well. The stutter during the LFO is a bit strange, you're right, but even when it gets a bit confused during the fast manual movement, it still recovers nice and quick. Good work :)


sn

--
You received this message because you are subscribed to the Google Groups "accelstepper" group.
To unsubscribe from this group and stop receiving emails from it, send an email to accelstepper...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Sandy Noble

anegroo

unread,
Nov 16, 2014, 6:28:04 PM11/16/14
to accels...@googlegroups.com
Another question Sandy....

Can I modify this for two steppers? I tried with the following code, which sometimes works, but sometimes, when I rotate one stepper, the another one also moves  or it makes little budges.  The general reaction speed is slower, but of course, this is understandable.

#include <AccelStepper.h>

AccelStepper stepper1(AccelStepper::HALF4WIRE, 8, 9, 10, 11);
AccelStepper stepper2(AccelStepper::HALF4WIRE, 7, 6, 5, 4);

long input1 = 0;
long input2 = 0;

int measurementInterval = 20;

long lastMeasurementTime = 0L;

void setup()
{
  stepper1.setMaxSpeed(1000);
  stepper1.setAcceleration(100);
  stepper2.setMaxSpeed(1000);
  stepper2.setAcceleration(100);
  Serial.begin(115200);
 
  Serial.setTimeout(2);
}

void loop(){


  if (millis() > (lastMeasurementTime + measurementInterval)) {

    input1 = Serial.parseInt();
    input2 = Serial.parseInt();

    if (input1 != 0) {
      stepper1.moveTo(input1);
    }
    if (input2 != 0) {
      stepper2.moveTo(input2);
    }
    Serial.flush();
    lastMeasurementTime = millis();
  }

  Serial.println(stepper2.run());
  Serial.println(stepper1.run());
}

Sandy Noble

unread,
Nov 17, 2014, 5:49:34 PM11/17/14
to accels...@googlegroups.com
Hello, I don't see why two motors would be a problem, but the extra time taken to parseInt() twice might be an issue. Apart from the delays coming from the extra read, you shouldn't really find it responds any slower.

Debug this by putting some Serial.println()s in your code to see what the real value of input1 and input2 is actually being set to. It'll be slow as molasses while the println()s are in the code, but should give you some insight into what is really happening.


sn

--
You received this message because you are subscribed to the Google Groups "accelstepper" group.
To unsubscribe from this group and stop receiving emails from it, send an email to accelstepper...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Sandy Noble

anegroo

unread,
Nov 17, 2014, 6:09:27 PM11/17/14
to accels...@googlegroups.com
The extra parseInt is for the second value for the second stepper`s position. From vvvv are sent the positions of the steppers simultaneously, separated by a comma. In arduino I used  this before to send multiple values in single serial message, and repeating the parseInt() can be read every value (like the members of an array). But the messeges were sent as single commands by a button press, and not so rapidly like here... Thanks for response, I will try tomorrow what you recommend.



anegroo

unread,
Nov 18, 2014, 4:41:41 PM11/18/14
to accels...@googlegroups.com
I can not use Serial.println() to see in serial window the messages because the port is open in vvvv when I send the values... Here is the link where the Serial.parseInt() is used for three times: arduino.cc/en/Tutorial/ReadASCIIString . Probably I didn`t understand it fully, and I adopted here in a wrong way.... But, as I wrote, it is working for individual "pockets", in a tested project, with six uses of  Serial.parseInt(),  to get values of speed,acceleration and position for each motor, sent from vvvv like this: 1000,100,750,2500,250,-450 . And now, this is not working with only two values of two changing positions... Any idea?

anegroo

unread,
Nov 19, 2014, 4:48:41 PM11/19/14
to accels...@googlegroups.com
I used a LCD instead of Serial.println(). .. Changing the first value from serial message the first motor moves accordingly, the LCD display it correctly. The second value from the LCD is not changing, but the second motor  makes little budges, but remains in the same position. When I change the second value from the serial message, the second motor moves accordingly and the second value from LCD display it correctly. But the first (now unchanged) value on LCD is changing randomly and the first motor is moving randomly. So there is some problem with the way the serial messege is interpreted by arduino...

Sandy Noble

unread,
Nov 20, 2014, 7:22:10 PM11/20/14
to accels...@googlegroups.com
LCDs themselves tend to be pretty slow, so there might be some odd behaviour creeping in. 

I don't see how stepper2 will be moving though. My guess is that there _is_ a instruction being sent to change stepper2 position, but it's quick, and then it's reset to stepper2's current position again. Really if that's the code that's running, then what else could it be except for a comms glitch?

I tried this, with serial.printlns, sent: 

100,200 - motors turn to 100 and 200.

100 <enter>
200 - stepper1 turns to 100, then to 200. stepper2 doesn't move at all.

100,200,300,400 - stepper1 starts moving to 100 and stepper2 starts moving to 200. 20 milliseconds later (measurementInterval), the targets are reset to 300 and 400.

There is no way in this scheme to send a command to stepper2 ONLY. Sending position instructions as pairs is the only way to make sure the instruction is getting to stepper2.

There is also no way to move to 0.


Not sure what to suggest, maybe give a look at the current code (if you haven't sorted it yet).


sn

On 19 November 2014 21:48, anegroo <ane...@gmail.com> wrote:
I used a LCD instead of Serial.println(). .. Changing the first value from serial message the first motor moves accordingly, the LCD display it correctly. The second value from the LCD is not changing, but the second motor  makes little budges, but remains in the same position. When I change the second value from the serial message, the second motor moves accordingly and the second value from LCD display it correctly. But the first (now unchanged) value on LCD is changing randomly and the first motor is moving randomly. So there is some problem with the way the serial messege is interpreted by arduino...

--
You received this message because you are subscribed to the Google Groups "accelstepper" group.
To unsubscribe from this group and stop receiving emails from it, send an email to accelstepper...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Sandy Noble

Stefan Gaillot

unread,
Jun 11, 2017, 6:24:16 AM6/11/17
to accelstepper
Thank you so much Sandy Noble!
I've been trying to do just that (the code you shared) for many hours, you saved my day/night!
So simple, beautiful!
Stefan
Reply all
Reply to author
Forward
0 new messages