Jump to content

Banner.jpg.b89429c566825f6ab32bcafbada449c9.jpg

DIY Moon Phase Dial


Gina

Recommended Posts

I'm told the actual stepper gearbox ratio is 63.68395:1 so 3.1841975 steps per second.  Thus basically 3 steps every second and then an extra step every so often.  That's 0.1841975 steps per second or 5.4289553332699955211118500522537 seconds.  So an extra step every 5 seconds and then some...  That gives the basic 3.2 steps per second that we had before with a 64:1 gearbox.  We now have a remainder of 0.2 - 0.1841975 = 0.0158025 which is i part in 63.281.  That gives 63 as the next correction period.  I think that's drop a step.

I think that is as far as I want to go with theoretical correction.

The ISR would seem to be :-

void timerIsr() {
  if (!timeIsSet) { return; } // Ignore the interrupt and return while setting the clock
  gbCount ++; // Increment gearbox count
  if (gbCount >= 63) { gbCount = 0; moveForward(2); }
    else if ((gbCount % 5) == 0) { moveForward(4); }
    else { moveForward(3); }
  for (int i = 3; i >= 0; i--) { digitalWrite(motorPins[i], 0); }
}

 

Link to comment
Share on other sites

  • Replies 1.1k
  • Created
  • Last Reply

I've got this all wrong, evidently.  gbCount starts at 0 so first interrupt it should send 4 steps to the motor then 3 steps for the next 4 etc.

Sequence is therefore :- 43333 43333 ~ 433334 43333 ~ 43333 43333 ~ 43333 43333 ~ 43333 43333 ~ 43333 43333 ~ 4332 so in 63 seconds we have 192 + 4  + 3 + 3 + 2 = 204 steps.  Correct number is 3.18 x 63 = 200.34.  According to that the clock should be running slightly fast not ridiculously slow.

It's now 5m slow in half an hour :(

Link to comment
Share on other sites

