Stepper motor issue, crackling sound, and more...

I recently go interested in Arduino and decided to make an ambitious project considering how new I am to all of it. The whole project is to measure the weight of an object from a robot arm using torque equilibrium, and output its mass on an lcd, something like a manual scale to measure your weight. The structural is all complete.

The first problem I had was with the lcd, (it's still a problem but ive encounter another bigger one) it didn't display any characters... But that is for its own discussion and will not be brought up here.

The bigger problem I had was with the stepper motors. I have extracted a part of my bigger and ongoing code (I'm not 100% finished, due to this problem) and tried to run that piece individually.

As soon as I turn the power,
1st: I hear a crackling sound.
2nd: the motor seems to be moving back and forth (maybe a dozen or more of steps) at the same time as the crackling sound.
3rd: when I press the button "up" (in the code below), nothing apparent happens, as if it's ignoring the input.

I doubt the problem is in the wiring of the controller because i triple check it with a multimeter. I also rebuilt the board that holds the A4988 drivers, from a cnc milled PCB to prototyping perf board. I tried disconnecting pins RESET and SLEEP, but when I do, nothing happens. As in the motor doesn't move at all.

I tested one example from the AccelStepper library, and it worked fine (the one that sets random values).
After that, I figured that the problem might be the code.

The board I'm using is a mega 2560 (not Arduino brand).

My questions are:
Is there any wrong with my code?
What might be a solution?

Any help is appreciated.

Here is the code:

#include <AccelStepper.h>
#include <MultiStepper.h>


#define stepY 42
#define dirY 44
#define up 50
int upState;
AccelStepper stepper(1, stepY, dirY);
void setup() {
  pinMode(up, INPUT);
  stepper.setMaxSpeed(1000);
  stepper.setAcceleration(1000);
 
}


void loop() {
  upState = digitalRead(up);
  if (upState==HIGH){
    for (int q = 0; q < 1000 && q > 0; q += 50){
      stepper.moveTo(q);
    }
  }
  stepper.run();
}

Sorry, I can't tell where the cracking sound comes from, either.
Paul

This piece of code does nothing useful - what had you in mind when you wrote it?

    for (int q = 0; q < 1000 && q > 0; q += 50){
      stepper.moveTo(q);
    }

You could replace it with

stepper.moveTo(950);

And your code should only set the moveTo() value when the upState changes from LOW to HIGH - and even then I'm assuming that cannot happen again until the move is complete.

My guess is that you need to re-think the logic.

...R

Robin2:
This piece of code does nothing useful - what had you in mind when you wrote it?

    for (int q = 0; q < 1000 && q > 0; q += 50){

stepper.moveTo(q);
   }



You could replace it with


stepper.moveTo(950);




And your code should only set the moveTo() value when the upState changes from LOW to HIGH - and even then I'm assuming that cannot happen again until the move is complete.

My guess is that you need to re-think the logic.


...R

Here is a better setup of what I want to do,
When inc (increment) is set high, I want the stepper motor to move a certain number of steps if the user were to press the button "up". When the user switches inc off and on again, I want the stepper to move a different (more) number of steps. And finally, when int q is at 150 or whatever the max value may be (i could switch it to 4 and add increments of 1 with another step increment of 800) I want it to move an infinite number of steps.
Basically, when the user holds the button, it moves until it hit a block or limit switch. I figure I can do the infinite increment without the accel library, by just writing the pins high and low with delays.

#include <AccelStepper.h>
#include <MultiStepper.h>


#define stepY 42
#define dirY 44
#define up 50
#define inc 51
int upState;
int incState;
AccelStepper stepper(1, stepY, dirY);
void setup() {
  pinMode(up, INPUT);
  stepper.setMaxSpeed(1000);
  stepper.setAcceleration(1000);
 
}


void loop() {
  upState = digitalRead(up);
  incState = digitalRead(inc);
    for (int q = 0; q < 150 && incState == HIGH; q += 50){//here inc is a switch, so it usually stays high.
      if (q = 0 && upState == HIGH){
        stepper.moveTo(200);
        stepper.run();
      }
      if (q = 50 && upState == HIGH){
        stepper.moveTo(400);
        stepper.run();
      }
    }
  
}

The problem I'm getting with this new code is that the stepper moves like it did before (with old code), It just moving back and forth in small number of steps. In other words, again my input is having no effect. I tried unplugging the inc and up, and it still does what it wants. When I unplug the stepY and dirY, it stops.
Same questions as in reply#0.

lamboant:
Here is a better setup of what I want to do,
When inc (increment) is set high, I want the stepper motor to move a certain number of steps if the user were to press the button "up". When the user switches inc off and on again, I want the stepper to move a different (more) number of steps. And finally, when int q is at 150 or whatever the max value may be (i could switch it to 4 and add increments of 1 with another step increment of 800) I want it to move an infinite number of steps.

Sorry, but I still don't understand. Please describe the project without reference to the code.

Also you are still using stepper.moveTo() incorrectly. It should be updated before a move starts and then the move should be allowed to complete. Something like this pseudo code

if (stepper.distanceToGo() == 0 and someButtonIsPushed) 
   stepper.moveTo(newPosition);
}
stepper.run();

...R

Robin2:
Sorry, but I still don't understand. Please describe the project without reference to the code.

Also you are still using stepper.moveTo() incorrectly. It should be updated before a move starts and then the move should be allowed to complete. Something like this pseudo code

if (stepper.distanceToGo() == 0 and someButtonIsPushed) 

stepper.moveTo(newPosition);
}
stepper.run();




