Go Down

Topic: Welding positioner control (Read 529 times) previous topic - next topic

JohnLynn

My first post on the forum.

I intend to make a welding positioner, this will be a lathe chuck on the end of a shaft supported by a couple of self centring bearings and have a strap or brushes on the shaft for the earth connection.

To try to learn something about controlling it I have been practising on a small scale with a Nema 17 stepper motor from an old printer. I have used a Uno with an L298 H bridge driver.

Ideally I would like the chuck in the finished project to simply rotate one revolution then stop, by reading and I must admit copying code I can get my miniature version to rotate at a given speed for a set number of revolutions. (But only in a loop)

Now for the basic questions. I understand that the set up runs once and the loop runs, well like a loop! This doesn't sound good as I want to just press a button and the chuck turn once, but of course repeatable on the next button press.
If I have a loop looking at the state of the button, how do I program the motor to turn a set number of revs then stop until the button is pressed again?

Also when the motor is stationary can I avoid current still passing through the coils? It doesn't need to be fixed in a stop position and from my limited knowledge current would be highest when the motor is not turning?

Robin2

#1
Mar 04, 2018, 02:28 pm Last Edit: Mar 04, 2018, 02:29 pm by Robin2
Now for the basic questions. I understand that the set up runs once and the loop runs, well like a loop! This doesn't sound good as I want to just press a button and the chuck turn once, but of course repeatable on the next button press.
If I have a loop looking at the state of the button, how do I program the motor to turn a set number of revs then stop until the button is pressed again?
You do that by having a variable that is changed when the button is pressed and changed again when the move finishes - so that it won't repeat until the button changes it again.

Have a look at the code in the second example in this Simple Stepper Code.

Also have a look at this recent Thread which has a somewhat similar requirement in terms of motor movements.

...R
Stepper Motor Basics

also look up the AccelStepper library

Two or three hours spent thinking and reading documentation solves most programming problems.

JohnLynn

#2
Mar 06, 2018, 04:09 am Last Edit: Mar 06, 2018, 07:02 am by JohnLynn
Thank you very much for pointing me in the right direction. I learned quite a bit by trying to correct the code in your second example.

I have my miniature mock up running by combining bits of the examples for button and stepper. It seems to work but could you please check and comment on what I am using:

Code: [Select]
const int buttonPin = 2;
int ledPin =  13;
int buttonState = 0;
#include <Stepper.h>
#define STEPS 200
Stepper stepper(STEPS,8,9,10,11);

void setup() {
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT);
}

void loop() {
buttonState = digitalRead(buttonPin);
if (buttonState == HIGH) {
    digitalWrite(ledPin, HIGH);
    stepper.setSpeed(60);
stepper.step(1000);
delay(2000);}
  else {
    digitalWrite(ledPin, LOW);}
  }


This just makes the motor spin five revolutions at 60 rpm, I added a 2 second delay at the end.
Unfortunately I do not know what is needed after led pin low so I did not add anything. Although I have tried a "ready" led on pin 12.
I am not sure if I will need anti "bounce" measures for the button.

The driver that I buy will match the motor that I use and I expect it will have settings for limiting the current. However is it possible to have all motor pins set equally after a sequence? As I will not need the motor to be held locked when stationary.
Could I use the "else" section to drive all motor pins high or low when the button is not pressed?

Robin2

The driver that I buy will match the motor that I use and I expect it will have settings for limiting the current. However is it possible to have all motor pins set equally after a sequence? As I will not need the motor to be held locked when stationary.
Could I use the "else" section to drive all motor pins high or low when the button is not pressed?
Specialized stepper drivers need very different Arduino commands compared to your L298. They just need one pin to produce a pulse for every step and another pin to determine direction. And they usually have an enable pin that can be used to de-power the motor.

I don't think there is anything to be gained by exploring your requirement with the L298 because of the all the later changes that will be needed. I suggest you get a Pololu DRV8825 stepper driver for use with your existing motor for learning purposes.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

JohnLynn

Good advice thank you, I am pleased that I waited for your response as I was about to order a couple of Pololu A4988 drivers.

Just out of interest is it possible to drive the step pins all high or low when the motor is stationary or is that impossible as they are already used in the step function with two high and two low when the motor has stopped.

Robin2

Just out of interest is it possible to drive the step pins all high or low when the motor is stationary or is that impossible as they are already used in the step function with two high and two low when the motor has stopped.
With a driver like the L298 that is certainly possible.

With an A4988 or DRV8825 you don't have direct control of the power to the motor.

I suggest you think carefully about the idea of de-powering your stepper motor. Once you do that you have no guarantee that you know where it is. Even if no external force moves the motor when it is re-powered it might decide to jump one step forwards or backwards to align with whichever pole is most convenient.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

JohnLynn

My DRV8825 has arrived, I am surprised at the size difference between the 8825 and my original L298 module.
I have blatantly copied other people's work to end up with what I hope will suit my needs for the positioner.
I can understand what you are saying about de-powering but I think in this case it would be an advantage as the chuck could be turned by hand. It doesn't matter where the chuck starts, just that it completes a revolution to give a neat welded seam on say a pipe.

