millis in a function

I suggest starting with another sketch that gets some Serial Monitor event working like you wish (frequency and timing). Once you figure out how to time your actions, you can add that back to your sketch.

Mashley:
I think I am going to restructure the program trying to put everything in the main loop in functions other than the millis section.

Good idea. It would take me ages to make any sense of the existing code.

Think about putting the tests as to whether a function should operate inside the function itself rather than in the code that calls the function. For example if a button state variable has a certain value, or if time has elapsed.

Do all the button reads in one place - don’t scatter them through the code. loop() repeats so fast that there will be no noticeable delay.

Leave all the LCD stuff out until you have the rest of it working - it will make the code much shorter and easier to debug.

…R

suggest starting with another sketch that gets some Serial Monitor event working like you wish (frequency and timing). Once you figure out how to time your actions, you can add that back to your sketch.

So I have gone and made a done as was suggested and written it in it’s own sketch and it seem to kind of work. I realised that using millis in a for loop was useless as it does not wait till currentmillis is the correct value before moving on it just keeps going through very quickly and the counter is incremented each time. I have since placed it in a while loop and incrementing i each step.

The problem I am getting now is that I get about 10 increments of i each step. Has anyone seen this before and if so was there a solution?

Thanks,

Matt

millis_function.ino (1.89 KB)

Has anyone seen this before

