<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Orion Jiang</title>
    <description>The latest articles on DEV Community by Orion Jiang (@orion_lc).</description>
    <link>https://dev.to/orion_lc</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4038996%2Fc48126c0-a3dd-418d-846b-9e2c0f4862a9.jpg</url>
      <title>DEV Community: Orion Jiang</title>
      <link>https://dev.to/orion_lc</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/orion_lc"/>
    <language>en</language>
    <item>
      <title>Convert Linear Travel Into Motor RPM and Step Pulses With Python</title>
      <dc:creator>Orion Jiang</dc:creator>
      <pubDate>Sat, 25 Jul 2026 08:35:46 +0000</pubDate>
      <link>https://dev.to/orion_lc/convert-linear-travel-into-motor-rpm-and-step-pulses-with-python-3jl2</link>
      <guid>https://dev.to/orion_lc/convert-linear-travel-into-motor-rpm-and-step-pulses-with-python-3jl2</guid>
      <description>&lt;p&gt;When controlling a screw-driven linear axis, the motion command usually begins in millimeters, but the motor operates in revolutions and step pulses.&lt;/p&gt;

&lt;p&gt;A small conversion function can help answer three useful questions:&lt;/p&gt;

&lt;p&gt;How many motor revolutions are required?&lt;br&gt;
What motor speed is needed?&lt;br&gt;
How many step pulses should the controller generate?&lt;br&gt;
The Basic Relationship&lt;/p&gt;

&lt;p&gt;For a screw with a lead of 10 mm per revolution:&lt;/p&gt;

&lt;p&gt;10 mm of travel = 1 screw revolution&lt;/p&gt;

&lt;p&gt;A 120 mm move therefore requires 12 revolutions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkwjfu1ax3jwhclj6u0os.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkwjfu1ax3jwhclj6u0os.png" alt=" " width="800" height="290"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://jlcmc.com/product/K01/stepper-motors" rel="noopener noreferrer"&gt;Motor&lt;/a&gt; speed depends on both the desired linear speed and the screw lead.&lt;/p&gt;

&lt;p&gt;Python Function&lt;br&gt;
def calculate_axis_motion(&lt;br&gt;
    distance_mm,&lt;br&gt;
    speed_mm_s,&lt;br&gt;
    screw_lead_mm_rev,&lt;br&gt;
    motor_steps_rev=200,&lt;br&gt;
    microsteps=16&lt;br&gt;
):&lt;br&gt;
    revolutions = distance_mm / screw_lead_mm_rev&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;motor_rpm = (
    speed_mm_s * 60 / screw_lead_mm_rev
)

step_pulses = (
    revolutions
    * motor_steps_rev
    * microsteps
)

pulse_frequency_hz = (
    motor_rpm
    / 60
    * motor_steps_rev
    * microsteps
)

