Simultaneous loops

I’m still relatively new to programming so please bare with me but I’m trying to drive a stepper motor and get a position reading at the same time.

I’m using a TB6600 to drive the motor and an AMS5600 to read the position. Both the bits of code work seperatly but when I try run them together I just get a reading every loop of the driving code:

void loop() {

    ang(); 
    drive();
}

void ang() {

    SERIAL.println(String(convertRawAngleToDegrees(ams5600.getRawAngle()),DEC));
}

void drive()
{

  
  digitalWrite(dirPin,HIGH); // Enables the motor to move in a particular direction
  // Makes 200 pulses for making one full cycle rotation
  for(int x = 0; x < 2000; x++) {
    digitalWrite(stepPin,HIGH); 
    delayMicroseconds(spd); 
    digitalWrite(stepPin,LOW); 
    delayMicroseconds(spd); 
  }
 

  digitalWrite(dirPin,LOW); //Changes the rotations direction
  // Makes 400 pulses for making two full cycle rotation
  for(int x = 0; x < 2000; x++) {
    digitalWrite(stepPin,HIGH);
    delayMicroseconds(spd);
    digitalWrite(stepPin,LOW);
    delayMicroseconds(spd);
  }

Is there a way to get these bits of cod to run at the same time?

Thanks in advance

Is there a way to get these bits of code to run at the same time?

Yes, use 2 separate processors.

The idea is not to run them at the same time but to interleave them and run them fast enough that for all practical purposes they are running at the same time.

Study these:
Using millis for timing
Demonstration for several things at the same time

Implement what you learn for your code.
Get rid of the delays and get rid of the for loops, let loop do the looping.

The processor can only run one instruction at a time. (There are often several machine code instructions required to execute one line of C++ code and these are executed in sequence, one instruction at a time.)

If you had something like an end-position sensor you could use an interrupt to "detour" the processor from whatever it's currently doing. Then when the interrupt code is done, your program will come back to whatever it was doing before.

But in your case, it might make sense to check the position between each motor-step.

You could use an output compare pin to toggle the stepPin at your desired microseconds. Then all you would have to do is read the conversionRawAngle... part of it.

Let the timers do the work of driving the motors so your code doesn't have to. You can also disconnect
the output compare pin when you want the motors to stop.

It's quite easy to use one of the timers to drive the step signal for a motor driver. If this is an ATMega part, Timer0 is especially easy to program for that purpose.

Regards,
Ray L.

So I’ve been researching all the different ways suggested and in trying to interleave the functions I’m trying to write a Function that steps the stepper motor “stp” number of times with “spd” delay between steps in “dir” direction (CW or CCW) and this is what I came up with:

void StepStepper (int stp, int spd, word dir)           //StepStepper function "stp" number of steps, "spd" speed in "dir" direction
{
  int CW = HIGH                                    //Converts "dir"          
  int CCW = LOW
  digitalWrite(enPin,LOW);                      //Enables stepper motor
  digitalWrite(dirPin,dir);                         //Sets direction
    for(int x = 0; x < stp; x++);              //Makes a loop "stp" times long
    {
      digitalWrite(stepPin,HIGH);               //Steps stepper motor 1 step with "spd" delay
      delay(spd);
      digitalWrite(stepPin,LOW);
      delay(spd);
    }
  digitalWrite(enPin,HIGH);                     //Disables stepper motor
}

Any help would be much appreciated as I’m pretty sure this isn’t right

Once this works I’ll look into trying to implement millis() instead of delay()

I'm pretty sure this isn't right

Correct, it uses delay.

Once this works I'll look into trying to implement millis() instead of delay()

In order to get it working properly you need to use millis instead of delay. If you wait to do that until you've got it right with delay you will have a long wait.

PerryBebbington:
Correct, it uses delay.In order to get it working properly you need to use millis instead of delay. If you wait to do that until you've got it right with delay you will have a long wait.

Can I have some help or pointers as to how I might do this?

Thanks

The usual - take a look at the blink without delay example in the IDE, without delay.

Can I have some help or pointers as to how I might do this?

I deliberately did not include any additional pointers, I have already given them in reply #1. I want you to learn by thinking about the problem, thinking about the answer, trying things out and, possibly, screaming and throwing your beer at the wall then going to sleep and waking up the next morning realising how to do it (and what a sticky mess beer makes on the carpet).

I am not going to spoon feed you the answer.

PerryBebbington:
I deliberately did not include any additional pointers, I have already given them in reply #1. I want you to learn by thinking about the problem, thinking about the answer, trying things out and, possibly, screaming and throwing your beer at the wall then going to sleep and waking up the next morning realising how to do it (and what a sticky mess beer makes on the carpet).

I am not going to spoon feed you the answer.

Trust me that has actually happened :') (without the getting it work bit)

Ok but can you just tell me if I'm setting up the Function correctly?

Trust me that has actually happened :') (without the getting it work bit)

Oh! :o

Ok but can you just tell me if I'm setting up the Function correctly?

My comment was about your continued used of delay(), not about anything else. As long as you use delay() then you won't achieve this:

I've been researching all the different ways suggested and in trying to interleave the functions.

If you want to do that you have to have a different mindset. At the moment you are trying to get StepStepper to do everything in one go, that's the wrong approach. The tutorials explain it.

You already know how to do this as you do it every day in normal life.

You wouldn’t expect this when you go into a restaurant:
A waiter meets you at the door, takes you to a table, gives you a menu then waits by your table while you decide what to order. The waiter takes your order, goes to the kitchen and waits there while the chef cooks your food. When the food is ready the waiter brings it to your table then waits by your table while you eat it. When you’ve finished eating the waiter takes your plates away and returns to ask if you want anything else. This continues until you leave. No one else gets served. This is how your code is working at the moment.
I’m not going to describe what really happens in a restaurant as you already know. A waiter uses exactly the same system as a state machine to serve people when they need serving and check to see who needs serving next between dealing with customers. You can build functions for the different tasks a waiter does such as:

void takeOrder();
void bringFoodToTable();

You call these from loop(); While in loop the waiter checks to see if any tables need attention, and if they do s/he goes to find out what they need. If not, then s/he keeps checking until someone needs something. Computer code should be written along the same principals.
See Demonstration for several things at the same time for how to implement a state machine in software rather than in a restaurant.
Also look at Using millis for timing, which is also relevant as frequently millis timing and a state machine are used together.

Here is one way to “unwrap” a for loop to use with millis(). I think it is as much as I should say, given the suggestions given above:
Here is how you implement a for loop using a state machine:

for(i=3; i<6; i++) {<somecode>}

decomposes as the sequence

i=3;
while (i<6) {
<somecode>
i++;
}

For the state machine you would do something like

if (state == INITIALIZE) {
 i=3;
 state = RUN;
}
else if (state == RUN and i<6) {
 <somecode>
 i++;
}
else {
 state = IDLE;
}

To activate it, you just assert:

state = INITIALIZE;
void loop()
{
  StepStepper(1);
  ReadAng(100);
}

void StepStepper(int interval){
unsigned long currentMillis = millis();

if (currentMillis - previousMillis >= interval) 
  {
    // save the last time step was made
  previousMillis = currentMillis;

    // if the steppin is off turn it on and vice-versa:
    if (stepState == LOW) 
    {
      stepState = HIGH;
    } 
    else 
    {
      stepState = LOW;
    }

    // Make a step with the stepState of the variable:
    digitalWrite(stepPin, stepState);
    
   
  }
}
  
void ReadAng(int interval){

  unsigned long currentMillis = millis();

if (currentMillis - previousMillis >= interval) 
  {
  previousMillis = currentMillis;
  
  SERIAL.println(String(convertRawAngleToDegrees(ams5600.getRawAngle()),DEC));
  }
  }

Ok . . . so we're here

Both functions work independently but when both are put in the loop() it only drives the stepper!!!

Surly I deserve some pointers now :smiley:

It is only dumb luck that the stepper is stepping at all. Your currentMillis variables are local to each function. Each one is created when you call each function, and discarded when you return from the function. They need to be two, separate either global, or static, variables, so they retain their values between calls the the functions.

Regards,
Ray L.

RayLivingston:
It is only dumb luck that the stepper is stepping at all. Your currentMillis variables are local to each function.

Err…
So?
In that case, a common “previous” variable is more of a problem because “current” is now.
But we can’t see all the code.

The AccelStepper library is a non-blocking library for controlling steppers, you'd probably benefit from checking it out.

All you code needs to be 'non-blocking' to achieve 'concurrency'. Good search terms for you...

TheMemberFormerlyKnownAsAWOL:
Err..
So?
In that case, a common "previous" variable is more of a problem because "current" is now.
But we can't see all the code.

Oops! I FUBAR'ed. Yes, previousMillis() is the problem. I got interrupted mid-post and my train of thought de-railed....

Regards,
Ray L.

You are on the right lines.

Maybe I have not woken up properly this morning but I don't see where previousMillis is declared at all!

previousMillis should be static and declared at the start of each function, otherwise, as Ray says, it loses its value between function calls.

RayLivingston:
It is only dumb luck that the stepper is stepping at all. Your currentMillis variables are local to each function. Each one is created when you call each function, and discarded when you return from the function. They need to be two, separate either global, or static, variables, so they retain their values between calls the the functions.

Regards,
Ray L.

When I try taking unsigned long currentMillis = millis(); out of the function and putting it at the beginning it doesn’t work.

Could you explain or point me in the right direction as to how I’d create two, separate either global, or static, variables?

Also even when I set the interval to 1 it doesn’t stall the motor whereas when using delay I’d need around 500 for it to run

Thanks