Once upon a time, lifes goes on as usual, boring. Until one day my friend showing me a weird clock on youtube. i said “wow, that was awesome!”, “how it works?”, “i should make one!”. Basically, i have experienced on electronic DIY stuffs. i started to figure out on how to make it, lots of information found. so basicaly, propeller clock based on POV (Persistence of vision)
http://en.wikipedia.org/wiki/Persistence_of_vision
The clock’s graph formed by cheating human eyes, one array of leds burst on constant interval/delay in one motor rotation, continuously (in this case divided to 360 degree in one rotation, can be more for higher resolution).
After i’ve found, understand, (and yet still confused on how it works :P). i started making prototypes with existing MCU module (atmega8535), wired to array of 8 leds. it works, and not good!! it’s too heavy, no index reference, the text is very unstable. i need to design new board which is lighter and throw out all unnecessary components. there are two web site that i’m using as references, when building this clock.
http://www.microsyl.com/index.php/2010/03/18/propeller-clock/
i used the codes from there with lots of modification, original code is writen using ICCAVR, i converted it to AVR Studio.
http://www.oocities.org/tjacodesign/propclock/propclock.html
i used his isolated power supply, to power up the propeller clock module.
For remote control, it was stolen from here: 😀
http://www.dharmanitech.com/2009/01/ir-remote-controlled-car-pwm-motor.html
picture
Isolated Power Supply / Wireless Power Transmission
the propeller clock works properly, only haven’t fix jitter yet when remote control is used ( i used SIRC/ sony IR remote control).
Video
Schematic
This is my first attempt designing propeller clock, i’ve been thinking using several shift register to drive more leds array.
Propeller Clock
Isolated Power Supply/ Wireless Power Transmission
Partlists Propeller Clock
Part Value C1 22pF C2 22pF C3 470uF C4 470uF C5 470uF C6 470uF C7 100nF C8 10nF C9 10uF D1 1N4004 D2 1N4004 D3 1N4004 D4 1N4004 IC1 MEGA16-A IC2 A1301UA IC3 LM7805 JP1 AVR-ISP-10 LED1 RED LED2 RED LED3 RED LED4 RED LED5 RED LED6 RED LED7 RED LED8 RED LED9 RED LED10 RED LED11 RED LED12 RED LED13 RED LED14 RED LED15 RED LED16 GREEN PAD1 P1 PAD2 P2 R1 1k R2 330 R3 330 R4 330 R5 330 R6 330 R7 330 R8 330 R9 330 R10 330 R11 330 R12 330 R13 330 R14 330 R15 330 R16 330 R17 330 R18 100 S1 RESET U$1 TSOP1838 X1 16MHz
most of all reststor, led, capacitor are smd1206
Code
#include <avr/interrupt.h> //#include <avr/wdt.h> #include <util/delay.h> #include <string.h> #include <stdio.h> #include <math.h> #define TRUE 0x01 #define FALSE 0x00 #define ANALOG 0x01 #define DIGITAL 0x02 #define WIDTH 9 const unsigned char table[12][6] = {{ 0x3e, 0x41, 0x41, 0x41, 0x3e, 0x00 }, // 0 { 0x00, 0x21, 0x7f, 0x01, 0x00, 0x00 }, // 1 { 0x21, 0x43, 0x45, 0x49, 0x31, 0x00 }, // 2 { 0x42, 0x41, 0x51, 0x69, 0x46, 0x00 }, // 3 { 0x0c, 0x14, 0x24, 0x5f, 0x04, 0x00 }, // 4 { 0x72, 0x51, 0x51, 0x51, 0x4e, 0x00 }, // 5 { 0x1e, 0x29, 0x49, 0x49, 0x06, 0x00 }, // 6 { 0x40, 0x47, 0x48, 0x50, 0x60, 0x00 }, // 7 { 0x36, 0x49, 0x49, 0x49, 0x36, 0x00 }, // 8 { 0x30, 0x49, 0x49, 0x4a, 0x3c, 0x00 }, // 9 { 0x00, 0x36, 0x36, 0x00, 0x00, 0x00 }, // : { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }};// space volatile int WeelPosition; volatile unsigned char Pos; volatile unsigned int Adder; volatile unsigned char LatchedIrData; volatile unsigned int Rps, CountRps; volatile unsigned char Sec; volatile unsigned char Min; volatile unsigned char Hrs; volatile int SecComp; volatile int MinComp; volatile int HrsComp; volatile unsigned char ClockStyle; unsigned int TimeString[50]; unsigned int *TimeStringPtr; void One(void); void Two(void); void Three(void); void Six(void); void Nine(void); void Hari(void); unsigned char i; void Time(unsigned char); void Display(void); void CopyData(int Value); void CopyDot(void); unsigned int read_IR (void); int main(void) { //WDTCR |= ((1 << WDE) | (1 << WDP2) | (1 << WDP1)); // Enable WatchDog at 1.0 sec MCUCR |= ((1<<ISC11)|(1<<ISC01)); // Int0 Int1 generate int on falling eadge GICR |= ((1 << INT0) | (1 << INT1)); // Int0 and Int1 enable TCCR0 |= ((1 << CS02) | (1 << CS00)); // Timer0 / 1024 //TCCR1B |= ((1 << CS11) | (1 << CS10) | (1 << WGM12)); // Timer1 prescaling 8 CTC //TCCR1B |= ((1 << CS10) | (1 << ICES1) | (1 << WGM12)); // Timer1 no prescaling TCCR1B |= ((1 << CS10) | (1 << WGM12)); // Timer1 no prescaling TCCR2 |= ((1 << CS22)|(1 << CS21) | (1 << CS20)); //TIMSK |= ((1 << OCIE1A) | (1 << TICIE1) | (1 << TOIE0)); TIMSK |= ((1 << OCIE1A) | (1 << TOIE0)); DDRA = 0xFF; PORTA = 0x00; DDRC = 0xFF; PORTC = 0x01; DDRD = 0x00; PORTD = 0x0C; Hrs = 2; Min = 40; Sec = 10; ClockStyle = ANALOG; sei(); //wdt_disable(); //wdt_enable(WDTO_2S); while(1) { //wdt_reset(); //for (i=0;i<200;i++); //if (LatchedIrData == 16) Time(TRUE); //if (LatchedIrData == 18) ClockStyle = DIGITAL; //if (LatchedIrData == 19) ClockStyle = ANALOG; //LatchedIrData = 0; } } void Time(unsigned char Fast) { if (Fast == FALSE) { Sec++; } //else Sec += 60; else { Min += 1; if (Min > 59) { Min = 0; Hrs++; if (Hrs > 11) { Hrs = 0; } } } if (Sec > 59) { Sec = 0; Min++; if (Min > 59) { Min = 0; Hrs++; if (Hrs > 11) { Hrs = 0; } } } if (ClockStyle == ANALOG) { SecComp = Sec*6; MinComp = Min*6; HrsComp = (Hrs*30)+(Min/2); } else { TimeStringPtr = &TimeString[0]; CopyData(Hrs); CopyDot(); CopyData(Min); CopyDot(); CopyData(Sec); } } void CopyData(int Value) { if (Value < 10) { for (i=0;i<6;i++) *TimeStringPtr++ = table[0][i]; for (i=0;i<6;i++) *TimeStringPtr++ = table[Value][i]; } else { for (i=0;i<6;i++) *TimeStringPtr++ = table[Value/10][i]; for (i=0;i<6;i++) *TimeStringPtr++ = table[Value-((Value/10)*10)][i]; } } void CopyDot(void) { for (i=0;i<6;i++) *TimeStringPtr++ = table[10][i]; } ISR(INT0_vect) { unsigned int LastWeel; LastWeel = WeelPosition; // get lasst wheel position either less/more than 360 WeelPosition = 0; // reset wheel count // this will make degree lock to 360 if (LastWeel > 360) { Adder += 1; } else if (LastWeel < 360) { Adder -= 1; } CountRps++; OCR1A = 1852 + Adder; // set TIMER1 compare value + offset (+/-) TIFR = (1 << OCF1A); // reset TIMER1 Display(); } ISR(TIMER1_COMPA_vect) { OCR1A = 1852 + Adder; Display(); } void Display(void) { unsigned char Min_Portc[5] = {0xF8, 0xFC, 0xFE, 0xFC, 0xF8}; unsigned char Min_Porta[5] = {0X00, 0xF0, 0xFF, 0xF0, 0x00}; unsigned char Hrs_Portc[5] = {0x00, 0x00, 0x80, 0x00, 0x00}; unsigned char Hrs_Porta[5] = {0x70, 0xF8, 0xFF, 0xF8, 0x70}; unsigned char port_c; //unsigned char port_a; PORTC = 0x00; PORTA = 0x00; if (ClockStyle == ANALOG) { // BEGIN HOURS // BEGIN HOUR on 12 if ((WeelPosition == HrsComp) && (WeelPosition == 0)) { PORTC |= Hrs_Portc[2]; PORTA |= Hrs_Porta[2]; } if (((WeelPosition - 1) == HrsComp) && (WeelPosition == 1)) { PORTC |= Min_Portc[3]; PORTA |= Min_Porta[3]; } if (((WeelPosition - 2) == HrsComp) && (WeelPosition == 2)) { PORTC |= Hrs_Portc[4]; PORTA |= Hrs_Porta[4]; } if (((WeelPosition - 358) == HrsComp) && (WeelPosition == 358)) { PORTC |= Hrs_Portc[0]; PORTA |= Hrs_Porta[0]; } if (((WeelPosition - 359) == HrsComp) && (WeelPosition == 359)) { PORTC |= Hrs_Portc[1]; PORTA |= Hrs_Porta[1]; } // END HOUR on 12 if (((WeelPosition + 2) == HrsComp) && (WeelPosition > 2) && (WeelPosition < 358)) { PORTC |= Hrs_Portc[0]; PORTA |= Hrs_Porta[0]; } if (((WeelPosition + 1) == HrsComp) && (WeelPosition > 2) && (WeelPosition < 358)) { PORTC |= Hrs_Portc[1]; PORTA |= Hrs_Porta[1]; } if ((WeelPosition == HrsComp) && (WeelPosition > 2) && (WeelPosition < 358)) { PORTC |= Hrs_Portc[2]; PORTA |= Hrs_Porta[2]; } if (((WeelPosition - 1) == HrsComp) && (WeelPosition > 2) && (WeelPosition < 358)) { PORTC |= Hrs_Portc[3]; PORTA |= Hrs_Porta[3]; } if (((WeelPosition - 2) == HrsComp) && (WeelPosition > 2) && (WeelPosition < 358)) { PORTC |= Hrs_Portc[4]; PORTA |= Hrs_Porta[4]; } // END HOURS // BEGIN MINUTE // BEGIN MINUTE on 12 if ((WeelPosition == MinComp) && (WeelPosition == 0)) { PORTC |= Min_Portc[2]; PORTA |= Min_Porta[2]; } if (((WeelPosition - 1) == MinComp) && (WeelPosition == 1)) { PORTC |= Min_Portc[3]; PORTA |= Min_Porta[3]; } if (((WeelPosition - 2) == MinComp) && (WeelPosition == 2)) { PORTC |= Min_Portc[4]; PORTA |= Min_Porta[4]; } if (((WeelPosition - 358) == MinComp) && (WeelPosition == 358)) { PORTC |= Min_Portc[0]; PORTA |= Min_Porta[0]; } if (((WeelPosition - 359) == MinComp) && (WeelPosition == 359)) { PORTC |= Min_Portc[1]; PORTA |= Min_Porta[1]; } // END MINUTE on 12 if (((WeelPosition + 2) == MinComp) && (WeelPosition > 2) && (WeelPosition < 358)) { PORTC |= Min_Portc[0]; PORTA |= Min_Porta[0]; } if (((WeelPosition + 1) == MinComp) && (WeelPosition > 2) && (WeelPosition < 358)) { PORTC |= Min_Portc[1]; PORTA |= Min_Porta[1]; } if ((WeelPosition == MinComp) && (WeelPosition > 2) && (WeelPosition < 358)) { PORTC |= Min_Portc[2]; PORTA |= Min_Porta[2]; } if (((WeelPosition - 1) == MinComp) && (WeelPosition > 2) && (WeelPosition < 358)) { PORTC |= Min_Portc[3]; PORTA |= Min_Porta[3]; } if (((WeelPosition - 2) == MinComp) && (WeelPosition > 2) && (WeelPosition < 358)) { PORTC |= Min_Portc[4]; PORTA |= Min_Porta[4]; } // END MINIUTE // second in circle bar mode if (WeelPosition == SecComp) { //PORTC |= 0x02; //PORTA |= 0x00; PORTC |= 0xFE; PORTA |= 0xFF; } // dot every 5 minutes 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)) { PORTC |= 0x02; PORTA |= 0x00; } //green if (((WeelPosition % 6) == 0) && (WeelPosition < 360)) PORTC |= 0x01; One(); Two(); Three(); Six(); Nine(); Hari(); } else { if (((WeelPosition % 6) == 0) && (WeelPosition < 360)) PORTC |= 0x01; Pos = ((WeelPosition-100) / 3); if (Pos < 49) { // shifted by 1 to MSB , we have different wiring port_c = (TimeString[48-Pos] << 1); PORTC |= port_c; } } WeelPosition++; } ISR(TIMER0_OVF_vect) { static unsigned char Tick; Tick++; if (Tick > 62) { Time(FALSE); Tick = 0; Rps = CountRps; CountRps=0; } TCNT0 = 0x04; // reload counter } ISR(INT1_vect) { unsigned char count; //, code, address; unsigned int IR_input; PORTC = 0x00; PORTA = 0x00; TCNT2 = 0; while(!(PIND & 0x08)); count = TCNT2; if(count < 30) //to verify start pulse (2.4 ms long) { //delay_ms(20); //ENABLE_INT0; _delay_ms(20); sei(); return; } //PORTC |= 0x20; IR_input = read_IR (); //code = (unsigned char) ((IR_input & 0xff00) >> 8); //address = (unsigned char) (IR_input & 0x00ff); //motorControl ( code, address ); LatchedIrData = (unsigned char) ((IR_input & 0xFF00) >> 8); if (LatchedIrData > 0) { if ((LatchedIrData & 0xFF) == 0x10) Time(TRUE); if ((LatchedIrData & 0xFF) == 0x12) ClockStyle = DIGITAL; if ((LatchedIrData & 0xFF) == 0x13) ClockStyle = ANALOG; LatchedIrData = 0; } _delay_ms(250); //PORTC &= ~0x20; } unsigned int read_IR (void) { unsigned char pulseCount=0, code = 0, address = 0, timerCount; unsigned int IR_input; while(pulseCount < 7) { while(PIND & 0x08); TCNT2 = 0; while(!(PIND & 0x08)); pulseCount++; timerCount = TCNT2; if(timerCount > 14) code = code | (1 << (pulseCount-1)); else code = code & ~(1 << (pulseCount-1)); } pulseCount = 0; while(pulseCount < 5) { while(PIND & 0x08); TCNT2 = 0; while(!(PIND & 0x08)); pulseCount++; timerCount = TCNT2; if(timerCount > 14) address = address | (1 << (pulseCount-1)); else address = address & ~(1 << (pulseCount-1)); } IR_input = (((unsigned int)code) << 8) | address; return(IR_input); } void One(void) { unsigned char Two_Portc[3] = {0x10, 0xF8, 0x00}; unsigned char Two_Porta[3] = {0x40, 0xC0, 0x40}; if ((WeelPosition >= 357) && (WeelPosition <= 359)) { PORTC |= Two_Portc[WeelPosition-357]; PORTA |= Two_Porta[WeelPosition-357]; } } void Two(void) { unsigned char Two_Portc[5] = {0x10, 0x08, 0x88, 0x48, 0x30}; unsigned char Two_Porta[5] = {0x40, 0xC0, 0x40, 0x40, 0x40}; if ((WeelPosition >= 2) && (WeelPosition <= 6)) { PORTC |= Two_Portc[WeelPosition-2]; PORTA |= Two_Porta[WeelPosition-2]; } } void Three(void) { unsigned char Two_Portc[7] = {0xF8, 0x10, 0x20, 0x10, 0x08, 0x88, 0x70}; if ((WeelPosition >= 88) && (WeelPosition <= 94)) { PORTC |= Two_Portc[WeelPosition-88]; } } void Six(void) { unsigned char Two_Portc[5] = {0x30, 0x48, 0x48, 0x48, 0xF0}; unsigned char Two_Porta[5] = {0x00, 0x40, 0x40, 0x80, 0x00}; if ((WeelPosition >= 178) && (WeelPosition <= 182)) { PORTC |= Two_Portc[WeelPosition-178]; PORTA |= Two_Porta[WeelPosition-178]; } } void Nine(void) { unsigned char Two_Portc[7] = {0x30, 0x40, 0x80, 0xF0, 0x88, 0x88, 0x70}; if ((WeelPosition >= 267) && (WeelPosition <= 273)) { PORTC |= Two_Portc[WeelPosition-267]; } } void Hari(void) { unsigned char P_Porta[65] = { 0x3E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x3E, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00 }; if ((WeelPosition >= 148) && (WeelPosition <= 211)) { PORTA |= P_Porta[WeelPosition-148]; } }
where have you put the magnet for hall effect sensor to work upon??
in project i put the magnet at 12 o’clock position. the hall effect is on the edge of pcb. the magnet is under hall effect.
in the PCB,i saw one unknown component adjacent to rest switch of light blue color,so would you please tell me what’s that?
i saw one component light blue in color adjacent to reset switch in the PCB,would you help me to figure it out what is that?
i saw one component,blue in color adjacent to reset switch in PCB,would you please help me to figure it out what it is?
could you tell the shape of component