Multiaxis stepper motors using RMT

Discussion about programs, libraries and tools that work with MicroPython. Mostly these are provided by a third party.
Target audience: All users and developers of MicroPython.
User avatar
OlivierLenoir
Posts: 19
Joined: Fri Dec 13, 2019 7:10 pm
Location: Picardie, FR

Re: Multiaxis stepper motors using RMT

Post by OlivierLenoir » Fri Jan 03, 2020 6:20 am

Probably not the most elegant method, but I'm close to the expected frequency with Axis.steps. I'll try the same approach in MultiAxis.

Code: Select all

from machine import Pin
from esp32 import RMT

DRV8825_mp = const(2)


class Axis(object):

    id_axis = 0

    def __init__(self, dir_pin, step_pin):
        self.d_pin = Pin(dir_pin, Pin.OUT)
        self.s_pin = RMT(Axis.id_axis, pin=Pin(step_pin), clock_div=80)
        self.wp = self.s_pin.write_pulses
        Axis.id_axis += 1
        self.pos = 0

    def set_dir(self, steps):
        d = self.d_pin()
        if steps < 0 and d:
            self.d_pin(0)
        elif steps > 0 and not d:
            self.d_pin(1)

    def steps(self, steps, period=4, p_size=100):
        self.set_dir(steps)
        d, m = divmod(abs(steps), p_size)
        pulse = (DRV8825_mp, max(DRV8825_mp, min(32767, period - DRV8825_mp)))
        wp = self.wp
        loops = range(d)
        for _ in loops:
            wp(pulse * p_size)
        if m:
            wp(pulse * m)
        self.pos += steps

x = Axis(dir_pin=15, step_pin=2)
x.steps(steps=100017, period=200)
x.steps(steps=10017, period=2)
x.steps(steps=20017, period=2000)

User avatar
OlivierLenoir
Posts: 19
Joined: Fri Dec 13, 2019 7:10 pm
Location: Picardie, FR

Re: Multiaxis stepper motors using RMT

Post by OlivierLenoir » Sat Jan 04, 2020 6:46 pm

Using preview post:

Code: Select all

x.steps(steps=1000017, period=4, p_size=100)
Provides an average frequency output of 210 kHz for an expected frequency of 250 kHz.

Code: Select all

x.steps(steps=1000017, period=4, p_size=400)
Provides an average frequency output of 237 kHz for an expected frequency of 250 kHz.
Increasing p_size allow you to get closer to the expected frequency, but uses more memory.

By analyzing the frequency spectrum, a second frequency appears at high frequency. It is related to the loop and the size of p_size . With a lower expected frequency, we do not have this anomaly.

OutoftheBOTS_
Posts: 717
Joined: Mon Nov 20, 2017 10:18 am

Re: Multiaxis stepper motors using RMT

Post by OutoftheBOTS_ » Sat Jan 04, 2020 9:15 pm

Just wondering why your chasing 250KHz?? many of the cheaper motion controllers only do about 50KHz and work quite well.

User avatar
OlivierLenoir
Posts: 19
Joined: Fri Dec 13, 2019 7:10 pm
Location: Picardie, FR

Re: Multiaxis stepper motors using RMT

Post by OlivierLenoir » Tue Jan 07, 2020 8:31 pm

DRV8825 Stepper Motor Controler IC allow a max step frequency of 250 kHz and up to 1/32 microstepping. Min Pulse duration, STEP high and STEP low is 1.9 µs. So I'm trying to drive this IC to its maximum, in case I need to use 1/32 microstepping resolution and speed.

Even if I'm close to reach 250 kHz with lag, it's only on one Axis. The max frequence on one Axis without lag should be around 100 kHz using current version of Axis.steps().
MultiAxis can drive up to 8 Axis with RMT on an ESP32. I still need to improve Multiaxis.g01() because more Axis I have and lower is the frequency I can reach.

It's the reason why I try to get this frequency. And also because it would be so fun to design a CNC or a 3D printer using MicroPython. :D

DRV8825 datasheet

OutoftheBOTS_
Posts: 717
Joined: Mon Nov 20, 2017 10:18 am

Re: Multiaxis stepper motors using RMT

Post by OutoftheBOTS_ » Wed Jan 08, 2020 7:11 am

OlivierLenoir wrote:
Tue Jan 07, 2020 8:31 pm
DRV8825 Stepper Motor Controler IC allow a max step frequency of 250 kHz and up to 1/32 microstepping. Min Pulse duration, STEP high and STEP low is 1.9 µs. So I'm trying to drive this IC to its maximum, in case I need to use 1/32 microstepping resolution and speed.

