Help needed for "detach" in my Sketch

I'm using servos to throw my turnouts on my model railroad. I adjust the "servoLowPos" and "servoHighPos" to get the throw I need, but some of my servos twitch or hum. I trying to figure out how to "detach" them after being thrown. I had a lot of help to get this sketch so the servos run slow and now need help to get detach to work.

I modified this sketch to throw 22 servos on a mega.

Here is the sketch

#include <Servo.h>

#define SERVOS 8
Servo pointServo[ SERVOS ];

// 4 moves per second:
#define TIME2UPDATE 22
#define BYSOME 1

byte servoPin = { 1, 2, 3, 4, 5, 6, 7, 8}; // pin numbers for servo signals
byte switchPin = { 19, 18, 17, 16, 15, 14, 12, 11}; // pin numbers for switch connections
// Uno analog pins A5 A4 A3 A2 A1 A0
byte servoLowPos = {120, 120, 120, 120, 120, 60, 60, 60, 60}; // degrees for low servo position
byte servoHighPos = { 60, 60, 60, 60, 60, 120, 120, 120, 120}; // degrees for high servo position

byte servoPos[ SERVOS ];
byte servoCommanded[ SERVOS ];

unsigned int before, now;

void setup( ) {
setupServosAndSwitches( );
before = now = millis( );
} // setup( )

void loop( ) {
// this gets the time since the uc started running
now = millis( );

// this checks if TIME2UPDATE time has been expired,
// so we only update servos to get towards their final destination every TIME2UPDATE milliseconds
if ( now - before > TIME2UPDATE ) {
before = now; // set before to now, so we can check for another expiration next time
for ( byte n = 0; n < SERVOS; n++ ) {
updateServo( n, BYSOME );
} // for
} // if time to update

for ( byte n = 0; n < SERVOS; n++ ) {
byte sw = digitalRead( switchPin[n] );
if ( sw == HIGH ) {
servoCommanded[n] = servoHighPos[n]; // not moving the servo, only setting where it should travel towards
} else { // if sw == LOW
servoCommanded[n] = servoLowPos[n]; // not moving the servo, only setting where it should travel towards
} // if
} // for
} // loop( )

void setupServosAndSwitches( ) {
for ( byte n = 0; n < SERVOS; n++ ) {
pointServo[n].attach( servoPin[n] ); // say which pin this servo is running on
servoPos[n] = servoLowPos[n]; // this is just a starting value and may be over-ridden immediately by a switch
pinMode( switchPin[n], INPUT_PULLUP ); // make this pin an input with a pull up resistor
} // for
} // setupServosAndSwitches( )

void updateServo( byte servo, byte byHowMuch ) {
if ( servoCommanded[ servo ] > servoPos[ servo ] ) { // if position smaller, increase
servoPos[ servo ] = servoPos[ servo ] + byHowMuch;
if ( servoPos[ servo ] > servoCommanded[ servo ] ) { // don't overshoot!
servoPos[ servo ] = servoCommanded[ servo ];
} // if
pointServo[ servo ].write( servoPos[ servo ] );
} else {
if ( servoCommanded[ servo ] < servoPos[ servo ] ) { // if position bigger, reduce
servoPos[ servo ] = servoPos[ servo ] - byHowMuch;
if ( servoPos[ servo ] < servoCommanded[ servo ] ) { // don't undershoot!
servoPos[ servo ] = servoCommanded[ servo ] ;
} // if
pointServo[ servo ].write( servoPos[ servo ] ); // only place we write to a servo
} else {
// do nothing, since you are there!
} // if
} // if
} // updateServo( int )

// the end

If it's making noise it's likely still being powered.
Are you certain that your code is turning it off at the correct time?

Yes, they are staying powered, and that is why I need to find a way to add "detach" to the sketch.
I'm no programmer and I had a lot of help developing this sketch.
I have the speed of the servos where I like them and just need a way to detach a few seconds after they have switched from either high to low or low to high.

Can you post a schematic, it is possible you have some fantom feeds in your design.

I use this type of shield and plug the servos into it.

I plug the servos into pins 1 through 8, and use on/off toggle switches on pins 19, 18, 17, 16, 15, 14, 12, 11. The switches ground the pins to throw the servo and ungrounded throws the other way.

I'm using a 5 volt, 30 amp power supply to power 4 mega's and 3 uno's.

