How to properly move stepper motor with potentiometer

I'm using Arduino Nano with nema 17 motor and tmc2209 driver.

First i set up everything and used example code without libraries to see if the motor will run correctly and it finally did.

Then i tried few code examples for potentiometer control, but the motor sounds like a meatgrinder and it spins by itself not affected by the potentiometer.

My plan is to have that as optional manual movement in the rail i'm making.

Here is the code example from how2electronics

const int stepPin = 3;

const int dirPin = 4; 

int customDelay,customDelayMapped; // Defines variables

void setup() {

  // Sets the two pins as Outputs

  pinMode(stepPin,OUTPUT);

  pinMode(dirPin,OUTPUT);

  digitalWrite(dirPin,HIGH); //Enables the motor to move in a particular direction

}

void loop() {

  

  customDelayMapped = speedUp(); // Gets custom delay values from the custom speedUp function

  // Makes pules with custom delay, depending on the Potentiometer, from which the speed of the motor depends

  digitalWrite(stepPin, HIGH);

  delayMicroseconds(customDelayMapped);

  digitalWrite(stepPin, LOW);

  delayMicroseconds(customDelayMapped);

}

// Function for reading the Potentiometer

int speedUp() {

  int customDelay = analogRead(A0); // Reads the potentiometer

  int newCustom = map(customDelay, 0, 1023, 300,4000); // Convrests the read values of the potentiometer from 0 to 1023 into desireded delay values (300 to 4000)

  return newCustom;  

}


Did the motor work correctly?

My crystal ball is out for its oil change so I think that we need to see your code. Read the forum guidelines to see how to properly post code and some information on how to get the most from this forum.
Use the IDE autoformat tool (ctrl-t or Tools, Auto format) before posting code in code tags.

And a schematic that shows how the project should be wired.

What is the stepper power supply?

I added the example code in the post, but haven't made the schematic yet.

The motor is powered by 12v and i added capacitor to smooth things out.

Do you want to control speed or position?

I use this code to control position.

#include <AccelStepper.h>

// change pins to match your setup.  enable pin just for my CNC shield
const byte stepPin = 2;
const byte dirPin = 5;
const byte enablePin = 8; // for CNC shield
const byte potPin = A0;  

AccelStepper stepper(AccelStepper::DRIVER, stepPin, dirPin);

void setup()
{
   Serial.begin(115200);
   pinMode(enablePin, OUTPUT); // for CNC shield
   digitalWrite(enablePin, LOW);  // enable stepper(s)
   stepper.setMaxSpeed(2000);
   stepper.setAcceleration(1000);
   stepper.setSpeed(0);   
}

void loop()
{
   int potValue = analogRead(potPin);
   stepper.moveTo(map(potValue, 0 ,1023, -1000, 1000));
   
   stepper.runSpeed();
}
1 Like

And this example code will control speed with pot center as stop, speed increases away from center and direction depends on direction from center.

#include <AccelStepper.h>

// change pins to match your setup.  enable pin just for my CNC shield
const byte stepPin = 2;
const byte dirPin = 5;
const byte enablePin = 8; // for CNC shield
const byte potPin = A0;  

AccelStepper stepper(AccelStepper::DRIVER, stepPin, dirPin);

void setup()
{
   Serial.begin(115200);
   pinMode(enablePin, OUTPUT); // for CNC shield
   digitalWrite(enablePin, LOW);  // enable stepper(s)
   stepper.setMaxSpeed(2000);
   stepper.setAcceleration(1000);
   stepper.setSpeed(0);
}

void loop()
{
   int potValue = analogRead(potPin);
   
   if (potValue >= 487 && potValue <= 537) // ±25 hysteresis for center (0 speed)
   {      
      stepper.setSpeed(0);     
   }
   else if (potValue < 487)
   {       
      stepper.setSpeed((487 - potValue) * 10); // your choice of multiplier     
   }
   else if(potValue > 537)
   {
      stepper.setSpeed((537 - potValue) * 10); // your choice of multiplier      
   }
   stepper.runSpeed();
}
1 Like

I made the diagram.

Well i want to control the position and when the rotation(of the potentiometer) stops the movement of the motor to completely stop. But ideally i want to control the speed also, for example if i rotate the potentiometer slowly the movement of the motor to be slow as well.

Thanks for the code!

When i used the second example the motor makes more noise, but it changes direction when i rotate the potentiometer.

With the first example it runs left and right even when i don't touch the potentiometer, but is not that noisy.

Just to note the potentiometer is connected with the DAT pin to A0.

but you're using the pot to control the delay, so don't you expect the motor to always be turning? the pot would just control the speed.

i've found that i cannot step a motor faster than 1 msec. this may

then the code should count steps and the pot should be used to determine at what step count to stop the motor, as well as what direction to step the motor in

1 Like

I tested both examples on my setup of an Uno with CNC shield running A4988 drivers to a NEMA 17 stepper motor with 12V power. Both examples run nice and smooth.

Are your drivers set up properly and have the coil current limit set? I am not so familiar with the TMC2209 drivers.

Put a 0.1uf ceramic cap from the pot wiper (A0) to ground to filter noise. That may help for both examples.