...R

I was using moveTo wrong, I updated it now, is this the proper way?
Because the motor is still behaving the same way.

I'll do my best to describe my project:
Last semester I learned about torque equilibrium on beams, etc...
So I decided to make a robot arm that uses that concept to measure the mass of a object it picks up, (the mass must be over a certain value).
Stucturally:
Like a standard robot arm guided on the Y axis (up, down) with a lead screw. Where the guide is attached to a "middle piece" that is on a pivot point. Imagine a stick going from the floor to sky 1m long, now imagine a stick that is perpendicular to that one going from left to right 1m (like a cross). Now imagine that stick can turn on the Z axis (front to back). Or imagine that the X axis suddenly goes up and down while the Y axis stay stable on a cartesian plane, (I'm trying to be a clear as possible).
When a force is applied to one end perpendicularly it will begin to rotate, to stop this rotation, I added a stepper motor (acting as weight) with a lead screw (lead screw being parallel to te floor) on the other end. I also added a potentiometer at the pivot point of the X axis. When it reads a certain value, it will send that value to the Arduino, and the Arduino will rotate the stepper motor a certain number of steps to counter the force on the opposite end. Thus, it goes back to equilibrium.
How i measure the mass:
I added a rotary encoder to the stepper acting as a weight. This encoder will track the number of steps (or number of times it makes an input). Each # of millimeters it moves corresponds to 1 input on the encoder.
I guess I could also keep track of the steps, but I do not know how to do that, so I added the encoder with a pulley attached to the shaft of the stepper. With the equations SUM*torque/moment *= SUMFd and F=mg, I should be able to get the mass of the object is being picked up.
If you need more clarification or if something isn't coherent let me know and ill attach a diagram to further explain myself.
thanks.

#include <AccelStepper.h>
#include <MultiStepper.h>


#define stepY 42
#define dirY 44
#define up 50
#define inc 51
int upState;
int incState;
AccelStepper stepper(1, stepY, dirY);
void setup() {
  pinMode(up, INPUT);
  stepper.setMaxSpeed(1000);
  stepper.setAcceleration(1000);
 
}


void loop() {
  upState = digitalRead(up);
  incState = digitalRead(inc);
    for (int q = 0; q < 150 && incState == HIGH; q += 50){//here inc is a switch, so it usually stays high.
      if (q = 0 && upState == HIGH && stepper.distanceToGo()==0){
        stepper.moveTo(200);
        
      }
      if (q = 50 && upState == HIGH && stepper.distanceToGo()==0){
        stepper.moveTo(400);
        
      }
    }
  stepper.run();
}

lamboant:
Imagine a stick going from the floor to sky 1m long, now imagine a stick that is perpendicular to that one going from left to right 1m (like a cross). Now imagine that stick can turn on the Z axis (front to back). Or imagine that

Please draw a simple diagram and post a photo of it.

...R
Simple Image Posting Guide

Here is the general setup and the working diagram of the general idea:

Am I correct to think that the device lowers the arm and positions it so the servos on the right can attach to something. Then the arm is raised and if the weight on the left is not positioned properly to balance whatever was picked up the arm will tilt. Then the stepper is moved in or out to restore the balance? (A modern version of scales that used to be common at railway stations)

If I now understand the problem, perhaps you can explain what it is that you want help with?

Or if my understanding is wrong, please correct me.

...R

Robin2:
Am I correct to think that the device lowers the arm and positions it so the servos on the right can attach to something. Then the arm is raised and if the weight on the left is not positioned properly to balance whatever was picked up the arm will tilt. Then the stepper is moved in or out to restore the balance? (A modern version of scales that used to be common at railway stations)

If I now understand the problem, perhaps you can explain what it is that you want help with?

Or if my understanding is wrong, please correct me.

...R

Your understanding of my project is correct.
The problem I'm having is getting the stepper motors to work as intended. So far, I'm havent written anything past the "Y" axis motor because of this issue.
the code i posted in #reply5 must be repeated 4 times for left, right, up, and down for 4 different step values.

(I tried using OOP and VS micro, but I couldnt get it to read the source files)
(So now I decided to simply use the original IDE)
What I want help with is writting the code to control the stepper motors using AccelStepper library and momentary push buttons.
Because everything I tried failed up to now. It is possible I'm not understanding the library correctly and using it wrong.
(i put this in bold in case one might skip over it while reading this post)
Once that is complete this part, I should be good to go for the rest of the project. (of course if the servos and gyro dont give me issues).

lamboant:
the code i posted in #reply5 must be repeated 4 times for left, right, up, and down for 4 different step values.

The code uses very cryptic variable names such as 'up' and 'inc'. Using descriptive meaningful names for variables and functions makes code much easier to understand and helps to show up silly errors.

Also put each statement on a separate line.

And you still have the strange FOR loop that I commented on in Reply #2

I wonder if you are trying to make the stepper move much too fast. Also your acceleration rate is almost instantaneous which is never good if the motor has to lift a load. Reduce the speed by a factor of 10 for testing.

...R

Robin2:
The code uses very cryptic variable names such as 'up' and 'inc'. Using descriptive meaningful names for variables and functions makes code much easier to understand and helps to show up silly errors.

Also put each statement on a separate line.

And you still have the strange FOR loop that I commented on in Reply #2

I wonder if you are trying to make the stepper move much too fast. Also your acceleration rate is almost instantaneous which is never good if the motor has to lift a load. Reduce the speed by a factor of 10 for testing.

...R

After relieving my headache, I got back writing some code.
I realized that the problem was that I was powering my Arduino via USB, after powering it via Vin and GND pins, the trouble stopped happening!
I can't seem to figure out how to get the stepper motor to continue moving after it moves 400 steps. I tried using the distanceToGo()==0 in the if statement like you proposed, but the motor didn't move at all. I'm guessing it's because the motor made some steps and then the if statement was false after that.
So, I removed it and now the motor only moves 400 steps (as expected).
What I want it to do is move 400 steps after each time the button is pressed, I have a feeling that solution is simple, but I just don't see it.
Do I reset the motors position after each time? Or is there another way?
thanks

Here is the code:

void setup() {
  // put your setup code here, to run once:
  pinMode(button, INPUT_PULLUP);
  stepper.setMaxSpeed(800);
  stepper.setAcceleration(500);
}


void loop() {
  // put your main code here, to run repeatedly:
  int button_state = digitalRead(button);
  if (button_state == LOW){
    stepper.moveTo(400);
    stepper.run();
  }


}

lamboant:
What I want it to do is move 400 steps after each time the button is pressed, I have a feeling that solution is simple, but I just don't see it.

You seem to have gone back to the code that I told you was wrong in Replies #2 and #4 - not surprising that it does not work.

You said

I tried using the distanceToGo()==0 in the if statement like you proposed, but the motor didn't move at all.

Even though it is not working now that will be a better starting point so post that program.

And, if you think about it carefully, the solution to your problem is described (by you) in this

What I want it to do is move 400 steps after each time the button is pressed

Think about how to update the moveTo() every time the button is pressed. You may also find that the move() function is more appropriate as it is a relative move.

...R

And, if you think about it carefully, the solution to your problem is described (by you) in thisThink about how to update the moveTo() every time the button is pressed. You may also find that the move() function is more appropriate as it is a relative move.

So, I decided to abandon the moveTo() for controlling 2 steppers (on Y axis and turning the base), and replace it with move(), since it more appropriate for my situation.
I'll still need moveTo() for the stepper that acts as a weight to rebalance the arm. I'll get to that later...
For now, I have another issue.
I want to choose based on a rotary switch (not encoder), the different number of steps.
For now, it just steps at 700 even when the input button2 are both LOW (they are INPUT_PULLUP and therefore set to LOW to indicate something).

#define stepY 42
#define dirY 30
#define button 50
#define button2 48
#define button3 46
int Speed;
#include <AccelStepper.h>
AccelStepper stepper(1, stepY, dirY);






void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(button, INPUT_PULLUP);
  stepper.setMaxSpeed(800);
  stepper.setAcceleration(500);
}


