You're right, I had the resistors wrong.
Making the change brought it up to 4.6V.
But, having the zeners in there adds about 40uS to the zero-cross signal.
It takes 35uS without the zeners, and 75uS with them.
Add in the interrupt latency for PBP type interrupts, time to do math in the handler, the minimum pauseus of 24us, and taking into account that a half cycle of 60hz is 8,333uS ... I'm sure the first step was quite a bit dimmer.
But the biggest problem is delaying inside the interrupt handler.
When 90% of the time is spent in the handler, the pause 10000 in the main loop takes almost a minute.
So here's my next attempt.
It uses Timer1 for the delays, so the main program can keep running in the foreground.
The handlers have been changed to ASM type to minimize latencies.
And the math is done in a separate subroutine that only runs once when you change the brightness, instead of having to do the math on every zero-cross.
It should be pretty close to the MAX/MIN dimming, but you may need to adjust the MaxBright/MinBright constants a little.
If you adjust them too far, it will start flashing.
Code:
INCLUDE "DT_INTS-14.bas" ; Base Interrupt System
INCLUDE "ReEnterPBP.bas" ; Include if using PBP interrupts
Include "modedefs.bas"
@ __Config _XT_OSC & _WDT_ON & _PWRTE_ON & _MCLRE_OFF & _BODEN & _CP & _CPD
MaxBright CON 8250 ; maximum brightness
MinBright CON 200 ; minimum dimming
Brightness var word
TriacDelay var Word
AlwaysON var BIT
AlwaysOFF var BIT
OffPeriod var BIT ; used by timer1 periods
Triac var PortA.1 ' Output to TRIAC gate
ACLine var PortA.2 ' Input for the FullWave rectify AC line
Buz var PortC.2
INTEDG VAR OPTION_REG.6
TMR1ON VAR T1CON.0
TMR1IF VAR PIR1.0
Timer1 VAR WORD EXT
@Timer1 = TMR1L
TRISA = %001100
TRISC = 0
CMCON = 7
ANSEL = 0
PORTA=0
PORTC=0
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler INT_INT, _ACDetect, ASM, yes
INT_Handler TMR1_INT, _T1Handler, ASM, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM
@ INT_ENABLE INT_INT ; enable external (INT) interrupts
@ INT_ENABLE TMR1_INT ; enable Timer1 interrupts
Triac=0 ' disable Triac Gate
brightness=0 ' Set delay to minimum
gosub SetDelay
while 1
pause 3000
high buz: pause 500 : low buz
brightness=MaxBright : gosub SetDelay : pause 10000 :high buz: pause 50 : low buz
brightness=MaxBright-2 : gosub SetDelay : pause 10000 :high buz: pause 50 : low buz
brightness=4500 : gosub SetDelay : pause 10000 :high buz: pause 50 : low buz
brightness=4000 : gosub SetDelay : pause 10000 :high buz: pause 50 : low buz
brightness=3500 : gosub SetDelay : pause 10000 :high buz: pause 50 : low buz
brightness=MinBright : gosub SetDelay : pause 10000 :high buz: pause 50 : low buz
brightness=0 : gosub SetDelay : pause 7000
wend
SetDelay:
Brightness = Brightness min MaxBright ; limit maximum brightness
AlwaysON = !(Brightness != MaxBright) ; MaxBright is always ON
AlwaysOFF = !(Brightness != 0) ; 0 is always OFF
if !AlwaysOFF then Brightness = Brightness max MinBright ; limit minimum dimming
triacdelay = -(MaxBright - Brightness) ; calc delay time
RETURN
;------------------------------------------
T1Handler:
if OffPeriod then ; triac delay finished
OffPeriod = 0
triac=1 ; turn on triac
Timer1 = -50 ; load timer for 50uS
else
triac = 0 ; turn off triac after 50uS
TMR1ON = 0
endif
@ INT_RETURN
;------------------------------------------
ACDetect:
if AlwaysON then
triac=1 ' Activate TRIAC
else
if AlwaysOFF then
triac = 0
else
Timer1 = triacdelay ; load delay into timer
TMR1IF = 0 ; clear the interrupt flag
TMR1ON = 1 ; start the timer
OffPeriod = 1 ; tell T1Handler this is the main delay
endif
endif
INTEDG = !INTEDG ; toggle INTEDG to get both edges
@ INT_RETURN
Hope that works better.
Bookmarks