I'm sure the calculation and code is right but OTOH it can't be :(  

The sequence is 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 where the "gbCount % 5" is shown in green.  Surely that's right?!

Evidently not - clock is now 15m slow in 60.  So it's running at three quarters of the right speed.  I can use modulo 4 instead of 5 which should make it nearer.  :icon_rolleyes:

Link to comment
Share on other sites

Gina,

Like you, I have great faith in stepper motors but your latest struggles do suggest that there are mechanical issues here, not software. I wonder about occasional missed steps due to gears sticking, motor speed problems ................Like all intermittent problems it would be almost impossible to diagnose so I wonder if you could test by disconnecting one of the step motors from the clock and, using a piece of thin wire - solder is perfect - make a pseudo hand. Line that up exactly with something then set the motor going and use the pointer position and full turn count to accurately check the motor rpm without any gear effects?

Other than that, 'tis a puzzle, t'aint it!

Regards, Hugh

Link to comment
Share on other sites

Thank you Hugh - that's a good idea.  I already have a Nano connected up to 3 of these stepper motors for my widefield imaging rig, so I can bung a pointer of one of these and set it running.  OTOH the calculation for setting the time works out correctly.  The difference is that this rotation is continuous rather than stop-start and that's the only difference I can think of.  Maybe the fact that the timing seems nearer correct when using bursts of 16 steps every 5s  than around 3 every second also points to some problem with the start-stop situation.

During all this ongoing timekeeping problem I've been thinking of running the stepper motor in the more reliable and higher power mode of half-stepping.  Currently I'm only powering one phase coil at a time with the sequence 1000, 0100, 0010, 0001, 1000 etc.  In half-step mode we have 2 phase coils powered half the time with the sequence 1000, 1100, 0100, 0110, 0010, 0011, 0001, 1001.  This is what I use for my focusers to get higher resolution.

Yes, I think I shall re-jig the clock sketch to use half-stepping - I've had enough of the continuing problems and thia is all I can think of ATM.

Link to comment
Share on other sites

Half-step uses an array of bit patterns rather than just bit-shifting a single variable so is a bit more complicated so rather than using a 2 dimensionay array with motorpin and pattern as the two dimensions I shall use just pattern in a 1 dimensional array.  It only adds a few lines and makes the code more comprehensible.

Another simplification is to make each motor movement one complete cycle of patterns ie. 8 half-steps.  That saves having to save the pattern array position between motor movements.  Nothing is exactly integer now anyway with the funny gearbox.  So Each "step" sent to the moveForward procedure is now 4 old steps.  Needing about 3.18 old steps per second is now 3.18/4 new steps = 0.795.  This means 1 new step per second and then drop a new step every 5 secs to start with. I think the next level will be 63 as before, where we add an extra step (2 instead of 1).

Testing again using half-stepping.  Started at 5:25pm.  Setup 1m fast.  This is the new sketch :-

// Filename :- Moon_Clock_with_RTC_16 2016-03-23 1720
// Arduino test sketch for moon clock with RTC
// Hardware interrupt from RTC on pin 2
// Code included to turn stepper off between ticks
// Timing uses RTC interrupt
// Minutes driven every 5 interrupts (5s) on first stepper motor.
// Everything to do with the seconds motor has been removed
// moveBackward has been removed
//
#include <DS3232RTC.h>    //http://github.com/JChristensen/DS3232RTC
#include <Time.h>         //http://www.arduino.cc/playground/Code/Time  
#include <Wire.h>         //http://arduino.cc/en/Reference/Wire (included with Arduino IDE)
//
int timeError = 28;  //  Amount of time setting error to be corrected
boolean timeIsSet = false;
//declare variables for the motor pins
int motorPin1 = 3;  // Blue   - 28BYJ48 pin 1
int motorPin2 = 4;  // Pink   - 28BYJ48 pin 2
int motorPin3 = 5;  // Yellow - 28BYJ48 pin 3
int motorPin4 = 6;  // Orange - 28BYJ48 pin 4
int lookup[8] = {B01000, B01100, B00100, B00110, B00010, B00011, B00001, B01001};

int delayTime = 1000;  //  Time between half-steps (μs)
int gbCount = 0;    // Counts 5s units for gearbox correction
long steps, h, units, extra ; // time set variables;
//
void setup() {
  Serial.begin (9600);     // Enable Serial Monitor via USB
  pinMode(motorPin1, OUTPUT);
  pinMode(motorPin2, OUTPUT);
  pinMode(motorPin3, OUTPUT);
  pinMode(motorPin4, OUTPUT);
  pinMode(2,INPUT_PULLUP);   //  Interrupt pin
  setSyncProvider(RTC.get);  // the function to get the time from the RTC
  if(timeStatus() != timeSet) 
      Serial.println(" Unable to sync with the RTC");
  else
      Serial.println(" RTC has set the system time");
  RTC.squareWave(SQWAVE_1_HZ);    // 1 Hz square wave            
  attachInterrupt(digitalPinToInterrupt(2), timerIsr, FALLING);
}
//
void moveForward(long steps)
{
  for (long s = 0; s < steps; s++) {
    for(int i = 7; i >= 0; i--) {
      digitalWrite(motorPin1, bitRead(lookup[i], 3));
      digitalWrite(motorPin2, bitRead(lookup[i], 2));
      digitalWrite(motorPin3, bitRead(lookup[i], 1));
      digitalWrite(motorPin4, bitRead(lookup[i], 0));
      delayMicroseconds(delayTime);}
  }
}
//
void timerIsr() {
  if (!timeIsSet) { return; } // Ignore the interrupt and return while setting the clock
  gbCount ++; // Increment gearbox count
  if (gbCount >= 63) { gbCount = 0; moveForward(2); }
    else if ((gbCount % 5) != 0) { moveForward(1); } // normal step
// Turn motor current off
  digitalWrite(motorPin4, 0);
  digitalWrite(motorPin1, 0);
  digitalWrite(motorPin2, 0);
  digitalWrite(motorPin3, 0);
  delayMicroseconds(delayTime);  // Allow time for motor to step
}
//
void loop(){
  // Main code loop - handles time set up
  if (timeIsSet) { return; } //  break out once time is set
  Serial.println(" Setting hands to 12 o'clock");
  while ((analogRead(A6) > 500) || (analogRead(A7) > 500)) { moveForward(1); } // move fast forward until 12 o'clock sensed
  moveForward(timeError);   // correct error
  h = hour(); if (h > 12) { h = h - 12; }  // convert 24hr clock to 12hr
  units = h * 720;
  units += minute() * 12;
  units += second() / 5;
  steps = units * 4;  //  was 16
  extra = steps / 400;
  steps = steps + extra;
  Serial.print(" Moving hands to ");
  Serial.print(h); Serial.print(":");
  Serial.print(minute()); Serial.print(" using ");
  Serial.print(steps);
  Serial.println(" steps");
  moveForward(steps);
  timeIsSet = true;
}
// End

 

Link to comment
Share on other sites

6pm and about 1m 45s fast - so gained about 45s in 35m.  About 1 in 47.

I've reversed the action every 63s from add a step to drop a step and reset clock.  Showing about 30s fast at 6:30pm.

Link to comment
Share on other sites

10pm and clock is about 15s slow.  Elapsed time 3h 30s - time lost about 45s.  45s in 210m ie. 1 in 280  Not too bad :)  Next correction factor 280 and add a step.

