How can I get scaled cycloid curves?

cmartinez

Joined Jan 17, 2007
8,783
Haven't had the time yet to go through your file. But just out of intuition, I can tell there's a direct relationship between the pinion's roller diameter and the pinion's pitch (and its number of rollers) and the rack's tooth geometry. Maybe there's one and only one pitch to roller diameter that results in a perfect rack tooth with no play, no interference, and perfect motion linearity ... but doing those calculations is something that's going to have to wait for now, right now I'm up to my neck with work... (say, you and I are probably the only two regulars here that still work for a living, whilst almost everyone else is retired, right?)
 

Thread Starter

strantor

Joined Oct 3, 2010
6,875
Haven't had the time yet to go through your file. But just out of intuition, I can tell there's a direct relationship between the pinion's roller diameter and the pinion's pitch (and its number of rollers) and the rack's tooth geometry.
Correct (*I think). The rack must be perfectly matched to the pinion (*I think). I suppose this would be a "con" in comparison to involute gearing, where pitch and pressure angle only need to be matched, and then you can mesh a pinion with any desired # of teeth with a given rack. But since these [are/would be] made as a set for specific applications, I don't see it as any more of an imposition than not being able to use a Thompson ballnut on an NSK ballscrew.

*part of the reason for the script is to answer this question. To be able to generate racks parametrically and mesh with various pinion designs, to prove this or not.

Maybe there's one and only one pitch to roller diameter that results in a perfect rack tooth with no play, no interference, and perfect motion linearity
I don't see that as a probability. You could be right but I don't see it. In my mind, any shape with a repeating pattern evenly distributed around its circumference could be a pinion if a rack were designed around it with inverse features to cancel out the pinion's geometry. For example the square-wheeled triangle in my other forum post I linked to. The only reason for using round bars as opposed to hexes or as opposed to a radial array of Christmas tree cookie cutters, is that being round enables the installation of rollers to eliminate friction.

... but doing those calculations is something that's going to have to wait for now, right now I'm up to my neck with work...
No worries, I have plenty of time to analyze this into oblivion before I'm ready for any real action. It will probably be a month or more before I get my CNC back online. Anyway, I don't think the discrepancy of the pinion size in the CAD file was due to a flaw of the concept; I think there is a flaw in the code, and I intend to get to the bottom of it as soon as I can. I hope to fix it before you spend any time on it. I really appreciate your time by the way, thank you for the help.

(say, you and I are probably the only two regulars here that still work for a living, whilst almost everyone else is retired, right?)
Is it really as bad as that? I know there are a lot of retirees in the ranks but I didn't realize they were the majority. Anyway I don't think I get to call myself a "regular" anymore. My attendance has been so spotty over the past couple of years that I'm waiting for someone to revoke my member status. I feel guilty when I come back because it's usually just when I need something. I don't contribute like I used to. But things are different now. I will return to my former position as a consistent contributor just as soon as life allows me.
 
Last edited:

Thread Starter

strantor

Joined Oct 3, 2010
6,875
OK I figured out why the pinion didn't fit. It had nothing to do with the rack. When I made the pinion I constrained the first roller to the dimension of the pitch circle radius but not to the actual radius of the pitch circle (then made a polar array). That probably sounds like nonsense but the bottom half of the following screenshot shows an exaggerated instance of the error.

Capture.PNG
 

Attachments

Thread Starter

strantor

Joined Oct 3, 2010
6,875
Not sure if you still had any interest in crunching numbers, but I can save you the time if so. I think I've confirmed, there is only one pinion that will ever mesh with a given rack. I've worked on a different script that generates the pinion and rolls it along the pitch diameter. I've tried many combinations of pitch diameter, roller diameter, and number of rollers, to see if I could get two rack shapes alike, and I could not. roller diameter pretty much has to remain constant, but different pitch diameters to # rollers does not scale, even in various multiples.

For example, here is 6" pitch diameter with 6 rollers vs 6" pitch diameter with 8 rollers:
pd6nr6v8.PNG


here is 8" pitch diameter with 8 rollers vs 6" pitch diameter with 6 rollerspd6v8nr6v8.PNG


