Automated Perpetual Calendar

66,861

1,036

106

Introduction: Automated Perpetual Calendar

About: My name is Troy. I'm a Mechatronics and Aerospace Engineer. I make things out of wood and electronics and spend time outdoors (especially SCUBA diving).

Years ago I came across a wooden perpetual calendar and I loved the idea. After thinking about it for months I decided I wanted to make one myself; however, there was a long list of things I wanted to do to improve on the idea. The most important change I wanted to make, is to automate the rings. I know me, and based on current wall calendars not showing the correct month for some time, if a daily change is necessary it would likely only be accurate a small percentage of the year.

Combining microcontrollers, 3D printing, woodworking, and laser jet image transfer, this project will have something for everyone to learn.

Step 1: Tools and Materials

Materials:

Tools:

Step 2: Cut Segments for Seven Segment "Week Day" Ring

Using the same method and calculations shown in my Segmented Bowl instructable, cut 21 segments that are 3/16 in. thick.

Glue together seven segments at a time resulting in three rings that are 3/16 in. thick each. This ring should be able to fit a 10 in. OD and 7 in. ID ring inside.

Step 3: Combine RIngs

I knocked off the corners of the rings, but this is not necessary. Sand the faces of each ring until they are flat. I used 80 grit sandpaper glued to my table.

Glue together the three rings so the seams are alternating. This gives the rings high strength from gluing the side grain of the wood.

Step 4: Cut and Assemble 12 Segment "Month" Ring

Follow the same math included in my Segmented Bowl instructable to cut 36 segments for three 12 segment rings 3/16 in. thick.

Glue this ring and the next ring together in smaller sections. Sand each face as before and combine the three rings by alternating the seams to increase ring strength.

This ring should be able to fit a 16 in. OD and 13 in. ID ring inside.

Step 5: Cut and Assemble 31 Segment "Number of Day" Ring

Follow the same math included in my Segmented Bowl instructable to cut 93 segments for three 31 segment rings 3/16 in. thick.

Glue this ring and the next ring together in smaller sections. Sand each face as before and combine the three rings by alternating the seams to increase ring strength.

This ring should be able to fit a 22 in. OD and 19 in. ID ring inside.

Step 6: Apply Ring Template

Print out and tape together the 1:1 template and cut out the individual rings. This will aid in getting the rings the exact size necessary. There are blue tick marks to help with aligning the template to each segment.

Step 7: Trim Each Ring

Using a disc sander and spindle sander, remove the wood to the outside circle of each ring.

Step 8: Print Ring Gears

Download and print the five files on this step. The names of each file include a set of numbers. The second number in the file name indicate how many of that file to print.

Assemble the rings and press three magnets into the flat hole (not countersunk screw holes) with the south pole facing the top. Magnets need to only be included on one segment of each ring.

Step 9: Route Ring Gear Groove

Using a 1/4 in. rabbeting bit, cut a rabbet on the back of each ring. If the ring gear doesn't quite fit, take light passes off the inside of the ring on the spindle sander then re cut the rabbet on the router until it fits. Use a 1/4 in. roundover bit to smooth the not rabbet edges.

Step 10: Attach Ring Gears

Using the depth stop on the drill press, drill pilot holes through the ring gear into the wooden ring. Secure with screws.

Step 11: Print Bracket and Spur Gears

Print off brackets, three spur gears, Arduino mount, and 12 standoffs for holding electronics (not shown here) on this step.

Step 12: Ring Supports

Cut ring supports from a piece of hardwood that's 3/4 in. thick. Use disc and spindle sanders to refine shape.

Step 13: Attach Stepper and Bracket to Support

Shave the top open part of the bracket down to allow room for the machine screws holding the stepper motor in place. Drill pilot holes through the bracket and secure with screws.

Step 14: Add Spline

The brackets needed to be shaved down in a next step. To keep everything aligned, I added a spline across the back using the table saw.

Step 15: Cut Front Face

