Serial data triggering interrupts to step stepper motors.

Hey Guys,

I am trying to use an arduino to drive stepper motors for a robot. There are three stepper motors that I want to be able to control simultaneously. I know there are libraries for this, but I need something a little more advanced. I need the steppers to accelerate at a continuous rate, aka no infinite jerk spikes.

My idea is this:

Have a c# program running on my beefy computer. Set the baud rate as high as I can. Have the computer do every single one of the calculations needed, and send the arduino the BARE minimum. This in my idea means sending a single serial character to the arduino. The arduino will know what to do using either an interrupt (not sure how??) or an if statement when it receives the single serial character. Similar to the following:

A: step motor 1 forward
B: step motor 2 forward
C: step motor 3 forward
1: step motor 1 backward
2: step motor 2 backward
3: step motor 3 backward

When the arduino receives one of these characters it will use the digitalWriteFast function to set the correct pin to high to trigger a step and a direction. While the program is waiting for serial data it will continuously set all the pins to low with digitalWriteFast.

That concludes part 1 of my desired plan.

Part 2 is HOPEFULLY storing any excess serial data received in a buffer if it is not able to be processed immediately, and executed as soon as possible after the arduino is no longer busy.

Is this a sound plan? Any suggestions? Any input or criticisms are extremely welcome. I originally bought a smoothieboard for the superior hardware, but I did not count on it coming completely loaded with hundreds upon hundreds of lines of c++ code and firmware embedded in it, pretty much making it untinkerable to someone who is not proficient in c++. If another option exists other than smoothieboard/arduino I would like to hear that as well. This is for a linear input delta robot btw.

Part 2 is HOPEFULLY storing any excess serial data received in a buffer if it is not able to be processed immediately, and executed as soon as possible after the arduino is no longer busy.

Do you know anything about how the Arduino handles serial data? Apparently not, or you'd know that the Arduino already does this.

need the steppers to accelerate at a continuous rate, aka no infinite jerk spikes.

I have never used it but have you tried the AccelStepper library ?

Soronemus:
Have the computer do every single one of the calculations needed, and send the arduino the BARE minimum. This in my idea means sending a single serial character to the arduino. The arduino will know what to do using either an interrupt (not sure how??) or an if statement when it receives the single serial character. Similar to the following:

A: step motor 1 forward
B: step motor 2 forward
C: step motor 3 forward
1: step motor 1 backward
2: step motor 2 backward
3: step motor 3 backward

I am all in favour of the PC doing the heavy lifting but what you describe seems very much more than the "BARE minimum"

I have a Python program that sends data to an Uno to control 3 steppers on a small lathe. For any given move the PC figures out 4 values. The total number of microsecs for the move, and for each stepper the number of µsecs between steps. It then sends those 4 numbers in binary format. A µsec value of 0 means that the relevant motor does not move. Negative µsec numbers are used to mean "backwards"

While the Arduino is executing that move the PC sends the data for the next move so it is waiting in the Arduino serial input buffer as soon as the first move is completed.

So far I have found digitalWrite() to be perfectly adequate. If I thought it was too slow I would use port manipulation.

...R

UKHeliBob:
I have never used it but have you tried the AccelStepper library ?

From what I understand the accelstepper library uses a trapezoidal velocity profile (infinite jerk spikes are present). Also the accelstepper library only supports very low speeds, which is what I am trying to maximize. :frowning:

As I said, I have never used it, so you could be right but as a matter of interest what are “infinite jerk spikes” ? Do you perhaps mean finite jerk spikes ?

Re-reading my Reply #3 I see that I mis-interpreted the OPs system for sending data. I thought he was planning to send the entire line "step motor 1 forward" whereas he is just proposing to send the single character 'A'.

However that leads to another and probably bigger problem. Unless he only wants a very slow step rate it will be impractical for the PC to send commands one step at a time. The system I suggested sends data for a sequence of steps for all of the motors.

...R

Soronemus:
From what I understand the accelstepper library uses a trapezoidal velocity profile (infinite jerk spikes are present). Also the accelstepper library only supports very low speeds, which is what I am trying to maximize. :frowning:

