ODD CLOCK

QUICK PROJECT DESCRIPTION

PROJECT OBJECTIVE: Build a non-linear clock that displays time accurately in 5-minute steps.

HARDWARE REQUIREMENTS: Provided in the Mango Labs Mechatronics Maker Kit: Arduino-compatible board, USB cable, RTC module, 2 stepper motors, 2 stepper drivers, 10 male to male jumper cables, 16 male to female jumper cables, mini breadboard, power supply.

Additional hardware: computer, printer, cardboard (or foam-core, balsa wood or a thin, rigid board), glue gun, 4 3m stove bolts with nuts, small screwdriver, CR2032 coin battery, sanding paper (fine grain), epoxy glue. Optional: soldering iron, solder, fine solid-core wire.

SOFTWARE REQUIREMENTS: Arduino environment (or online editor). Download the RTC library here and the stepper library here. Unzip and paste the folder in the Arduino libraries folder. It’s in the same location as your default sketches. You can look it up under File/Preferences Sketchbook location.

KNOW-HOW REQUIREMENTS: Basic Arduino environment knowledge (learn more here). Basic electrical skills.

QUICK OVERVIEW
  1. Print out these templates.
  2. Use the templates to make the parts in the material of your choice.
  3. Mount the stepper motors and microswitches in their corresponding positions.
  4. Glue the clock hands to the stepper shafts.
  5. Connect everything as shown in the diagram.
  6. Install the RTC and access stepper libraries (if you tested the board with the Hello World example you have the libraries already installed).
  7. Compile and upload this sketch to your board.
  8. Connect your Arduino-compatible board to the power supply.
  9. Calibrate your homing by ensuring that the clock hands close the microswitches and modifying the values on lines 156 and 188 to compensate the position if your hands don’t home at 12’o clock.
PIN OUT DIAGRAM
1
2
3
4
5
6
7
8
9
Odd Clock connections diagram
1

5 VOLTS and Ground for the RTC module

2

Black cable is Ground
Red cable is power (5 volts)
White cable goes from SCL to A5 on your Arduino compatible board
Turquoise cable goes from SDA to A4 on your Arduino compatible board

3

Stepper motors
(have keyed connectors)

4

Microswitches (homing switches)
Hour homing to Digital 10 on your Arduino compatible board
Minute homing to Digital 11 on your Arduino compatible board

5

Stepper driver for hour hand
IN1 to Digital 2 on your Arduino compatible board
IN2 to Digital 3 on your Arduino compatible board
IN3 to Digital 4 on your Arduino compatible board
IN4 to Digital 5 on your Arduino compatible board

6

Stepper driver for minute hand
IN1 to Digital 6 on your Arduino compatible board
IN2 to Digital 7 on your Arduino compatible board
IN3 to Digital 8 on your Arduino compatible board
IN4 to Digital 9 on your Arduino compatible board

7

Hour homing to Digital 10 on your Arduino compatible board
Minute homing to Digital 11 on your Arduino compatible board

8

Vin power distribution (power supply voltage in)

9

Use an external power supply, steppers are current hungry

SETUP

This example is made of plywood. Depending on the material you choose, you may have to adjust some assembly guidelines.

Use the template to cut out the pieces. After cutting out all the pieces, I sanded them, taking special care with the clock hands. The minute hand was sanded down 1 mm thinner than the hour hand, since the hour hand must be able to pass over the minute hand.

The shaft and mounting holes, as well as recesses to counter-sink the screw heads to mount the stepper motors, are shown in the print-out.

Be careful to mount the minute stepper with the screw heads below the surface level. I used a warm blob of hot glue to level the motor and mount it parallel to the back of the clock without counter-sinking the shaft. Don’t over-tighten the screws.

I recommend to counter-sink the hour stepper motor shaft by carving away a hole with a small abrasive tool (I used a Dremel with a sanding attachment) to mount it flush with the back of the clock.

The vibration of the motors will loosen the nuts. Use cyanoacrylate.

The best solution I found for fixing the hands to the stepper shafts was using a two-part epoxy glue. Most brands require 24 hours to cure, so be aware of the extra time you will need for this step. However, the epoxy glue is worth the wait because you need the hands to push the microswitches, and the lever action of the long hands exerts force on the shaft. Glue the minute hand first, flush with the clock face. In order to avoid gluing the motor stuck, I put a little grease on the bottom of the shaft. There are two rings on the clock template. They are spacers for raising the hour shaft. I used one, glued the hour clock pointing to six o’clock so that it rested on top of the minute hand and used folded paper as a spacer. The thickness of the material I used made it harder to space the hour hand any more, because of the microswitches’ size. If you can leave more space between the hands it will be easier to prevent the hands getting stuck.

