Turning a Mill into CNC to help with an electric car conversion

What are the signals and units on that plot? Label your axes and legend. D-minus must try harder :stuck_out_tongue:

+/- 0.75 oscillation of… what? Position in degrees? (can’t be counts…)

Ah yes, as follows: -
0 = Position of M0
1 = Demanded Position of M0
2 = Position of M1
3 = Demanded Position of M1

Was aiming for a B+ at least.
Can you label the axes on the plot itself?
Here’s the command I use: -

start_liveplotter(lambda:[odrv0.axis0.encoder.pos_estimate, odrv0.axis0.controller.pos_setpoint, odrv0.axis1.encoder.pos_estimate, odrv0.axis1.controller.pos_setpoint])

1 Like

So the units are encoder counts, then?
How is it possible to have following error of 3/4 of a count?
I mean, very impressive if so! :smiley:

How is it possible to have following error of 3/4 of a count?

Very good question, I hadn’t thought of it before.

Is it because they are estimates, similar to how steppers have multiple steps between each pole. I am guessing the ODrive knows when the pulses happen so it can estimate exactly where it is, but not from the encoder counts (that’s just for encoder to motor angular syncing), instead from the fine PWM control. So 8192 counts per revolution of the encoder, although the motor control has 4 times more position control, so 32768 positions per revolution.

@Wetmelon / @madcowswe, are we way off here ;-).

Thanks

1 Like

The amt102 encoders have 2048 ppr, or positions. The cpr is that number times the quadrature counting factor(x4 in this case). So 8192 counts.

Hi @Roiki1, Yes, hence 8192 counts per revolution for the AMT102, where the plot above seems to show 0.25 motor steps per count, hence 32768 motor steps (resolution of PWM control) per 1 revolution.

So 2048 ppr x 4 (quadrature from A, B) = 8192 cpr, then 8192 cpr x 4 motor steps per count = 32768.

I suppose this is to allow for much higher counting encoders. I’m wondering what the resolution of the motor PWM signal is?

I’m still a bit confused. How could you divide the count between individual counts to 4 parts when you have no reference to do so? The math only knows a movement happens when one bit flips?

So, my thoughts are: Say the A output of AMT102 goes positive as the motor is rotating slowly (3 x 120º phase shifted sine waves rotating slowly), and looking at 1 sine wave, there were 32768 positions for that sine wave per 1 period (cycle); then there would be 4 phase positions of that sine wave before the B output of the AMT102 goes positive.

Therefore, the ODrive knows where the Encoder counts are in relation to phase changes of the motor coils, so it would be able to move between encoder counts.

Or put differently: -

  1. Motor Phase = 0, Quadrature A = 0, Quadrature B = 0
  2. Motor Phase = 01, Quadrature A = 1, Quadrature B = 0
  3. Motor Phase = 02, Quadrature A = 1, Quadrature B = 0
  4. Motor Phase = 03, Quadrature A = 1, Quadrature B = 0
  5. Motor Phase = 04, Quadrature A = 1, Quadrature B = 0
  6. Motor Phase = 05, Quadrature A = 1, Quadrature B = 1
  7. Motor Phase = 06, Quadrature A = 1, Quadrature B = 1
  8. Motor Phase = 07, Quadrature A = 1, Quadrature B = 1
  9. Motor Phase = 08, Quadrature A = 1, Quadrature B = 1
  10. Motor Phase = 09, Quadrature A = 0, Quadrature B = 1
  11. Motor Phase = 10, Quadrature A = 0, Quadrature B = 1
  12. Motor Phase = 11, Quadrature A = 0, Quadrature B = 1
  13. Motor Phase = 12, Quadrature A = 0, Quadrature B = 1

I may be going off at a tangent, but that is how I see it working in my head. Hope that helps. This may need clarifying from the ODrive guru’s

P.S. Am I still on a D- @towen? :wink:

The position/velocity used for control comes from the estimator in encoder.cpp, which is a PLL that functions as a tracking filter. The key is that pos_estimate is vel_estimate * time_elapsed * gain1 + number of counts since last update * gain2. If you want to see the actual raw encoder position, you can use odrv0.axisX.encoder.shadow_count.