How long does it take a serial connection to send the character "A" at 115200 baud? (Remember to add the start bit and stop bit to your calculations.) is this time duration for one single step consistent with your definition of "not very slow"?

You will find that you need to send commands like "take 500 steps" and have the Arduino figure out the acceleration and jerk. G-code takes this even further, because it has commands to move millimetres and to synchronise the movements of multiple motors.

MorganS:
How long does it take a serial connection to send the character "A" at 115200 baud? (Remember to add the start bit and stop bit to your calculations.) is this time duration for one single step consistent with your definition of "not very slow"?

You will find that you need to send commands like "take 500 steps" and have the Arduino figure out the acceleration and jerk. G-code takes this even further, because it has commands to move millimetres and to synchronise the movements of multiple motors.

You bring up a good point. Here are some calculations that I just did, I am not an expert on serial communication so please point out if you see faulty logic.

Each serial command will contain 1 start bit, 1 stop bit, and 7 data bits (enough for one ASCII character). That is 9 bits per serial transmission.

At a baud rate of 115200 bits per second, that is 12800 transmissions per second.

Dividing this by 3 (for three motors), and assuming all three motors are turning at the same speed, and are using a 1/8 microstepping (1600 steps per revolution in my case), that results in 4266.666667 pulses per second per motor, or 2.66 revolutions per second for each motor.

Multiplying 2.66rps2pi*6mm (the radius of my timing pulley) gives 100mm/s for each carriage of my delta robot. I could definitely live with that speed for my thesis if that is the case. Does anyone see any faults with this or anywhere I could optimize this?

Better yet... The arduino mega has FOUR serial communication lines. The main communication line and three auxiliary ones. If each of those four serial lines is dedicated to a motor (three translation motors, and one extruder motor) that eliminates the need to split the bandwidth of any serial line between motors. This would allow up to 301mm/s for each motor (assuming my logic above is correct).

100mm/s is kind of slow. It depends on what you want to do. This is not fast enough for a 3D printer. You want more than 250mm/s for fast moves. Actual print moves will be in the range 75-150mm/s, at least on my printer.

You have used 7 bits per byte when it's more normal to use 8. This does not make a huge difference to your calculations. You could have used individual bits within the byte to control the step+direction for each motor. That could make it 3 times faster.

I don't see how the 4 serial lines make it faster. You have 4 different computers commanding one Arduino to step the steppers?

G-code is a better way to do it. Your scheme can only move one motor at a time, even though the steps are small. A G-code interpreter can make simultaneous steps.

Each serial command will contain 1 start bit, 1 stop bit, and 7 data bits (enough for one ASCII character). That is 9 bits per serial transmission.

The default Serial setup sends 8 data bits, for 10 bits per character/byte.

Soronemus:
At a baud rate of 115200 bits per second, that is 12800 transmissions per second.

Dividing this by 3 (for three motors), and assuming all three motors are turning at the same speed, and are using a 1/8 microstepping (1600 steps per revolution in my case), that results in 4266.666667 pulses per second per motor, or 2.66 revolutions per second for each motor.

This sort of calculation may be appropriate for all the bytes within a single message. But it takes no account of the completely undefined time interval between messages. You should also be aware that a stop bit has a minimum length, but no maximum. The start bit is what determines the end of the stop bit.

If you want smooth movement you MUST leave it to the Arduino - that is the sort of thing it is especially good at because it does not have an operating system to get in the way.

...R

MorganS:
You have used 7 bits per byte when it's more normal to use 8. This does not make a huge difference to your calculations. You could have used individual bits within the byte to control the step+direction for each motor. That could make it 3 times faster.

I don't see how the 4 serial lines make it faster. You have 4 different computers commanding one Arduino to step the steppers?

G-code is a better way to do it. Your scheme can only move one motor at a time, even though the steps are small. A G-code interpreter can make simultaneous steps.

Could you elaborate on how I could go about using the individual bits instead of using an entire character?

About the 4 serial lines, I was under the impression that the maximum baud rate was 115200 (which after reading about it is nowhere close to the max which people say is 1Mbps) I was suggesting using four different serial lines coming from the same computer to split up the data transfer. Now that I know that the baud rate is able to be set higher it doesn't sound worth it.