void loop() {
  
  if (digitalRead(button2) == LOW){
    Speed = 500;
  }
  if (digitalRead(button3) == LOW){
    Speed = 700;
  }
  
  
  if (digitalRead(button) == LOW){
    stepper.move(Speed);
    stepper.run();
  }
  
}

You need to draw a diagram showing how the rotary switch is wired and then post a photo of the drawing.

If button2 and button3 cannot both be LOW at the same time maybe an ELSE would help.

And if you are using a rotary switch why are the variables called "button" - a deliberate attempt to make the code confusing?

...R

Here is the diagram, I assume this is how it can be wired from different pictures and pinouts. I bought it online recently due to my rotary encoder displaying multiple outputs at once.

I named the pins connected to the switch "button" because I was using buttons to test it.
I'll try adding an ELSE and post my results later.

With the changes you proposed, it behaved the same unfortunately.
I'm not sure if I can simply use ELSE as is, because there will be 4 different speeds to adjust to. (4 inputs in the final code)
What I mean by final code: it has all the variables and will include the entire code for the arm, I'm breaking it into steps to try to identify where there might be problems instead of writing it all and having a bunch of issues.

I also changed the speed from 500 to 100, in case 500 was unnoticeable from 700. It just runs at 100, even when I press the other buttons (in the code I changed them, button2=state1, button3=state2). I measured <1 volt when the buttons weren't pressed, so it's unlikely the wiring.

