Archive for November, 2009

    Steam Clock code

    Wednesday, November 11th, 2009

    As promised, here is the steam clock source code.

    It uses two non-standard Arduino libraries:

    1. Stepper – with half-stepping
    2. DateTime – a software clock

    The code is pretty straightforward. move() does most of the stepper work. hour() and minute() do the minimal calculation needed to point at the right places on the dial. minute() is used for seconds as well. wiggle() bounces the needle around the current point. Its fun to look at and makes a nice noise.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    
    #include <DateTime.h>
    #include <Stepper.h>
     
    #define TIME_MSG_LEN  11   // time sync to PC is HEADER and unix time_t as ten ascii digits
    #define TIME_HEADER  't'   // Header tag for serial time sync message
    #define TZ 8               // How many hours off of GMT are you?
     
    Stepper s(200, 4,5,6,7, 1);  // Stepper is on pins 4, 5, 6, 7.  Using the enhanced Stepper library with half-stepping.
     
    int p = 0;
     
    void setup() {
      Serial.begin(9600);
      Serial.println("Steam Clock 0.8");
     
      DateTime.sync(10000000);  // Needs to come from RTC.
     
      pinMode(2, INPUT);  // home sensor
      pinMode(3, OUTPUT); // home ir led
     
      find_home();
      allminutes();
      allhours();
      bouncehome();
    }
     
    void find_home() {
      digitalWrite(3, HIGH);  // turn on LED
      digitalWrite(2, HIGH);  // turn on pull-up for sensor
     
      for(int i=0; i < 900; i++) {
        s.step(1);
        delay(25);
        if(digitalRead(2)) {
           Serial.println("Home!!!");
            p = 0;
           break;
         }
       }
     
       digitalWrite(3, LOW);  // turn off LED
       digitalWrite(2, LOW);  // turn off pull-up.
    }
     
    void allminutes() {
      for(int t=0;t<=60;t++) {
        minute(t);
        delay(500);
        if(t % 10 == 0) {
          wiggle(20);
          delay(500);
        } 
      }
    }
     
    void allhours() {
      for(int t=0;t<=24;t++) {
         hour(t);
         delay(500);
      } 
    }
     
    void bouncehome() {
       minute(0);
       wiggle(100); 
    }
     
    void move(int to,int speed) {
      s.setSpeed(speed);
      if(to != p) {
        int steps = to - p;
        s.step(steps);
        p += steps;
      }
    }
     
    void wiggle(int i) {
      s.setSpeed(200);
      for(; i > 1; i -= 5){
         s.step(i);
         s.step(-i);
         s.step(-i);
         s.step(i);
      }  
    }
     
    void hour(int h) {
    //  move((int)(h * 2.125), 200);  // this shoulnd't be a float...
      move((int)(h * 2), 200);  // oh, 2 seems to work better anyway. yay!
    }
     
    void minute(int m) {
      move(400 - (m * 4), 200);
    }
     
    void getPCtime() {
      // if time available from serial port, sync the DateTime library
      while(Serial.available() >=  TIME_MSG_LEN ){  // time message
        if( Serial.read() == TIME_HEADER ) {        
          time_t pctime = 0;
          for(int i=0; i < TIME_MSG_LEN -1; i++){   
            char c= Serial.read();          
            if( c >= '0' && c <= '9')   
              pctime = (10 * pctime) + (c - '0') ; // convert digits to a number            
          }   
          DateTime.sync(pctime - (TZ * 60 * 60));   // Sync DateTime clock to the time received on the serial port
        }  
      }
    }
     
    void debugOutput() {
      Serial.print('t');
      Serial.println(DateTime.now()); 
     
      Serial.print(DateTime.Hour, DEC);
      Serial.print(':');
      Serial.print(DateTime.Minute, DEC);
      Serial.print(':');
      Serial.println(DateTime.Second, DEC);
     
      Serial.print(DateTime.Day, DEC);
      Serial.print('/');
      Serial.print(DateTime.Month, DEC);
      Serial.print('/');
      Serial.println(DateTime.Year, DEC);
    }
     
    void loop() {
      getPCtime();
      debugOutput();
     
      DateTime.available();
      hour(DateTime.Hour);
      wiggle(20);
      delay(2000);
     
      DateTime.available();
      minute(DateTime.Minute);
      wiggle(20);
      delay(2000);
     
      DateTime.available();
      minute(DateTime.Second);
     
      DateTime.available();
      if(DateTime.Second < 50) {
         move(400 - ((DateTime.Second + 10) * 4), 1);
      } else {
         move(400 - ((60) * 4), 1);
      }
    }

    Steam Clock

    Tuesday, November 10th, 2009

    I picked up an old pressure gauge from my local reclaimed building hardware co-op (RE-store!).  I’ve had it for several months with the idea to replace the guts with a stepper motor to allow microcontroller control of the needle.  In the end it has turned into a clock!

    Steam Clock brass core

    This is the ‘core’ of the meter.  It originally had a pressure tube meter movement thing hanging off it.  I remove that part and drilled out the copper body to more easily handle power wires.

    Stepper motor mount.

    Where the meter movement itself went now needed to go a stepper motor.  This aluminum plate holds the motor.  The plate is made of aluminum salvaged from a CommutaCar charger case.  The standoffs are from the voice coil assembly of an old hard drive.

    Stepper motor clearance!

    This is the stepper motor itself.

    Stepper and 'home' sensor.

    This is the stepper motor mounted and the ‘home’ sensor added.

    Movement!

    This then is the whole working clock.

    Clock components:

    1. Meter movement itself.  (lower left)
    2. Arduino.  (upper right)
    3. Darlington motor driver. (middle)
    4. Home sensor.  (under clock face)
    5. Power supply.  (on the left)
    6. Real time clock.  (not pictured)

    Many of the parts were ‘rescued’ from old hardware.  The stepper motor is from an old HP DLT tape drive (each of these drives have 3 steppers in them!  Plus a bunch of bearings and a brushless motor).  The Home sensor is an IR beam-break (what are those called anyway?) detector.  Both its LED and detector are directly connected to the AVR.  They are turned on for calibration and then turned back off.  The Darlington driver chip was in my junk box.  It just provides more current handling than the AVR can do on its own.  The real time clock and power supply will be new parts.

    When complete the guts will all fit behind the clock face.  The arduino will be replaced with a ‘naked’ ATMEGA168 (probably, or a mega8 if the code will fit).  The power supply will be swapped out for another regulator since the one on the breadboard doesn’t work very well (it has an overly sensitive PTC thingy that likes to shut it down for no reason).  I don’t have the real time clock yet, but it will be a self-contained clock chip with a backup battery.  Probably a DS1307.

    The arduino code uses two libraries: Stepper, to run the motor, and DateTime, which is used to keep the time.  When the RTC is added it will be used to ‘seed’ the DateTime with the real time every once in a while (hourly?).  I’m guessing the clock will keep better time than the arduino, thus the desire to resync every once in a while.

    The next post will include code!

    Looking for something?

    Use the form below to search the site:

    Still not finding what you're looking for? Drop a comment on a post or contact us so we can take care of it!

    Visit our friends!

    A few highly recommended friends...

    Archives

    All entries, chronologically...