Go Down

Topic: Controlling a big stepper motor (Read 4942 times) previous topic - next topic

Robin2

Exactly like this.
Only the pins are different.
ALWAYS post a diagram that shows exactly how YOUR parts are connected.

The business of making the diagram of your own system can identify faults.

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

zeus2kx

That's the plan for current control using enable.
I looked into the manual, I didn't find anything besides

Quote
5. Off-line Function (EN Terminal):
If you turn on the Off-line function, the motor will enter a free state. You can adjust
the motor shaft freely, and the pulse signal will be no response. If you turn it off, it will be
back into automatic control mode
Note: Generally, EN terminal is not connected.

zeus2kx

ALWAYS post a diagram that shows exactly how YOUR parts are connected.

The business of making the diagram of your own system can identify faults.

...R
Sure will do that.

zeus2kx

It'll work.  :)
TB6600 didn't help.
I switched to ST-M5045 and I see things are moving.

zeus2kx

#34
Mar 01, 2018, 10:25 pm Last Edit: Mar 01, 2018, 10:25 pm by zeus2kx
Some update:
I am trying to combine example 4 and 7 from this tutorial.

Basic idea is to control my big motor through buttons (local control) as well as from serial.
Logic is: If serial is available, send instructions through serial, otherwise use local control.
Both examples I adapted are working. However there is a slight change in the example 7. But this is WORKING independently.
Code: [Select]
#include <AccelStepper.h>

AccelStepper stepper(AccelStepper::DRIVER, 6, 5);

int spd = 1000;    // The current speed in steps/second
int sign = 1;      // Either 1, 0 or -1

void setup()
{  
  Serial.begin(9600);
  stepper.setMaxSpeed(500);
  stepper.setSpeed(500);    
}

void loop()
{  
  char c;
  if(Serial.available()) {
    c = Serial.read();
    if (c == 'f') {  // forward
      sign = 1;
    }
    if (c == 'r') {  // reverse
      sign = -1;
    }
    if (c == 's') {  // stop
      sign = 0;
    }
    if (c == '1') {  // super slow
      spd = 50;
    }
    if (c == '2') {  // medium
      spd = 100;
    }
    if (c == '3') {  // fast
      spd = 500;
    }
    stepper.setSpeed(sign * spd);
    
  }
stepper.runSpeed();
}


After I combined both codes, bottons are working correctly however the serial control (example 7 and above) is failing.
Code:
Code: [Select]
#include <AccelStepper.h>
AccelStepper stepper(AccelStepper::DRIVER, 6, 5);
int spd = 1200;
char c;
int sign = 1;
int flag=0;

#define  LEFT_PIN  8
#define  RIGHT_PIN 9
// Define our analog pot input pin
#define  SPEED_PIN 0

// Define our maximum and minimum speed in steps per second (scale pot to these)
#define  MAX_SPEED 1200
#define  MIN_SPEED 200

void setup() {
  // The only AccelStepper value we have to set here is the max speeed, which is higher than we'll ever go
  stepper.setMaxSpeed(10000.0);
  // Set up the three button inputs, with pullups
  pinMode(LEFT_PIN, INPUT_PULLUP);
  pinMode(RIGHT_PIN, INPUT_PULLUP);
  digitalWrite(LEFT_PIN, HIGH);
  digitalWrite(RIGHT_PIN, HIGH);
  Serial.begin(9600); //Open Serial connection for debugging
  stepper.setMaxSpeed(1200);
  stepper.setSpeed(1200);
}

void loop() {
   if(Serial.available()) {
      c = Serial.read(); //Read user input and trigger appropriate function
     if (Serial.find("s")) {
        spd = Serial.parseInt();
/*        Serial.print("Step number: " );
        Serial.print(spd);*/
        // for example: "s5\n":
      }
      if (c == 'f') {  // forward
      sign = 1;
      }
      if (c == 'r') {  // reverse
        sign = -1;
      }
      if (c == 's') {  // stop
        sign = 0;
      }
      if (c == '1') {  // super slow
        spd = 500;
      }
      if (c == '2') {  // medium
        spd = 1000;
      }
      if (c == '3') {  // fast
        spd = 1200;
      }
/*      else
      {
        Serial.println("Invalid option entered.");
      }*/
stepper.setSpeed(sign * spd);
Serial.print(spd);
stepper.runSpeed();
}
else {
  static float current_speed = 0.0;         // Holds current motor speed in steps/second
  static int analog_read_counter = 1000;    // Counts down to 0 to fire analog read
  static char sign = 0;                     // Holds -1, 1 or 0 to turn the motor on/off and control direction
  static int analog_value = 0;              // Holds raw analog value.
 
  // If a switch is pushed down (low), set the sign value appropriately
  if (digitalRead(LEFT_PIN) == 0) {
    sign = 1;
  }
  else if (digitalRead(RIGHT_PIN) == 0) {
    sign = -1;
  }
  if ((digitalRead(LEFT_PIN) == 1) && digitalRead(RIGHT_PIN) == 1)
  {
    sign = 0;
  }
   
  if (analog_read_counter > 0) {
    analog_read_counter--;
  }
  else {
    analog_read_counter = 3000;
    analog_value = analogRead(SPEED_PIN);
    stepper.runSpeed();
    current_speed = sign * (((analog_value/1023.0) * (MAX_SPEED - MIN_SPEED)) + MIN_SPEED);
    stepper.setSpeed(current_speed);
  }

 stepper.runSpeed();

}
  }