Even if I'm close to reach 250 kHz with lag, it's only on one Axis. The max frequence on one Axis without lag should be around 100 kHz using current version of Axis.steps().
MultiAxis can drive up to 8 Axis with RMT on an ESP32. I still need to improve Multiaxis.g01() because more Axis I have and lower is the frequency I can reach.

It's the reason why I try to get this frequency. And also because it would be so fun to design a CNC or a 3D printer using MicroPython. :D

DRV8825 datasheet
doing some math

1/32 micro steps is 32 * 200 = 6,400 steps per revolution.

at 250KHz that's 250,000 / 6,400 * 60 = 2,343.75 RPM

any sort of stepper motor your goin to be driving with DRV8825 won't spin at that RPM and have enough torque to push anything without losing steps.

Normally with steppers you go for lots of smaller steps when the motor needs to turn slowly (e.g 3D printer) but if you goin to be spinning the motor fast then you don't need such small steps to make it smooth.

It would be pretty rare to turn a stepper on a 3D printer faster than 10 RPM that's 0.166 revolutions per second at 1/32 micro steps that is just a tiny bit over 1KHz. Honestly if your getting 50KHz it is probably more than what a stepper motor can rotate at while pushing something without losing steps.

User avatar
mattyt
Posts: 274
Joined: Mon Jan 23, 2017 6:39 am

Re: Multiaxis stepper motors using RMT

Post by mattyt » Thu Jan 09, 2020 1:33 am

OlivierLenoir wrote:
Sat Jan 04, 2020 6:46 pm
Provides an average frequency output of 237 kHz for an expected frequency of 250 kHz.
Increasing p_size allow you to get closer to the expected frequency, but uses more memory.

By analyzing the frequency spectrum, a second frequency appears at high frequency. It is related to the loop and the size of p_size . With a lower expected frequency, we do not have this anomaly.
Huh, that's interesting; I tested RMT into the 10s of MHz range and it appeared very accurate (two decimal points of precision in the oscilloscope I was using). Bit surprising that you observed such a discrepancy. Was the base frequency accurate with just a high-frequency glitch?

User avatar
OlivierLenoir
Posts: 19
Joined: Fri Dec 13, 2019 7:10 pm
Location: Picardie, FR

Re: Multiaxis stepper motors using RMT

Post by OlivierLenoir » Sat Jan 11, 2020 5:57 pm

mattyt wrote:
Thu Jan 09, 2020 1:33 am
Huh, that's interesting; I tested RMT into the 10s of MHz range and it appeared very accurate (two decimal points of precision in the oscilloscope I was using). Bit surprising that you observed such a discrepancy. Was the base frequency accurate with just a high-frequency glitch?
First, RMT is perfectly accurate when we use it as it has been designed.

In my use case, it's a hack of RMT to be able to generate a specific number of steps at a specific frequency. On top of that I try to synchronize many output to drive any type of MultiAxis device.

The following tests have been done in repl on an ESP32 with MicroPython V1.12 esp32-idf3-20191220-v1.12.bin.

Code: Select all

# Test 1
from machine import Pin
from esp32 import RMT

ch1 = RMT(0, pin=Pin(2), clock_div=255)
ch1_wp = ch1.write_pulses
ch1_frame = (32767, 32767) * 3

ch2 = RMT(1, pin=Pin(4), clock_div=255)
ch2_wp = ch2.write_pulses
ch2_frame = (32767, 32767)

steps = range(1000000)

for _ in steps:
    ch1_wp(ch1_frame)
    ch2_wp(ch2_frame)
ch1: red and ch2: yellow.
Test 1, expected frequency on ch1 4.787 Hz, measure: 4.786 Hz :-). 3 pulses on ch1 and 1 pulse on ch2. ch1 and ch2 are synchronized.
250ms per div.
Image

A small delay of 35µs exist between ch1 and ch2.
10µs per div.
Image

At 25ms per div, very difficult to see this delay.
Image

Code: Select all

# Test 2
from machine import Pin
from esp32 import RMT

ch1 = RMT(0, pin=Pin(2), clock_div=255)
ch1_wp = ch1.write_pulses
ch1_frame = (1000, 1000) * 3

ch2 = RMT(1, pin=Pin(4), clock_div=255)
ch2_wp = ch2.write_pulses
ch2_frame = (1000, 1000)

steps = range(1000000)

for _ in steps:
    ch1_wp(ch1_frame)
    ch2_wp(ch2_frame)
Test 2, expected frequency on ch1 156.86 Hz, measure: 156.9 Hz :-).
5ms per div.
Image

Same delay of 35µs exist between ch1 and ch2.
10µs per div.
Image


Code: Select all

# Test 3
from machine import Pin
from esp32 import RMT

