Go Down

### Topic: Increasing two different servo PWM's with different delay's (Read 4778 times)previous topic - next topic

#### flotilla

##### Jul 11, 2012, 06:49 pm
Hi,
I have a program running a couple of sail winch servos to control some clock face hands.  One servo for hour hand, one for minute hand.

I have the minute hand working well using a delay to incrementally increase the pwm to simulate the minutes, simulating a real
clock.

The servo takes +235PWM to do a full rotation so for the minute hand I have been increasing the PWM by 2 increments every 30 seconds

(Maths bit - 235PWM / 60mins = 3.9PWM per min so - 4PWM per min (rough, but ok for what I need) = 2PWM per 30 seconds.

The code below works fine for the minute hand however I have now come to doing the hour hand and I need to find a way of having
two different delays, or an alternative method to have the pwm's increasing at different speeds.

(Hour hand maths bit - 4PWM (1 Min clock time) x 10mins (1 hr clock time) = 40PWM per 60 mins 'real time'

40PWM / 60mins = 1.5PWM Per min =

1.5 increments per minute or 3 increments every two minutes (due to not being able to use 0.5 of a PWM)

I hope this makes sense,

basically I want to know if

1/there is a way of increasing, incrementally the two different PWM's with different delays within the same case?

2/does anyone know if servo's can use fractions of a PWM, for example 1503.9PWM? or will this just cause problems?

Thanks in advance, please no suggestions of using Steppers etc, I have to use servos's for this particular setup for reasons
that will take too long to explain here.

Code: [Select]

// I HAVE TAKEN OUT THE HOUR HAND CODE FOR NOW, MINUTE HAND CODE WORKS FINE

case 7: // Commence Time

MinutePulse = MinutePulse + 2;  //incremental time increase every 30 seconds (30000)
//HourPulse = HourPulse + 3; //incremental time increase needs to be every two minutes (120000)

MinuteHand.writeMicroseconds(MinutePulse);
//HourHand.writeMicroseconds(HourPulse);

//Serial.print("HOUR PWM VALUE IS SET TO ");
//Serial.println(HourPulse);
Serial.print("MINUTE PWM VALUE IS SET TO ");
Serial.println(MinutePulse);
delay (30000);
break;

#### PaulS

#1
##### Jul 11, 2012, 07:21 pm
Some clocks have second and minute hands that jump to the next position - once per second or once per minute. I take it that is not what you are trying to do.

I'll admit that I don't really understand what you are trying to do. It seems to me that either there is a constant writeMicroseconds() value that will cause the second hand to sweep once per minute, or there is not. If not, I don't see how you know when to fudge the speed. The same holds true for the minute hand. There is either a constant speed, or there is not.

So, perhaps you could explain just how you envision this clock working, and when you would change the speed that the servo is operating at.

#### flotilla

#2
##### Jul 11, 2012, 07:46 pm
I am basically trying to simulate a real clock with two servos, one for each hand (Hours and Minutes).
The reason for using servos is I have multiple buttons. You press one and the clock hands instantly zips to a particular time and starts running at a normal clock time. You press another and it zips to that time and starts running etc.

Normal servos can only do 180 degrees so I am using sail winch servos to allow me a couple of rotations however they work on the basis that 600pwm is all the way left and 2500pwm is approx three/four rotations to the right. I have calculated through testing that increasing the microseconds from 1000 to 1253 gives me one full rotation on the servo (this can be done anywhere within the 600-2500 range. I picked the 1000 point because it seems to be the most reliable area in the range.

So, to get one minute on the minute hand in a minute of normal time, matching a normal clock, the servo has to move 4pwm per minute (3.9 actually but it has been rounded up) I have this working in the code shown

Simultaneous to that I need the hour hand to move. This should move 1.5pwm per minute to simulate moving from say midnight to 1 over the space of an hour, however I have rounded this up to 3pwm per two minutes due to my belief that I can't use fractions of a pwm.

What I am asking is how can I have two different servos moving incrementally by different amounts with different delays.

Also I wanted to check if it is possible to increase the microseconds in decimal fractions such as 1.5 or 3.9.

#### AWOL

#3
##### Jul 11, 2012, 07:48 pm
Quote
Also I wanted to check if it is possible to increase the microseconds in decimal fractions such as 1.5 or 3.9.

You could using floating point, or you could use a fixed point representation.
"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.
I speak for myself, not Arduino.

#### flotilla

#4
##### Jul 11, 2012, 07:55 pmLast Edit: Jul 11, 2012, 08:00 pm by flotilla Reason: 1
I realise this is very complicated for what is essentially a simple idea.

Here is the 'wrong code version' of what I am trying to do

Case 0:
MinutePulse = MinutePulse + 4; //(increases the value by 4 every loop)
ServoA.WriteMicroseconds(MinutePulse) //writes value to servo
Delay (60000); // delay for 60 seconds before moving again

// In the same case 0 I need the following to happen within the same program loop (simultaneously)

HourPulse = HourPulse + 3; //(increases the value by 3 every loop)
ServoB.WriteMicroseconds(HourPulse) //writes value to servo
Delay (120000); // delay for 120 seconds before moving again

#### flotilla

#5
##### Jul 11, 2012, 07:58 pm

Quote
Also I wanted to check if it is possible to increase the microseconds in decimal fractions such as 1.5 or 3.9.

You could using floating point, or you could use a fixed point representation.

Sorry, I am fairly new to this and still learning, how would I do this, and would this cause problems with the servo, or are they ok with reading a signal of say 3.9?

Thanks

#### PaulS

#6
##### Jul 11, 2012, 08:19 pm
Quote
Here is the 'wrong code version' of what I am trying to do

Case 0:

I'm sorry, but a case statement without the enclosing switch statement is useless. I can't figure out under what conditions you expect this code to be executed.

#### wildbill

#7
##### Jul 11, 2012, 08:28 pm
An alternative aproach might be to use millis to tell you how much time has elapsed and calculate hours and minutes values from that. Then use the map function to map 0-59 into 0-180 (or however you have to tweak it for your servos)and write it to the servo. For the simple case that would give you time since power up. When you go to your setpoints, you'll have to add in the appropriate (unsigned long) number of milliseconds. No worries about timing or delays.

#### flotilla

#8
##### Jul 11, 2012, 08:35 pm

Quote
Here is the 'wrong code version' of what I am trying to do

Case 0:

I'm sorry, but a case statement without the enclosing switch statement is useless. I can't figure out under what conditions you expect this code to be executed.

Sorry I cut out most of the stuff that was not relevant to what I am trying to get across. I was trying to explain the fact that I am trying to have two different delays running simultaneously within the same loop. I have many switch/ case statements working perfectly within my code at the moment, I should have left the 'case' out to avoid confusion.

#### PaulS

#9
##### Jul 11, 2012, 09:23 pm
Quote
I should have left the 'case' out to avoid confusion.

I don't think that would have helped. I still need to understand under what circumstances you want to change the speed of the motors.

Quote
I was trying to explain the fact that I am trying to have two different delays running simultaneously within the same loop.

By now, you should know that you can't do this. You should not have ANY delays(). Look at the blink without delay example to see how to write delay()less code.

#### flotilla

#10
##### Jul 11, 2012, 09:41 pm

Quote

By now, you should know that you can't do this. You should not have ANY delays(). Look at the blink without delay example to see how to write delay()less code.

I do know this, hence the reason for asking for an alternative method. I dont really see how I could use 'millis' to help here, can you suggest how?.

My understanding is that Millis counts the time since the program started, however my program waits for inputs and runs other switch/modes before running my 'clocktime loop'

The absolute simplest explanation I can think of what I trying to achieve' is:

Within one continous loop

every 60 seconds - increase servoA pwm by 4
every 120 seconds - increase servoB pwm by 3

looped forever, (or until reset)

I am trying to understand the code for timing/updating the pwm on the two servos within the same executed loop.

#11
##### Jul 11, 2012, 09:55 pm
The Blink Without Delay sample shows you how to time a particular event using millis().  It requires you track the required timing yourself, and execute the specific task when the appropriate amount of time has passed.

This is really the only method of timing multiple independent events.

#### wd40bomber7

#12
##### Jul 11, 2012, 10:42 pmLast Edit: Jul 11, 2012, 11:13 pm by wd40bomber7 Reason: 1

Quote

By now, you should know that you can't do this. You should not have ANY delays(). Look at the blink without delay example to see how to write delay()less code.

I do know this, hence the reason for asking for an alternative method. I dont really see how I could use 'millis' to help here, can you suggest how?.

My understanding is that Millis counts the time since the program started, however my program waits for inputs and runs other switch/modes before running my 'clocktime loop'

The absolute simplest explanation I can think of what I trying to achieve' is:

Within one continous loop

every 60 seconds - increase servoA pwm by 4
every 120 seconds - increase servoB pwm by 3

looped forever, (or until reset)

I am trying to understand the code for timing/updating the pwm on the two servos within the same executed loop.

There are tons of different ways to do this, but here's a simple one for you.

Code: [Select]

int servoA = 0;
int servoB = 0;
int counter = 0;
void loop() {

delay(60);
servoA += 4;

counter++;

if (count == 2) {
servoB += 3;
counter=0;
}
}

Obviously instead of incrementing variables you'll have to increment the PWMs themselves.

Edit: Fixed a missing semicolon. I don't actually have the editor in front of me, so I just typed that up in notepad.

#### flotilla

#13
##### Jul 11, 2012, 11:27 pm
Just wanted to thank you all for your patience and help.  I managed to get it working with the 'millis' method
as suggested. After staring at it for an hour it finally clicked into place

My code for that particular section is below for anyone who is interested (majority omitted).

Thanks Again!

Code: [Select]

(Setup declarations)

unsigned long currentMillisA = millis();  //Storage for Timer
unsigned long currentMillisB = millis();  //Storage for Timer

long previousMillisA = 0;        // Millis Counter Store
long previousMillisB = 0;        // Millis Counter Store

long StepperAinterval = 60000; // 60 seconds break time
long StepperBinterval = 120000; // 120 seconds break time

(inside void loop())

case 7: // Commence Time
////////////

if (MinutePulse >= 2500) mode = 10; //servo safety to stop it over-turning
if (HourPulse >= 2500) mode = 10;
////////////

if(CurrentMillisA - previousMillisA > StepperAinterval) {
MinutePulse = MinutePulse + 4;
previousMillisA = CurrentMillisA;
MinuteHand.writeMicroseconds(MinutePulse);
Serial.print("MINUTE PWM VALUE IS SET TO ");
Serial.println(MinutePulse);
}
if(CurrentMillisB - previousMillisB > StepperBinterval) {
HourPulse = HourPulse + 3;
previousMillisB = CurrentMillisB;
Serial.print("HOUR PWM VALUE IS SET TO ");
Serial.println(HourPulse);
HourHand.writeMicroseconds(HourPulse);
}

break;

#### PaulS

#14
##### Jul 12, 2012, 01:10 am
Quote
Within one continous loop

every 60 seconds - increase servoA pwm by 4
every 120 seconds - increase servoB pwm by 3

I'm really curious why you want the motor to run faster and faster, instead of a constant speed. Every clock I own has a motor that runs at a constant speed. I can't help but think I am missing something.