On a 1/4 in. board that measures 13 x 6 in. apply the included template. I used a jig saw to roughly cut the sections out then smoothed them out with a sanding stick.

Finally use an 1/8 in. roundover bit on the front of the board.

Step 16: Attach Supports

Glue supports in place. Position them using the completed rings.

Step 17: Attach Top and Bottom Standoffs

Attach wooden standoffs that measure 6 x 1 1/2 x 1 3/4 in. at the top and bottom. This will hold the rings away from the wall and give enough clearance for the electronics.

My pieces were just a bit larger, but I trimmed them to fit after the glue dried.

Sand and roundover edges.

Step 18: Attach Lables

For the transfer of ink I used the polycrylic method shown here. It's a simple but time consuming process.

Print off a few copies of the attached PDF so when you mess up you can try again right away. I was impatient with a few of the labels but I like the rustic look it provided. You can also touch up the labels with a sharpie or black paint.

Apply 3-4 coats of polycrylic to all rings and face.

Step 19: Insert Power Plug

Drill a hole the size of the threads on your plug. Then carefully drill a larger hole the outside diameter of the plug until the threads just stick out on the inside of the standoff.

Step 20: Assemble Electronics and Upload Code

Following the attached schematic, wire everything up and upload the code.

#include 
#include "RTClib.h"
RTC_DS1307 rtc;

// Call for steppers
#define oneRotation 2038 // the number of steps in one revolution of 28BYJ-48 stepper motor
Stepper numberOfDay(oneRotation, 2, 4, 3, 5);
Stepper nameOfMonth(oneRotation, 6, 8, 7, 9);
Stepper nameOfDay(oneRotation, 10, 12, 11, 13);

// Location of the hall effect sensors used to find the home position of the rings.
#define NUMBER_OF_DAY_SENSOR A0
#define NAME_OF_MONTH_SENSOR A1
#define NAME_OF_DAY_SENSOR A2

// Variables used to keep track of the current day.
uint8_t thisNumberDay = 0;
uint8_t thisMonth = 0;
uint8_t thisNameDay = 0;
uint8_t nextNumberDay = 0;
uint8_t nextMonth = 0;
uint8_t nextNameDay = 0;

// Constants used to advance each ring one day/month.
const int NUMBER_OF_DAY_TO_STEP = -1661;//1108 steps per day
const int NAME_OF_MONTH_TO_STEP = -2946;//1965 steps per month
const int NAME_OF_DAY_TO_STEP = -2745;//1831 steps per day
const int COUNTERCLOCKWISE = -1;

// Update these constants to adust the position of the rings at the reset position.
// Negative numbers will advance the rings forward (counterclockwise) positive will reverse the rings.
const int NUMBER_OF_DAY_RESET_ADJUST = -130;
const int NAME_OF_MONTH_RESET_ADJUST = -60;
const int NAME_OF_DAY_RESET_ADJUST = -35;

// Bit used to test if the ring has been reset to home.
bool NUMBER_OF_DAY_RESET = LOW;
bool NAME_OF_MONTH_RESET = LOW;
bool NAME_OF_DAY_RESET = LOW;