For the minute homing microswitch, break away the metal lever with small pliers. Insert it from behind through the square hole, taking care not to hurt your fingers with the terminals. Connect cables to the C and NO terminals. If you don’t want to solder, you can use the female to male jumper cables and fix them to the microswitch using hot glue. For a more permanent installation you can solder some thin wires (I used solid core network cable stripped wires).

For the minute hand, the microswitch will be almost flush. For the hour hand it will be almost on top of the clock face. I fixed the microswitches from the back using a lot of hot glue. Calibration of the height is critical and should be done after the hands are already attached. You must make sure the hands will close the switches.

I sanded the edges of the microswitches round to avoid the hands getting stuck.

Arrange the components on the back of the clock and fix them using either hot glue or small screws, depending on the thickness of the material. Connect everything as shown on the diagram. You should hot glue all connections to prevent any problems (even the pros do it). Upload the code and connect your Arduino-compatible board to the power supply. Don’t forget to put the coin battery into the RTC module. If the hands don’t stop turning, it means the home switches aren’t closing and you need to raise the microswitches, bend the metal lever or find another way to make the hands close the switches. If the hands aren’t pointing precisely to the numbers (because your setup doesn’t close the home switches exactly on 12 o’clock) you can fix this in the code: adjust the homing position on line 156 for hours and line 188 for minutes. There is a comment on those lines signaling it is the place to do so. Use positive numbers to if your clock is overshooting and negative numbers if it is undershooting.

This clock is a metaphor for the non-linearity of time at a quantum level, where time leaps back and forth.
Get ready for some crazy times!

Have Fun!

CODE

/* By Dr. Mangus for www.mangolabs.de 
 *   
 *   Motor Homing by Yvan from Brainy Bits
 */

#include "AccelStepper.h" // Library created by Mike McCauley at http://www.airspayce.com/mikem/arduino/AccelStepper/

#include <SPI.h>
#include <Wire.h>
#include "RTClib.h"
RTC_DS1307 rtc;


// AccelStepper Setup
// Define a stepper and the pins it will use
AccelStepper stepperH(AccelStepper::FULL4WIRE, 2, 4, 3, 5);
                                  // 
                                  // 
AccelStepper stepperM(AccelStepper::FULL4WIRE, 6, 8, 7, 9);
                                  // 
                                  // 

// Define the Pins used
#define home_switch 10 // Pin 10 connected to hour Home Switch (MicroSwitch)
#define home_switchM 11 // Pin 11 connected to  minute Home Switch (MicroSwitch)

// Stepper Travel Variables
int move_finished=1;  // Used to check if move is completed
long initial_homing=-1;  // Used to Home Stepper at startup
long initial_homingM=-1;  // Used to Home Stepper at startup
//matrix representing real position of numbers
int positionH[13] = {0, 341, 682, 1706, 1193, 1857, 852, 0, 1535, 170, 1364, 1023, 511};
int positionM[12] = {682, 1535, 1877, 1023, 1193, 511, 0, 1364, 170, 341, 852, 1706};

DateTime now;
int hr;
int mi;
int mim;
int oldhr;
int oldmi;


void setup() {
   Serial.begin(9600);  // Start the Serial monitor with speed of 9600 Bauds
  //Establish connection with real time clock
  Wire.begin();
  if (!rtc.begin()) {
        Serial.print("RTC failed com");
  }
  
  //Set the time and date on the real time clock if necessary
  if (! rtc.isrunning()) {
    // following line sets the RTC to the date & time this sketch was compiled
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }

   
   pinMode(home_switch, INPUT_PULLUP);
     pinMode(home_switchM, INPUT_PULLUP);
   delay(5);  // Wait for EasyDriver wake up
   
   homeH();
   stepperH.disableOutputs();
   homeM();
  stepperM.disableOutputs();
  
  stepperH.setMaxSpeed(100.0);      // Set Max Speed of Stepper (Faster for regular movements)
  stepperH.setAcceleration(75.0);  // Set Acceleration of Stepper
  stepperM.setMaxSpeed(200.0);      // Set Max Speed of Stepper (Faster for regular movements)
  stepperM.setAcceleration(100.0);  // Set Acceleration of Stepper
  
   now = rtc.now();
  DateTime now = rtc.now();
  hr = now.hour();
    if (hr > 12)
  { hr = map(hr, 13, 24, 1, 12);} //convert from 24 to 12 hours
  mi = now.minute();
   mim = map(mi, 0, 60, 0, 12); //map 60 min to 12 positions on the clock
    Serial.println("Inital Time setting");
   stepperM.enableOutputs();
   stepperM.runToNewPosition(positionM[mim]);
   stepperM.disableOutputs();
   stepperH.enableOutputs();
   stepperH.runToNewPosition(positionH[hr]);
   stepperH.disableOutputs();
}