So i actually found exactly what i need here, but since i'm using different driver i don't have sleep pin so i connected it to the EN(enable) is that wrong or i should modify the code to use it with that particular pin? I tried it and it doesn't run properly, the motor only turns when i press the reset button for the first few times. Also i was working with a rotary encoder instead of a pot, my bad.

Here is the code from brainy-bits.com

// EasyDriver connections
#define step_pin 9  // Pin 9 connected to Steps pin on EasyDriver
#define dir_pin 8   // Pin 8 connected to Direction pin
#define MS1 10       // Pin 10 connected to MS1 pin
#define MS2 11      // Pin 11 connected to MS2 pin
#define SLEEP 12     // Pin 12 connected to SLEEP pin
                    
volatile boolean TurnDetected;  // need volatile for Interrupts
volatile boolean rotationdirection;  // CW or CCW rotation

// Rotary Encoder Module connections
const int PinCLK=2;   // Generating interrupts using CLK signal
const int PinDT=3;    // Reading DT signal
const int PinSW=4;    // Reading Push Button switch

int StepperPosition=0;    // To store Stepper Motor Position
int StepsToTake=4;      // Controls the speed of the Stepper per Rotary click

int direction;   // Variable to set Rotation (CW-CCW) of stepper


// Interrupt routine runs if CLK goes from HIGH to LOW
void rotarydetect ()  {
delay(4);  // delay for Debouncing
if (digitalRead(PinCLK))
rotationdirection= digitalRead(PinDT);
else
rotationdirection= !digitalRead(PinDT);
TurnDetected = true;
}


void setup ()  {

   pinMode(MS1, OUTPUT);
   pinMode(MS2, OUTPUT);
   pinMode(dir_pin, OUTPUT);
   pinMode(step_pin, OUTPUT);
   pinMode(SLEEP, OUTPUT);   
   digitalWrite(SLEEP, HIGH);  // Wake up EasyDriver
   delay(5);  // Wait for EasyDriver wake up
   
 /* Configure type of Steps on EasyDriver:
 // MS1 MS2
 //
 // LOW LOW = Full Step //
 // HIGH LOW = Half Step //
 // LOW HIGH = A quarter of Step //
 // HIGH HIGH = An eighth of Step //
 */ 
   digitalWrite(MS1, LOW);      // Configures to Full Steps
   digitalWrite(MS2, LOW);    // Configures to Full Steps
   
  pinMode(PinCLK,INPUT);  // Set Pin to Input
  pinMode(PinDT,INPUT);  
  pinMode(PinSW,INPUT);
  digitalWrite(PinSW, HIGH); // Pull-Up resistor for switch
  attachInterrupt (0,rotarydetect,FALLING); // interrupt 0 always connected to pin 2 on Arduino UNO
}


void loop ()  {

  if (!(digitalRead(PinSW))) {   // check if button is pressed
  if (StepperPosition == 0) {  // check if button was already pressed
  } else {
      if (StepperPosition > 0) {  // Stepper was moved CW
        while (StepperPosition != 0){  //  Do until Motor position is back to ZERO
          digitalWrite(dir_pin, HIGH);  // (HIGH = anti-clockwise / LOW = clockwise)
          for (int x = 1; x < StepsToTake; x++) {
              digitalWrite(step_pin, HIGH);
              delay(1);
              digitalWrite(step_pin, LOW);
              delay(1);            
            }
            StepperPosition=StepperPosition-StepsToTake;
        }
      }
      else {
        while (StepperPosition != 0){ 
          digitalWrite(dir_pin, LOW);  // (HIGH = anti-clockwise / LOW = clockwise)
              for (int x = 1; x < StepsToTake; x++) {
              digitalWrite(step_pin, HIGH);
              delay(1);
              digitalWrite(step_pin, LOW);
              delay(1);            
            }
           StepperPosition=StepperPosition+StepsToTake;
        }
      }
      StepperPosition=0; // Reset position to ZERO after moving motor back
    }
  }

// Runs if rotation was detected
  if (TurnDetected)  {
        TurnDetected = false;  // do NOT repeat IF loop until new rotation detected

// Which direction to move Stepper motor
        if (rotationdirection) { // Move motor CCW
            digitalWrite(dir_pin, HIGH);  // (HIGH = anti-clockwise / LOW = clockwise)
            for (int x = 1; x < StepsToTake; x++) {
              digitalWrite(step_pin, HIGH);
              delay(1);
              digitalWrite(step_pin, LOW);
              delay(1);            
            }
            StepperPosition=StepperPosition-StepsToTake;
        }

        if (!rotationdirection) { // Move motor CW
            digitalWrite(dir_pin, LOW);  // (HIGH = anti-clockwise / LOW = clockwise)
            for (int x = 1; x < StepsToTake; x++) {
              digitalWrite(step_pin, HIGH);
              delay(1);
              digitalWrite(step_pin, LOW); 
              delay(1);         
            }
            StepperPosition=StepperPosition+StepsToTake;
        }
  }
}

At the moment i don't have a working multimeter, so i haven't set up the limit properly.
I think when i removed pinMode(enablePin, OUTPUT); // for CNC shield this line the motor ran smoothly, but i might be wrong. I don't use it with shield so is that option mandatory in my case?

You do not need the enablePin. It conflicts with your dir_pin.

I removed the sleep function in the code and it works fine now, thanks!

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.