void setup() {
  Serial.begin(9600);
  rtc.begin();

  // Setup real time clock and reset hall effect sensors.
  pinMode(NUMBER_OF_DAY_SENSOR, INPUT_PULLUP);
  pinMode(NAME_OF_MONTH_SENSOR, INPUT_PULLUP);
  pinMode(NAME_OF_DAY_SENSOR, INPUT_PULLUP);


  // Uncomment line below to set time.
  // rtc.adjust(DateTime(2022, 1, 4, 23, 55, 0));
  // rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));

  // Get current date
  DateTime now = rtc.now();
  thisNumberDay = now.day();
  thisMonth =  now.month();
  thisNameDay = now.dayOfTheWeek();

  Serial.print("Date: ");
  Serial.print(thisNumberDay);
  Serial.print(" ");
  Serial.print(thisMonth);
  Serial.print(" ");
  Serial.println(thisNameDay);

  // Set top speed of stepper motors.
  numberOfDay.setSpeed(15);
  nameOfMonth.setSpeed(15);
  nameOfDay.setSpeed(15);

  // Loop to move any ring off of the hall effect sensor if it is currently tripped.
  while (digitalRead(NUMBER_OF_DAY_SENSOR) == LOW ||  digitalRead(NAME_OF_MONTH_SENSOR) == LOW || digitalRead(NAME_OF_DAY_SENSOR) == LOW)
  {
    if (digitalRead(NUMBER_OF_DAY_SENSOR) == LOW )
    {
      numberOfDay.step(COUNTERCLOCKWISE);
    }

    else
    {
      delay(1);
    }

    if (digitalRead(NAME_OF_MONTH_SENSOR) == LOW)
    {
      nameOfMonth.step(COUNTERCLOCKWISE);
    }

    else
    {
      delay(1);
    }

    if (digitalRead(NAME_OF_DAY_SENSOR) == LOW)
    {
      nameOfDay.step(COUNTERCLOCKWISE);
    }

    else
    {
      delay(1);
    }
  }

  // Loop until all rings are at the reset position.
  while (digitalRead(NUMBER_OF_DAY_SENSOR) != LOW || digitalRead(NAME_OF_MONTH_SENSOR) != LOW || digitalRead(NAME_OF_DAY_SENSOR) != LOW)
  {
    if (digitalRead(NUMBER_OF_DAY_SENSOR) != LOW )
    {
      numberOfDay.step(COUNTERCLOCKWISE);
    }

    else
    {
      delay(1);
    }

    if (digitalRead(NAME_OF_MONTH_SENSOR) != LOW )
    {
      nameOfMonth.step(COUNTERCLOCKWISE);
    }

    else
    {
      delay(1);
    }

    if (digitalRead(NAME_OF_DAY_SENSOR) != LOW)
    {
      nameOfDay.step(COUNTERCLOCKWISE);
    }

    else
    {
      delay(1);
    }
  }

  //  Use these functions to carefully adjust position of rings after it's been reset.
  numberOfDay.step(NUMBER_OF_DAY_RESET_ADJUST);
  nameOfMonth.step(NAME_OF_MONTH_RESET_ADJUST);
  nameOfDay.step(NAME_OF_DAY_RESET_ADJUST);

  // Move each ring to the correct number, month, and day of week
  for (int i = 1; i < thisNumberDay; i++)
  {
    numberOfDay.step(NUMBER_OF_DAY_TO_STEP);
  }

  for (int i = 1; i < thisMonth; i++)
  {
    nameOfMonth.step(NAME_OF_MONTH_TO_STEP);
  }

  for (int i = 0; i < thisNameDay; i++)
  {
    nameOfDay.step(NAME_OF_DAY_TO_STEP);
  }

}

