Vector Clock

From Public Wiki
Jump to navigation Jump to search

Synopsis

Use an oscilloscope in XY mode to display time. Uses two MCP4725 and a DS1302.

Notes

Known bug. 12 hour hand is missing. Hour hand does not creep, but instead moves in one hour notches. Ideally, use the Sine function to determine precise positioning.

Code

  1 //Arduino UNO
  2 //Pin 5  : DS1302 Chip Enable 
  3 //Pin 6  : DS1302 Data
  4 //Pin 7  : DS1302 Data Clock
  5 //Pin A4 : MCP4725 SDA pins
  6 //Pin A5 : MCP4725 SCK pins
  7 //
  8 //5 Volt pin powers all external devices
  9 //Please verify that your modules are also
 10 //compatible with a 5 volt supply.
 11 //
 12 //On the MCP4725 devices, attach one A0
 13 //pin to 5 volts and the other to ground
 14 //to ensure these are on different addresses
 15 //The SDA and SCK pins on these can be attached
 16 //to each other.  The device ID of the
 17 //MCP4725 had to be discovered experimentally
 18 //and you may need to discover those values as
 19 //well.
 20 //
 21 //On the MCP4725, choose the voltage out pins
 22 //to be connected to the X and Y inputs of
 23 //your oscilloscope such that the clock is suitably rotated.
 24 
 25 #include <Wire.h>
 26 #include <Adafruit_MCP4725.h>
 27 #include <DS1302.h>
 28 
 29 //Begin DS1302 Configuration
 30 const int kCePin  = 5;  // Chip Enable
 31 const int kIoPin   = 6;  // Input/Output
 32 const int kSclkPin = 7;  // Serial Clock
 33 DS1302 rtc(kCePin, kIoPin, kSclkPin);
 34 //End DS1302 Configuration
 35 
 36 // Begin MCP4725 Configuration
 37 Adafruit_MCP4725 dac_X;
 38 Adafruit_MCP4725 dac_Y;
 39 // End MCP4725 Configuration
 40 
 41 //timing and counnters
 42 long us;
 43 bool toggle;
 44 byte t=0;
 45 
 46 const uint16_t DACLookup_FullSine_8Bit[256] =
 47 {
 48   2048, 2098, 2148, 2198, 2248, 2298, 2348, 2398,
 49   2447, 2496, 2545, 2594, 2642, 2690, 2737, 2784,
 50   2831, 2877, 2923, 2968, 3013, 3057, 3100, 3143,
 51   3185, 3226, 3267, 3307, 3346, 3385, 3423, 3459,
 52   3495, 3530, 3565, 3598, 3630, 3662, 3692, 3722,
 53   3750, 3777, 3804, 3829, 3853, 3876, 3898, 3919,
 54   3939, 3958, 3975, 3992, 4007, 4021, 4034, 4045,
 55   4056, 4065, 4073, 4080, 4085, 4089, 4093, 4094,
 56   4095, 4094, 4093, 4089, 4085, 4080, 4073, 4065,
 57   4056, 4045, 4034, 4021, 4007, 3992, 3975, 3958,
 58   3939, 3919, 3898, 3876, 3853, 3829, 3804, 3777,
 59   3750, 3722, 3692, 3662, 3630, 3598, 3565, 3530,
 60   3495, 3459, 3423, 3385, 3346, 3307, 3267, 3226,
 61   3185, 3143, 3100, 3057, 3013, 2968, 2923, 2877,
 62   2831, 2784, 2737, 2690, 2642, 2594, 2545, 2496,
 63   2447, 2398, 2348, 2298, 2248, 2198, 2148, 2098,
 64   2048, 1997, 1947, 1897, 1847, 1797, 1747, 1697,
 65   1648, 1599, 1550, 1501, 1453, 1405, 1358, 1311,
 66   1264, 1218, 1172, 1127, 1082, 1038,  995,  952,
 67    910,  869,  828,  788,  749,  710,  672,  636,
 68    600,  565,  530,  497,  465,  433,  403,  373,
 69    345,  318,  291,  266,  242,  219,  197,  176,
 70    156,  137,  120,  103,   88,   74,   61,   50,
 71     39,   30,   22,   15,   10,    6,    2,    1,
 72      0,    1,    2,    6,   10,   15,   22,   30,
 73     39,   50,   61,   74,   88,  103,  120,  137,
 74    156,  176,  197,  219,  242,  266,  291,  318,
 75    345,  373,  403,  433,  465,  497,  530,  565,
 76    600,  636,  672,  710,  749,  788,  828,  869,
 77    910,  952,  995, 1038, 1082, 1127, 1172, 1218,
 78   1264, 1311, 1358, 1405, 1453, 1501, 1550, 1599,
 79   1648, 1697, 1747, 1797, 1847, 1897, 1947, 1997
 80 };
 81 
 82 const long HandsX[60] = 
 83 {
 84   2047, 2261, 2473, 2680, 2880, 3071, 3251, 3417,
 85   3569, 3704, 3820, 3918, 3994, 4050, 4083, 4095,
 86   4083, 4050, 3994, 3918, 3820, 3704, 3569, 3417,
 87   3251, 3071, 2880, 2680, 2473, 2261, 2048, 1834,
 88   1622, 1415, 1215, 1024,  844,  678,  526,  391,
 89    275,  177,  101,   45,   12,    1,   12,   45,
 90    101,  177,  275,  391,  526,  678,  844, 1024,
 91   1215, 1415, 1622, 1834
 92 };
 93 const long HandsY[60] =
 94 {
 95   4095, 4083, 4050, 3994, 3918, 3820, 3704, 3569,
 96   3417, 3251, 3071, 2880, 2680, 2473, 2261, 2048,
 97   1834, 1622, 1415, 1215, 1024,  844,  678,  526,
 98    391,  275,  177,  101,   45,   12,    1,   12,
 99     45,  101,  177,  275,  391,  526,  678,  844,
100   1024, 1215, 1415, 1622, 1834, 2047, 2261, 2473,
101   2680, 2880, 3071, 3251, 3417, 3569, 3704, 3820,
102   3918, 3994, 4050, 4083
103 };
104 
105 void Hand(byte v, byte len)
106 {
107   long i,x,y;
108   for(i=0;i<len;i++)
109   //Draw from center
110   {
111     //2048,2048 is the center.
112     x=2048+(HandsX[v]-2048)*i/100; 
113     y=2048+(HandsY[v]-2048)*i/100; 
114     dac_X.setVoltage(x   , false,400000);
115     dac_Y.setVoltage(y   , false,400000);
116   }
117 }
118 
119 void Circle()
120 {
121     uint16_t i;
122     uint16_t j;
123       for (i = 0; i < 256; i++)
124       {
125         dac_X.setVoltage(DACLookup_FullSine_8Bit[i], false);
126 
127         j=i+193;
128         j=j%256;
129         dac_Y.setVoltage(DACLookup_FullSine_8Bit[j], false);
130         
131       }
132 }
133 
134 void setup(void) {
135   Serial.begin(9600);
136   delay(1000);
137   rtc.writeProtect(true);
138   Serial.println("This page intentionally left blank.");
139 
140   dac_X.begin(0x63);
141   dac_Y.begin(0x62);
142   us = 500000 + micros();
143 }
144 
145 void loop(void) 
146 {
147   byte hr;
148   Time tm;
149   tm = rtc.time();
150   hr=tm.hr;
151   while(hr>12) hr -= 12;
152   
153    if(t==0)
154   {
155     //Update time from rtc
156 
157     t=1;
158   }
159 
160   
161   if(micros()<us)
162   {
163     Circle();
164     Hand(tm.min,70);  //Minutes
165     Hand(hr*5,50); //Hours
166     if(toggle){Hand(tm.sec,90);} //Seconds
167   }
168   else
169   {
170       us = 500000 + micros();
171       if(toggle) toggle=LOW; else toggle=HIGH;
172       
173       t++;  
174   }
175 }