Not even a double-diameter pinion will fit, while skipping teeth. here is 12" pitch diameter with 6 rollers vs 6" pitch diameter with 6 rollers
pd12v6nr6.PNG


And a 12" pinion with 12 rollers, exact double of a 6" pinion with 6 rollers, has the same teeth per inch, but a different tooth pitch
pd12v6nr6v12.PNG

Here's the code I'm using if you're curious.
Python:
import matplotlib.pyplot as plot
import numpy as np
#import csv
import ezdxf

class cycloidRP():

    def __init__(self, pitchDiameter=6, rollerDiameter=1, noOfRollers=6, noOfTeeth=8, webThickness=2,xOffset=0, yOffset=0):
        # Variable Parameters to be input
        self.pitchDiameter = pitchDiameter  # Diameter of the rolling circle
        self.rollerDiameter = rollerDiameter  # Diameter of a smaller circle centered on the focal point of the rolling circle
        self.noOfRollers = noOfRollers  # number of rollers (teeth) in pinion
        self.noOfTeeth = noOfTeeth  # desired number of teeth in rack assembly
        self.webThickness = webThickness  # distance from center of roller at lowest point, and bottom edge of rack
        self.yOffset = yOffset
        self.xOffset = xOffset
        # constants (DON'T CHANGE)
        self.pi = np.pi
        # calculated variables (DON'T CHANGE)
        self.rollerRadius = self.rollerDiameter / 2
        self.pitchRadius = self.pitchDiameter / 2
        self.pitchCircumference = self.pitchDiameter * self.pi
        self.rollerCircumference = self.rollerDiameter * self.pi

    def createCircle(self, radius=1, center = [0,0], start = 0, end = 360, inchResolution = .1,color='k'):
        # convert degrees to radians
        start = np.radians(start)
        end = np.radians(end)
        # estabish a list to contain the angles for which we're about to generate X & Y values
        rads = []
        # estabish 2 lists to contain the X & Y values we're about to generate

        xCoords = []
        yCoords = []
        # calculate the angular resolution needed to achieve the desired resolution in inches, given the circle dimensions
        # Triangle math for an acute isosceles triangle with 2 sides equal to the radius and the 3rd side equal to the
        #   inch resolution
        # https://www.calculator.net/triangle-calculator.html?vc=&vx=.001&vy=1&va=&vz=1&vb=&angleunits=d&x=79&y=23
        a = radius
        b = inchResolution
        c = radius
        B = np.arccos(((a**2)+(c**2)-(b**2))/(2*a*c)) # angle between line segments from center of circle
        angularResolution = B
        noOfSegments = int((end-start)/angularResolution)
        # calculate X & Y values:
        # https://www.google.com/search?q=equation+of+a+circle+in+python&rlz=1C1CHBF_enUS867US867&oq=equation+of+a+circle+in+py&aqs=chrome.1.69i57j0.7983j0j7&sourceid=chrome&ie=UTF-8#kpvalbx=_oyNZXvrADdesytMPldqq6AQ19
        t = np.linspace(start,end,noOfSegments+1) # this creates a numpy array which henceforth appears to be a single variable
        x = radius*np.cos(t)+center[0] + self.xOffset# This is a numpy function, acting on a numpy array, wh
        y = radius*np.sin(t)+center[1] + self.yOffset
        plot.plot(x, y,color)
        return (x,y)

    def createPinion(self,rotationDegrees=10):
        # calculate rotational offset of pinion
        rotationRads = np.radians(-rotationDegrees) # pinion simulated to roll to the right, clockwise, so rotationDegress are inverted
        rollerAngles = np.linspace(0, 2*np.pi, self.noOfRollers+1) + rotationRads
        # calculate linear offset of Pinion based on rotational offset
        pinionCenterX = (rotationDegrees/360)*self.pitchCircumference
        pinionCenterY = self.pitchRadius

        # Create low-res (36 sides) representative pitch circle
        #self.createCircle(radius=self.pitchRadius,
                          #center=[pinionCenterX, pinionCenterY],
                          #start=0+rotationDegrees,
                          #end=360+rotationDegrees,
                          #inchResolution=self.pitchCircumference / 35)
        # Create low-res (36 sides) representative roller circle
        for i in range (0,self.noOfRollers):
            x = self.pitchRadius * np.cos(rollerAngles[i])+pinionCenterX
            y = self.pitchRadius * np.sin(rollerAngles[i])+pinionCenterY
            if i == 0:
                linecolor = 'b'
            else:
                linecolor = 'k'
            self.createCircle(radius=self.rollerRadius,
                              center=[x, y],
                              start=0,
                              end=360,
                              inchResolution=self.rollerCircumference/35,
                              color=linecolor)



