/elec/propeller-clock

To get this branch, use:
bzr branch http://bzr.ed.am/elec/propeller-clock

« back to all changes in this revision

Viewing changes to src/propeller-clock.ino

  • Committer: edam
  • Date: 2012-01-26 23:54:36 UTC
  • Revision ID: edam@waxworlds.org-20120126235436-mlq6e00q6rxqudy2
updated schematic

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * propeller-clock.pde
 
2
 * propeller-clock.ino
3
3
 *
4
 
 * Copyright (C) 2011 Tim Marston <edam@waxworlds.org>
 
4
 * Copyright (C) 2011 Tim Marston <tim@ed.am> and Dan Marston.
5
5
 *
6
6
 * This file is part of propeller-clock (hereafter referred to as "this
7
 
 * program"). See http://ed.am/software/arduino/propeller-clock for more
 
7
 * program"). See http://ed.am/dev/software/arduino/propeller-clock for more
8
8
 * information.
9
9
 *
10
10
 * This program is free software: you can redistribute it and/or modify
23
23
 
24
24
/******************************************************************************
25
25
 
26
 
  For a schematic, see propeller-clock.sch.
27
 
 
28
 
  Set up as follows:
29
 
 
30
 
  - a PC fan is wired up to the 12V supply.
31
 
 
32
 
  - the fan's SENSE (tachiometer) pin is connected to pin 2 on the
33
 
    arduino.
34
 
 
35
 
  - the pins 4 to 13 on the arduino should directly drive an LED (the
36
 
    LED on pin 4 is in the centre of the clock face and the LED on pin
37
 
    13 is at the outside.
38
 
 
39
 
  - if a longer hand (and a larger clock face) is desired, pin 4 can
40
 
    be used to indirectly drive (via a MOSFET) multiple LEDs which
41
 
    turn on and off in unison in the centre of the clock.
42
 
 
43
 
  - a button should be attached to pin 3 that grounds it when pressed.
44
 
 
45
 
  Implementation details:
46
 
 
47
 
  - the timing of the drawing of the clock face is recalculated with
48
 
    every rotation of the propeller (for maximum update speed).
49
 
 
50
 
  - pressing the button cycles between display modes
51
 
 
52
 
  - holding down the button for 2 seconds enters "set time" mode. In
53
 
    this mode, the fan must be held still and the LEDs will indicate
54
 
    what number is being entered for each time digit. Pressing the
55
 
    button increments the current digit. Holding it down moves to the
56
 
    next digit (or leaves "set time" mode when there are no more). In
57
 
    order, the digits (with accepted values) are: hours-tens (0 to 2),
58
 
    hours-ones (0 to 9), minutes-tens (0 to 5), minutes-ones (0 to 9).
 
26
Set up:
 
27
 
 
28
 * a PC fan is wired up to a 12V power supply
 
29
 
 
30
 * the fan's SENSE (tachiometer) pin connected to pin 2 on the
 
31
   arduino.
 
32
 
 
33
 * the pins 4 to 13 on the arduino should directly drive an LED (the
 
34
   LED on pin 4 is in the centre of the clock face and the LED on pin
 
35
   13 is at the outside.
 
36
 
 
37
 * if a longer hand (and a larger clock face) is desired, pin 4 can be
 
38
   used to indirectly drive a transistor which in turn drives several
 
39
   LEDs that turn on anf off in unison in the centre of the clock.
 
40
 
 
41
 * a button should be attached to pin 3 that grounds it when pressed.
 
42
 
 
43
 * A DS1307 remote clock is connected via I2C on analog pins 4 and 5.
 
44
 
 
45
Implementation details:
 
46
 
 
47
 * for a schematic, see ../project/propeller-clock.sch.
 
48
 
 
49
 * the timing of the drawing of the clock face is recalculated with
 
50
   every rotation of the propeller.
 
51
    
 
52
 * a PC fan actually sends 2 tachiometer pulses per revolution, so the
 
53
   software skips every other one. This means that the clock may
 
54
   appear upside-down if started with the propeller in the wrong
 
55
   position. You will need to experiment to dicsover the position that
 
56
   the propeller must be in when starting the clock.
 
57
    
 
58
Usage instructions:
 
59
 
 
60
 * pressing the button cycles between variations of the current
 
61
   display mode.
 
62
  
 
63
 * pressing and holding the button for a second cycles between display
 
64
   modes (e.g., analogue and digital).
 
65
 
 
66
 * pressing and holding the button for 5 seconds enters "time set"
 
67
   mode. In this mode, the following applies:
 
68
    - the field that is being set flashes
 
69
    - pressing the button increments the field currently being set
 
70
    - pressing and holding the button for a second cycles through the
 
71
      fields that can be set
 
72
    - pressing and holding the button for 5 seconds sets the time and
 
73
      exits "time set" mode
59
74
 
60
75
******************************************************************************/
61
76
 
62
77
 
63
78
#include <Bounce.h>
 
79
#include <DS1307.h>
 
80
#include <Wire.h>
64
81
 
65
82
//_____________________________________________________________________________
66
83
//                                                                         data
143
160
}
144
161
 
