I am trying to make a small LED stroboscope using PIC16F72.
I am also including a display to show the frequency of flickering in RPM.
For this I am using two pots for tuning, one for adjusting frequency and the other for adjusting duty cycle.
**broken link removed**
I would love to have the PWM frequency down to 8 hz which according to this formula
**broken link removed**
requires that I use Fosc = 131 Khz at most. So, I choosed to run the pic with a 32768 Hz crystal. It would be fine, but I am not getting enough cpu speed to do the multiplexed display interrupt routine.
Any help please?
Here is my code.
I am also including a display to show the frequency of flickering in RPM.
For this I am using two pots for tuning, one for adjusting frequency and the other for adjusting duty cycle.
**broken link removed**
I would love to have the PWM frequency down to 8 hz which according to this formula
**broken link removed**
requires that I use Fosc = 131 Khz at most. So, I choosed to run the pic with a 32768 Hz crystal. It would be fine, but I am not getting enough cpu speed to do the multiplexed display interrupt routine.
Any help please?
Here is my code.
Code:
#include<htc.h>
#define _XTAL_FREQ 32768
#define D0 RC7
#define D0_tris TRISC7
#define D1 RC6
#define D1_tris TRISC6
#define D2 RC5
#define D2_tris TRISC5
#define D3 RC4
#define D3_tris TRISC4
#define CCP_tris TRISC2
#define Freq_input_tris TRISA0
#define Duty_input_tris TRISA1
#define Dutyorfreq CHS0
#define Display PORTB
#define Display_tris TRISB
const char segdata[10] = {
// 7-bits for displaying numeral 0,1,2,3...
// most be negated when used for common anode
0b01111110, // 0
0b00110000, // 1
0b01101101, // 2
0b01111001, // 3
0b00110011, // 4
0b01011011, // 5
0b01011111, // 6
0b01110000, // 7
0b01111111, // 8
0b01111011 // 9
};
// voltatile necessary for all variables used by interrupt
volatile char count0; // counter for first display
volatile char count1; // counter for second display
volatile char count2; // counter for third display
volatile char count3; // counter for 4th display
void interrupt isr(void){ // timer0 interrupt This function is automatically called everytime Timer0 Register overflows
static unsigned char turnof = 0; // static necessary to retain data between sucessive call to function.
// initialization is done only once
// it is variable to cycle through the display slection
switch(turnof){
case 0: // Turn of Display 1
D0 = 1; //
D1 = 1; // Deselct all display
D2 = 1; //
D3 = 1;
Display = ~segdata[count1];
D0 = 0; // select Display1
break;
case 1:
D0 = 1; //
D1 = 1; // Deselct all display
D2 = 1; //
D3 = 1;
Display = ~segdata[count2];
D1 = 0; // select Display1
break;
case 2:
D0 = 1; //
D1 = 1; // Deselct all display
D2 = 1; //
D3 = 1;
Display = ~segdata[count2];
D2 = 0; // select Display1
break;
case 3:
D0 = 1; //
D1 = 1; // Deselct all display
D2 = 1; //
D3 = 1;
Display = ~segdata[count3];
D3 = 0; // select Display1
}
turnof++;
if(turnof>3) turnof = 0;
TMR1 = 150;
T0IF = 0;
}
void main(){
char i;
int sum = 0;
int rpm = 0;
int period = 0;
char desired_freq = 0;
// minimum frequency, 8 hz (480 rpm)
// maximum frequency, 158 hz (9480 rpm)
// so, ADRES = 0 corresponds to 8hz (1250 * 100 us time period)
// ADRES = 255 corresponds to 158 hz (
__delay_ms(100);
Display_tris = 0; // all PortB output
D0_tris = 0;
D1_tris = 0;
D2_tris = 0;
D3_tris = 0;
CCP_tris = 0;
Duty_input_tris = 1;
Freq_input_tris = 1;
char xxx;
OPTION = 0b11010000 ;// Disable internal weak pullup,,internal clock source for T0
// ,, assign prescaler to TMR0,prescaler 100
GIE = 1;
TMR0IE = 1;// enable timer 0 interrupt
T2CON = 0b00000101; // 1:4 prescale
CCP1CON = 0b000011111; // pwm mode
ADCON1 = 0b00000100; // RA0, RA1 and RA3 analog inputs
ADCON0 = 0b11000011; // RC clock, channel 0, Done, - , ADON
count0 = 0;
count1 = 0;
count2 = 0;
while (1){
sum = 0;
CHS0 = 0; // frequency reading channel
__delay_us(50);
for(i=10;i>=1;i--){
GODONE = 1;
while(GODONE);
sum+=ADRES;
__delay_us(10);
}
sum /= 10;
desired_freq = sum*150/255 + 8;
PR2 = 32768/((int)desired_freq*4*4) - 1; // 1:4 prescale
rpm = 32768*60/((PR2+1)*4*4);
// extract the 4 digits of rpm
count0 = rpm % 10;
rpm /= 10;
count1 = rpm % 10;
rpm /= 10;
count2 = rpm % 10;
rpm /= 10;
count3 = rpm;
CHS0 = 1; // duty cycle reading channel
__delay_us(50);
for(i=10;i>=1;i--){
GODONE = 1;
while(GODONE);
sum+=ADRES;
__delay_us(10);
}
sum /= 10;
CCPR1L = sum; // duty cycle is equal to the avg of analog reading
// wait for few second before looping
for(i=20;i>=1;i--){
__delay_ms(100);
}
}
}