void loop() {

  // Check the current day number
  DateTime now = rtc.now();
  nextNumberDay = now.day();


  // If the current checked day is different than it was last time it was checked, move the rings to the next date.
  if (thisNumberDay != nextNumberDay)
  {
    // Get the next month and day of week.
    nextMonth =  now.month();
    nextNameDay = now.dayOfTheWeek();

    // If the number of the day is 1 (and it's not currently at 1) reset to 1
    if (nextNumberDay == 1 && thisNumberDay >= 28)
    {
      while (digitalRead(NUMBER_OF_DAY_SENSOR) != LOW)
      {
        numberOfDay.step(COUNTERCLOCKWISE);
        NUMBER_OF_DAY_RESET = HIGH;
      }
      numberOfDay.step(NUMBER_OF_DAY_RESET_ADJUST);
    }

    // If the month is Jan and was Dec, rest to Jan.
    if (nextMonth == 1 && thisMonth == 12)
    {
      while (digitalRead(NAME_OF_MONTH_SENSOR) != LOW)
      {
        nameOfMonth.step(COUNTERCLOCKWISE);
        NAME_OF_MONTH_RESET = HIGH;
      }
      nameOfMonth.step(NAME_OF_MONTH_RESET_ADJUST);
    }

    // If the day is Sun but was Sat, reset to Sun.
    if (nextNameDay == 0 && thisNameDay == 6)
    {
      while (digitalRead(NAME_OF_DAY_SENSOR) != LOW)
      {
        nameOfDay.step(COUNTERCLOCKWISE);
        NAME_OF_DAY_RESET = HIGH;
      }
      nameOfDay.step(NAME_OF_DAY_RESET_ADJUST);
    }

    // If the ring wasn't reset to the beginning and needs to change, step to the next position
    if (NUMBER_OF_DAY_RESET == LOW && thisNumberDay != nextNumberDay)
    {
      numberOfDay.step(NUMBER_OF_DAY_TO_STEP);
    }

    if (NAME_OF_MONTH_RESET == LOW && thisMonth != nextMonth)
    {
      nameOfMonth.step(NAME_OF_MONTH_TO_STEP);
    }

    if (NAME_OF_DAY_RESET == LOW && thisNameDay != nextNameDay)
    {
      nameOfDay.step(NAME_OF_DAY_TO_STEP);
    }

    // reset check values to test each loop
    thisNumberDay = nextNumberDay;
    thisMonth = nextMonth;
    thisNameDay = nextNameDay;
    NUMBER_OF_DAY_RESET = LOW;
    NAME_OF_MONTH_RESET = LOW;
    NAME_OF_DAY_RESET = LOW;
  }

  delay(60000);
}

Step 21: Enjoy!

Now hang up your new calendar and always enjoy knowing what date it is without needing to use any brain power.

2 People Made This Project!

Recommendations

  • Summer Fun: Student Design Challenge

    Summer Fun: Student Design Challenge
  • Maps Challenge

    Maps Challenge
  • Make it Fly Challenge

    Make it Fly Challenge

106 Comments

0
UweHH
UweHH

6 months ago

Great project, but I've made some changes for myself. First, I reduced the diameter of the rings. The outer ring now has a diameter of 20 cm, for the days of the week there is now a disc with a 9 cm diameter that is attached directly to the stepper motor. For the test everything is printed on the 3D printer, later the rings are produced on the CNC milling machine.
Furthermore, I found it unnecessary that the motors constantly receive the holding current and thus the motors get unnecessarily hot. The circuit needs about 900mA permanently. To reduce this, the motors should only be supplied with power when they are really needed.
To do this, I changed the sketch and added functions with which the stepper drivers are switched on at the right moment.
A MOSFET switches the ON / OFF PIN of the driver. These MOSFETs are controlled by D0 and D1, where D0 only controls the driver for the month ring and D1 controls the drivers for the day of the week and the date.
In the sketch, a function is inserted at the appropriate points in order to switch on the driver at the right moment.
The circuit now works with a supply of 6V DC and a quiescent current of 150 mA. Perhaps that could be further reduced to make battery supply possible.

My test setup is a prototype, but it works ;-)

CircularCalendar.jpg
0
JonS4
JonS4

6 months ago

Very cool. I once made a clock with a similar design, it used a large ring with hours and minutes cut into the face and gear teeth cut into the inner edge. The teeth on the ring match teeth on a motor geared to turn at a very specific speed. The motor turned once per hour and the ring had 12x as many gear teeth as the motor. No need for the Arduino, RTC and Sensors

0
UweHH
UweHH

Reply 6 months ago

"simply anyone can"...they say in germany ;-)

0
FranciscoR130
FranciscoR130

Question 9 months ago

good and made your montage which is very well sprinkled all the motaje but I have a peguiño can you allude me with the failure the rings do not stop rolling and I do not know what the failure is and I rebissado everything but I can not find the failure
It is powered by 2 batteries type 18650 3000Ah a3.4 v it may be the fault
greetings and thank you very much for the prototype is very good

0
UweHH
UweHH

