Stepper Motor whine at idle

I have searched and searched but have been unable to find the solution.
I have a machine for cutting wires and everything works exactly as it should. The only issue is a constant whine while it's idle. It also squeals in the pause between each movement. I understand that it's sending current to maintain the motor position, but I don't need that. The design of the machine holds the position by friction. Can someone take a look at the code and help me change it so it stops sending current between operations? I can use it the way it is if I have to, but it would change it from great to perfect if I could just kill the whine.


#include <LiquidCrystal.h>
#include <Servo.h>
 
//------------------------------- lcd ----------------------------------
LiquidCrystal lcd(12, 11, 2, 3, 4, 5);
 
//------------------------------- stepper ----------------------------------
#define stepPin 7
#define dirPin 8
 
//------------------------------- servo ----------------------------------
Servo snippers;
#define servo 10
#define openAngle 180
#define closedAngle 0
 
//------------------------------- input ----------------------------------
 
#define leftButton 14
#define rightButton 9
#define upButton 15
#define downButton 6
 
//------------------------------- user settings ----------------------------------
unsigned int wireLength = 65;
unsigned int wireQuantity = 0;
 
//------------------------------- system settings ----------------------------------
int state = 1;
int incrementSpeed = 1;
int previousWireLength = 65;
int previousWireQuantity = 0;
float mmPerStep = 0.18096;
 
 
void setup() {
  Serial.begin(9600);
 
 
  lcd.begin(16, 2); //LCD columns and rows
 
 
  pinMode(upButton, INPUT_PULLUP);
  pinMode(downButton, INPUT_PULLUP);
  pinMode(leftButton, INPUT_PULLUP);
  pinMode(rightButton, INPUT_PULLUP);
 
  pinMode(stepPin,OUTPUT);
  pinMode(dirPin,OUTPUT);
 
  snippers.attach(servo);
 
  snippers.write(openAngle);
   
  delay(1000);
}
 
void loop() {
  if (!digitalRead(rightButton)){
    if(state == 5){
      state = 0;
    }
    else{
      state += 1;
    }
    delay(200);
    lcd.clear();
  }
  if (!digitalRead(leftButton) && state > 0 && state < 4){
    state -=1;
    delay(200);
    lcd.clear();
  }
 
 
  switch (state){
    case 0:
      homeScreen();
      break;
    case 1:
       chooseWireLength();
       break;
    case 2:
      chooseWireQuantity();
      break;
    case 3:
      confirm();
      break;
    case 4:
      currentlyCutting();
      break;
    case 5:
      finishedCutting();
      break;
  }
 
}
 
 
void homeScreen(){
  lcd.setCursor(0, 0);
  lcd.print("EAR WIRE CUTTER");
  lcd.setCursor(11, 1);
  lcd.print("NEXT>");
  delay(100);
}
 
 
void chooseWireLength(){
  wireLength = changeValue(wireLength);
 
  //clear LCD if required
  if(previousWireLength != wireLength){
    lcd.clear();
    previousWireLength = wireLength;
  }
 
  //Display information on LCD
  lcd.setCursor(0, 0);
  lcd.print("LENGTH:" + (String)wireLength + "mm");
  displayNavigation();
}
 
void chooseWireQuantity(){
  wireQuantity = changeValue(wireQuantity);
 
  //clear LCD if required
  if(previousWireQuantity != wireQuantity){
    lcd.clear();
    previousWireQuantity = wireQuantity;
  }
 
  //Display information on LCD
  lcd.setCursor(0, 0);
  lcd.print("QUANTITY:" + (String)wireQuantity);
  displayNavigation();
}
 
void confirm(){
  lcd.setCursor(0, 0);
  lcd.print((String)wireLength + "mm x " + (String)wireQuantity + "pcs");
  lcd.setCursor(0, 1);
  lcd.print("<BACK");
  lcd.setCursor(10, 1);
  lcd.print("START>");
  delay(100);
}
 