There is interpolation, but it is not intentionally 1/4 count or anything like that. It seems to me that your 0.75 counts is a numerical artifact of the position estimation

1 Like

Ahh, that makes a lot of sense, hence why it is only an estimate and not a true value. There are a lot of variables there to make up the pos_estimate.

I will put shadow_count into the live plotter and look at that data instead.

So from this, is it best for the my Arduino to track pos_estimate or shadow_count? not that it would make much difference.

Thank you for posting, it could have gone down a rabbit hole :wink:

No problem! If you are using the Arduino for DRO purposes, I’d probably stick with pos_estimate, just because it’ll be marginally less noisy.

Yeah, I’ll stick with pos_estimate.

The Arduino is a Mega 2560 and it runs the ODrive using the ASCII protocol, shows DRO info and will convert G-Code (hopefully) from an SD Card.

I am currently writing the sketch in accordance with the Mach4 reference and Fusion 360 standard Post Processing G-Code, so will be able to post process in Fusion 360, transfer to SD card then let the Arduino and ODrive do their thing :thinking:

It’s currently working with G00 and G01, where G02/03 are a little head scratching :exploding_head:

I suspected that might be it :slight_smile:

But still, that means that @Dev255 really does have less than one count of steady-state error, which is pretty impressive since this is for a CNC machine. It probably does mean that the ODrive is responding in sub-count resolution (i.e. the applied torque will be dependent on the average amount of time that the error is positive or negative) - I wonder if it would be possible to command sub-count positions, by driving this average to a particular value?
(it would still have to oscillate by at least +/- 1 count though, so I don’t know if controlling the average position inside of that is useful)

But in any case, it’s pretty impressive that the 8192cpr encoder is the sole bottleneck to positioning accuracy. @Dev255 What’s 1/8192 rev in terms of microns at the cutting tool?

A* for practical! But theory (like mine) needs work. :stuck_out_tongue_winking_eye:

Pfft, mere µm, it’s 61nm per encoder count :grin:, not bad for a home mill, although can’t guaranteee anywhere near that accuracy with the rigidity of the machine. So 2 revolutions per 1mm being 1/16384.

No point in being perfect :grinning::+1:

2 Likes

I have now successfully tested out my programming skills by machining out this part.

The Arduino Mega 2560 now accepts standard G-Code to churn out parts. Now all I need is an Z Axis and a spindle motor fitted, where I have the pulleys and am currently 3D CAD’ding the Z-Axis and Spindle components. I’m going with a 1:1 ratio on the spindle motor and may even add a small flywheel to the spindle shaft as a torque reservoir, hmmm…

With the G-Code, admittedly, I have only programmed G00, G01, G02 and G03, although 02 & 03 are the hardest to achieve, where I had to get my head back in to trigonometry and work out arc radians, feed speeds at different radii and all manor of other calculations and conundrums to make it all work, including maintaining backlash control, hence the time taken to get to this point.

Hope you like the latest video.

P.S. I used lubricant on this one @Jerry.Atrick :wink:

2 Likes

Hi all,

A new video :grinning:, I am so confident with the ODrive system that I now leave it to run in its box.

I’m looking forward to making the Z-Axis and just have it make stuff on its own.

This video is about using a septic tank aeration pump to blow the chips away, it works really well, but you do need a corner to blast it into.

The part I’m making is a Machine Squared End Stop, so it’s at true 90 every time it’s placed down.

Hope you enjoy.

Happy ODriving,

Neil.

1 Like

lol. when I saw that I was thinking of fish tanks, not septic tanks, and thought no way could an aeration pump be powerful enough for that! :stuck_out_tongue:
I didn’t know septic tank aeration pumps were a thing… sounds like a smelly business!

1 Like

The pump just smells a little of rubber from the diaphragm, but luckily not the smelly one, although I don’t smell the harm in buying a second hand model :wink:

1 Like

Hi Neil, another great episode!
And no question as the blower sure does it’s job; kudos to you. I doubt that anyone else would have thought this creatively :thinking:
Maybe you can get another blower unit, and make is SUCK, that will quietly remove all those pesky chips :laughing:

Regards Jerry.
PS: maybe one day soon I will ask you about speeds and feeds, as it appears you know what you are really doing! “if that’s okay”

1 Like