Of course. With no delay() (that's a good thing), on several iterations of the function, Currentmillis will equal Previousmillis.

What you need to do is a create a couple of flags: bool beenThere = false; bool doneThat = false;

Set one of the flags (beenThere) to true when the time is right. Set the other flag (doneThat) to true when the action has been performed. Set both flags to false whenever the time is not right.

Actually perform the action only when the doneThat flag is false.

Mashley:
So I have gone and made a done as was suggested and written it in it’s own sketch and it seem to kind of work.

Now that things are a little clearer it looks like you are trying to control a stepper motor through a series of coil sequences.

First BIG question - why not save yourself all the hassle and use the AccelStepper library ?

If you insist on the DIY approach I would go at it differently.

You have 4 small functions for the 4 different sequences and (presumably) they need to be used one after the other 12341234123 etc

But all your main code needs to be concerned with is whether it is time to make the next step. Leave it to a motorStep() function to figure out which sequence is required. Something like this

void motorStep() {
  static byte seqNum = 0;
  if (seqNum == 0) {
    mm1();
  }
  else if seqNum == 1 {
    mm2();
  }
  else if seqNum == 2 {
     mm3();
   }
  else {
      mm4();
   }
   seqNum ++;
   if (seqNum > 3) {
       seqNum = 0;
    }
}

You can see that this code has no timing requirements at all and is very simple to follow.

Now simplify the code that decides how many times motorStep() needs to be called and how long to leave between the steps.

…R

First BIG question - why not save yourself all the hassle and use the AccelStepper library ?

Yep I am using a stepper motor and yep I probably should have looked into that library much sooner but I got so far with out it that I might as well carry on.

But all your main code needs to be concerned with is whether it is time to make the next step. Leave it to a motorStep() function to figure out which sequence is required. Something like this

The project is to move a camera along a slider, acording to the user settings input from the lcd screen, such as interval between photos, how many steps per photo, how far along the slider they want to go etc etc. I am doing it this way to avoid having loads of different sections of the main code setting up timings for one step, two steps, three steps, whether they want a two second exposure or a 1/3200 sec exposure etc etc. This way I am clearing up my main loop. I will look into your way but at the moment I will keep it as it is thanks.

Anyway back to the topic in hand,

Of course. With no delay() (that's a good thing), on several iterations of the function, Currentmillis will equal Previousmillis.

That makes sense, I have just added a dealy of 1ms (delay(1);) and it has stopped it. Will this stop the millis counting so I will lose a millisecond or will the millis keep counting through the delay?

My immediate response would be that I would lose the millisecond as nothing else can happen in a delay, is this true?

If so I will have to look further into the setting of boolean flags (as I have not done this before I would try the cheat option first).

Thanks,

Your use of delay() won't affect the millis() timer functions. Getting into interrupts could, as previously mentioned.

Your use of delay() won't affect the millis() timer functions.

I have just run a quick test by displaying the Currentmillis before and after the delay and the two numbers are the same, does this not suggest that the delay is stopping the millis counter for a millisecond then resarting it where it left of, or have I read this wrong?

I could always counter act for this by removing 1ms from the step_x time I guess.

I have just run a quick test by displaying the Currentmillis before and after the delay and the two numbers are the same, does this not suggest that the delay is stopping the millis counter for a millisecond then resarting it where it left of, or have I read this wrong?

If you are displaying the value in the variable Currentmillis before and after the delay() there is no reason to expect the values shown to be different.

If you are displaying the value returned by millis() before and after the delay(), then the values should be different.

Yep that makes sense, I have added my code to show you how I have tested this below just to make sure I have not made any silly mistakes.

    if (Currentmillis - Previousmillis == move_1) {
      i++;
      mmm_1();
      Serial.println("Move_1");
      Currentmillis = millis();
      Serial.println(Currentmillis);
      delay(1);
      Currentmillis = millis();
      Serial.println(Currentmillis);
    }

output is giving,

move_1 200 201 move_2

so looks good to me.

Thanks for all your help I think I am there now, the next steps are to go and tidy up my code.

Mashley: The project is to move a camera along a slider, acording to the user settings input from the lcd screen, such as interval between photos, how many steps per photo, how far along the slider they want to go etc etc. I am doing it this way to avoid having loads of different sections of the main code setting up timings for one step, two steps, three steps, whether they want a two second exposure or a 1/3200 sec exposure etc etc. This way I am clearing up my main loop. I will look into your way but at the moment I will keep it as it is thanks.

I must be explaining myself very poorly because I firmly believe that what I suggested will make your code very much easier to manage.

Of course, not as easy as AccelStepper.

...R

I firmly believe that what I suggested will make your code very much easier to manage.

I do too. Breaking the code into smaller, individually testable functions makes life so much easier. Once you know that step() makes the stepper motor take one step, you can forget about how it works. You can, instead concentrate on making a rotate() function that calls step to make the motor rotate a certain amount. Once that works, you can call the function with the angle that the motor is to rotate.

Then, you can concentrate on getting the menu system working or the xxxx part working or the yyyy part working, instead of getting the whole confusing mass of code all working at once.

All I can see is what you are suggesting is a different way of doing what I have done.

I have written code that gets all the information needed from the user from an lcd screen with four buttons. All these menus are in functions, the movement of buttons and final selection to move on is still in the main loop but I will work on clearing this out.

Breaking the code into smaller, individually testable functions makes life so much easier.

I agree this is why I have set my code up like follows. Once all the settings are input (through functions) a function is called to set up when the motor should move (lapse_steps). Once these are setup a function is called to move the stepper motor (timelapse_go), when it is needed to move it calls another function that does the movement part (mmm_1) then back to wait for the next move (mmm_2). The only part of my code that was not working was the timelpase_go section.

This code is not finished so it may look like I could simplify parts but they are set up in this way for later addition of more features.

The question I was asking and have now fixed was how to get the millis working in a function, as all the other parts of my code were working just not the timelapse_go function. Maybe this is not the way you would have done it but hey it works.

Thanks everyone for there advice, you've all been a massive help.

PaulS:

I firmly believe that what I suggested will make your code very much easier to manage.

I do too.

There is an old saying "You can take a horse to water but you can't make it drink".

...R

I firmly believe that what I suggested will make your code very much easier to manage. I do too.

There is an old saying "You can take a horse to water but you can't make it drink".

And all because I want to write my programme the way I want to, If we were all the same and programmed exactly the same this forum would not be here. I came here to find out how to fix a problem, people have been very helpful in doing that, I don't need a lecture on how to re-write my code.

There is an old saying "You can take a horse to water but you can't make it drink".

But, if you lead the horse to whiskey, you don't need to make it do anything.

Mashley:

I firmly believe that what I suggested will make your code very much easier to manage. I do too.

There is an old saying "You can take a horse to water but you can't make it drink".

And all because I want to write my programme the way I want to, If we were all the same and programmed exactly the same this forum would not be here. I came here to find out how to fix a problem, people have been very helpful in doing that, I don't need a lecture on how to re-write my code.

Little bit of a chip on your shoulder, no?

You can write your program however you want. What these folks are saying is that they've been there and done that and they can see where you're going to run into trouble shortly. If you would rather not take that advise and run into those problems on your own that's fine.

It's like running into a highway worker and he's got a sign saying "Bridge Out Ahead" and you're screaming out the window at him, "I'll drive wherever I damn well please."

take another look at this before you go off running:

    if (Currentmillis - Previousmillis == move_1) {
      i++;
      mmm_1();
      Serial.println("Move_1");
      Currentmillis = millis();
      Serial.println(Currentmillis);
      delay(1);
      Currentmillis = millis();
      Serial.println(Currentmillis);
    }
Currentmillis - Previousmillis == move_1

if it is possible to miss the mills() timer recording the exact millisecond you are trying to measure to (move_1) you may miss that number…

look at making sure you hit the target by perhaps substituting “>=” or “<=” whichever is right for your code.