if __name__ == "__main__":

    myCycloid = cycloidRP(pitchDiameter=12, rollerDiameter=1,noOfRollers=12,yOffset=0.5,xOffset=-np.pi*(9/6))
    for i in range (0,90):
        myCycloid.createPinion(rotationDegrees=i*2)

    myCycloid2 = cycloidRP(pitchDiameter=6, rollerDiameter=1, noOfRollers=6, yOffset=.5)#, xOffset=6*np.pi)
    for i in range(0, 90):
        myCycloid2.createPinion(rotationDegrees=i * 2)

    #myCycloid.createCircle(radius=myCycloid.rollerRadius, center=[0, 0], start=0, end=360)
    #myCircleX, myCircleY = myCycloid.createCircle(radius=3, center=[0,3], start=0, end=360)
    plot.axis("equal")
    plot.grid()
    #plot.plot(myCircleX,myCircleY)
    plot.show()
 

cmartinez

Joined Jan 17, 2007
8,783
Not sure if you still had any interest in crunching numbers, but I can save you the time if so. I think I've confirmed, there is only one pinion that will ever mesh with a given rack. I've worked on a different script that generates the pinion and rolls it along the pitch diameter. I've tried many combinations of pitch diameter, roller diameter, and number of rollers, to see if I could get two rack shapes alike, and I could not. roller diameter pretty much has to remain constant, but different pitch diameters to # rollers does not scale, even in various multiples.

For example, here is 6" pitch diameter with 6 rollers vs 6" pitch diameter with 8 rollers:
View attachment 200200


here is 8" pitch diameter with 8 rollers vs 6" pitch diameter with 6 rollersView attachment 200202


Not even a double-diameter pinion will fit, while skipping teeth. here is 12" pitch diameter with 6 rollers vs 6" pitch diameter with 6 rollers
View attachment 200203


And a 12" pinion with 12 rollers, exact double of a 6" pinion with 6 rollers, has the same teeth per inch, but a different tooth pitch
View attachment 200204

Here's the code I'm using if you're curious.
Python:
import matplotlib.pyplot as plot
import numpy as np
#import csv
import ezdxf