145
162
 
 
163
// turn an led on/off
 
164
void ledOn( int num, bool on )
 
165
{
 
166
        if( num < 0 || num > 9 ) return;
 
167
 
 
168
        // convert to pin no.
 
169
        num += 4;
 
170
 
 
171
        // pin 4 needs to be inverted (it's driving a PNP)
 
172
        if( num == 4 ) on = !on;
 
173
 
 
174
        digitalWrite( num, on? HIGH : LOW );
 
175
}
 
176
 
 
177
 
146
178
// draw a segment for the test display
147
179
void drawNextSegment_test( bool reset )
148
180
{
152
184
        segment++;
153
185
 
154
186
        // turn on inside and outside LEDs
155
 
        digitalWrite( 4, HIGH );
156
 
        digitalWrite( 13, HIGH );
 
187
        ledOn( 0, true );
 
188
        ledOn( 9, true );
157
189
 
158
190
        // display segment number in binary across in the inside LEDs,
159
191
        // with the LED on pin 12 showing the least-significant bit
160
192
        for( int a = 0; a < 8; a++ )
161
 
                digitalWrite( 12 - a, ( ( segment >> a ) & 1 )? HIGH : LOW );
 
193
                ledOn( 8 - a, ( segment >> a ) & 1 );
162
194
}
163
195
 
164
196
 
165
197
// draw a segment for the time display
166
198
void drawNextSegment_time( bool reset )
167
199
{
168
 
        static unsigned int second = 0;
169
 
        static unsigned int segment = 0;
 
200
        static int second = 0;
 
201
        static int segment = 0;
170
202
 
171
203
        // handle display reset
172
204
        if( reset ) {
175
207
        }
176
208
 
177
209
        // what needs to be drawn?
178
 
        bool draw_tick = second % 5 == 0;
179
 
        bool draw_second = second == time_seconds;
180
 
        bool draw_minute = second == time_minute;
181
 
        bool draw_hour = second == time_hour;
 
210
        bool draw_tick = !segment && second % 5 == 0;
 
211
        bool draw_second = !segment && second == time_seconds;
 
212
        bool draw_minute = !segment && second == time_minutes;
 
213
        bool draw_hour = !segment && second == time_hours;
182
214
 
183
215
        // set the LEDs
184
 
        digitalWrite( 13, HIGH );
185
 
        digitalWrite( 12, draw_tick || draw_minute );
186
 
        for( int a = 10; a <= 11; a++ )
187
 
                digitalWrite( a, draw_minute || draw_second );
188
 
        for( int a = 4; a <= 9; a++ )
189
 
                digitalWrite( 10, draw_minute | draw_second || draw_hour );
 
216
        ledOn( 9, true );
 
217
        ledOn( 8, draw_tick || draw_minute );
 
218
        for( int a = 6; a <= 7; a++ )
 
219
                ledOn( a, draw_minute || draw_second );
 
220
        for( int a = 0; a <= 5; a++ )
 
221
                ledOn( a, draw_minute || draw_second || draw_hour );
190
222
 
191
223
        // inc position
192
224
        if( ++segment >= NUM_SECOND_SEGMENTS ) {
292
324
        // set up mode-switch button on pin 3
293
325
        pinMode( 3, INPUT );
294
326
 
 
327
        // get the time from the real-time clock
 
328
        int rtc_data[ 7 ];
 
329
        RTC.get( rtc_data, true );
 
330
        time_hours = rtc_data[ DS1307_HR ];
 
331
        time_minutes = rtc_data[ DS1307_MIN ];
 
332
        time_seconds = rtc_data[ DS1307_SEC ];
 
333
 
295
334
        // serial comms
296
335
        Serial.begin( 9600 );
297
336
}