I would love to use g-code, and I probably will once my thesis is done once I turn this into an actual 3d printer, but I have designated continuous acceleration (no infinite jerk spikes) as a goal of my thesis. Grbl which seems to be the most widely used g-code interpreter uses constant acceleration in its motion planning which is out of the question for me because it DOES produce infinite jerk spikes.

Robin2:
This sort of calculation may be appropriate for all the bytes within a single message. But it takes no account of the completely undefined time interval between messages. You should also be aware that a stop bit has a minimum length, but no maximum. The start bit is what determines the end of the stop bit.

If you want smooth movement you MUST leave it to the Arduino - that is the sort of thing it is especially good at because it does not have an operating system to get in the way.

...R

Could you point me in the right direction to fully understand how stop bit length works? I thought you just specified the start bits, stop bits, and data bits through a command in arduino to initialize the communication. I am not seeing anything contrary to that on google but I haven't dug very deep.

I definitely want to have continuous movement, I am willing to do what ever it takes to do it, I bought a 140 dollar smoothieboard because of the hardware advantages over the arduino because I had read it was the best of the best for 3d printer control (my mistake was assuming I would be able to customize it other than just tweaking a few parameters, and they use motion planning which causes infinite jerk spikes). Can you think of a different method I could use for having complete control over the trajectories of my robot joints?

I thought of using three timer interrupts in arduino, each one constantly modulating the time between the steps for each stepper motor, however after looking into it it does not seem feasible. The reason being that when the arduino enters in to an interrupt it ignores all other interrupts until it exits the one it is in, which would result in lots of missed steps.

Do you think that a computer would not be capable of sending precisely timed step commands for the arduino to handle? If I needed to I am pretty sure I can split the work up between the four cores of my computer. I have a quad core overclocked to 4.5GHz so I can't imagine the computer's responsibilities would be a bottleneck.

BTW I sincerely appreciate all of your feedback, keep it coming!

Soronemus:
Could you point me in the right direction to fully understand how stop bit length works? I thought you just specified the start bits, stop bits, and data bits through a command in arduino to initialize the communication. I am not seeing anything contrary to that on google but I haven't dug very deep.

It's a while since I studied this and wrote the code in Yet Another Software Serial. Maybe I have my terminology slightly off. What I was trying to convey is that there is no defined length of interval between successive characters. It could be a short as the stop bit and it could be 5 minutes or 5 hours. You can only rely on Serial timing within a single byte.

I have to say I don't really understand the problem you are trying to address. It sounds to me as if you want to send a sequence of step signals to a motor with a smoothly varying interval between successive steps from a long interval for slow to a short interval for fast.

Do you know how many steps will be involved in a specific movement so that you could tell the Arduino "move 500 steps and vary the interval from (say) 100 millisec to 10 millisecs over the course of the 500 steps"

Or, as that is probably wrong, can you describe what you want in smiliar terms.

...R

Robin2:
It's a while since I studied this and wrote the code in Yet Another Software Serial. Maybe I have my terminology slightly off. What I was trying to convey is that there is no defined length of interval between successive characters. It could be a short as the stop bit and it could be 5 minutes or 5 hours. You can only rely on Serial timing within a single byte.

I have to say I don't really understand the problem you are trying to address. It sounds to me as if you want to send a sequence of step signals to a motor with a smoothly varying interval between successive steps from a long interval for slow to a short interval for fast.

Do you know how many steps will be involved in a specific movement so that you could tell the Arduino "move 500 steps and vary the interval from (say) 100 millisec to 10 millisecs over the course of the 500 steps"

Or, as that is probably wrong, can you describe what you want in smiliar terms.

...R

Basically, when a robot wants to go from point A to point B, one of the things that must be done is plan the trajectory of each motor's shaft. This involves doing the inverse kinematics of the robot, and finding an initial motor shaft angle, and a final motor shaft angle to reach the desired point B.

So if we are looking at just one motor we have an initial theta and a final theta. The only question is how to get it from the initial angle to the final angle, what path will it take to achieve a smooth motion? There are many methods of generating the "trajectory" of the motor shaft. The entire 3d printing world pretty much uses a trapezoidal velocity profile, in which the motor shaft accelerates at a constant rate until it reaches its target velocity, then stays at that velocity for however long before decelerating at a constant rate before stopping.

