chain - a parametric chain generator

A chain wrapped around a set of sprockets can be generated with the Chain class by providing the size and locations of the sprockets, how the chain wraps and optionally the chain parameters.

For example, one can create the chain for a bicycle with a rear deraileur as follows:

import cadquery as cq
from cq_warehouse.chain import Chain

MM = 1

derailleur_chain = Chain(
        spkt_teeth=[32, 10, 10, 16],
        positive_chain_wrap=[True, True, False, True],
        spkt_locations=[
                (0, 158.9 * MM, 50 * MM),
                (+190 * MM, 0, 50 * MM),
                (+190 * MM, 78.9 * MM, 50 * MM),
                (+205 * MM, 158.9 * MM, 50 * MM),
        ],
)
if "show_object" in locals():
        show_object(derailleur_chain.cq_object, name="derailleur_chain")

The chain is created on the XY plane (methods to move the chain are described below) with the sprocket centers being described by:

  • a two dimensional tuple (x,y)

  • a three dimensional tuple (x,y,z) which will result in the chain being created parallel to the XY plane, offset by “z”

  • the cadquery Vector class which will displace the chain by Vector.z

To control the path of the chain between the sprockets, the user must indicate the desired direction for the chain to wrap around the sprocket. This is done with the positive_chain_wrap parameter which is a list of boolean values - one for each sprocket - indicating a counter clock wise or positive angle around the z-axis when viewed from the positive side of the XY plane. The following diagram illustrates the most complex chain path where the chain traverses wraps from positive to positive, positive to negative, negative to positive and negative to negative directions (positive_chain_wrap values are shown within the arrows starting from the largest sprocket):

chain direction
class Chain(spkt_teeth, spkt_locations, positive_chain_wrap, chain_pitch=12.7, roller_diameter=7.9375, roller_length=2.3812499999999996, link_plate_thickness=1.0, spkt_normal=(0, 0, 1))

Roller Chain

Create a new chain object as defined by the given parameters. The input parameter defaults are appropriate for a standard bicycle chain.

Parameters
  • spkt_teeth (list[int]) – list of the number of teeth on each sprocket the chain will wrap around

  • spkt_locations (list[VectorLike]) – location of the sprocket centers

  • positive_chain_wrap (list[bool]) – the direction chain wraps around the sprockets, True for counter clockwise viewed from positive Z

  • chain_pitch (float) – distance between two adjacent pins in a single link. Defaults to 1/2 inch.

  • roller_diameter (float) – size of the cylindrical rollers within the chain. Defaults to 5/16 inch.

  • roller_length (float) – distance between the inner links, i.e. the length of the link rollers. Defaults to 3/32 inch.

  • link_plate_thickness (float) – thickness of the link plates (both inner and outer link plates). Defaults to 1 mm.

  • spkt_normal (VectorLike) – direction of the sprocket axes - only required for two sprocket configurations. Defaults to (0, 0, 1).

Variables
  • pitch_radii (float) – radius of the circle formed by the center of the chain rollers on each sprocket

  • chain_links (int) – length of the chain in links

  • num_rollers (int) – number of link rollers in the entire chain

  • roller_loc (list[Vector]) – location of each roller in the chain

  • chain_angles (list[tuple[float,float]]) – chain entry and exit angles in degrees for each sprocket

  • spkt_initial_rotation (list[float]) – angle in degrees to rotate each sprocket in-order to align the teeth with the gaps in the chain

  • chain_plane (Plane) – the plane defined by the location of the sprockets

  • cq_object – cadquery chain object

Raises
  • ValueError – invalid roller diameter

  • ValueError – length of spkt_teeth, spkt_locations, positive_chain_wrap not equal

  • ValueError – sprockets in the same location

Examples

c = Chain(
    spkt_teeth=[32, 32],
    spkt_locations=[(-300, 0), (300, 0)],
    positive_chain_wrap=[True, True]
)

print(c.spkt_initial_rotation)       # [5.625, 193.82627377380086]

c.cq_object.save('chain.step')       # save the cadquery assembly as a STEP file
assemble_chain_transmission(spkts)

Build Socket/Chain Assembly

Create the transmission assembly from sprockets for a chain

Parameters

spkts (list[Sprocket]) – sprockets to include in transmission

Return type

Assembly

Returns

Chain wrapped around sprockets

Create roller chain link pair

Create either inner or outer link pairs. Inner links include rollers while outer links include fake roller pins.

Parameters
  • chain_pitch (float) – distance between roller pin centers. Defaults to 0.5*INCH.

  • link_plate_thickness (float) – thickness of single plate connecting rollers. Defaults to 1*MM.

  • inner (bool) – is this an inner (or outer) chain link?. Defaults to True.

  • roller_length (float) – length of the internal roller. Defaults to (3 / 32)*INCH.

  • roller_diameter (float) – diameter of the internal roller. Defaults to (5 / 16)*INCH.

Return type

Workplane

Returns

A single link pair

Note that the chain is perfectly tight as it wraps around the sprockets and does not support any slack. Therefore, as the chain wraps back around to the first link it will either overlap or gap this link - this can be seen in the above figure at the top of the largest sprocket. Adjust the locations of the sprockets to control this value.

Note that the make_link instance method uses the @cache decorator to greatly improve the rate at links can be generated as a chain is composed of many copies of the links.

Once a chain or complete transmission has been generated it can be re-oriented as follows:

two_sprocket_chain = Chain(
    spkt_teeth = [32, 32],
    positive_chain_wrap = [True, True],
    spkt_locations = [ (-5 * IN, 0), (+5 * IN, 0) ]
)
relocated_transmission = two_sprocket_chain.assemble_chain_transmission(
    spkts = [spkt32.cq_object, spkt32.cq_object]
).rotate(axis=(0,1,1),angle=45).translate((20, 20, 20))

Future Enhancements

Two future enhancements are being considered:

  1. Non-planar chains - If the sprocket centers contain z values, the chain would follow the path of a spline between the sockets to approximate the path of a bicycle chain where the front and rear sprockets are not in the same plane. Currently, the z values of the first sprocket define the z offset of the entire chain.

  2. Sprocket Location Slots - Typically on or more of the sprockets in a chain transmission will be adjustable to allow the chain to be tight around the sprockets. This could be implemented by allowing the user to specify a pair of locations defining a slot for a given sprocket indicating that the sprocket location should be selected somewhere along this slot to create a perfectly fitting chain.