The timekeeping correction part becomes :-

  gbCount ++; // Increment gearbox count
  if (gbCount >= 280) { gbCount = 0; moveForward(2);} // add an extra step
    else if ((gbCount % 63) == 0) {  }                // skip a step
    else if ((gbCount % 5) != 0) { moveForward(1); }  // normal step

 

Link to comment
Share on other sites

Adjustment for time to set the hands to the right time amended to allow for the faster full speed mode. 

Time correct at 2016-03-03 23:20. 

Link to comment
Share on other sites

0900 and clock is 2m 30s slow.  Elapsed time 9h 40m = 580m so error = 2.5 in 590 = 1 in 236.8 (240).  So the 280 correction is insufficient and needs the number reduced.  1 in 280 = 0.0037 and 1 in 236.8 = 0.0042 so error of 0.0079 or 1 in 127 so I'll change the 280 to 127 and see what that gives.

Clock reset and correct at 0926.

Link to comment
Share on other sites

I'm a bit worried you are chasing shadows.

A stepper will move by an exact amount each time, even if the gearbox ratio is 'not as advertised', you know the exact gear in the clock and the Nano is crystal controlled.

In principle this is exactly the same as my RA drive (AVR, stepper, gears, worm drive) and by calculation I was able to get this tracking spot on with no adjustment needed.

I think that if your calculations are accurate then you MUST be missing steps for some reason.

I think you are driving the stepper too fast.

When moving rapidly to set the hand position, any lost steps at the beginning will be trivial and won't matter when the motor is up to speed.

On the other hand, when you do a small move (e.g. every second) if a step or two are lost getting the stepper started, these will slowly accumulate. The error will be similar every time, but vary randomly and may also vary with temperature etc.

I seriously think it's worth trying with the stepper drive delay rather longer, even if you step faster when setting.

Link to comment
Share on other sites

Thank you Neil :)  I'm inclined to agree and have wondered the same, as I think I've said.  There is no reason why the routine the steps the motor fast for setting up needs to be the same one used for running the clock.  I have improved things by using half-step mode but I may still be losing steps, as you say.  I'll change the sketch to increase the phase time for the running drive.

Link to comment
Share on other sites

Hi Gina,

Is it feasible to put some kind of encoder on the movements so that you could correct that way?

Cheers

Steve

 

Link to comment
Share on other sites

I effectively have that already Steve, in the form of the Hall sensors that detect when both hands are at the 12 o'clock position.  If the stepper motor is stepping properly the ratio is known (even if it is a non-integer value) and can be corrected accurately enough to get within a second or so in 12 hours.  The residual error can be corrected by reading the RTC at 12 o'clock and adding or dropping steps as appropriate.

 

Link to comment
Share on other sites