class cycloidRP():

    def __init__(self, pitchDiameter=6, rollerDiameter=1, noOfRollers=6, noOfTeeth=8, webThickness=2,xOffset=0, yOffset=0):
        # Variable Parameters to be input
        self.pitchDiameter = pitchDiameter  # Diameter of the rolling circle
        self.rollerDiameter = rollerDiameter  # Diameter of a smaller circle centered on the focal point of the rolling circle
        self.noOfRollers = noOfRollers  # number of rollers (teeth) in pinion
        self.noOfTeeth = noOfTeeth  # desired number of teeth in rack assembly
        self.webThickness = webThickness  # distance from center of roller at lowest point, and bottom edge of rack
        self.yOffset = yOffset
        self.xOffset = xOffset
        # constants (DON'T CHANGE)
        self.pi = np.pi
        # calculated variables (DON'T CHANGE)
        self.rollerRadius = self.rollerDiameter / 2
        self.pitchRadius = self.pitchDiameter / 2
        self.pitchCircumference = self.pitchDiameter * self.pi
        self.rollerCircumference = self.rollerDiameter * self.pi

    def createCircle(self, radius=1, center = [0,0], start = 0, end = 360, inchResolution = .1,color='k'):
        # convert degrees to radians
        start = np.radians(start)
        end = np.radians(end)
        # estabish a list to contain the angles for which we're about to generate X & Y values
        rads = []
        # estabish 2 lists to contain the X & Y values we're about to generate

        xCoords = []
        yCoords = []
        # calculate the angular resolution needed to achieve the desired resolution in inches, given the circle dimensions
        # Triangle math for an acute isosceles triangle with 2 sides equal to the radius and the 3rd side equal to the
        #   inch resolution
        # https://www.calculator.net/triangle-calculator.html?vc=&vx=.001&vy=1&va=&vz=1&vb=&angleunits=d&x=79&y=23
        a = radius
        b = inchResolution
        c = radius
        B = np.arccos(((a**2)+(c**2)-(b**2))/(2*a*c)) # angle between line segments from center of circle
        angularResolution = B
        noOfSegments = int((end-start)/angularResolution)
        # calculate X & Y values:
        # https://www.google.com/search?q=equation+of+a+circle+in+python&rlz=1C1CHBF_enUS867US867&oq=equation+of+a+circle+in+py&aqs=chrome.1.69i57j0.7983j0j7&sourceid=chrome&ie=UTF-8#kpvalbx=_oyNZXvrADdesytMPldqq6AQ19
        t = np.linspace(start,end,noOfSegments+1) # this creates a numpy array which henceforth appears to be a single variable
        x = radius*np.cos(t)+center[0] + self.xOffset# This is a numpy function, acting on a numpy array, wh
        y = radius*np.sin(t)+center[1] + self.yOffset
        plot.plot(x, y,color)
        return (x,y)

    def createPinion(self,rotationDegrees=10):
        # calculate rotational offset of pinion
        rotationRads = np.radians(-rotationDegrees) # pinion simulated to roll to the right, clockwise, so rotationDegress are inverted
        rollerAngles = np.linspace(0, 2*np.pi, self.noOfRollers+1) + rotationRads
        # calculate linear offset of Pinion based on rotational offset
        pinionCenterX = (rotationDegrees/360)*self.pitchCircumference
        pinionCenterY = self.pitchRadius

        # Create low-res (36 sides) representative pitch circle
        #self.createCircle(radius=self.pitchRadius,
                          #center=[pinionCenterX, pinionCenterY],
                          #start=0+rotationDegrees,
                          #end=360+rotationDegrees,
                          #inchResolution=self.pitchCircumference / 35)
        # Create low-res (36 sides) representative roller circle
        for i in range (0,self.noOfRollers):
            x = self.pitchRadius * np.cos(rollerAngles[i])+pinionCenterX
            y = self.pitchRadius * np.sin(rollerAngles[i])+pinionCenterY
            if i == 0:
                linecolor = 'b'
            else:
                linecolor = 'k'
            self.createCircle(radius=self.rollerRadius,
                              center=[x, y],
                              start=0,
                              end=360,
                              inchResolution=self.rollerCircumference/35,
                              color=linecolor)



if __name__ == "__main__":

    myCycloid = cycloidRP(pitchDiameter=12, rollerDiameter=1,noOfRollers=12,yOffset=0.5,xOffset=-np.pi*(9/6))
    for i in range (0,90):
        myCycloid.createPinion(rotationDegrees=i*2)

    myCycloid2 = cycloidRP(pitchDiameter=6, rollerDiameter=1, noOfRollers=6, yOffset=.5)#, xOffset=6*np.pi)
    for i in range(0, 90):
        myCycloid2.createPinion(rotationDegrees=i * 2)

    #myCycloid.createCircle(radius=myCycloid.rollerRadius, center=[0, 0], start=0, end=360)
    #myCircleX, myCircleY = myCycloid.createCircle(radius=3, center=[0,3], start=0, end=360)
    plot.axis("equal")
    plot.grid()
    #plot.plot(myCircleX,myCircleY)
    plot.show()
Yeap... intuition told me there's no avoiding doing the math... this is not the kind of problem where guesswork's gonna solve it.
 

shortbus