ch1 = RMT(0, pin=Pin(2), clock_div=255)
ch1_wp = ch1.write_pulses
ch1_frame = (100, 100) * 3

ch2 = RMT(1, pin=Pin(4), clock_div=255)
ch2_wp = ch2.write_pulses
ch2_frame = (100, 100)

steps = range(1000000)

for _ in steps:
    ch1_wp(ch1_frame)
    ch2_wp(ch2_frame)
Test 3, expected frequency on ch1 1.568 kHz, measure: 1.487 kHz.
500µs per div.
Image

Same delay of 35µs exist between ch1 and ch2.
10µs per div.
Image


Code: Select all

# Test 4
from machine import Pin
from esp32 import RMT

ch1 = RMT(0, pin=Pin(2), clock_div=255)
ch1_wp = ch1.write_pulses
ch1_frame = (10, 10) * 3

ch2 = RMT(1, pin=Pin(4), clock_div=255)
ch2_wp = ch2.write_pulses
ch2_frame = (10, 10)

steps = range(1000000)

for _ in steps:
    ch1_wp(ch1_frame)
    ch2_wp(ch2_frame)
Here is the limit of this hack!
Test 4, expected frequency on ch1 15.686 kHz, measure: 13.26 kHz. This discrepancy is due to the delay to loop. Almost same delay of 35µs exist between ch1 and ch2.
50µs per div.
Image

Code: Select all

# Test 5
from machine import Pin
from esp32 import RMT

ch1 = RMT(0, pin=Pin(2), clock_div=255)
ch1_wp = ch1.write_pulses
ch1_frame = (1, 1) * 3

ch2 = RMT(1, pin=Pin(4), clock_div=255)
ch2_wp = ch2.write_pulses
ch2_frame = (1, 1)

steps = range(1000000)

for _ in steps:
    ch1_wp(ch1_frame)
    ch2_wp(ch2_frame)
Test 5, expected frequency on ch1 156.86 kHz, measure: 32.35 kHz.
25µs per div.
Image

Delay of 40µs exist between ch1 and ch2.
10µs per div.
Image

Conclusion
RMT is very accurate when used as designed ;) .

Now regarding my need, for MultiAxis, let me know if you can think to an other solution in pure MicroPython.
Last edited by OlivierLenoir on Sun Jan 12, 2020 11:18 am, edited 3 times in total.

OutoftheBOTS_
Posts: 717
Joined: Mon Nov 20, 2017 10:18 am

Re: Multiaxis stepper motors using RMT

Post by OutoftheBOTS_ » Sat Jan 11, 2020 8:54 pm

At the end of the day you are turning a motor in the real world and the real world never has that high an accuracy.

At 1/32 micro steps on a 200 step motor that is 360 / (32 * 200) = 0.05625 of a degree. These motor doesn't have that kind of accuracy in the real world then also add back lash in your drive gear and some real world flex of all your components.

You can then add the fact when the MCU pulses the stepper driver the motor has an acceleration time and depending upon how much load each motor has on it will lead to a different acceleration time too so the motors will never be sycned at the accuracy your chasing.

We have to understand the differences between the speed and accuracy in cyber space/electrical world and the speed and accuracy in the real mechanical world. The type of accuracies your chasing in the electrical world are not possible for the real world to carry out.

If you were to put a scope on the most expensive professional CNC machine you would find that the step pulses are not to the accuracy your chasing because the designers know your only as strong as your weakest link and the highest inaccuary come from the mechanical components due to back lash and flex

User avatar
OlivierLenoir
Posts: 19
Joined: Fri Dec 13, 2019 7:10 pm
Location: Picardie, FR

Re: Multiaxis stepper motors using RMT

Post by OlivierLenoir » Sat Jan 11, 2020 9:21 pm

OutoftheBOTS_ wrote:
Sat Jan 11, 2020 8:54 pm
At the end of the day you are turning a motor in the real world and the real world never has that high an accuracy.
...
I'm perfectly aware of every thing you are talking.
But I still want to reach 250 kHz synchronized frame on different output. So, forget the mechanic design for the moment.

OutoftheBOTS_
Posts: 717
Joined: Mon Nov 20, 2017 10:18 am

Re: Multiaxis stepper motors using RMT

Post by OutoftheBOTS_ » Sat Jan 11, 2020 9:27 pm

OlivierLenoir wrote:
Sat Jan 11, 2020 9:21 pm
OutoftheBOTS_ wrote:
Sat Jan 11, 2020 8:54 pm
At the end of the day you are turning a motor in the real world and the real world never has that high an accuracy.
...
I'm perfectly aware of every thing you are talking.
But I still want to reach 250 kHz synchronized frame on different output. So, forget the mechanic design for the moment.
:)

Post Reply