Propeller Analog/Digital

Clock
History
I got this idea by browsing the web. I found by hazard Mr. Bob
Blick's page who make the first propeller clock. I began to
check how can I build one myself. Base on AVR AT90S2313 I
saw rapidly that my MCU must be clocked very fast to make
all the calculations needed to light the leds at the right place.
The speed is at 16Mhz, 4 times faster than Atmel's
specifications. It's working without any problems.
Each time the PCB passed at 12h00 an hall effect sensor
sensed the magnet and generated an interruption. At this
time, we have to check the counter to se how many ticks had
been passed from this rotation since the last rotation tooks
this value and divide it by 360. This calculation will gives you
the time between each degree. Now, you have to set an
interruption to occur at each degree and after you will be able
to light leds whenever you want at any of 360 degrees. At
this MCU speed, there is no jitter everything is just FIXED!!!

Leds are not lighted very long so the mcd's power must be high. Features Analog clock mode Digital clock mode Infrared clock setting with a standard universal remote control Pictures Click to enlarge Anoalog mode Digital mode Sources codes & Shematics -Shematic in PDF format Stopped with flash at 1/60 sec . Don't forget to use HIGH BRIGHTNESS LEDS 1600mcd.A simple IR sensor is used to take the signal from the remote control (set to a Sony protocol).

IR_interrupt(void). Degre_interrupt(void).0 Janvier 2002 // Sylvain Bissonnette //************************************** //************************************** // INCLUDE //************************************** #include <io2313v.h> #include <macros. CopyData(int Value). CopyDot(void). .//************************************** // Clock 16Mhz // Version 1. Time(unsigned char). Ticker_interrupt(void).h> //************************************** // DEFINE //************************************** #define TRUE 0x01 #define FALSE 0x00 #define ANALOG 0x01 #define DIGITAL 0x02 //************************************** // I N T E R R U P T H A N D L E R //************************************** #pragma interrupt_handler Crossing_interrupt:2 #pragma interrupt_handler IR_interrupt:4 #pragma interrupt_handler Degre_interrupt:5 #pragma interrupt_handler Ticker_interrupt:7 //************************************** // PROTOTYPE //************************************** void void void void void void void void Crossing_interrupt(void). Display(void).

0x21. 0x45. 0x41. 0x00 }. unsigned char Sec. 0x01. // 7 { 0x36. // 3 { 0x0c. 0x00 }. unsigned char Hrs. 0x7f. 0x04. 0x47. 0x00. 0x3e. unsigned char LatchedIrData. 0x51. 0x00 }. // 4 { 0x72. 0x50. 0x00 }. int SecComp. 0x41. unsigned char TimeString[50]. 0x00. 0x00 }. 0x43. // 8 { 0x30. // 0 { 0x00. unsigned char Pos. 0x51. 0x49. 0x41. 0x60. 0x51. // 1 { 0x21. 0x00. unsigned char i. 0x06. 0x00 }. 0x5f. 0x51.//************************************** // G L O B A L V A R I A B L E //************************************** int WeelPosition. int MinComp. 0x49. 0x31.// space . 0x49. 0x36. 0x4e. 0x49. 0x00 }. 0x14. 0x00 }. 0x00 }. 0x29. 0x48. 0x00 }. // 6 { 0x40. 0x3c. 0x00 }}. unsigned int Adder. unsigned char *TimeStringPtr. unsigned char Min. 0x41. 0x4a. int HrsComp. 0x24. 0x46. // 2 { 0x42. 0x00 }. // 9 { 0x00. 0x49. 0x49. unsigned char ClockStyle. 0x00. 0x49. 0x00. //************************************** // CONSTANT //************************************** const unsigned char table[12][6] = {{ 0x3e. 0x36. // : { 0x00. // 5 { 0x1e. 0x49. 0x00. 0x36. 0x69. 0x00.

