Millis-based code to replace servo delay?

Yes, mine too now. No gonna tell you the stupid mistake that made it not.

I am not so sure we have the OP's problem understood.

The requirement for one servo is to move, delay and move again.

I think (!) that the matter is how to make two servos both have an ability to move IN and OUT with adjustable times.

And all solutions, even the OP's example, simply repeat the motion; perhaps the state machine that handles making the servo moves should be designed to do one such move each time it is (re)started, on demand of externally determined conditions.

a7

1 Like

The README.md in the nodelay library on GitHub is probably one of the best readme files I have seen in a while.

The object works fine without ever calling update()- I just use it because I want the delay time to vary randomly.

Thanks a7. I’m looking for complete independence between two servos. The delay-based code for each looks like that example in my initial post. Actually I think non-blocking code for a single servo rotation could be all I need. I could then apply that ‘template’ to any rotation from one angle to another, over a specified duration. Three parameters, apart from the servo identity. The resulting action would be independent of that occurring in any other servo or elsewhere.

Note that in practice I’ve found I can only arrive at angles and durations by experiment. Typically I’m pressing various buttons with the servo arm.

I have not yet tested Stefan’s code but will do so tomorrow. If it really is as simple as he says then I’m plainly making unnecessarily heavy weather of it!

Terry

Thanks gcrj. I’ll hopefully try that tomorrow, although I’m (happily) building up quite a To Do list here!

Terry

As you’ve probably now seen from my reply to you a little earlier, before seeing this, your assumption is exactly correct.

Terry

Many thanks Steve, I’m looking forward to trying that library. But, as a relative novice, I’m going to grasp the the millis-based approach first.

Terry

OK probably in this sequence

   myservo.write(inPos);
   delay(waitBeforeRelease);
   myservo.write(outPos);
   delay(waitAfterRelease);

the final delay woukd not be needed, would not be part of the machine that handles move IN, delay and move OUT. The motion is complete and ready to repeat whenever after the second servo call.

This is the first time you’ve hinted at moving the servo other than as fast as possible to a new position. Quite possible and easy enough, just wanna be sure you need and want this additional functionality.

Also, I happen to know you are pressing buttons at least on one camera you prolly don’t want to “go into”, but I am compelled to point out and remind anyone else reading along that there are many ways to get a button to appear pressed on the external device, not all of which are mechanical solutions. If you dare go in and play around a bit with the external device circuitry that is.

a7

1 Like

Thanks Stefan. If it really is as simple as that then I’m plainly making unnecessarily heavy weather of it! I wil try it in the morning.

Pleased to see you discussing Wokwi in Discord. As a ‘forum’ I find it alien and hard going so far. But as there’s so much I want to learn about this great simulator I joined it today and made my first post. It included this link to my wokwi simulation of the simple delay-based two LED sketch I posted previously.

https://wokwi.com/arduino/projects/309899435981144642

If you or a7 find a good tutorial in any format (my preference is the same as yours) please let me know.

Terry

Nice. Sadly my idea of fun - making virtual garage doors go up and down with blocking delays.

I added something I've been working on recently, this is an approach I've already left behind, but works OK.

For each case replace the Serial.println with a call to printState, like:

    case doorIsDown: // Nothing happening, waiting for switchInput
      printState(doorIsDown, "door down");

Then supply printState, to be called in every case with arguments the state we have entered and some text to display, viz:

void printState(unsigned char theState, char *theText)
{
  static unsigned char printedState = 0xff;    // matches no state

  if (theState != printedState) {
    Serial.println(theText);
    printedState = theState;
  }
}

This will let you follow the state machine progress and not flood the serial monitor with repetitive messages.

I'm working on my macro chops to warp this up a little nicer but as I said, this does the job.

HTH

a7

a7

Devices currently in use are Polaroid CUBE and Canon Ixus HS, both with inaccessible internal circuitry - for me at least!

Not sure about that final delay to be honest. Think I started using it when my CUBE sketches included powering it up, which needed a 3s press. It then needed a 1s to 1.5s recovery time for reliable subsequent operation.

Nor am I really sure I properly understand the speed versus duration factors. Or whether torque defends on either. Happy to defer entirely to you and other experienced users on these and other points, and then try code and report back.

With small servos the torque curve is kinda flat, slower speeds will give more torque.

If a new PWM rate appears, the servo does its best to move to the position corresponding to the pulse. It will move as fast as it can to the final angle.

If you want or need to make it creep or crawl from one angle to another, it is necessary to feed the servo new values periodically to get it to move in a step like fashion. As slow as you want, with steps as small as you can make the difference in pulse width.

I haven't seen any really clever code to do this - too infrequently updating the desired position would mean the servo would come to a stop between steps, on the other hand too frequent and you'd end up with the equivalent of just having put the final position in in the first place.

I have never needed to slow a servo down. If you've been getting success with an IN position and an OUT position and max speed between the two I'd just stick with that.

It can be painful getting the constants just right. Maybe a small program that did nothing but read a potentiometer and send a mapped signal to the servo would let you rapidly close in on the calibrated values.

a7

1 Like

Sorry, that garage code was an old link. Hopefully this one is correct.

Thanks a7, very helpful analysis as usual. I’ll make an excursion into more methodical servo experiments.

For background, I’ve probably been conflating two types of delay: one that I thought was needed to allow the servo to complete its movement (I.e. not being prematurely interrupted); and another delay type necessary for other reasons.

Examples of the latter particularly arise with the CUBE. Still true even though I’m no longer using code to power it up (with a single very long press), by instead attaching its USB input to a charger. For instance, two presses of the (quite stiff) button are needed to start a video recording. One press to take a photo. Naturally, if the gap between two is too long the CUBE will take two photos, instead of a starting a video. If the gap is too short I think the video fails to start - but I will double check in the light of your comments.

BTW, I’ve recently added a solenoid to my repertoire of button pressing improvisations, with mixed results. Simpler and more reliable code (although some front end legacy electronics, of course), providing the mechanics are carefully positioned. But this particular solenoid not only needs its own 24V supply but also makes a worryingly loud noise on activation. I suspect the conspicuous absence of overnight fox videos may be down to that!

Note that the VarSpeedServo library has some functionality not in the simpler Servo version.

Terry

The below code not only controls Servo motor in non-blocking mode but also controls speed of servo motor

#include <Servo.h>

Servo myServo;
unsigned long MOVING_TIME = 3000; // moving time is 3 seconds
unsigned long moveStartTime;
int startAngle = 30; // 30°
int stopAngle  = 90; // 90°

void setup() {
  myServo.attach(9);
  moveStartTime = millis(); // start moving

  // TODO: other code
}

void loop() {
  unsigned long progress = millis() - moveStartTime;

  if (progress <= MOVING_TIME) {
    long angle = map(progress, 0, MOVING_TIME, startAngle, stopAngle);
    myServo.write(angle); 
  }

  // TODO: other code
}

You can refer more to how to control the speed of dc motor within a period of time without using delay

1 Like

Thanks, added to my list of Try Soon sketches. My servo commands so far have been relatively unadventurous. As you may have gathered from my posts #30 & #33 that’s partly because trial and error have proved difficult even with my simple parameters.

Terry