Sunday, March 14, 2010


Hydra Joins the Acceleration Party... with multiple heads

So after about a week and a half of work I uploaded a new release of the Hydra-MMM software and firmware to the sourceforge page this afternoon ( Most of the work was done on the firmware because I got the crazy idea in my head that I wanted to be able to do accelerated movements in 3 dimensions. While this seems somewhat simple at first, I had a hell of a time getting it all to work out. Here are the main problems I ran into
  • If you have a constant acceleration with a non-zero initial velocity, the time interval for stepping cannot be directly determined. A quadratic equation needed to be used to solve for the time interval. This is due to the fact that the motor speed is dependent on the stepping interval (delay between steps), and the distance the machine travels is also dependent on this velocity as well as the constant specified acceleration.
  • (Solved) For some reason, every time I derive the kinematic equation to relate distance, velocity, and acceleration together I get a different result than that which is in the physics textbooks I have used in school. If V = delta x / delta t, and a = (V-Vo)/delta t, if you combine these you get a*deltat + Vo = V = deltax/deltat. Multiplying both sides by deltat, you get a*(deltat^2) + Vo*deltat - deltax = 0. The equation in my textbooks is1/2*a*(deltat^2) + Vo*deltat - deltax = 0. I was forgetting that the V term is actually Vavg which would equal (V-Vo)/2 which answers the factor of 2 difference. Thanks for pointing this out guys!
  • Solving quadratic equations while moving is not a good idea. It was too slow and it was actually limiting my maximum speed (the delay from solving the equation was greater than the interval I was using for stepping). The whole idea of doing this is to allow for faster and smoother stepping so a change was needed. I decided the best way was to compute the acceleration scalers (% of desired speed) for each step and to store those in an array. See the next point.
  • Storing large arrays (200+ items) of floating point numbers eats up SRAM real fast. A 200 item float array requires 200*4 Bytes = 800 Bytes! That is almost all of the available memory on the ATmega168! To fix this I scaled the acceleration scalers up to integer values. The scalers only range from 0.0 to 1.0 so this was not hard to do and it cut the memory usage in half (integers only require 2 Bytes instead of 4 Bytes for floating point numbers).
  • I originally intended to have separate acceleration and deceleration calculations, but it proved to be must faster to just calculate the acceleration values and then duplicate those in reverse for deceleration. I also has a problem when solving the quadratic equation for negative acceleration. The radical is negative if Vo^2 < -2*a*deltax which can happen for deceleration. See the 2 figures below.
Figure 1 - Acceleration from 0 to 80 inch/min

Acceleration is smooth from 0 to 80 inch/min with no errors in the calculations.

Figure 2 - Deceleration from 0 to 80 inch/min

Note the circled section where there should be 2 or 3 more steps before getting to zero velocity, however, this is the area where the value inside the square root was negative and thus, it could not be calculated.
  • So again, it was must easier to just use the acceleration calculations where acceleration is positive and the value inside the square root can never be negative. To help with this problem, I also added a startup speed variable so the motors can start from a specified velocity. For example, if they have no problem jumping to 0 to 30 inch/min, start them at 30 and then ramp up to 80. While this change, as well as only calculating the positive acceleration values got around this problem, I am still intrigued why this was happening.
Eventually, I got everything working, however, it took much longer than I expected. The end result is pretty awesome and allows for a much smoother initial startup as the motors can start from a lower speed and slowly ramp up to the higher speed. Before this, they were just instantly trying to run at the desired feedrate and that made things pretty shaky. I can't wait to test this out of the machine once we get the X and Z axes fully operational (hopefully in the next 2 weeks). I now also have a great deal of respect for Adrian who also got this working on the Reprap front. I wonder if he had as many problems as I did??

Anyways, in addition to adding acceleration to the mix, I also added support for multiple toolheads (the end goal of the Hydra-MMM project). This includes functions for switching heads and tracking the location of each head while building. I still have more work to do with this, but the basic functionality is there. See the release notes below for all of the other new features added in the 1.3 release!

- Acceleration is now supported and computed using kinematics (no linear approximations here!). The computations are performed before each move and have been optimized to reduce CPU and SRAM usage.
- Added support for several T (toolhead) commands for managing up to 4 independent toolheads. See firmware for list of new commands. Also note that there are new parameters that must be declared if multiple toolheads are to be used. See the top of the firmware.
- Added support for physical max and min endstops on each axis
- Maximum software endstops added in case physical max endstops are not available
- PID temperature library and cpwStepper library are now options and can be excluded from the firmware if it is not desired
- GUI now supports M105 command to receive temperature from the firmware and print to screen
- Fixed bug with time to move calculation being dependent on the x axis
- Lots of optimization to get the firmware small enough to fit on the ATmega328 (reduced total firmware size more than 6KB!)
- Serial baud rate changed to 19200 for compatibility with Reprap and Makerbot hardware

As always, you can download the release files at the sourceforge project page:

Let me know what you think!

Labels: , ,

With respect to your kinematics problem, have you taken calculus? If so, the steps to solve this equation are:

v = dx/dt
a = dv/dt
-> multiply both sides by dt:
a*dt = dv
-> integrate:
v = vo + a*t = dx/dt
-> multiply both sides by dt:
vo + a*t dt = dx
-> integrate:
x = xo + vo*t + 1/2 a*t^2

Perhaps using this formula will also solve your problem of imaginary roots?

The error is quite subtle, but the error comes in the last step: When you have
a*delta t + vo = delta x / delta t,
you can't multiply both sides by delta t. It's because if you plot the a*delta t term, it's growing linearly in time (a triangle), and the velocity growth in time period delta t is the area underneath that triangle, which is 1/2 base times height. If you just multiply by delta t, then you're assuming it's a square, which gives you base*height but is off by the factor of one half :)

As an example, if you want to find the distance traveled by an apple falling for three seconds from rest, if you simply say delta x = 9.8*(3^2), you'll get twice the experimentally measured distance. Because you have to account for the fact that the apple goes more slowly at the start!

Anyway, good job on the software, I'm very excited about anything that supports multiple toolheads!
You will find a very simple piece of code to do this here:,27970,27974#msg-27974

I use the same table for acceleration and deceleration as it is just a mirror image.
Ah that makes sense. The only problem I am having is that the time it takes to accelerate to the desired speed does not match what I think I should be getting. Maybe it is another problem with my acceleration equation. I am using the equation a = (V-Vo)/t. In the 0 to 80 inch/min case it is now taking 0.32 seconds (at 30000 in/min^2 acceleration) to reach 80 in/min where the a = (V-Vo)/t equation says it should only take 0.16s. I agree that the equation should include the 1/2 before the a, but I'm not seeing why these numbers aren't matching up...

And nophead, thanks for the link! I'll definitely give it a read
You're getting your variables mixed up. The first equation includes final velocity while the second includes average velocity. You ran into trouble because you called both of them "V".

Not true: a*deltat + Vo = V = deltax/deltat

True: a*deltat + V_o = V_final

True: V_average = deltax/deltat

V_average = (V_final - V_initial)/2
Ah. That answers it. Thanks for the quick responses guys! I went ahead and updated the firmware so the minor change to the acceleration equation is in there. Clearly I need to brush up on my physics from 4 years ago..
Just a quick update on some testing I have been doing. Using the 5V power supply that I currently have (I have a 27V one in the mail), I was only able to run the motors at ~85 inch/min before implementing any acceleration code. Anything higher than this and the motors would skip steps. After adding acceleration (30 inch/min starting speed with 100000 inch/min^2 max acceleration), I am now able to run the motors all the way up to 120 inch/min without skipping any steps! That's a significant difference! I suspect that my larger 27V power supply will help even more because a 5V power supply can only energize the motor coils so fast and has a limit on its maximum stepping frequency.
I teach physics by day and hack on the MakerBot by night. Solving this problem was pretty damn exciting!
Post a Comment

Links to this post:

Create a Link

<< Home

This page is powered by Blogger. Isn't yours?

Subscribe to
Posts [Atom]