int cnt; // counter variable to store zero crossing count
unsigned char FlagReg;
sbit ZC at FlagReg.B0;
void interrupt(){
if (INTCON.INTF){ //INTF flag raised, so external interrupt occured
ZC = 1;
cnt++;
INTCON.INTF = 0;
}
}
void fire() {
PORTD.B0 = 1; //Send a 1ms pulse
delay_us(500);
PORTD.B0 = 0;
}
void main() {
TRISA = 0;
PORTA = 0;
PORTB = 0;
TRISB = 0x01; //RB0 input for interrupt
PORTD = 0;
TRISD = 0; //PORTD all output
ANSEL = 0; // make ports digital (lower order)
ANSELH = 0; // make ports digital (higher order)
OPTION_REG.INTEDG = 0; //interrupt on falling edge
INTCON.INTF = 0; //clear interrupt flag
INTCON.INTE = 1; //enable external interrupt
INTCON.GIE = 1; //enable global interrupt
cnt =0;
do {
if (ZC){ //zero crossing occurred
delay_ms(1);
fire();
ZC = 0;
}
} while(cnt<=100);
PORTD = 0b00000010;
}
for(i=0;i<100;i++){
while(!ZC); //wait for interrupt
delay_ms(1); //short delay
fire(); //turn on triac
ZC=0; //clear flag
}
while(1); //wait forever
Something like,
Code:for(i=0;i<100;i++){ while(!ZC); //wait for interrupt delay_ms(1); //short delay fire(); //turn on triac ZC=0; //clear flag } while(1); //wait forever
You could instead of using interrupts just use INTF as the flag.
Mike.
int cnt; // counter variable to store zero crossing count
unsigned char FlagReg;
sbit ZC at FlagReg.B0;
void interrupt(){
if (INTCON.INTF){ //INTF flag raised, so external interrupt occured
ZC = 1;
INTCON.INTF = 0;
}
}
void fire() {
PORTD.B0 = 1; //Send a 1ms pulse
delay_us(500);
PORTD.B0 = 0;
}
void main() {
TRISA = 0;
PORTA = 0;
PORTB = 0;
TRISB = 0x01; //RB0 input for interrupt
PORTD = 0;
TRISD = 0; //PORTD all output
ANSEL = 0; // make ports digital (lower order)
ANSELH = 0; // make ports digital (higher order)
OPTION_REG.INTEDG = 0; //interrupt on falling edge
INTCON.INTF = 0; //clear interrupt flag
INTCON.INTE = 1; //enable external interrupt
INTCON.GIE = 1; //enable global interrupt
cnt =0;
for(cnt=0;cnt<100;cnt++){
while(!ZC); //wait for interrupt
delay_ms(1); //short delay
fire(); //turn on triac
ZC=0; //clear flag
}
PORTD = 0b00000010;
while(1); //wait forever
}
Yes it is unless there is a mistake in the way I have done it.Is RELAY1 connected as intended?
Yes, it's still using your interrupt. It just replaces your do loop.With the above code, does it mean I will still be using interrupts?
Regards
Thank you let me redo and see what happensYes, it's still using your interrupt. It just replaces your do loop.
Mike.
Thank you, on the actual circuit that I am testing with, I have included itIf you do not have a resistor in series with the optoisolator LED, that's likely to be fried..
The OP appears to have a transformer followed by a bridge rectifier and is detecting falling edges. This will detect all zero crossings. However, as currently drawn the schematic lacks smoothing capacitors and when theses are added they will prevent the LED from ever switching off. A blocking diode or two bridges will fix this.With the circuit as shown, you are only triggering on one polarity zero crossing rather than both, so only possibly switching the triac on alternate half cycles.
Great advice, hadn't thought of thatAlso, just use the normally open contact on the relay to directly bridge the triac - there is no need to break that connection and doing so means the relay contacts are switching under high inductive load, while just shorting a triac after the starter has ramped up to full will be a very "clean" operation with no contact burn.
The OP appears to have a transformer followed by a bridge rectifier and is detecting falling edges. This will detect all zero crossings. However, as currently drawn the schematic lacks smoothing capacitors and when these are added they will prevent the LED from ever switching off. A blocking diode or two bridges will fix this.
Afterthought:The OP appears to have a transformer followed by a bridge rectifier and is detecting falling edges. This will detect all zero crossings. However, as currently drawn the schematic lacks smoothing capacitors and when these are added they will prevent the LED from ever switching off. A blocking diode or two bridges will fix this.
Mike.
transformer followed by a bridge rectifier
;
; PAGE 0 Register setup ***
;
bcf STATUS,RP0 ; Select page 0
movlw 000 ; Set port B to
movwf PORTB ; $00 = all o/p off.
movlw D'001' ; Init. timer
movwf TMR0 ; to avoid w/d
;
; Clear workspace
;
movlw 021 ; Clear RAM
movwf FSR ; Set indirect ptr
movlw 05E ; Byte Count
movwf iomode ; Save Count
;
begin2 clrf INDF ; Clear ram via indirect
incf FSR,f ; next addr
decfsz iomode,f ; Loop till done
goto begin2 ;
clrf iomode ;
;
; All ram clear.
;
; Set o/p on phase
; (Higher value = shorter firing pulse)
;
movlw d'160' ; Triac firing pulses turned off
movwf outphase ; at ??/256 from end of each half cycle.
;
; Set master Timer value
;
movlw D'050' ; 256 - 50 = 200 Cycles
movwf clockref ;
movwf TMR0 ; Reset Timer
bcf INTCON,2 ; Reset int flag.
;
; Enable Interrupts.
;
bsf INTCON,T0IE ; Enable timer int
bsf INTCON,GIE ; & global int.
;
;
; Interrupt driven routines
;
; Executed at interval of (200nS * 200) = approx. 40uS
;
intrpt movwf w_temp ; Save W
swapf STATUS,w ; Save context
bcf STATUS,5 ; Bank 0
movwf stat_temp ;
movf PCLATH,w ; Get latch
movwf pcl_temp ; save it
;
;Timer counts UP, Int at rollover 255->0
;
movf clockref,w ; Get timer value
movwf TMR0 ; reload timer
bcf INTCON,2 ; reset ctr int flg
;
; Shift Phase counter
;
decf phase,f ; Next step
;
; Do Phase Control outputs
;
outangle movf phase,w ; Get Phase
subwf outphase,w ; Compare to o/p value
btfsc STATUS,C ; Negative result?
goto out_off ; No, turn OFF
out_on bcf PORTB,s_oe ; Yes, turn ON
goto endphase ;
out_off bsf PORTB,s_oe ; Set outputs OFF
;
; Do mains Zero-Crossing detection ;
;
;endphase movf phase,w ; Look at phase
; subwf D'64' ; 3/4 way through?
; btfsc STATUS,Z ;
; bsf mainsref,7 ; Show zero crossing occurred for async. program.
;
endphase btfsc mainsref,0 ; Look at present value
goto mains10 ;
;
; Last was 0, has it changed?
;
mains00 btfss PORTA,hz ; Still 0?
goto exitint ; Yes.
bsf mainsref,0 ; Update flag,
; bsf PORTB,mref ;
goto mainsx ;
;
; Last was 1, has it changed?
;
mains10 btfsc PORTA,hz ; Still 1?
goto exitint ; yes.
bcf mainsref,0 ;
; bcf PORTB,mref ;
;
; Zero crossing occurred.
;
; Update phase values from output values.
;
; Look at Phase counter (counts down from 255 - 0).
; Adjust master clock to get as near 255 counts as possible per sequence.
;
;
; Do clock timing.
;
mainsx movf phase,w ; Look at count
btfsc STATUS,Z ; Is it Zero?
goto mainsnul ; Yes, no change.
btfsc phase,7 ; Look at phase counter
goto mainsdec ;
;
; Phase has not overflowed, shorten timer interval.
;
mainsinc incf clockref,f ; Clock will run faster.
goto mainsnul ;
;
; Phase has overflowed, lengthen timer interval.
;
mainsdec decf clockref,f ; Clock will run slower.
;
mainsnul movlw 0FE ; Start just below 255, so 100% on possible.
movwf phase ; Restart phase counter
bcf clockref,7 ; Ensure clock can't get too fast...
;
bsf mainsref,7 ; Show zero crossing occurred for async. program.
;
;
; Restore context & return
;
exitint movf pcl_temp,w ; Restore saved regs.
movwf PCLATH ;
swapf stat_temp,w ;
movwf STATUS ;
swapf w_temp,f ;
swapf w_temp,w ;
retfie ; Back to prog.
;
; End of base program.
;
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?