Schematic please I do not have the time to draw it. FYI I am very poor with word problems and the numbers tell me nothing! Links to each of the hardware devices showing technical information. The same description fits many different devices. Remember you built it and have it in front of you, my eyes are getting old and cannot see it.

I have no idea what you mean by "schematic". All the shield does provides plugs for the servos. They have a common ground, common 5 volts on pins for the servos to be plunged into. Then they have numbered pins to the Arduino.
It would be like a common buss for the servos, 5 volt and ground and then a pin for the signal pin on the Arduino. The pin assigned to throw said servo in either high or low by grounding the the pin.

There is nothing else on the shield other than 2 LEDS. The shield just makes it easier being able to just plug a servo in.

Begin with a block diagram showing all the boards and power supply. Add lines to show each connection and the name of the pins being connected. That will do for a beginning.
Paul

1 Like

The top line is the 5 volt buss
The bottom line is ground
Boxes are the servos
The center line coming out of the box is signal going to pins on the Uno

You are moving the servos in little steps (1 degree each 22 milliseconds). You have to decide if you want to detach after every 1° move or wait until the last 1° move has completed. You also have to decide if you want to re-attach before each 1° move or only when the servo is about to move to a new destination.

Hi John,

I want to detach about 5 seconds after total movement. Then when it's switched from either high or low again, to recycle.

OK. So I would start with more arrays.

For each servo, you need to know if the servo is attached, detached or waiting to detach. That would be a good use for an 'enum'. If the servo is 'waiting to detach' you also need to know when it started waiting.

enum State {DETACHED, ATTACHED, WAITING2DETACH} States[SERVOS];
unsigned long DetachWaitStartTime[SERVOS];

Then when you update the servos you can check the state.

void updateServo( byte servo, byte byHowMuch )
{
  if (servoCommanded[servo] > servoPos[servo])   // if position smaller, increase
  {
    servoPos[servo] += byHowMuch;
    if ( servoPos[servo] > servoCommanded[servo] )   // don't overshoot!
    {
      servoPos[servo] = servoCommanded[servo];
    } // if
    if (States[servo] == DETACHED)
    {
      pointServo[servo].attach(servoPin[servo]);
      States[servo] = ATTACHED;
    }
    pointServo[servo].write( servoPos[servo] );
  }
  else
  {
    if ( servoCommanded[servo] < servoPos[servo] )   // if position bigger, reduce
    {
      servoPos[servo] -= byHowMuch;
      if ( servoPos[servo] < servoCommanded[servo] )   // don't undershoot!
      {
        servoPos[servo] = servoCommanded[servo] ;
      } // if
      if (States[servo] == DETACHED)
      {
        pointServo[servo].attach(servoPin[servo]);
        States[servo] = ATTACHED;
      }
      pointServo[servo].write( servoPos[servo] ); // only place we write to a servo
    }
    else
    {
      // At destination.

      // If we're still attached, start the wait to detach.
      if (States[servo] == ATTACHED)
      {
        States[servo] = WAITING2DETACH;
        DetachWaitStartTime[servo] = millis();
      }

      // If waiting to detach, check to see if the wait is over
      if (States[servo] == WAITING2DETACH &&
          millis() - DetachWaitStartTime[servo] >= 5000)
      {
        pointServo[servo].detach();
        States[servo] = DETACHED;
      }
    } // if
  } // if
} // updateServo( int )

Why would somebody detach a servo while the device is still in use?
To keep a servo in a defined state the servo needs a neverending continously streem of servo-pulses. Otherwise it might catch up some noise on the signal wire starting twitching around.
So IMHO the correct way to switch of a servo is to switch of power.
As long as you use a more or less "standard"-servo the gearing will keep the servo-horn it is position as long as the force into the horn is medium strong.

To make a servo hold its position against strong forces it needs to be switched on and feeded with an apropriate servo-signal all the time which means no detaching

best regards Stefan

I'm with @StefanL38 on this. If you want the servos to hold their position against forces trying to move them, then they must stay powered and receive servo signals continuously.

If there is no particular force trying to move them, then they'd be better off powered down.

This suggests the need for software control of the power feed to the servos. Simple enough with lots of options - including a simple software-controlled relay.

The forces on the horn is light. When unpowered, they don't move.

Thanks John, for taking the time to write this out.

I'll give the code a try sometime in the next few days and let you if it works.

OK, thanks. @johnwasser has shown you what to do, and it will be simpler than switching the servo power. However, you might consider it as an alternative approach.