void loop() {

 DateTime now = rtc.now();
  hr = now.hour();
  mi = now.minute();
  if (hr > 12)
  { hr = map(hr, 13, 24, 1, 12);}
     mim = map(mi, 0, 60, 0, 12);
    // if minute changes (5-min steps) enable stepper and move
   if (mim != oldmi) {
    stepperM.enableOutputs();
      delay(5);
      if ((mim == 6) || (mim == 0)) homeM();
      oldmi = mim;
    stepperM.runToNewPosition(positionM[mim]);
    // serial print for testing purposes
  Serial.print(hr, DEC);
  Serial.print(':');
  Serial.print(mim, DEC);
  Serial.println();
  Serial.print(now.hour(), DEC);
  Serial.print(':');
  Serial.print(now.minute(), DEC);
  Serial.println();
  }
 stepperM.disableOutputs();
 // if hour changes enable stepper and move
 if (hr != oldhr) {
   stepperH.enableOutputs();
   delay(5);
   homeH();
    oldhr = hr;
   stepperH.runToNewPosition(positionH[hr]);
    }
 stepperH.disableOutputs();
 



}

float homeH(){
     //  Set Max Speed and Acceleration of each Steppers at startup for homing
  stepperH.setMaxSpeed(100.0);      // Set Max Speed of Stepper (Slower to get better accuracy)
  stepperH.setAcceleration(50.0);  // Set Acceleration of Stepper
 // Start Homing procedure of Stepper Motor at startup

  Serial.print("Stepper is Homing . . . . . . . . . . . ");

  while (digitalRead(home_switch)) {  // Make the Stepper move CCW until the switch is activated   
    stepperH.moveTo(initial_homing);  // Set the position to move to
    initial_homing--;  // Decrease by 1 for next move if needed
    stepperH.run();  // Start moving the stepper
    delay(5);
}

  stepperH.setCurrentPosition(0);  // Set the current position as zero for now
  stepperH.setMaxSpeed(100.0);      // Set Max Speed of Stepper (Slower to get better accuracy)
  stepperH.setAcceleration(50.0);  // Set Acceleration of Stepper
  initial_homing=1;

  while (!digitalRead(home_switch)) { // Make the Stepper move CW until the switch is deactivated
    stepperH.moveTo(initial_homing);  
    stepperH.run();
    initial_homing++;
    delay(5);
  }
  
  stepperH.setCurrentPosition(10); // change this value to calibrate homing of hours
  Serial.println("Homing Completed");
  Serial.println("");
}

float homeM(){
     //  Set Max Speed and Acceleration of each Steppers at startup for homing
  stepperM.setMaxSpeed(100.0);      // Set Max Speed of Stepper (Slower to get better accuracy)
  stepperM.setAcceleration(50.0);  // Set Acceleration of Stepper
 // Start Homing procedure of Stepper Motor at startup

  Serial.print("Stepper is Homing . . . . . . . . . . . ");

  while (digitalRead(home_switchM)) {  // Make the Stepper move CCW until the switch is activated   
    stepperM.moveTo(initial_homingM);  // Set the position to move to
    initial_homingM--;  // Decrease by 1 for next move if needed
    stepperM.run();  // Start moving the stepper
    delay(5);
}

  stepperM.setCurrentPosition(0);  // Set the current position as zero for now
  stepperM.setMaxSpeed(100.0);      // Set Max Speed of Stepper (Slower to get better accuracy)
  stepperM.setAcceleration(50.0);  // Set Acceleration of Stepper
  initial_homingM=1;

  while (!digitalRead(home_switchM)) { // Make the Stepper move CW until the switch is deactivated
    stepperM.moveTo(initial_homingM);  
    stepperM.run();
    initial_homingM++;
    delay(5);
  }
  
  stepperM.setCurrentPosition(-40);// change this value to calibrate homing of minutes
  Serial.println("Homing Completed");
  Serial.println("");
}