void currentlyCutting(){
  lcd.setCursor(0, 0);
  lcd.print((String)0 + "/" + (String)wireQuantity);
  lcd.setCursor(0, 1);
  lcd.print("???s");
  int stepsToTake = (int)wireLength/mmPerStep;
  for(int i = 0; i < wireQuantity; i++){
    unsigned long timeForOneCycle = millis();
    digitalWrite(dirPin,HIGH);
    for(int x = 0; x < stepsToTake; x++) {
      digitalWrite(stepPin,HIGH);
      delayMicroseconds(500);
      digitalWrite(stepPin,LOW);
      delayMicroseconds(500);
    }
   
    lcd.setCursor(0, 0);
    lcd.print((String)(i+1) + "/" + (String)wireQuantity);
   
    snippers.write(closedAngle);
    delay(600);
    snippers.write(openAngle);
    delay(600);
 
   
    lcd.setCursor(0, 1);
 
    unsigned long timeRemaining = ((millis() - timeForOneCycle)*(wireQuantity - (i+1)))/1000;
    lcd.print((String)timeRemaining + "s    ");
   
  }
  wireLength = 0;
  wireQuantity = 0;
  state = 5;
}
 
void finishedCutting(){
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("CUTTING COMPLETE");
  lcd.setCursor(11, 1);
  lcd.print("NEXT>");
  delay(100);
}
 
 
int changeValue(int currentValue){
  if (!digitalRead(upButton)) {
    delay(100);
    currentValue += incrementSpeed;
    
  }
  if (!digitalRead(downButton)) {
    if(currentValue - incrementSpeed >= 0){
      delay(100);
      currentValue -= incrementSpeed;
    
    }
    else{
      currentValue = 0;
    }
  }
  if (!digitalRead(downButton) && !digitalRead(upButton)){
    incrementSpeed = 1;
  }
  return currentValue;
}
 
void displayNavigation(){
  lcd.setCursor(0, 1);
  lcd.print("<BACK");
  lcd.setCursor(11, 1);
  lcd.print("NEXT>");
  delay(100);
}```

I agree that the current limiter, using PWM, could be the reason for the noise.

Check the data sheet of your driver chip or module for which pin can be used to disable the driver.

On a small (8 bit) Arduino the String type is very problematic.

You can use the "<<" output concatenation by #including <Streaming.h> and rewrite above statement as
lcd << 0 << "/" << wireQuantity;
This works at least for Serial, eventually a type cast is required for the lcd object?

The whine is normal, and results from the motor wiring vibrations, due to the current limiting action.

A different motor may not produce that whine.

My apologies, but as I'm sure that makes perfect sense to you, I still don't understand what to do. I assumed you meant to replace:
lcd.print((String)0 + "/" + (String)wireQuantity);
with
lcd << 0 << "/" << wireQuantity;
Which I tried and it returns:

cutter:168:9: error: no match for 'operator<<' (operand types are 'LiquidCrystal' and 'int')
     lcd << 0 << "/" << wireQuantity;
     ~~~~^~~~
exit status 1
no match for 'operator<<' (operand types are 'LiquidCrystal' and 'int')

The error indicates that the LiquidCrystal class does not inherit from the stream class which implements the operator<<. Unfortunately this disallows to use the streaming operators :frowning:

For understanding the streaming operators try Serial with code like

Serial << "test " << 123 << F(" text in flash");

to print multiple items to Serial in one statement.

To be honest: I don't know how "<<" works internally. If it uses the String type then it will not be useful with the small 8-bit Arduinos.

I always feel so stupid asking for help on forums. I didn't write that code and don't understand it at all. That's why I asked for help. Again, while I'm sure it's perfectly understandable to you and someone with coding knowledge, to me it's just word salad. You keep mentioning small 8-bit Arduinos. I assume mine is. It's an Arduino Nano.

A certain lack of knowledge is okay. But you should answer the questions as good as you can. My crystal ball is on repair, I cannot see what hardware you are using :frowning:

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