SEI(). for (i=0. // PB0-7 as output Hrs = 0. // Enable WatchDog at 0. DDRD = 0x03.97 sec PORTD = 0x0d.//************************************** // MAIN //************************************** void main() { WDTCR = 0x0e. // Int0 generate int on falling eadge // Int0 enable //Timer0 TCCR0 = 0x05. Min = 0. ClockStyle = ANALOG. if ((LatchedIrData == 0xb3) || (LatchedIrData == 0xb0)) ClockStyle = DIGITAL.i++). Sec = 0. GIMSK = 0x40. if ((LatchedIrData == 0xbb) || (LatchedIrData == 0x92)) Time(TRUE). .i<200. // Timer1 / 8 & Input Capture on Rising eadge TIMSK = 0x4a. DDRB = 0xff. PD7-I // Pull up on PD2&PD3 & Led White ON // PD0-O PD1-O PD2-I PD3-I PD4-I PD5-I PD6-I //INT 0 MCUCR = 0x02. // int enable on Timer1 Compare Match // int enable on Timer 1 Input Capture // int enable on Timer0 Overflow PORTB = 0x00. // Timer0 / 1024 //Timer1 TCCR1B = 0x42. while(1) { asm("WDR").

HrsComp = (Hrs*30)+(Min/2). if (Hrs > 11) { Hrs = 0. } } /********************************************************** Name: void Time(void) Description: Input: Output: none none Misc: **********************************************************/ void Time(unsigned char Fast) { if (Fast == FALSE) Sec++. . MinComp = Min*6. } } } if (ClockStyle == ANALOG) { SecComp = Sec*6. Min++. if (Sec > 59) { Sec = 0. Hrs++. if (Min > 59) { Min = 0. else Sec += 60. LatchedIrData = 0.if ((LatchedIrData == 0xb4) || (LatchedIrData == 0xb1)) ClockStyle = ANALOG.

i++) *TimeStringPtr++ = table[Value/10][i].i<6. for (i=0. } else { for (i=0. CopyDot().i<6.i++) *TimeStringPtr++ = table[Value][i]. CopyData(Sec).i<6. } } /********************************************************** Name: void CopySpace(void) .i++) *TimeStringPtr++ = table[Value-((Value/10)*10)] [i]. CopyData(Min). CopyDot(). CopyData(Hrs).} else { TimeStringPtr = &TimeString[0]. } } /********************************************************** Name: void CopyData(int Value) Description: Input: Output: none none Misc: **********************************************************/ void CopyData(int Value) { if (Value < 10) { for (i=0. for (i=0.i<6.i++) *TimeStringPtr++ = table[0][i].

if (Lap > 250) { Adder = TotalCount / 378. TotalCount = Latch . Lap++. Lap = 0. .i++) *TimeStringPtr++ = table[10][i]. static unsigned char Lap. LastCount = Latch.Description: Input: none Output: none Misc: **********************************************************/ void CopyDot(void) { for (i=0. Latch = TCNT1.i<6. static int Latch. static unsigned int TotalCount.LastCount. } /********************************************************** Name: void Crossing_interrupt(void Description: Input: Output: none none Misc: **********************************************************/ void Crossing_interrupt(void) { static unsigned int LastCount.

Display(). } /********************************************************** Name: void Display(void) Description: Input: Output: none none Misc: **********************************************************/ void Display(void) { PORTB = 0x00. . } /********************************************************** Name: void Degre_interrupt(void) Description: Input: none Output: none Misc: **********************************************************/ void Degre_interrupt(void) { OCR1 = TCNT1 + Adder. Display(). OCR1 = Latch + Adder.} WeelPosition = 0. TIFR |= 0x80.

if (WeelPosition == MinComp) PORTB = 0xff. The header length = 4T (2. } /********************************************************** Name: void IR_interrupt(void) Description: This routine is called whenever a rising edge (beginning of valid IR signal) is received. } } WeelPosition++. . - The data codes are sent using pulse coding. The basic time period T = 550us. Each packet has 12 bits and a header. if (WeelPosition == SecComp) PORTB |= 0x03. 1 = pulse with length 2T followed by space of length T. if ((WeelPosition == 0) || (WeelPosition == 30) || (WeelPosition == 60) || (WeelPosition == 90) || (WeelPosition == 120) || (WeelPosition == 150) || (WeelPosition == 180) || (WeelPosition == 210) || (WeelPosition == 240) || (WeelPosition == 270) || (WeelPosition == 300) || (WeelPosition == 330)) PORTB |= 0x01.2ms) 0 = pulse with length T followed by space of length T. if (Pos < 49) { PORTB = TimeString[48-Pos]. } else { Pos = ((WeelPosition-100) / 3).if (ClockStyle == ANALOG) { if (WeelPosition == HrsComp) PORTB = 0x80.

IrData = 0. unsigned int PulseWidth. . } } /********************************************************** Name: void Ticker_interrupt(void) Description: Input: none .The first 7 bits represent the command. IrPulseCount++.A packet is transmitted every 25ms while a button is down.The last 5 bits represent the Addess. if (IrPulseCount == 12) LatchedIrData = ((IrData >> 4) & 0x00ff). Input: none Output: Misc: Global variable LatchedIrData Sony VCR protocol **********************************************************/ void IR_interrupt(void) { static unsigned int LastCapture. } else { IrData = IrData >> 1. if (PulseWidth > 4000) { IrPulseCount = 0.. . LastCapture = ICR1.LastCapture. static unsigned int IrData. if (PulseWidth > 2800) IrData = IrData | 0x8000. PulseWidth = ICR1 . static unsigned int IrPulseCount.

Tick = 0. } TCNT0 = 0x04. if (Tick > 62) { Time(FALSE). Tick++.Output: none Misc: **********************************************************/ void Ticker_interrupt(void) { static unsigned char Tick. // reload counter } .

Sign up to vote on this title
UsefulNot useful