return {
    "revolutions": revolutions,
    "motor_rpm": motor_rpm,
    "step_pulses": step_pulses,
    "pulse_frequency_hz": pulse_frequency_hz
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;result = calculate_axis_motion(&lt;br&gt;
    distance_mm=120,&lt;br&gt;
    speed_mm_s=80,&lt;br&gt;
    screw_lead_mm_rev=10&lt;br&gt;
)&lt;/p&gt;

&lt;p&gt;for key, value in result.items():&lt;br&gt;
    print(f"{key}: {value:.2f}")&lt;/p&gt;

&lt;p&gt;Expected output:&lt;/p&gt;

&lt;p&gt;revolutions: 12.00&lt;br&gt;
motor_rpm: 480.00&lt;br&gt;
step_pulses: 38400.00&lt;br&gt;
pulse_frequency_hz: 25600.00&lt;/p&gt;

&lt;p&gt;If you are unfamiliar with the mechanical components behind this conversion, this ball screw actuator working guide explains how the motor, coupling, screw, ball nut, carriage, and support structure work together.&lt;/p&gt;

&lt;p&gt;Important Limitations&lt;/p&gt;

&lt;p&gt;This calculation assumes:&lt;/p&gt;

&lt;p&gt;Direct motor-to-screw transmission&lt;br&gt;
No gearbox or belt reduction&lt;br&gt;
Constant screw lead&lt;br&gt;
No lost motion&lt;br&gt;
The selected microstepping setting remains fixed&lt;/p&gt;

&lt;p&gt;It also does not confirm whether the motor can produce enough torque at the calculated RPM. Acceleration, load inertia, friction, screw efficiency, critical speed, and controller pulse limits must still be checked.&lt;/p&gt;

&lt;p&gt;The calculation tells the controller how far and how fast to command the axis. It does not guarantee that the mechanics can follow.&lt;/p&gt;

&lt;p&gt;Still, it is a useful first bridge between a CAD dimension and an actual motion-control command.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>news</category>
      <category>discuss</category>
      <category>learning</category>
    </item>
    <item>
      <title>A Tiny OpenSCAD Test Coupon Can Save Your Heat-Set Inserts</title>
      <dc:creator>Orion Jiang</dc:creator>
      <pubDate>Fri, 24 Jul 2026 10:10:52 +0000</pubDate>
      <link>https://dev.to/orion_lc/a-tiny-openscad-test-coupon-can-save-your-heat-set-inserts-2hl8</link>
      <guid>https://dev.to/orion_lc/a-tiny-openscad-test-coupon-can-save-your-heat-set-inserts-2hl8</guid>
      <description>&lt;p&gt;This post was created with AI assistance. Please review the code and technical details before publication.&lt;/p&gt;

&lt;p&gt;Heat-set inserts are an excellent way to add reusable metal threads to 3D-printed enclosures, sensor brackets, and robot parts.&lt;/p&gt;

&lt;p&gt;The difficult part is often not the insert. It is the hole.&lt;/p&gt;

&lt;p&gt;A hole that measures 4.2 mm in CAD may print smaller or less circular because of extrusion width, shrinkage, filament behavior, layer settings, and printer calibration. Using one “recommended” diameter for every printer can produce loose inserts, cracked bosses, or a brass insert that slowly leans sideways during installation.&lt;/p&gt;

&lt;p&gt;Instead of testing the final enclosure, print a small calibration coupon first.&lt;/p&gt;

&lt;p&gt;A Simple OpenSCAD Coupon&lt;/p&gt;

&lt;p&gt;The following model creates four holes with slightly different diameters:&lt;/p&gt;

&lt;p&gt;hole_diameters = [4.0, 4.1, 4.2, 4.3];&lt;br&gt;
spacing = 12;&lt;br&gt;
coupon_height = 6;&lt;/p&gt;

&lt;p&gt;difference() {&lt;br&gt;
    cube([&lt;br&gt;
        len(hole_diameters) * spacing,&lt;br&gt;
        12,&lt;br&gt;
        coupon_height&lt;br&gt;
    ]);&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for (i = [0 : len(hole_diameters) - 1]) {
    translate([
        i * spacing + 6,
        6,
        -1
    ])
    cylinder(
        h = coupon_height + 2,
        d = hole_diameters[i],
        $fn = 48
    );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;/p&gt;

&lt;p&gt;Change the diameter values to match the insert you are testing.&lt;/p&gt;

&lt;p&gt;Print It Under Real Conditions&lt;/p&gt;

&lt;p&gt;The coupon should use the same:&lt;/p&gt;

&lt;p&gt;Filament&lt;br&gt;
Layer height&lt;br&gt;
Wall count&lt;br&gt;
Print orientation&lt;br&gt;
Nozzle&lt;br&gt;
Temperature settings&lt;/p&gt;

&lt;p&gt;After printing, install one insert in each hole and compare:&lt;/p&gt;

&lt;p&gt;How much pressure is required?&lt;br&gt;
Does the plastic flow around the knurl?&lt;br&gt;
Does the insert remain straight?&lt;br&gt;
Does the boss crack or bulge?&lt;br&gt;
Does the insert rotate when the screw is tightened?&lt;/p&gt;

&lt;p&gt;The best hole is not necessarily the tightest one. Excessive interference can damage the surrounding plastic, while insufficient interference may allow the insert to rotate or pull out.&lt;/p&gt;

&lt;p&gt;Hole diameter is only one part of the design. Boss diameter, wall thickness, installation depth, plastic type, load direction, and print orientation also affect the final joint. This design guide for threaded inserts in plastic provides a broader checklist for evaluating those variables.&lt;/p&gt;

&lt;p&gt;A ten-minute calibration print is much cheaper than discovering the wrong hole size after a six-hour enclosure print.&lt;/p&gt;

&lt;p&gt;Small coupon, fewer surprises.&lt;/p&gt;

</description>
      <category>3dprinting</category>
      <category>devops</category>
      <category>news</category>
    </item>
    <item>
      <title>Three Mechanical Checks Before Blaming Your PID Loop</title>
      <dc:creator>Orion Jiang</dc:creator>
      <pubDate>Thu, 23 Jul 2026 10:22:32 +0000</pubDate>
      <link>https://dev.to/orion_lc/three-mechanical-checks-before-blaming-your-pid-loop-34h4</link>
      <guid>https://dev.to/orion_lc/three-mechanical-checks-before-blaming-your-pid-loop-34h4</guid>
      <description>&lt;p&gt;When a linear axis vibrates, overshoots, or produces inconsistent positioning, the controller is usually the first suspect.&lt;/p&gt;

&lt;p&gt;Sometimes the PID values are wrong. Sometimes the mechanism is simply asking the controller to perform magic.&lt;/p&gt;

&lt;p&gt;Before spending another hour tuning gains, I like to check three mechanical conditions.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Check for binding&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Move the axis slowly through its complete stroke and record:&lt;/p&gt;

&lt;p&gt;timestamp&lt;br&gt;
command_position&lt;br&gt;
actual_position&lt;br&gt;
motor_current&lt;br&gt;
travel_direction&lt;/p&gt;

&lt;p&gt;A current spike that repeatedly appears at the same position may indicate misalignment, rail binding, contamination, or an uneven mounting surface.&lt;/p&gt;

&lt;p&gt;If the spike only appears in one travel direction, friction or preload deserves attention before the control loop does.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0wkrkdktrz3ja7n6zrrc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0wkrkdktrz3ja7n6zrrc.png" alt=" " width="476" height="315"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Check the sensor mount&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A sensor can be accurate while its bracket is not.&lt;/p&gt;

&lt;p&gt;With the axis stationary, monitor the feedback signal and lightly disturb the cable or surrounding structure. If the reading changes, check:&lt;/p&gt;

&lt;p&gt;Bracket stiffness&lt;br&gt;
Fastener tightness&lt;br&gt;
Cable strain&lt;br&gt;
Sensor-to-target distance&lt;br&gt;
Nearby vibration sources&lt;/p&gt;

&lt;p&gt;Filtering unstable feedback may hide the symptom, but it does not make the measurement more trustworthy.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Check the coupling and drive alignment&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Misalignment between a motor, coupling, and lead screw can create periodic load changes. At low speed, watch for motor-current peaks that repeat once per revolution.&lt;/p&gt;

&lt;p&gt;That pattern is usually more informative than random vibration. It points toward eccentricity, angular misalignment, a bent shaft, or poor support alignment.&lt;/p&gt;

&lt;p&gt;A useful debugging order&lt;/p&gt;

&lt;p&gt;When an axis behaves badly, try this sequence:&lt;/p&gt;

&lt;p&gt;Mechanical freedom&lt;br&gt;
→ Sensor stability&lt;br&gt;
→ Drive alignment&lt;br&gt;
→ Electrical noise&lt;br&gt;
→ Control tuning&lt;/p&gt;

&lt;p&gt;PID tuning works best when the mechanism is predictable. Otherwise, the controller is only being tuned around a moving target.&lt;/p&gt;

&lt;p&gt;What mechanical problem has wasted the most control-tuning time in one of your projects?&lt;/p&gt;

</description>
      <category>robotics</category>
      <category>automation</category>
    </item>
  </channel>
</rss>