I will be very thankful if I receive any help.

Thanks.

Robin2

I will be very thankful if I receive any help.
You have posted two programs in Reply #34. What is the difference between them and which one do you need help with?

I don't plan to wade through 7 examples on some other website. Sorry.

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

zeus2kx

The first program is for serial control of the motor. Just to add, this code works.

Second program is the combined code where I need help.
This program includes the first.
Issue I have is, the second program is not controlling the motor through serial.

I hope I explained this time properly. Thanks Robin.

Robin2

It seems to me your
Code: [Select]
if(Serial.available()) {

}
else {

}

can't work because as soon as the Serial Input Buffer is empty it will go back to the ELSE. But having the buffer empty does not mean that serial control should end.

What are the circumstances in which the system should switch from one control system to the other?

What is the purpose of this
Code: [Select]
        if (Serial.find("s")) {
            spd = Serial.parseInt();
    /*        Serial.print("Step number: " );
            Serial.print(spd);*/
            // for example: "s5\n":
        }


Have a look at the examples in Serial Input Basics - simple reliable ways to receive data. There is also a parse example to illustrate how to extract numbers from the received text.

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

zeus2kx

What are the circumstances in which the system should switch from one control system to the other?
I would prefer not to switch control depending on availability of serial, rather on engagement.
For example, if serial command is sent, buttons shouldn't work. And if buttons are in use, a different user shouldn't be able to send commands through serial.
Please help me with this.

What is the purpose of this
Code: [Select]
        if (Serial.find("s")) {
            spd = Serial.parseInt();
    /*        Serial.print("Step number: " );
            Serial.print(spd);*/
            // for example: "s5\n":
        }


Have a look at the examples in Serial Input Basics - simple reliable ways to receive data. There is also a parse example to illustrate how to extract numbers from the received text.
This is for parsing so that user can give spd value though commands.
Once the idea works, I will improve parsing using your tutorial.

Thanks a lot Robin.

Robin2

I would prefer not to switch control depending on availability of serial, rather on engagement.
For example, if serial command is sent, buttons shouldn't work. And if buttons are in use, a different user shouldn't be able to send commands through serial.
Please help me with this
You need to do some hard thinking about this to sort out precisely how you want things to work.

A serial command tends to be a single event even if it will in due course be followed by another serial command. Maybe you need to check for the time between serial commands and only change to the other system if the interval is too long. Or maybe there should be a special serial command that conveys the message "ok to switch to buttons"

On the other side, how will you know that the buttons are no longer in use and that it is OK to accept serial commands?

This is really a problem of logic rather than of program code.

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

zeus2kx

#40
Mar 02, 2018, 11:34 am Last Edit: Mar 02, 2018, 01:14 pm by zeus2kx
On the other side, how will you know that the buttons are no longer in use and that it is OK to accept serial commands?

This is really a problem of logic rather than of program code.

...R
Using local control - motor only rotates when button is pressed.
Logic can be to check the state of left and right buttons.
On the other hand, I can give priority to local control. Let's say a left or right button to disengage serial commands before rotating the motor.
This I will deal with in later stages.
Please help me with serial first.


Robin2

#41
Mar 02, 2018, 01:36 pm Last Edit: Mar 02, 2018, 01:39 pm by Robin2
.On the other hand, I can give priority to local control. Let's say a left or right button to disengage serial commands before rotating the motor.
This I will deal with in later stages.
Please help me with serial first.
You have not said how the system will know that local control is finished and serial commands can be accepted.

And I don't understand what you mean by "help me with serial first" because IIRC you already have a program that works with serial commands.

...R

PS ... Responding to my Reply #39 after 6 minutes does not show evidence of hard thinking :)
Two or three hours spent thinking and reading documentation solves most programming problems.

zeus2kx