Answer 6 months ago

The power supply must be 5V.

0
Andrew Sleigh
Andrew Sleigh

7 months ago

Hi - I'm trying to make this and modelling it in Fusion so I can cut some parts on the laser and 3D print others. Do you have measurements for the key parts? - eg I'm at the stage of trying to figure out how deep to inset the rings to take the gears, but there are no measurements, only the instruction to use a 1/4" router bit...

0
tomatoskins
tomatoskins

Reply 7 months ago

Yeah, I guess I used the printed rings to measure the depth. It should be 1/4 in. deep as well. Sorry for the confusion. Let me know if you have any other questions.

0
Mike6158
Mike6158

Question 11 months ago

I've been looking into 3D printing for about a year. There are "best printer for 2020" articles all over the web. Which printer did you use to print these parts?

0
tomatoskins
tomatoskins

Answer 11 months ago

I started this project using an old Afinia printer. However it stopped working half way through the project. I finished it using a Creality 10.

0
Mike6158
Mike6158

Reply 11 months ago

Thank you for the reply. I've been looking at the Ender 5 Pro but from what I can tell it needs upgrades right out of the box. Maybe that's just 3D printers. I'll look into the Creality 10.

1
mastiffmike
mastiffmike

1 year ago

Nice work! If I had the tools and talent I'd make a version that includes the time of day. Something along the lines of this:

RING-CLOCK.png
0
woodchipwilbur
woodchipwilbur

Reply 11 months ago

*I* think that looks top-heavy. The rings in the original design work because they are hanging down on the stepper motor gear. The top ones can't do that - and there is little to stop them trying to topple over. I mulled over this sort of project and reckoned that it was better either to make a second, companion clock (maybe even three rings, and include the seconds?) or to add the two extra rings as smaller ones with hours on the bigger one and minutes on the smaller (just 5-10-15 etc - or even 0-15-30-45).

1
gordyt47
gordyt47

1 year ago

I do not see where you index the magnets to the numbers or words? I am have laser cut wood and need to locate the magnets.

0
tomatoskins
tomatoskins

Reply 1 year ago

The magnets are located in the back on the ring gear. I indexed them by placing the ring gears in the rabbets then slowly adjusting them until one of the segments is centered in the window. Once centered, I marked that as the home position of each ring. I'm not sure the best way to do this without an adjustable magnet on the back.

0
woodchipwilbur
woodchipwilbur

Reply 11 months ago

Presumably... If you have laser cut the wood, I am slightly guessing that you've not made each ring out of multiple segments. If that's the case, set the magnet anywhere and calibrate the machine. Mark where the "1", "January" and the "Sunday" ** windows sit on the machine and use that as the index for labelling the rings.
** Or is it the secular start of the week, on a Monday?!
I'll repeat that you need to be very careful - if you follow the steps though in the order given, you'll do a number of processes at the wrong time.

0
kuipers.henk
kuipers.henk

12 months ago

Very nice project! Starting to build one for meself. Do you have any plans or designs for a clock with hour and minutes? That would be super. Or can you help us with the desing of this clock, i do not have the programming and calculating skils.
Fantasic project!

2
Jan5412
Jan5412

Reply 11 months ago

Also had the idea to add minutes and hours and the construction in such a way that no 3D printer is needed. I'm going to think about it.

0
LienSnik
LienSnik

Question 12 months ago

I see in the printed parts there are some stand offs????
No mention anywhere to where they go??

0
woodchipwilbur
woodchipwilbur

Answer 12 months ago

They go between:
The Nano holder and the bottom stepper bracket (2)
The three stepper drivers and their associated stepper brackets (6)
Spares (I think) (4)
You need a bunch of M3 x 10mm setscrews (bolts) or the US equivalent.

0
kyfehr
kyfehr

Question 12 months ago on Step 8

For 3d printing the parts, no matter my printer settings the parts do not connect, the one end slot is too small or the other end is too large. Any tips to get these to print to fit better - settings used. Thanks.