The code below drives my mock up motor a set number of turns then stops with the coils powered up as usual. I have connected a "ready" LED which can also be connected to the "enable" pin on the 8825 after a delay. This seems to work on my small scale testing.

I hope that you don't mind having a quick look at what I have done and pointing out any glaring errors:

Code: [Select]
#define DISTANCE 8000

int StepCounter = 0;
int Stepping = false;
int readyPin = 12;
int buttonState = 0;
int buttonPin = 2;

void setup() {               
  pinMode(8, OUTPUT);   
  pinMode(9, OUTPUT);
  pinMode(readyPin, OUTPUT);
  digitalWrite(8, LOW);
  digitalWrite(9, LOW);

  pinMode(2,INPUT);
}

void loop() {
buttonState = digitalRead(buttonPin);
 
  if (digitalRead(2) == HIGH && Stepping == false)
  {
    Stepping = true;
  }

  if (Stepping == true)
  {
    digitalWrite(9, HIGH);
    delay(1);         
    digitalWrite(9, LOW);
    delay(1);

    StepCounter = StepCounter + 1;

    if (StepCounter == DISTANCE)
    {
    StepCounter = 0;
    delay(10000);
    Stepping = false;
  }
}
if (Stepping == true) {
    digitalWrite(readyPin, LOW);
}
else {
    digitalWrite(readyPin, HIGH);
    }
}


Robin2

I am not good at examining code without testing it.

This is the only point that occurs to me
Code: [Select]
buttonState = digitalRead(buttonPin);
 
  if (digitalRead(2) == HIGH && Stepping == false)


The second line should be
Code: [Select]
  if (buttonState == HIGH && Stepping == false)

The way you have it the actual decision is based on a separate reading of the buttonPin and might have a different value to buttonState.

And digitalRead(buttonPin) is a much better style than digitalRead(2)

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

Paul_KD7HB

#8
Mar 11, 2018, 05:29 pm Last Edit: Mar 11, 2018, 05:32 pm by Paul_KD7HB
You can easily use the ENABLE pin of the controller set LOW to let the table turn free with no other changes. Set back HIGH to continue normal operation.

Paul

added: In fact this is how I use that controller on a coil winder to let the operator solder wires after the coil is wound and before they take the coil off the spindle. Use a foot switch to tell the Adruino to set the ENABLE pin low. Switch up, set the pin HIGH.

JohnLynn

Thank you for all your help. Perhaps I should have stopped once I have what I wanted but I wondered if it would be possible to control the speed with a potentiometer whilst retaining the other features.

I found an example which controls the speed but have straggled massively when trying to combine this with what I already have.

This is my best attempt so far after several hours of trial and mainly error. This seems to work when it feels like it but does not complete the set number of rotations and seems to have a mind of it's own.

Code: [Select]
#define DISTANCE 4000
int StepCounter = 0;
int Stepping = false;
int readyPin = 12;
int buttonState = 0;
int buttonPin = 2;
int stepPin = 9;
int dirPin = 8;
int customDelay, customDelayMapped;

void setup() {
  pinMode(9, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(readyPin, OUTPUT);
  digitalWrite(8, LOW);
  digitalWrite(9, LOW);
  pinMode(2, INPUT);
}
void loop() {
  buttonState = digitalRead(buttonPin);
  if (buttonState == HIGH && Stepping == false)
  {
    Stepping = true;
  }
  if (Stepping == true)
  {
    digitalWrite(9, HIGH);
    delay(customDelayMapped);
    digitalWrite(9, LOW);
    delay(customDelayMapped);
    StepCounter = StepCounter + 1;
    if (StepCounter == DISTANCE)
    {
      StepCounter = 0;
      delay(5000);
      Stepping = false;
    }
  }
  if (Stepping == true)
  {
    digitalWrite(readyPin, LOW);
  }
  else
  {
    digitalWrite(readyPin, HIGH);
  }
}

int speedUp()
{
  int customDelay = analogRead(A0);
  int newCustom = map(customDelay, 0, 1023, 1, 10);
  return newCustom;
}

zeus2kx

Why don't you try AccelStepper library? It will make things easier for you.
For speed control, you can apply similar idea from example 5.

Robin2

Thank you for all your help. Perhaps I should have stopped once I have what I wanted but I wondered if it would be possible to control the speed with a potentiometer whilst retaining the other features
Controlling the speed of a stepper motor just means altering the value of the variable that represents the interval between steps.

I notice in your code in Reply #9 that you have
Code: [Select]
int customDelay, customDelayMapped;
and later
Code: [Select]
int speedUp()
{
  int customDelay = analogRead(A0);

It is very confusing to use the same name for two different variables.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

JohnLynn

#12
Mar 13, 2018, 12:34 pm Last Edit: Mar 13, 2018, 12:48 pm by JohnLynn
Thanks once again for your hints, I deleted the first custom delay then realised that I wasn't reading the speed up function properly for the mapped custom delay so I added the line in the loop and it does seem to work a treat.

I must draw out the wiring diagram before I forget!

Edit thanks to zeus2kx as well, unfortunately I had managed to make some progress before I read your post. I will look at the link as always keen to learn

Go Up