This trajectory generation method works for most applications, but it has one major downfall: using constant accelerations creates infinite spikes in jerk (the derivative of acceleration). An infinite jerk spike is impossible in the real world, and asking a motor to follow a trajectory that produces infinite jerk reduces the life of the motor and makes things hard on the motor in general.

The solution is to ask the motors to follow a trajectory that does not involve infinite jerk spikes. There are many complicated and computation-intensive ways to generate these trajectories, but my advisor (a former roboticist at NASA) has developed a very simple method using polynomials. If you are curious about it here is the paper. My thesis is the design, construction, control, and analysis of a unique style of linear input delta robot, and I have specified as one of my goals to control the robot without infinite jerk spikes using the polynomial trajectory generation detailed in the article.

The method I am hoping will work and what I have been describing in this thread is this: Do all of the computation inside the computer. The computer will generate the trajectories, a 6th order polynomial that each motor will follow from angle A to angle B. The computer will break the polynomial up into individual stepper motor pulses, and send a serial signal to the arduino precisely when a step is needed from any one motor.

The arduino will be waiting for serial data to arrive, and as soon as it does it will send the signal to the correct motor that it needs to take one step forward or backwards. The arduino will have no concept of time, other than that it sends steps to the motor as soon as the computer tells it to (which will be timed to follow the desired trajectories).

All of this should result in the motors following the correct trajectories from point A to point B. The benefit of this will be a much smoother, less jerky motion. Possible benefits of this may include less missed steps when operating at extremely high speeds, less jerky motion (inducing vibrations in the frame, which may cause loss of print quality if strained enough), and less stress on the motors (possibly resulting in longer motor life).

Soronemus:
The entire 3d printing world pretty much uses a trapezoidal velocity profile, in which the motor shaft accelerates at a constant rate until it reaches its target velocity, then stays at that velocity for however long before decelerating at a constant rate before stopping.

This trajectory generation method works for most applications, but it has one major downfall: using constant accelerations creates infinite spikes in jerk (the derivative of acceleration).

"Entire 3D printing world" is a pretty big statement. I own a 3D printer, which is nearly one year old, and it has settings for controlling jerk. It's using Marlin firmware, which seems to be one of the more popular open-source firmwares available.

I suggest you look at how Marlin does it. There may be a better way but this is a relatively mature area of the 3D printer world.

MorganS:
"Entire 3D printing world" is a pretty big statement. I own a 3D printer, which is nearly one year old, and it has settings for controlling jerk. It's using Marlin firmware, which seems to be one of the more popular open-source firmwares available.

I suggest you look at how Marlin does it. There may be a better way but this is a relatively mature area of the 3D printer world.

You are correct Marlin uses a term called "jerk" but it is used very loosely and not in the correct mathematical/physical sense. It is not used as the derivative of acceleration, but a fudge factor they use to soften the motion when turning corners. Already looked into it :confused:

Soronemus:
The computer will break the polynomial up into individual stepper motor pulses, and send a serial signal to the arduino precisely when a step is needed from any one motor.

It was all going great up to this moment. This ain't going to happen unless you get an old PC with a parallel printer port.

The reason people use Arduinos for CNC and 3D printing is because the USB system is incapable of the sort of precision you envisage. Have a look at this FTDI paper.

You did not answer my question about whether it would be possible to send a message to the Arduino describing a large number of steps, rather than just a single step.

Maybe you just need something more powerful than a 16MHz Arduino and offload the entire job to that.

...R

Seems to me the OP is so focused on one aspect of the "problem" he's over-looking other, equally important, problems in the solution. Using serial communications to "time" step pulses will be anything but precise, and will, by itself, introduce significant timing errors that will also create jerk.

Even so, unless the robot, or whatever it is, is doing surgery, or is extremely large, or extremely fast, or expected to operate for decades unattended, jerk really is not a major problem, and certainly not something that will have any measurable affect on life of the machine. Many, if not most, ery large, VERY precised commercial machine tools also use linear acceleration, and have no problems with shortened lifetime as a result.