#42
Mar 02, 2018, 02:13 pm Last Edit: Mar 02, 2018, 04:23 pm by zeus2kx
Hi Robin,
No my combined code is not working. I will try to explain.
At this stage, I am looking for a simple solution for serial and local control in parallel. In parallel means, a user will only use local or serial once.

To this end, I have two working separate codes - one for serial and another for local. Just to repeat, both of these individual codes are working.

Now when I combine both, I see that only local control part of the combined code is working.

Please help me figure out the problem with serial control.

Combined code:
Code: [Select]
#include <AccelStepper.h>
AccelStepper stepper(AccelStepper::DRIVER, 6, 5);
int spd = 1200;
char c;
int sign = 1;
int flag=0;

#define  LEFT_PIN  8
#define  RIGHT_PIN 9
// Define our analog pot input pin
#define  SPEED_PIN 0

// Define our maximum and minimum speed in steps per second (scale pot to these)
#define  MAX_SPEED 1200
#define  MIN_SPEED 200

void setup() {
  // The only AccelStepper value we have to set here is the max speeed, which is higher than we'll ever go
  stepper.setMaxSpeed(10000.0);
  // Set up the three button inputs, with pullups
  pinMode(LEFT_PIN, INPUT_PULLUP);
  pinMode(RIGHT_PIN, INPUT_PULLUP);
  digitalWrite(LEFT_PIN, HIGH);
  digitalWrite(RIGHT_PIN, HIGH);
  Serial.begin(9600); //Open Serial connection for debugging
  stepper.setMaxSpeed(1200);
  stepper.setSpeed(1200);
}

void loop() {
   if(Serial.available()) {
      c = Serial.read(); //Read user input and trigger appropriate function
     if (Serial.find("s")) {
        spd = Serial.parseInt();
/*        Serial.print("Step number: " );
        Serial.print(spd);*/
        // for example: "s5\n":
      }
      if (c == 'f') {  // forward
      sign = 1;
      }
      if (c == 'r') {  // reverse
        sign = -1;
      }
      if (c == 's') {  // stop
        sign = 0;
      }
      if (c == '1') {  // super slow
        spd = 500;
      }
      if (c == '2') {  // medium
        spd = 1000;
      }
      if (c == '3') {  // fast
        spd = 1200;
      }
/*      else
      {
        Serial.println("Invalid option entered.");
      }*/
stepper.setSpeed(sign * spd);
Serial.print(spd);
stepper.runSpeed();
}
else {
  static float current_speed = 0.0;         // Holds current motor speed in steps/second
  static int analog_read_counter = 1000;    // Counts down to 0 to fire analog read
  static char sign = 0;                     // Holds -1, 1 or 0 to turn the motor on/off and control direction
  static int analog_value = 0;              // Holds raw analog value.
  
  // If a switch is pushed down (low), set the sign value appropriately
  if (digitalRead(LEFT_PIN) == 0) {
    sign = 1;
  }
  else if (digitalRead(RIGHT_PIN) == 0) {
    sign = -1;
  }
  if ((digitalRead(LEFT_PIN) == 1) && digitalRead(RIGHT_PIN) == 1)
  {
    sign = 0;
  }
  
  if (analog_read_counter > 0) {
    analog_read_counter--;
  }
  else {
    analog_read_counter = 3000;
    analog_value = analogRead(SPEED_PIN);
    stepper.runSpeed();
    current_speed = sign * (((analog_value/1023.0) * (MAX_SPEED - MIN_SPEED)) + MIN_SPEED);
    stepper.setSpeed(current_speed);
  }

 stepper.runSpeed();

}
  }




For the next step:

You have not said how the system will know that local control is finished and serial commands can be accepted.

I can simply check if left or right button state is HIGH or LOW.
Based on that I can say whether local control is active.

This time I took 30 mins  :smiley-grin:

Robin2

For the next step:
I can simply check if left or right button state is HIGH or LOW.
Based on that I can say whether local control is active.
 
I suspect you are missing my point altogether.

You cannot have the 2 systems in the same program without having a comprehensive arrangement for deciding which one is in use at any one time.

What you have at the moment is the equivalent of two actors on stage with a screen between them and each one reading a word at a time from the scripts for 2 different plays. What the audience hears is just a jumble of words.

One solution might be to have a toggle switch that is detected by one of the Arduino I/O pins. If the switch is thrown one way the buttons are used. If it is thrown the other way the serial commands are used. That would be the equivalent of the director telling one actor to speak and the other guy to shut up.

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

zeus2kx

wow, I just finished doing what you wrote.
I used a simple on/off switch I had for the switching between the two modes.

Go Up