Since I'm only using one or two new steps (8 half-steps) there is no need for a step counter in the routine - for two I can just call it twice.  I have a new routing called stepForward with a phase time of 10ms rather than 1ms.  I think that should be plenty :)  Here is the routine.  The order is reversed because the rotation is reversed between motor shaft and minute wheel.  This routine sends 8 half-steps to the motor.

void stepForward(void)
{
  for(int i = 7; i >= 0; i--)
  {
    digitalWrite(motorPin1, bitRead(lookup[i], 3));
    digitalWrite(motorPin2, bitRead(lookup[i], 2));
    digitalWrite(motorPin3, bitRead(lookup[i], 1));
    digitalWrite(motorPin4, bitRead(lookup[i], 0));
    delayMicroseconds(10000);
  }
}

Now to re-calculate the step rate to be sent to the motor.  Actual stepper (before gearbox) rotates 64 half-steps per revolution.  Thus at the output shaft this becomes gb-ratio x 64 = 63.68395 x 64 = 4075.7728.  Now the stepForward subroutine produces 8 half-steps per call so we have 4075.7728 / 8 call per revolution = 509.4716.  Ratio of gears from motor to minute hand is 8:45 so one revolution of the minute hand = 509.4716 x 45 \ 8 = 2865.77775.  One revolution of the minute hand = 3600s so we need 2865.77775 / 3600 = 0.796049375 calls to stepForward per second.

I'm allowing for the awkward gearbox ratio by successive approximation (to use it's mathematical description) whereby we get closer and closer to the desired value by adding or dropping steps at successively longer intervals until we get within a few seconds in 12 hours whereupon the residual error may be corrected by reading the RTC at 12 o'clock and adding or dropping calls as appropriate.

Requiring 0.796049375 the first approximation is 0.8 which means 4 runs of 1 call followed by doing nothing for the fifth.  Thus every 5s we have 1+1+1+1+0 or 4 in every 5 giving an average of 0.8.

Second approximation takes the remainder and calculates the nearest whole number of seconds that will get as close as possible.  So we have 0.8 and require 0.796049375 which is again slightly less so we drop a call.  The amount is 0.8 - 0.796049375 = 0.003950625 which is 1 in 253.124505616199968359436797975 and nearest whole number is 253.  So next approximation is to drop a call every 253 seconds.