I think the OP needs to take a few steps away from the problem, and consider the negative side effects this "cure" is creating, which could well be worse than the "disease" itself....

Regards,
Ray L.

Robin2:
It was all going great up to this moment. This ain’t going to happen unless you get an old PC with a parallel printer port.

The reason people use Arduinos for CNC and 3D printing is because the USB system is incapable of the sort of precision you envisage. Have a look at this FTDI paper.

You did not answer my question about whether it would be possible to send a message to the Arduino describing a large number of steps, rather than just a single step.

Maybe you just need something more powerful than a 16MHz Arduino and offload the entire job to that.

…R

Thank you very much for your help. I took a look at the resource you linked. After reading it I think I understand the gist of your concerns. From what I have gathered from reading this the computer sends information in packets of sorts every 1millisecond, and in some cases every 1/8th of a millisecond. So trying to send all of my information at time intervals an order of magnitude or more faster than that would cause so much resolution loss that it would be completely useless. I am probably not understanding this 100% correctly but am I along the correct lines?

RayLivingston:
Seems to me the OP is so focused on one aspect of the “problem” he’s over-looking other, equally important, problems in the solution. Using serial communications to “time” step pulses will be anything but precise, and will, by itself, introduce significant timing errors that will also create jerk.

Even so, unless the robot, or whatever it is, is doing surgery, or is extremely large, or extremely fast, or expected to operate for decades unattended, jerk really is not a major problem, and certainly not something that will have any measurable affect on life of the machine. Many, if not most, ery large, VERY precised commercial machine tools also use linear acceleration, and have no problems with shortened lifetime as a result.

I think the OP needs to take a few steps away from the problem, and consider the negative side effects this “cure” is creating, which could well be worse than the “disease” itself…

Regards,
Ray L.

You bring up a lot of very good points! It is definitely looking like the serial pulse control is a no go to control individual stepper motor steps. I agree now after understanding a little better the way serial communication is done in terms of timing that it would completely counteract the problem I am trying to alleviate.

As I have touched on earlier in this thread, I understand that the current trapezoidal velocity profiles are ‘good enough’. I guess the main usefulness of jerk-free motion would only apply at extremely high speeds to prevent missed microsteps (maybe someday we will be able to 3d print at those speeds) and in terms of very minuscule print quality improvements due to reduced vibrations induced into the frame.

I will be including a discussion about how the modern control is sufficient for our current needs even with the infinite jerk spikes in my thesis. However wouldn’t you agree that if there was a computationally efficient and economical way to create continuous acceleration motion it would be better than the current methods? Even if it is at very low speeds, I have specified as a goal of my thesis to create continuous acceleration motion, which if it is reasonably possible I need to try.

After I am finished with the theoretical thesis work, controlling the stepper motors with continuous acceleration I will be turning my delta robot into a 3d printer for personal use and using a smoothieboard and its linear acceleration for 3d printing.

After concluding with all of your help (THANK YOU by the way) that the serial pulses will not work, I think the best course of action will be to purchase an arduino due. It comes with a 32 bit processor and 50+MHz clock speed which should be a monumental speed increase over an uno or a mega. Hopefully the computational speed will allow me to perform the calculations needed while also being able to send steps to the motors at a reasonable speed (ideally to create 200mm/s top speeds at minimum). I am already extremely proficient at the programming language arduino uses so I will not miss a step when transitioning to it. Along with this, it is compatible with the ramps 1.4 board and pololu stepper drivers of which I already own.

What do you guys think of this approach, do you see any holes? Lastly, is there an approach that you would suggest for generating the stepper motor pulses inside the arduino’s code? I will have a 6th order polynomial that I want each stepper motor shaft angle to follow. I am currently brainstorming ways of doing this without relying on grbl which uses the linear acceleration like everyone else.

Robin2:
You did not answer my question about whether it would be possible to send a message to the Arduino describing a large number of steps, rather than just a single step.

Currently thinking of a way to do this, I think you might be right about it being a good way to do it. Maybe have the computer generate the 6th order polynomials, they have a symbolic solution that is easily solved for each polynomial coefficient. Maybe the arduino due will be able to handle that with no problem.