Assistance (help) needed - Stepper motors, buttons combined

Hi!

I am trying to do a project - it's actually part of my thesis on the university.
The basics:

  • I'd like to control two stepper motors (I have two Nema23s).

  • Each of them move an installment in one direction forwards and backwards. - Basically a special XY-table.

  • The motors have to move the table in a special motion.

  • Go along one axis with little pauses in between,

  • one step along the secondary axis,

  • then come back along the primary axis.

  • One step along the secondary axis again, the same direction as before, etc.

  • You get the idea, I hope. Like a sweep.

  • The sweep has pauses, which are for ultrasonic measurements to be done (that's why I have the time intervals set up at the beginning of th ecode) - not part of my thesis.

  • After completing the sweep, the table needs to return to its original position.
    I need to run this only once per power cycle - as I don't need the installment to run around like a maniac - so I put my code in the setup() section.

For the buttons: I'd like to use three buttons, functions below:

  • One to move the installment - as long as pressed - along the primary axis (opposite direction) to setup a starting position along the primary axis.
  • One to move the installment along the secondary axis. Goal: same as the one above.
  • One to start the sweep (described above).

I am getting a bit confused how to do this, because every example I read about buttons and their usage used the buttons in the loop() section as their status needs to be checked repeatedly.

How can I get a basic loop for checking the buttons' status inside the setup() phase?

Project code in attached .txt file.
(The code would be too long to post here in "code" . Will try writing a procedure for movement to call in the setup() - e.g.: moveX(), moveY(), etc.)
Forgive me if any of the lines are not understandable, I had to translate the comments from Hungarian to English.

Thanks a lot for all the help in advance!
Cheers,
MacTavish

XY-axis.txt (4.79 KB)

I have two Nema23s

Before you make that claim, perhaps you ought to look up exactly what the NEMA 23 specification defines.

I am getting a bit confused how to do this, because every example I read about buttons and their usage used the buttons in the loop() section as their status needs to be checked repeatedly.

So, why don't you? You could have:

bool areWeThereYet = false;

void setup()
{
}

void loop()
{
   if(!areWeThereYet)
   {
      // Move the table, checking the limit switches
      if(bothLimitSwitchesPressed)
      {
         areWeThereYet = true;
      }
   }
}

How can I get a basic loop for checking the buttons' status inside the setup() phase?

By replicating the loop() functionality. But that is needless as it is easy to count how many times something has been done, and do nothing once the count reaches 1.

PaulS:
Before you make that claim, perhaps you ought to look up exactly what the NEMA 23 specification defines.

Okay, rephrase: I got two bipolar stepper motors with 1.2 Nm of torque, with dimensions of 57 by 57 by 56 mm. The motor needs 2.8 A of current and 2.5V of voltage, one step is 1.8°.

PaulS:
So, why don't you? You could have...

Because I thought that if the main code is in the setup() I shouldn't put the codes for the buttons in the loop() as it is done AFTER the setup().

I think I can do the code for the motion initiated by button-press but I would have to press the button a lot of times to get the thing where I want it, instead of push-go-push-stop behaviour. I think.

I am a novice in programming, so maybe I am thinking the wrong way...
I am definitely not trying to make other people do MY work, so no need for any hostility. (At least I felt it that way.) I want to figure things out by myself, it's just that I need sometimes a little guidance or a little push in the right direction.
Thanks for the understanding. (This was definitely no whining. :D)

I am definitely a novice in programming, so maybe I am thinking the wrong way...

I think that you are. You put stuff in setup() that happens once - like initializing the serial port. You put stuff in loop that happens over and over, like moving stepper motors, checking limit switches, etc.

That stuff is only to be done while some limit condition (are we there yet?) has not been met is a triviality that I showed how to deal with.

What is your field of study? When I graduated 36 years ago, I could program computers by the end of my freshman year. I don't understand why today's students get to be seniors without learning something about computer programming. I don't like using magic, and that's what computers are unless you understand how to make the magic happen.

I know that stuff in the setup() run only once, that's why I put it there, and that's why I mentioned it in the topic starter that I only need to run the installment ONCE. Not running around till the end of time.

Field of Study: Food Engineering, just as it is visible below the blank profile picture, below "Karma:0", etc.

I studied programming some semesters ago, but it was only an introdutory class. In fact it could have been called "Programming 101". But it wasn't. I studied food chemistry, chemical engineering, process management, etc.

I only need to run the installment ONCE.

But "run the installment" is not a discrete event, like turning an LED on. "Run the installment" is a series of steps - move left and right, move forward and backwards, check limit switches, etc. - that are done zero or one at a time on any given pass through loop().

I studied food chemistry, chemical engineering, process management, etc.

I'm not saying that you are an idiot, by any means. I just can't imagine how any kind of comprehensive food chemistry class, any chemical engineering class, or any process management class can fail to include computers, and I can't imagine not wondering "how do they do that and can I do it better". I guess that's why I haven't done any engineering with my engineering degree. Instead, I'm a computer programmer.

So, what part(s) of the process are working/not working? Can you move the stepper motors? Can you read the limit switches? Can you determine when the process is complete?

For the buttons: I'd like to use three buttons, functions below:

One to move the installment - as long as pressed - along the primary axis (opposite direction) to setup a starting position along the primary axis.

Opposite what?

I would start with a complete set of requirements. The first requirement is that nothing happens until the start switch is pressed, so that should not be the third item in the list.

PaulS:
The first requirement is that nothing happens until the start switch is pressed, so that should not be the third item in the list.

It was just a hastily put together list. Not in working order, of course.
So, basically my code (see in first post) goes down the drain, right?

How will I stop the stuff in the loop() section from repeating itself? E.g. the installment not want to deliberately run into the sides, etc.

PaulS:
... can fail to include computers...

There were programming classes but thanks to politics, funds have been cut drastically, so there are not enough associate professors, assistant professors, professors, etc. Less money means fewer employees. And a lot less lectures, classes...

How will I stop the stuff in the loop() section from repeating itself?

Using the process I showed in reply #1.

There were programming classes but thanks to politics, funds have been cut drastically, so there are not enough associate professors, assistant professors, professors, etc. Less money means fewer employees. And a lot less lectures, classes...

Everybody loses but the politicians. Fking aholes.

PaulS:
Using the process I showed in reply #1.

No limit switches. Only distance I need covered.
100 millimeters along X-axis, 120 along Y-axis.
That's why I tried doing it with calculating how much steps I need from the stepper motors.

No limit switches. Only distance I need covered.

OK, so no physical switches. There are still limits.

Lets start with trying to get the requirements defined. You mentioned three switches. Specifically, what should each do?

Does the start switch move the carriage along the x axis until the x stop switch is pressed? Does pressing the x stop switch cause the carriage to along the y axis until the y stop switch is pressed?

Naming things helps. Instead of switch one, switch two, and switch three, refer to them by function - start, define x travel, define y travel, etc.

Thanks again, for helping me!
If I forgot to mention, I have momentary push-button switches. (I hope I got the proper name for them. I press it, it clicks, but jumps right back up. Looks like this.

Start Switch: It should enable running the carriage program. (The Carriage Program (CP) will be used to move the carriage below the ultrasound sensor.) I thought of only one start switch, like a Main Start button.

PosX: To define the starting position of Carriage-X before running CP. Figured it would be a movement opposite to the direction X-wise CP will start to.

PosY: To define the starting position of Carriage-Y before running CP. Opposite to the direction Y-wise where CP will head to.

Stop Switch: To stop all things immediately, like an emergency stop. (Actual position would be nice if it could be stored to continue it from.)

PosX and PosY buttons: opposite of future movements, in case something caused the carrages to stop, so I can move them back to a position what is acceptable to star the run again.

Start Switch: It should enable running the carriage program. (The Carriage Program (CP) will be used to move the carriage below the ultrasound sensor.) I thought of only one start switch, like a Main Start button.

If you connect the switch to a digital pin, say 5, and ground:

const byte startPin = 5;
bool beenThereDoneThat = false;

void setup()
{
   pinMode(startPin, INPUT_PULLUP);
}

void loop()
{
   if(digitalRead(startPin) == LOW)
   {
      if(!beenThereDoneThat)
      {
         RunProgram();
         beenThereDoneThat = true;
      }
   }
}

So, all that is left to do is write the RunProgram() function.

PosX: To define the starting position of Carriage-X before running CP. Figured it would be a movement opposite to the direction X-wise CP will start.

You've said that nothing is to happen before RunProgram() is called, and that happens only when the start switch is pressed. So it is unreasonable to talk about something happening before the program is run, with respect to the x position switch.

We're talking, but we are not communicating. Perhaps you can try again to get through to me.

Is the start switch supposed to trigger something besides calling the RunProgram() function? Is it supposed to start something moving?

How is the initial position of the carriage defined? How does the Arduino know how far to move the carriage in the X direction? How does it now when to start moving it in the X direction? How does it know when to stop moving it in the X direction?

When it gets done with the initial move(s) in the X direction, how does it know when to start moving in the Y direction?

PaulS:
Is the start switch supposed to trigger something besides calling the RunProgram() function? Is it supposed to start something moving?

It should only start the moving. I mean literally.

How does the Arduino know how far to move the carriage in the X direction?

I got exact distances: the sample tray is 100 mm by 120 mm. So in the X dir it is 100 mm

How does it now when to start moving it in the X direction?

When I press the Start Switch, wait for example 2 seconds, then start going.
100 mm movement along X (in smaller steps, like 20 times 5 mm steps). Stop. 5 mm movement along Y. Stop. 20x5 mm movement along X, backwards. Stop. Another 5 mm along Y.

How does it know when to stop moving it in the X direction?

From the distance it moved.

When it gets done with the initial move(s) in the X direction, how does it know when to start moving in the Y direction?

Like above. When the exact X-distance is driven (100 mm) it should stop. Move along Y. Stop at the given distance (5 mm).

Am I getting through? :smiley: Am I doing this right? :slight_smile: Or is distance a bit difficult to measure from rotation?

@MacTavish, it may be helpful to have a look at the early part of Planning and Implementing a Program (and at all of it, for preference) as it may help you to describe the sequence of events - both for yourself and for us.

I think you are falling into a common trap of assuming a computer program is "sensible" when in fact it is grossly stupid. You have to describe every detail and take special account of situations that should not be allowed to happen. In order to do that you have to be very clear in your own mind about what should happen. Time spent writing down (in English, not code) exactly what should happen will be a great investment. With it you will have perhaps 70% or more of the intellectual effort completed.

...R

I'm still missing something. If the start switch is to start the carriage moving, along x for some number of steps, then along y for some number of steps, then along -x for some number of steps, then move along y for some number of steps, repeating until the end of the x travel and the end of the y travel have happened, what are the PosX and PosY switches supposed to do?

Once I understand what PosX and PosY are to do, the rest seems pretty simple. The start switch can change roles, once the process is started, causing it to resume if stopped. Or, the stop switch can be a pause/continue switch instead.

Robin2:
@MacTavish, it may be helpful to have a look at the early part of Planning and Implementing a Program (and at all of it, for preference) as it may help you to describe the sequence of events - both for yourself and for us.

Thank you, I will read it through and try to apply it into practice.

PaulS:
what are the PosX and PosY switches supposed to do?

Once I understand what PosX and PosY are to do, the rest seems pretty simple. The start switch can change roles, once the process is started, causing it to resume if stopped. Or, the stop switch can be a pause/continue switch instead.

Pause/Continue looks better. Definitely.

PosX and PosY: I just thought of them as an option to reposition the carriage, if some Error should come up and suddenly the movement should stop. After restarting the Arduino I could resposition the carriage to start from the beginning. As the drive is achieved by a trapeze screw (which is the shaft of the stepper motor. I hope I get the name right, or at least you know what I'm trying to say) and a nut (fastened to the carriege) on the screw the only option to move it backwards is by the motor to turn the shaft.

PosX and PosY: I just thought of them as an option to reposition the carriage, if some Error should come up and suddenly the movement should stop. After restarting the Arduino I could resposition the carriage to start from the beginning. As the drive is achieved by a trapeze screw (which is the shaft of the stepper motor. I hope I get the name right, or at least you know what I'm trying to say) and a nut (fastened to the carriege) on the screw the only option to move it backwards is by the motor to turn the shaft.

So, these would be independent of starting and stopping the automatic motion.

I would have the start switch be a start/abort switch. Press once to start the process. Press again to abort the run.

I would have the 4th switch be a pause/continue switch which would pause or resume the automatic process.

This is why the code belongs in loop(). The start switch has different roles, depending on state (start, abort). The pause switch has different roles, depending on state (pause, resume, nothing).

The PosX and PosY switches have different roles, depending on state (move the carriage in the -x direction or do nothing; move the carriage in the -y direction or do nothing).

So, you have a bunch of states - waiting to start, running, paused, done.

You have 2 switches to switch between the 4 states.

You have 2 independent states/switches - to move the carriage "manually".

So, on any given pass through loop(), you read the state of all 4 switches. You do something based on the state, that may have changed depending on the state of a switch.

This should give you some idea how to start.

bool running = false;
bool paused = false;

void loop()
{
  int moveX = digitalRead(jogXPin);
  int moveY = digitalRead(jogYPin);

  int startStop = digitalRead(startStopPin);
  int pauseContinue = digitalRead(pauseContinuePin);

  // If running, and the start/abort switch is pressed, stop running
  if(running)
  {
     if(startStop != lastStartStop)
     {
        // The startStop pin changed state
        if(startStop == HIGH)
        {
           running = false;
        }
     }
  }

  if(running)
  {
     // Determine whether to do anything, based on the change in state
     // of the pause/continue pin and the current state of the pin

     if(!paused)
     {
       // Determine if it is time to step again in the x direction,
       // based on when the last step happened and the position

       // Determine if it is time to step again in the y direction,
       // based on when the last step happened and the position

       // Determine if it is time to stop, based on x and y location
       // If it is, set running to false
     }
  }
  else // Not running, so maybe we need to jog the carriage
  {
     // If the jog x switch is pressed, and we are not at the 0 position
     // step once in the -x direction

     // If the jog y switch is pressed, and we are not at the 0 position
     // step once in the -y direction
  }

  lastStartStop = startStop;
  lastPauseContinue = pauseContinue;
}

PaulS:
So, these would be independent of starting and stopping the automatic motion.

Yes, absolutely. (I do really need to get my head to think like the post Robin2 linked...)

This should give you some idea how to start.

bool running = false;

bool paused = false;

void loop()
{
 int moveX = digitalRead(jogXPin);
 int moveY = digitalRead(jogYPin);

int startStop = digitalRead(startStopPin);
 int pauseContinue = digitalRead(pauseContinuePin);

// If running, and the start/abort switch is pressed, stop running
 if(running)
 {
    if(startStop != lastStartStop)
    {
       // The startStop pin changed state
       if(startStop == HIGH)
       {
          running = false;
       }
    }
 }

if(running)
 {
    // Determine whether to do anything, based on the change in state
    // of the pause/continue pin and the current state of the pin

if(!paused)
    {
      // Determine if it is time to step again in the x direction,
      // based on when the last step happened and the position

// Determine if it is time to step again in the y direction,
      // based on when the last step happened and the position

// Determine if it is time to stop, based on x and y location
      // If it is, set running to false
    }
 }
 else // Not running, so maybe we need to jog the carriage
 {
    // If the jog x switch is pressed, and we are not at the 0 position
    // step once in the -x direction

// If the jog y switch is pressed, and we are not at the 0 position
    // step once in the -y direction
 }

lastStartStop = startStop;
 lastPauseContinue = pauseContinue;
}

I'll try to get my head around it. Thanks a lot. (My english vocabulary is not as good as it was some yrs ago, so I had to look up some words. This slows things down a bit.)

MacTavish:
(My english vocabulary is not as good as it was some yrs ago, so I had to look up some words. This slows things down a bit.)

Wi a name lik MacTavish that must mean ye are a native Scots Gallic speaker ? :slight_smile:

...R

Robin2:
Wi a name lik MacTavish that must mean ye are a native Scots Gallic speaker ? :slight_smile:

No, unfortunately. :smiley: Hungarian.