Third approximation is calculated from the difference between the current correction and the required correction.  Current correction is 1/253 plus the 0.2 from the first.  1/253 = 0.00395256916996047430830039525692 and the required correction for this stage = 0.003950625 so this correction is the difference = 0.003952569 - 0.003950625 = 0.000001944.  ie. 1 in 514403 which is about 2 parts per million and well within a second per 12 hours.  (1s in 12h = 3600x12 = 43200.  So a third approximation isn't needed.

Well that's my calculations - hope they're right :D

This is the new part of the sketch.

void stepForward(void)
{
  for(int i = 7; i >= 0; i--)
  {
    digitalWrite(motorPin1, bitRead(lookup[i], 3));
    digitalWrite(motorPin2, bitRead(lookup[i], 2));
    digitalWrite(motorPin3, bitRead(lookup[i], 1));
    digitalWrite(motorPin4, bitRead(lookup[i], 0));
    delayMicroseconds(10000);
  }
}
//
void timerIsr() {
  if (!timeIsSet) { return; } // Ignore the interrupt and return while setting the clock
  gbCount ++; // Increment gearbox count
  if (gbCount >= 253) { gbCount = 0; }              // skip call to stepForward
    else if ((gbCount % 5) != 0) { stepForward(); } // normal call to stepForward but skip 1 in 5
//
//  Remove all current from stepper motor
    digitalWrite(motorPin4, 0);
    digitalWrite(motorPin1, 0);
    digitalWrite(motorPin2, 0);
    digitalWrite(motorPin3, 0);
}

 

Link to comment
Share on other sites

Post didn't upload - good job I kept a copy - it was just this :-

"Clock reset and time correct at 1:37pm  ie. 2016-03-04 1337."

 

Link to comment
Share on other sites

3pm and the clock appears to be about 15s fast :(  There can be some error due to inaccurate dial alignment and also due to parralax so although the clock appears to be gaining around 10s and hour, it might not be.  The only way to be sure is to take the reading when the minute hand is in the same position each time such as 12 o'clock. So I'll leave the clock running for a few hours and check on the hour.

I have checked the calculation and get exactly the same result.  The gears of the clock are exact for ratio - there can be no slippage or anything like that.  I can understand the stepper motor losing a step or two but see no mechanism for gaining. 

The assumption that all these stepper motors are identical could be flawed.  There is no maker's name - just the model number and a serial number plus the voltage - 5v or 12v.  The latter just might mean there are two different versions with the vanishingly small possibility that the gearboxes could be different.  I wonder...

 

Link to comment
Share on other sites

I suppose I could take a stepper motor apart and examine the gearbox :eek:   OTOH I could use Hugh's suggestion of testing a stepper motor on its own (not on the clock that is).  Using a separate Arduino Nano I could write a sketch to rotate the motor shaft by a whole number of turns and then check the pointer to see what error there was.

INTERRUPT :-  The hour is 4pm and the clock is definitely around 30s fast ie. 20s more than at 3pm.  I'll report at 5pm... Back to post topic...

I would want to check that the rotation was correct to within the equivalent of a second in 12 hours of the clock.  Number of calls to the stepForward subroutine is about 0.8 a second.  Seconds in 12 hours = 43200.  Thus calls to stepForward would be 34560.  Half-steps for 12 clock rotation will be 8 x 34560 = 276480.  Half-steps per revolution was said to be 4075.7728 so we need a minimum of 276480 / 4075.7728 revolutions of the motor shaft = 67 odd revolutions.  Let's say 100 revolutions then errors could be worked out as percentages.

100 revolutions will be 100 x 4075.7728 = 407577.28 half steps.  We can divide that by 8 for number of calls to stepForward and get 50947.16 or 50947 which is well within the accuracy of a second in 12 hours (1 in 43200).

Time expected for this test to run = 50947 x 8 x 10ms = 4075760ms = 4076s = 68m or 1h 8m.

Here is the test sketch.

// Filename :- Moon_Clock_Test_for_stepper_gearbox_01
// Arduino test sketch for 28BYJ-48 to calibrate gearbox
//
//declare variables for the motor pins
int motorPin1 = 2;  // Blue   - 28BYJ-48 pin 1
int motorPin2 = 3;  // Pink   - 28BYJ-48 pin 2
int motorPin3 = 4;  // Yellow - 28BYJ-48 pin 3
int motorPin4 = 5;  // Orange - 28BYJ-48 pin 4
int lookup[8] = {B01000, B01100, B00100, B00110, B00010, B00011, B00001, B01001};
//
void setup() {
  pinMode(motorPin1, OUTPUT);
  pinMode(motorPin2, OUTPUT);
  pinMode(motorPin3, OUTPUT);
  pinMode(motorPin4, OUTPUT);
}
//
void stepForward(void){
  for(int i = 7; i >= 0; i--) {
    digitalWrite(motorPin1, bitRead(lookup[i], 3));
    digitalWrite(motorPin2, bitRead(lookup[i], 2));
    digitalWrite(motorPin3, bitRead(lookup[i], 1));
    digitalWrite(motorPin4, bitRead(lookup[i], 0));
    delayMicroseconds(10000);  }
}
//
void loop(){
  for (long i = 50947; i >= 0; i--) { stepForward(); }  // rotate motor shaft 100 turns
}
// End

 

Link to comment
Share on other sites

I've had a thought about the way I'm running the stepper motor.  This is to send pulses to the coils over 8 half steps then switch the current off to save power (in case I want to use a backup battery for power cuts) and to keep the motor cool (though at rated voltage there shouldn't be any problem of overheating even running continuously).  I'm wondering if the motor could be "running on" after the burst each second.

I'll check again at 5pm but I think I'll try without the power off sequence between ticks.

Link to comment
Share on other sites

Just after the last post the power went off and it's only just come back on :eek: 

Commented out the stepper power off between bursts and trying again.

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. By using this site, you agree to our Terms of Use.