I'll try some other code and report what I get.

#define stepY 42
#define dirY 30
#define button 50
#define state1 48
#define state2 46
int Speed;
#include <AccelStepper.h>
AccelStepper stepper(1, stepY, dirY);






void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(button, INPUT_PULLUP);
  stepper.setMaxSpeed(800);
  stepper.setAcceleration(500);
}


void loop() {  
  if (digitalRead(state1) == LOW){
    Speed = 100;
  }
  else if (digitalRead(state2) == LOW){
    Speed = 700;
  }
  
  
  if (digitalRead(button) == LOW){
    stepper.move(Speed);
    stepper.run();
  }
  
}

lamboant:
With the changes you proposed, it behaved the same unfortunately.

You need to post the program so we can see exactly what you did.

I'll try some other code and report what I get.

"some other code" is the best way I know to waste time.

Stick with the code you have been trying and get it to work. Debugging a program requires patience and method. Trying "some other code" means that whatever you learned from the first program is wasted even though the error might be very small - if we could see the code.

...R

Robin2:
You need to post the program so we can see exactly what you did.

I apologize for my last response, your proposed idea does work, I simply kept declaring the input pins as INPUT instead of INPUT_PULLUP... (this mistake is not found in the previous codes I posted since I never included state1 and state2).

This sample code now works:

#define stepY 42
#define dirY 30
#define button 50
#define state1 48
#define state2 46


int Speed;


#include <AccelStepper.h>
AccelStepper stepper(1, stepY, dirY);


void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(button, INPUT_PULLUP);
  pinMode(state1, INPUT_PULLUP);
  pinMode(state2, INPUT_PULLUP);
  stepper.setMaxSpeed(800);
  stepper.setAcceleration(500);
}


void loop() {  
  if (digitalRead(state1) == LOW){
    Speed = 100;
  }
  else if (digitalRead(state2) == LOW){
    Speed = 700;
  }
  
  
  if (digitalRead(button) == LOW){
    stepper.move(Speed);
    stepper.run();
  }
  
}

The question I have is: If I mention a different piece of code that is relevant to my project but is not relevant to this title (in this case a potentiometer and a stepper), do I still bring it up here not to confuse people or do I create a brand-new topic to stay coherent with the topic title (even it says "and more...").

My concern would be if I have any trouble controlling that specific stepper according to the input of a potentiometer (I'll check other forums for a solution before I ask here if that answer to my question is yes to, I can keep posting here).

For those who want a solution to the crackling sound:
I bought a mega2560 (not Arduino brand), and when I powered the Arduino via USB, the stepper motor did what it wanted. When I powered via Vin and GND, all the crackling noise and "self-aware"(motors moving without input) behavior stopped.