The white cylinder over the LEDs is just an old milky-white colored 35mm film canister. But it makes a heck of difference on how the light output is seen by the human eye. Certainly far more interesting with it. By varying the direction in which the LEDs point different light patterns on the cylinder can be created.
The MCU is run at 1MHz. LED switching occurs in the interrupt service routine. Maximum switching frequency is approximately 325Hz--each LED is on for just around 1ms. Minimum frequency is around 1.27Hz. Period T = on-time of each LED x number of LEDs. Frequency = 1/T. Timer0 is used for timing the LEDs. Its prescale is set to 256. With the clock running at 1MHz, time for one instruction cycle = 4/1MHz = 4µs. Timer0 tick = TMR0 x 256 x 4µs. The reset value of TMR0 can range from zero to 255 depending on the position of the potentiometer.
Timer2 is used to periodically read the pot and store its value in a variable which then gets copied to TMR0 during every timer0 interrupt.
#define int1 bit #define int8 unsigned char #define int16 unsigned int #define int32 unsigned long #define on 1 #define off 0 #define _on 0 #define _off 1 #define yes 1 #define no 0 #define input 1 // for TRISx #define output 0 // for TRISx #define analog 1 // for ANSELx #define digital 0 // for ANSELx #define lred LATC.f0 // red led #define lgreen LATC.f1 // green led #define lblue LATC.f2 // blue led #define tris_lred TRISC.f0 // for setting LED pin as output #define tris_lgreen TRISC.f1 // for setting LED pin as output #define tris_lblue TRISC.f2 // for setting LED pin as output #define an_lred ANSELC.f0 // for setting LED pin as digital #define an_lgreen ANSELC.f1 // for setting LED pin as digital #define an_lblue ANSELC.f2 // for setting LED pin as digital #define ch_pot 3 // analog channel of potentiometer // ================================================================================================================== // global variables // ================================================================================================================== int8 TMR0COUNT; // ================================================================================================================== // functions // ================================================================================================================== void IniReg() { OSCCON = 0b1011000; // internal clock = 1MHz // set LED pins as output tris_lred = 0; tris_lgreen = 0; tris_lblue = 0; // set LED pins as digital an_lred = 0; an_lgreen = 0; an_lblue = 0; lred = 1; // start off with red LED // Timer0 setup OPTION_REG = 0b10000111; // Weak pull ups disabled // timer0 uses internal clock, // prescaler assigned to timer0, prescaler = 1:256 TMR0 = 0; INTCON.TMR0IE = 1; // timer0 interrupt enable // Timer2 setup // with a 1MHz clock, prescale = 1:16, postscale = 1:1, PR2 = 200 // timer2 tick = 250 * 64 / (1MHz/4) = 64ms T2CON = 0b111; // timer2 on, prescale = 1:64, postscale = 1:1 PR2 = 250; // timer2 counts up from zero until the value of PR2 and then resets // Analog to Digital Coverter setup ADCON0 = ch_pot << 2; // shift in analog channel to be made active ADCON0.ADON = 1; // turn on ADC ADCON1 = 0; // left justified, Fosc/2, Vss as negative reference, Vdd as positive reference INTCON.GIE = 1; // global interrupt enabled } // void IniReg() /* ========================================================================================================= According to PIC12F1824 Silicon Errata sheet DS80510D the ADC unit in certain silicon revisions is buggy: "An ADC conversion may not complete under these conditions: 1. When FOSC is greater than 8 MHz and it is the clock source used for the ADC converter. 2. The ADC is operating from its dedicated internal FRC oscillator and the device is not in Sleep mode (any FOSC frequency). When this occurs, the ADC Interrupt Flag (ADIF) does not get set, the GO/DONE bit does not get cleared, and the conversion result does not get loaded into the ADRESH and ADRESL result registers." mikroC Pro compiler's Adc_Read() built-in ADC function uses the FRC oscillators o it cannot be used. The workaround used here is as per method 1 in the said errata: "Select the system clock, FOSC, as the ADC clock source and reduce the FOSC frequency to 8 MHz or less when performing ADC conversions." ========================================================================================================= */ int8 ADC() { ADCON0.GO = 1; // start ADC conversion while (ADCON0.GO) ; // just wait until AD conversion is done return ADRESH; // return only the 8 most significant bits of the 10-bit value } void interrupt() { if (INTCON.TMR0IF) { TMR0 = TMR0COUNT; if (lred) { lgreen = on; lred = off; } else if (lgreen) { lblue = on; lgreen = off; } else { lred = on; lblue = off; } INTCON.TMR0IF = 0; } } void main() { IniReg(); while(1) { if (PIR1.TMR2IF) { TMR0COUNT = ADC(); PIR1.TMR2IF = 0; } } // while(1) } // void main()
No comments:
Post a Comment