Pages: [1] 2   Go Down
Author Topic: timing a movement for a watch winder  (Read 1875 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello everyone,

I'm not sure this is the right section to post this question to, but the other ones seemed rather irrelevant. I'm making a watch winder for a friend of mine using arduino.
I use a Tower Pro servo which I modified for continuous movement by removing the mechanical stop and soldering the potentiometer in 90 degree position. Although it's a little underpowered for this application it seems adequate.

It might seem a little silly but I'm new to embedded electronics but here is the problem;

I need the servo to run for a set period of time after the arduino is connected to the power, then stop, then run again in a loop without user input. Since the pot is fixed I cannot measure turns it has made and use a "for loop" to count the turns to find out roughly the time the servo needs to pause. The run-stop structure is as follows: 10 * (run 30 min stop 15 min) then stop for 990 minutes. (thus having a 24 hour cycle)

I use servo library to run the servo but don't know how to stop it and restart it automatically...

Any ideas?
« Last Edit: May 15, 2011, 08:43:26 pm by electricBunny » Logged

Massachusetts, USA
Offline Offline
Tesla Member
***
Karma: 180
Posts: 8081
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

void loop()
    {
   for (int i=0; i<10; i++)
        {
        startMotion();
        delay(30L*60L*1000L);  // 30 seconds
        stopMotion();
        delay(15L*60L*1000L);  // 15 seconds
        }
   delay(990L*60L*1000L);  // 990 seconds
    }
Logged

Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for the reply but since the servo never reaches the position (since it's pot is fixed) when I write delays in between it is forever stuck on the first movement... Is there a command to execute a function for a set period of time?

The code I wrote is as follows;

{
   for (int i=0; i<10; i++)
        {
       
        myservo.write(100);
        delay(30L*60L*1000L);  // 30 seconds
        myservo.write(92);    //this is the position in which the servo stops
        delay(15L*60L*1000L);  // 15 seconds
        }
   delay(990L*60L*1000L);  // 990 seconds
}

Maybe I didn't get something?
Logged

0
Offline Offline
Sr. Member
****
Karma: 0
Posts: 360
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

30L * 60L * 1000L = 30 minutes * 60 seconds per minute * 1000 milliseconds per second.

Seems like your error is there xD.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Well as I have said before the program never gets to the delay part... No matter how long or short the delay maybe writing a position to the servo means it will turn indefinitely since the encoder is not working any more due to the modifications made on the servo. Is there a way to control the servo with another code perhaps? Like digitalwrite? I know that I need to send a pulsating signal to tell the servo to do something but don't know how to send it in any other way then using the servo library.

OR; tell the servo to try to write a position for sometime - stop - continue...

Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 549
Posts: 46107
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You really need to post all of your code. We have no idea what the rest of the code is doing from the snippets you've posted.

The servos should be started moving using the Servo::writeMicroseconds() method.

There are interactions between the Servo library and PWM on certain pins, depending on which board you have. The PWM pins you are using, if any, are in the code you haven't posted.

Interrupt usage can cause the delay() function to not work. Are you using interrupts? We can't tell, since you haven't posted all of your code.

Quote
Well as I have said before the program never gets to the delay part.
How do you KNOW that the program hasn't gotten to the DoNothingPeriod() function (aka delay())?
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

#include <Servo.h>
 
Servo myservo; 
 
int pos = 0;   
 
void setup()
{
  myservo.attach(9);
}
 
 
void loop()
{
   for (int i=0; i<10; i++)
        {
       
        myservo.write(100);
        delay(30L*60L*1000L);  // 30 seconds
        myservo.write(92);    //this is the position in which the servo stops
        delay(15L*60L*1000L);  // 15 seconds
        }
   delay(990L*60L*1000L);  // 990 seconds
}


this is the whole code... The board is an Arduino Uno, + to 5V Gnd to Gnd and the signal pin goes to digital 9.

I don't "know" that it doesn't get to that part it's just common sense but it may be wrong...

From what I gather I need to be able to send the signal for a set period of time then stop. With the servowrite() function it tries to set the servo to a certain position without any success.
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 549
Posts: 46107
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I use a Tower Pro servo which I modified for continuous movement by removing the mechanical stop and soldering the potentiometer in 90 degree position. Although it's a little underpowered for this application it seems adequate.
The thing you have now is not a servo. Please stop referring to it as such. What you now have is a variable speed, bi-directional electric motor.

You can make a servo move to a specific position, and stop, using the Servo::write() function. You can NOT make a variable speed, bi-directional electric motor move to a specific position, and stop, using ANY Servo function. You CAN make the servo move in one direction, or the other, or stop, by using Servo::writeMicroseconds() with the appropriate value as the argument. Typically, values less than 1500 move the no-longer-a-servo one way, and values greater than 1500 move it the other way, while 1500 causes it to stop. The exact value where it stops needs to be determined experimentally. The range of values that cause movement, and the speed of that movement, also needs to be determined experimentally.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

OK, I know that it is no longer a servo but the common way of referring to bi-directional, variable speed motors that are made from servos is 'continuous rotation servo' so I used the incorrect term...

Using the servo library alone I now know that it is impossible to stop the motor once the command to move it is given. However is there a library for timing events which can be used for this purpose. Pseudocode example below:

#the time is defined as the time since the program started to run, the unit is hours

if (12.00<time <13.00)
{
write servo(500);
}
else
{
stop the once-a-servo and return to the beginning of the scope
}
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 238
Posts: 24370
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Seems to be some confusion between seconds and minutes, but this should help accelerate testing:

Code:
#include <Servo.h>
 
Servo myservo;  

//#define DEBUG   // uncomment this line to run the sketch at 10x speed.

#ifdef DEBUG
  #define ONE_SECOND (100L)
#else
  #define ONE_SECOND (1000L)
#endif

#define ONE_MINUTE (ONE_SECOND * 60L)
#define ONE_HOUR   (ONE_MINUTE * 60L)
 
void setup()
{
  myservo.attach(9);
}
 
 
void loop()
{
   for (int i=0; i<10; i++) {
     myservo.write(100);
     delay(30L * ONE_MINUTE);
     myservo.write(92);
     delay(15L * ONE_MINUTE);
   }
   delay(990L * ONE_MINUTE);
}
« Last Edit: May 16, 2011, 08:39:03 am by AWOL » Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thank you good sir,

I don't have the Arduino with me right now but I'll try as soon as I get home. Still I don't think this will work but it takes a minute to test, my guess is it will try to write the position indefinitely. The problem I suppose is that I'm trying to use a servo library to control something that no longer has the most important feature of a servo (namely, the ability to know it's motor position). But there doesn't seem to be a library for these modified once-a-servos (or OAS, if you will) and obviously a dc motor control code won't work since the thing that tells a servo to move is the pulsating signal that is transmitted through the Orange/White cable.

With an external sensor I would be able to stop the motor like

if (photocell receives light)
{
write servo (130)
}
else
{
stop
}

But since it needs to be tied to time and not an external sensor the problem still exists. Well... it might not and I might have been confused about the time, in that case thanks for the advice and code.

BTW if I can get this to work I will use this example to make picture drawing robots.
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 549
Posts: 46107
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Using the servo library alone I now know that it is impossible to stop the motor once the command to move it is given.
This is not at all correct. By calling Servo::writeMicroseconds() with the correct value, the no-longer-a-servo will stop.

Please stop trying to use Servo.write(). That method is used ONLY for servos, which you do NOT have.
Logged

0
Offline Offline
Sr. Member
****
Karma: 0
Posts: 360
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

OP, please clarify: What is your issue?

myservo.write(100); <-- this code on a modified servo will set it to rotate in one direction relatively slowly.
myservo.write(180); <-- this code will set it to rotate in the same direction faster
myservo.write(92); <-- this code will stop the rotation (exact value needs to be tested empirically, but it should be near 90)

Your issue is one of these two (I can't tell which from your posts):

a) Modified Servo starts moving, doesn't stop
       Reason: You aren't waiting for half an hour, which is how long the first delay is in code.  It won't stop until you tell it to with myservo.write(92)
b) Modified Servo doesn't start moving
       Reason: You have power supply issues, or your modified servo is broken.

General statements: You NO LONGER have ANY position feedback on your servo, unless you get around to ADDING an encoder or infinite-turn potentiometer to the output shaft.  The ONLY WAY to control position in your case is to guesstimate the amount of time it takes to travel theta degrees at a set speed, then wait that long and hope the servo's in the right place.  

Using the servo library alone I now know that it is impossible to stop the motor once the command to move it is given.

This is false.  Where did you get that from?  Setting the desired 'angle' back to wherever the servo's internal potentiometer is glued will stop the motor.

However is there a library for timing events which can be used for this purpose. Pseudocode example below:
#the time is defined as the time since the program started to run, the unit is hours

if (12.00<time <13.00)
{
write servo(500);
}
else
{
stop the once-a-servo and return to the beginning of the scope
}
This is going to tell the servo to move at maximum speed (500 is more than the servo's write command will take) in one direction, for an hour.  I'm not sure what you're trying to get at here - running it in one direction for x hours is not going to give you position control.  

On a modified servo, the |setAngle - centerPoint| is approximately proportional to the speed that the motor will move at.  If setAngle < centerPoint, it will turn one way, and if setAngle > centerPoint, it will turn the other.  If setAngle == centerPoint, it will stop.  It WILL try to write the position indefinitely - but since it can't actually get there, it will simply keep rotating.  

There isn't a point to make another library for these modified servos - the commands are the same and the signals are the same.  The only difference is what the output of the servo will be.  
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 238
Posts: 24370
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

If you have problems stopping an ex-servo (I've found they sometimes drift), you could try a detach, but two things to be aware of:
1) There will be no holding torque, except for that due the gearing
2) you'll need to attach it again before moving.
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

Massachusetts, USA
Offline Offline
Tesla Member
***
Karma: 180
Posts: 8081
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
#include <Servo.h>
 
Servo myservo; 
 
int pos = 0;   
 
void setup()
{
}
 
 
void loop()
{
   for (int i=0; i<10; i++)
        {
       
        myservo.write(100);    // Pre-set the motor speed
        myservo.attach(9);     // Attach the servo to start the motor spinning
        delay(30L*60L*1000L);  // Wait 30 minutes
        myservo.write(92);    //  Set the motor speed to zero (between forward and backward)
        myservo.detach();     // Stop sending pulses to the servo
        delay(15L*60L*1000L);  // Wait for 15 minutes before running again
        }
   delay(990L*60L*1000L);  // Wait for 990 minutes
}
Logged

Send Bitcoin tips to: 1L3CTDoTgrXNA5WyF77uWqt4gUdye9mezN
Send Litecoin tips to : LVtpaq6JgJAZwvnVq3ftVeHafWkcpmuR1e

Pages: [1] 2   Go Up
Jump to: