Controlling servo without needing to use delay

This is an excerpt from my loop. I would prefer to have as few as possible uses of delay in my sketch. I would prefer to "detach" the servo to cause it to return to its original position (the servo arm is connected to a spring so the power of the (now) unresisted spring should enable a return). However, this doesn't seem to work.

if (bedroomVoltsRead < 100)
  {
    if (currentMillis-bedroomTriggeredTime > debounce)  
    {
      bedroomTriggeredTime = currentMillis;

      if (bedroomState == OFF)
      {
        bedroomState = ON;
        if (bedroomLEDState == OFF)
        {
          bedroomLEDState = ON;
          if(value3)  
          {
            BellControlServo.attach(6);
            BellControlServo.writeMicroseconds(2300);
            delay(200);              // wait for a bit
          }
          bedroomLEDTimeStamp1 = currentMillis;
          Serial.println();
        }
        else if (bedroomLEDState == ON)
        { 		

          bedroomLEDState = FLASH;
          if(value3)  
          {
            BellControlServo.attach(6);
            BellControlServo.writeMicroseconds(2300);
            delay(200);              // wait for a bit
          }
          bedroomLEDTimeStamp1 = currentMillis;	
        }
      }
    }
    else
    {
      bedroomState = OFF;
      BellControlServo.attach(6);
      BellControlServo.writeMicroseconds(600);
      delay(200);              // wait for a bit
      BellControlServo.detach(); 
    }
  }
  if (bedroomLEDTimeStamp1 + LEDOnDuration < currentMillis) 
  {		
    bedroomLEDState = OFF;
  }

In particular I understand each time the arduino goes through the loop this bit is executed. So I have a delay of 1.2seconds every time the loop is executed even if nothing is happening because I have six of these in my loop. If something is happening the delay is potentially 7.2 seconds!

    else
    {
      bedroomState = OFF;
      BellControlServo.attach(6);
      BellControlServo.writeMicroseconds(600);
      delay(200);              // wait for a bit
      BellControlServo.detach(); 
    }

Any ideas?

Thanks!

(the servo arm is connected to a spring so the power of the (now) unresisted spring should enable a return).

Not a good idea. The servo normally goes through a worm gear and it is not a good idea to try and drive those backwards.

Any ideas?

Use the blink without delay method to write your program.

Grumpy_Mike:

(the servo arm is connected to a spring so the power of the (now) unresisted spring should enable a return).

Not a good idea. The servo normally goes through a worm gear and it is not a good idea to try and drive those backwards.

Oh? I thought it was possible to move a servo manually through its range of rotation (for example to test its limits)? Didn't realise it was damaging...

Grumpy_Mike:

Any ideas?

Use the blink without delay method to write your program.

OK...was hoping to avoid that as it's going to be quite complicated for my sketch.

Any ideas?

Not really, as you talk of code that doesn't work for you without explaining what you are actually trying to do. If you are using "hobby" servos, I've never seen one containing worm gears. Having a servo strain against a spring might not be a good idea unless the spring is used as a counter balance for some type of a load. You should also describe what function a delay in your code serves.

zoomkat:

Any ideas?

Not really, as you talk of code that doesn't work for you without explaining what you are actually trying to do. If you are using "hobby" servos, I've never seen one containing worm gears. Having a servo strain against a spring might not be a good idea unless the spring is used as a counter balance for some type of a load. You should also describe what function a delay in your code serves.

Sorry.

If I don't include a delay after each instruction to the servo, the servo doesn't move. It doesn't seem to have time to complete the task required of it and the arduino seems to continue onin the loop and forget the command to the servo. If I include a delay the servo moves.

The delay after a command to move to Microseconds(2300) is manageable. It's the delay after Microseconds(600) that I'm keen to eliminate because this is encountered ALL the time in my sketch.

I had hoped to be able to use "detach" to return the servo to a default position given that the bell cord is lightly sprung.

Basically my servo pulls a string which is attached to and thus rings a bell. It's important that for the bell to ring just once per request that the back and forth movement of the servo arm is conflated into one as far as the bell is concerned.

I can attach a YouTube video if this is still unclear.

You may need to revisit your mechanical setup for ringing a bell with a servo. Servos move slowly, which may require a mechanical setup different from what you have to be successful.

Dane:
I can attach a YouTube video if this is still unclear.

A video would help.

zoomkat:
You may need to revisit your mechanical setup for ringing a bell with a servo. Servos move slowly, which may require a mechanical setup different from what you have to be successful.

The bell rings just fine - it's just this darned delay I want to eliminate. :wink:

Post the whole sketch. I suspect that it's overriding the bell ringing commands on each iteration of loop. Delay would mask that. As ever, can't tell without seeing the code.

it's just this darned delay I want to eliminate

The problem is that the servo produces mechanical movement and that takes time. So you are using delay to make the processor wait until the servo has had time to move. I suspect that the code is operating so fast that it is commanding the servo to move back before it has even set off. This is why you think it is ignoring the command. Software does not ignore anything.

You can get round this in two ways:-

  1. Have some sort of sensor that detects when the servo has reached the correct position and don't command the servo to move again until the sensor has been triggered.

  2. Have a value set by millis() when the servo is first commanded to move, then don't command it to move again until that value plus a delay constant is less than the current value of millis()