Joined Sep 30, 2009
10,049
For example, here is 6" pitch diameter with 6 rollers vs 6" pitch diameter with 8 rollers:
That is because they are a different "diametral pitch". You can't have two gears with different tooth counts in the same "pitch diameter". I think it would work, a 6 or 8 roller(tooth) as long as you keep the spacing between the rollers the same, which means the pitch diameter and thus OD of the pinion is bigger.

I may be wrong on this but that's how it works in regular gears. And is why a for the sake of argument a 20DP gear won't mate with a 24DP gear, no matter what tooth count..
 

cmartinez

Joined Jan 17, 2007
8,783
That is because they are a different "diametral pitch". You can't have two gears with different tooth counts in the same "pitch diameter". I think it would work, a 6 or 8 roller(tooth) as long as you keep the spacing between the rollers the same, which means the pitch diameter and thus OD of the pinion is bigger.

I may be wrong on this but that's how it works in regular gears. And is why a for the sake of argument a 20DP gear won't mate with a 24DP gear, no matter what tooth count..
DP (Diametral Pitch) is not the same as pitch diameter. Pitch diameter (aka pitch circle) is the "basic circle" that goes through the (more or less) a gear's mean height of a tooth of a given geometry. Whereas diametral pitch is the ratio expressed as the number of teeth per inch of pitch diameter. That means that gears of different diametral pitch can never match simply because their geometry is different.

A graph can explain this a lot better than I can:

1583020232600.png
 

Thread Starter

strantor

Joined Oct 3, 2010
6,875
That is because they are a different "diametral pitch". You can't have two gears with different tooth counts in the same "pitch diameter". I think it would work, a 6 or 8 roller(tooth) as long as you keep the spacing between the rollers the same, which means the pitch diameter and thus OD of the pinion is bigger.

I may be wrong on this but that's how it works in regular gears. And is why a for the sake of argument a 20DP gear won't mate with a 24DP gear, no matter what tooth count..
Have a look at the racks in the 2nd and 4th images in post #44. In both cases, the rack has the same teeth per inch (or "inches per tooth", or "the spacing between the rollers" or however you want to express "pitch") yet the tooth profiles are different. In the 2nd image the difference is subtle but if you look closely you will see the rack tooth on the left is about .25" taller than that on the right. If this were being utilized just like an ordinary rack and pinion where there is no force pushing the pinion down into the rack (furthermore with .001" or more of forced separation via shims or adjustments), then in the case of the second image, you might be right. It may "work" (albeit with a bit of nonlinearity) if we use the pinion on the left with the rack on the right (but not the other way around) just by virtue of them sharing the same pitch. But this isn't meant to work like an ordinary rack and pinion. It's meant to serve as a combination of linear rail and rack/pinion with the pinion bearing a load forced into the rack. The rack tooth geometry must be a "perfect" inverse of the roller motion profile such that there are always at least two rollers in contact with rack teeth at any given time. This is how it achieves zero backlash and [linear] linear motion.
 

shortbus

Joined Sep 30, 2009
10,049
DP (Diametral Pitch) is not the same as pitch diameter. Pitch diameter (aka pitch circle) is the "basic circle" that goes through the (more or less) a gear's mean height of a tooth of a given geometry. Whereas diametral pitch is the ratio expressed as the number of teeth per inch of pitch diameter. That means that gears of different diametral pitch can never match simply because their geometry is different.
The DP of a single DP gear system is the same no matter how many teeth in the gear or rack. DP and CP are the same thing, it just depends on the company explaining it. You just said the same thing I said in a different way. I know the difference between pitch diameter(the point where the addendum and dedendum meet on the tooth) and diametral pitch.

Where I served my apprenticeship I cut a lot of gears for one of the things we made, rubber band cutting machines. We cut the gears oversize on one and undersized on the mating gear to throw people off, to keep them buying spare parts from us. When only one gear wore out and they would by an off the shelf one from another vendor and it wouldn't fit they would then call us. Little did they know was if they had bought both gears from the outside they would have worked, because the center to center of the gears was the same in ours, just the cut size was different.

When I learned this stuff the standard was the Boston Gear Company and their literature. This was before the metric "module" gear system came into common use. Module calls out DP as CP, and just like all thing machining wise, metric screws thing up.:)
 
Last edited:
Top