How to set up zero crossing software to trigger a Triac
This AN was submitted by Mike Crean.
Here is some additional info from Mike. He sent this after the first circuit
was published.
If anyone is trying to use the zero crossing detector in AN125 there are corrections.
The 10k resistor from pin 1 of the 4069 hex. Inverter should NOT be pulled LOW
It should be pulled HIGH (5V+). The pulse width on pin 4 should be less than 1ms.
The pull up resistor on the collector of the BC548 should be 1K NOT 1K5.
If anyone is using a sensitive gate TRIAC remember to use a bias resistor (10k) on
the gate to neutral or timing cap line side. This will prevent erratic triggering by
external electrical noise.
The 2nd. zero crossing circuit in AN125 should be used for more stable operation
of the TRIAC.
It also shows how to use Timer0, Urxc ISR and ADCs from the AT90S8535.
Here are two methods to derive the zero crossing from the mains.
DANGER - WARNING
High voltages are present when equipment
is connected to a mains supply.
Some Authorities may only allow suitably
qualified & licensed persons to connect
any such equipment to a high voltage
supply.
Take CAUTION. Avoid electric SHOCK

The pulse time will depend on the mains frequency used in your country.
Below you can find the program. You can also download
it.
For a dimmer with fader, download
Mikes sample
'*****************************************************
'** **
'** 24Volt 40A Battery Charger **
'** **
'** Mike Crean
Perth Western Australia **
'** mike.crean@y7mail.com **
'** **
'** mgc
Start 02/01/2003 **
'** Finish 23/01/2003 **
'** **
'*****************************************************
'@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
'@@ @@
'@@ This is a program to drive a MOC into a Triac @@
'@@ using an AT90S8535 AVR micro. @@
'@@ @@
'@@ Demo of using INT0 for zero crossing detection @@
'@@ & Timer0 for Triac control, also shows use of @@
'@@ Urxc ISR for comm's interface & use of ADCs. @@
'@@ @@
'@@ The hardware for this project is reserved & @@
'@@ will not be released. @@
'@@ @@
'@@ This battery charger was developed to charge @@
'@@ 24V 500A/Hr batteries on stationary Gen. Sets. @@
'@@ It has to shut OFF when the prime mover is @@
'@@ cranking (500-800A). It has 4 levels of voltage @@
'@@ Control 25, 27, 28 & 28.5V and 4 levels of @@
'@@ current control 40, 12, 8(variable) & 0A.
Some @@
'@@ of the current controls very with battery @@
'@@ condition. It has a float & Triac fail @@
'@@ timer (4min.) @@
'@@ @@
'@@ There are a number of features that could be @@
'@@ added, like|- de-sulfate timer with voltage & @@
'@@ current control @@
'@@ @@
'@@ @@
'@@ Must set up
AVR-IDE for AT90S8535 @@
'@@ --------------------------------- @@
'@@ @@
'@@ From Options
menu, select compiler, chip & @@
'@@ set to 8535,
in communications tab set @@
'@@ Fequency to
8000000 @@
'@@ From the
programmer menu set programmer to @@
'@@ STK200/STK300
programmer, Auto Flash tick @@
'@@ only and cable
to Parallel @@
'@@ This is for
the ISP programmer dongle in the @@
'@@ BASCAVR1.PDF
manual (about page 396). @@
'@@ @@
'@@ ** F7
Compile @@
'@@ ** F2
Simulate @@
'@@ ** F4 Send to
chip @@
'@@ @@
'@@ ** $sim must
be included & compiled when @@
'@@ simulate is
run. @@
'@@ ** $sim must
be REM out when compiled to @@
'@@ send to
chip @@
'@@ @@
'@@ FOR MORE INFORMATION
ON IDE set up and @@
'@@ programming,
READ THE BASCAVR1.PDF manual or @@
'@@ use HELP @@
'@@ @@
'@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
'$sim
$regfile = "8535def.dat"
$crystal = 8000000
$baud = 9600
Config Adc = Single , Prescaler = Auto
Config Timer0 = Timer , Prescale = 1 '** Sets T0 / rate
'** Values (1,8,64,256 &
Config Int0 = Falling '** Interrupt 0, PIN 16 (Int0)
Config Portd = Input '** Set Portd to Inputs
Config Portb = Output '** Set Portb to Outputs
Config Portc = Output '** Set Portc to Outputs
Cursor Off
'** Config variables
Dim Rx As Byte , Channel As Byte , Flag27 As Byte , Flag28 As Byte
Dim Flagchk As Byte , Lv As Byte , Mv As Byte , Hv As Byte , Ea As Byte
Dim Eep As Byte , Shit As Byte , Fdcount As Byte , Fdmult As Byte
Dim Startflag As Byte , Stod As Byte , Ep As Byte , Ehv As Byte
Dim Count As Integer , Td As Integer , Tds As Integer , Dcount As Integer
Dim Vd As Single , Amps As Single
Dim W As Word , Stuff As Word , Stuffs As Word , Ftd As Word
Startflag = 0
'** Get Values from Eeprom
Readeeprom Ea , 2
Readeeprom Hv , 3
Readeeprom Mv , 4
Readeeprom Lv , 5
Readeeprom Shit , 6
Readeeprom Fdmult , 7
Readeeprom Stod , 8
Readeeprom Ehv , 9
'** 1st. run after programming, Ea should be 255
'** If Ea > 251 then load defaults to variables &
write to Eeprom **
If Ea > 251 Then
Ea = 145 : Hv = 141 : Mv = 138 : Lv = 130 : Tds = 110 : Shit = 255
Dcount = 0 : Fdcount = 0 : Fdmult = 240 : Stod = 2 : Ehv = 143
Writeeeprom Ea , 2
Waitms 10
Writeeeprom Hv , 3
Waitms 10
Writeeeprom Mv , 4
Waitms 10
Writeeeprom Lv , 5
Waitms 10
Writeeeprom Shit , 6
Waitms 10
Writeeeprom Fdmult , 7
Waitms 10
Writeeeprom Stod , 8
Waitms 10
Writeeeprom Ehv , 9
Waitms 10
End If
Ftd = Shit * 100
Flag27 = 0 : Flag28 = 0 : Flagchk = 0 : Startflag = 0 '** Set Flags
On Urxc Rec_isr '** Call Recv. Interrupt service routine
Enable Urxc '** Enable ISR calls
On Timer0 Tim0_isr '** Call Timer0 ISR
Enable Timer0 '** Enable Timer0 ISR calls
Enable Int0 '** Enable Int0 ISR calls
On Int0 Int0_isr '** Call Int0 ISR
Enable Interrupts '** Enable all interrupts
Stop Timer0 '** Stop the Timer
Start Adc '** Start the Adc
Portc = 0 '** Set Portc LOW (0)
Portc.0 = 1 : Portc.2 = 1 : Portc.3 = 1 : Portc.4 = 1 '** Set Portc
Portb = 255 '** Set all bits on Portb High
'** all bits pulled HIGH with
'** internal pull up resistors
Portb.2 = 0 '** Pull PortB.2
Low (Triac OFF)
'***** MAIN PROGRAM
LOOP *****
Do
nop
Loop
Getadc:
'** Read the ADC
channels (10 bit ADC) = (0 to 1023 count)
For Channel = 0 To 7
W = Getadc(channel) '** Loop to
read 8 Adcs
If Channel = 0 Then Stuff = W / 3 '** Put ADC0 / 3
into Stuff (Amps)
If Channel = 1 Then Stuffs = W / 3 '** Put ADC1 / 3
into Stuffs (Volts)
Next Channel
'** If a start
sig. is seen on Pd6
If Pind.6 = 1 Then '** Turn OFF Charger & Starter ON
If Startflag = 0 Then
Portc.0 = 0 : Portc.3 = 1 : Portc.4 = 1
Wait Stod
Portc.1 = 1
Startflag = 1
Portc.1 = 1
End If
End If
'** If No start
sig. on Pd6
If Pind.6 = 0 Then '** Turn Starter OFF & Charger ON
If Startflag = 1 Then
Startflag = 0
Portc.1 = 0
Wait Stod
Portc.0 = 1
End If
End If
If Startflag = 1 Then Goto Starting '** Jump this lot if Starting
Td = Stuff '** Put Stuff (word) into Td (Integer)
If Stuffs > Td Then Td = Stuffs
If Stuffs < Lv Then '** If Batt < 25.5V set to max C/R
Flag27 = 0 '** C/R is Charge Rate
Flag28 = 0
Portc.2 = 0 : Portc.3 = 1 : Portc.4 = 1 '** Set LEDs on
Portc
End If
If Stuffs > Mv Then '** If Batt > 27V set 27V Flag
If Flag27 = 0 Then
If Flagchk = 0 Then
Flag27 = 1
Portc.2 = 1 : Portc.3 = 0 : Portc.4 = 1 '** Set LEDs on
Portc
End If
End If
End If
If Stuffs > Hv Then '** If Batt > 28V set 28V Flag
If Flag27 = 1 Then
If Flagchk = 0 Then
If Flag28 = 0 Then
Flag28 = 1
Portc.2 = 1 : Portc.3 = 1 : Portc.4 = 0 '** Set LEDs on
Portc
End If
End If
End If
End If
If Stuffs > Ehv Then '** If Batt > 29V set 28V Flag = 2
Portb.2 = 0 : '** Turn off Triac
Waitms 250 '** Wait .25 Sec.
Portc.0 = 0 '** Turn OFF mains relay TRIAC may be
Flag28 = 2 '** at FAULT (will cycle every 4 min.)
Portc.2 = 1 : Portc.3 = 1 : Portc.4 = 1
'** Turn all LEDs ON to indicate FAULT
End If
If Flag28 = 1 Then
Portb.2 = 0 '** Set Portb.2 LOW Triac OFF
Flag28 = 2 : Count = 0
End If
If Flag28 = 0 Then
If Td < Tds Then Td = Tds '** Set Td not < Zero Cross or max amps
If Td > 217 Then Td = 217 '** Set Td not > next Zero Cross
If Flag27 = 1 Then Td = Ea '** If Batt > 27V Set max Amps to 8
End If '** value 145
Starting:
Return
Int0_isr: '** Interrupt0 Interrupt Service Routine
Start Timer0 '** Start Timer 0
Gosub Getadc '** Get the Amps & Volts from the ADC
'** The ADC conversion & other
'** calculations are in this section
'** because they take the most time.
Return '** Return to MAIN Program Loop
Tim0_isr: 'Timer0 ISR, called if T0 overflows
If Startflag = 1 Then '** If Startting set Portb Low
Portb = 0
Goto Yes_start '** Jump to Yes_start
End If
If Flag28 = 0 Then
Count = Count + 1 '** Start counter (No. of interrupts)
'** counts each time T0 overflows
If Count > Td Then '** If the count > AD0 / 3 then send
Count = 0 '** pulses & set count to 0
Stop Timer0 '** Stop Timer 0
'** Send 3 pulses to the Triac
Set Portb.2 '** Turn Portb.2 on (high), PIN 3
Waitus 100 '** Wait 100 u/s
Reset Portb.2 '** Turn Portb.2 off (low), PIN 3
Waitus 100 '** Wait 100 u/s
Set Portb.2 '** Repeat for 3 pulses
Waitus 100
Reset Portb.2
Waitus 100
Set Portb.2
Waitus 100
Reset Portb.2
Waitus 100
End If
End If
If Flag28 = 2 Then '** If 28V Battery Flag is set to 2
Portb.2 = 0 '** Turn Portb,2 OFF (Triac OFF)
Dcount = Dcount + 1 '** Set up a 4min. Timer
If Dcount > Ftd Then
Dcount = 0 : Fdcount = Fdcount + 1
If Fdcount > Fdmult Then
Fdcount = 0 : Dcount = 0 : Flag27 = 0 : Flag28 = 0
Portc.0 = 1
Waitms 250
End If
End If
End If
Yes_start:
Return '** Return to MAIN Program Loop
Rec_isr: '** Recv. buffer
ISR
Rx = Inkey() '** Get Char (ASCII) from Recv. buffer
If Rx = 63 Then '** 63 = chr ?
Print : Print " 24V Battery
Charger" '** Send to Tx buffer
Print "
-----------------------------"
Print : Print " | - Get All
Values"
Print " ! - Set Max Amps (40A) value
110 "
Print " @ - Get Volts & Amps"
Print " # - Turn 27V & 28V Flags
OFF"
Print " $ - Turn Voltage Flags ON"
Print " % - Set all Micro values &
write to Eeprom"
Print " ^ - Read Micro values from
Eeprom"
End If
If Rx = 124 Then '** 124 = chr |
Print : Print " Td = " ; Td '** Send Td to Tx
buffer
Print " Count = " ; Count
Print " Ea = " ; Ea
Print " Tds = " ; Tds
Print " W = " ; W
Print " Stuffs = " ; Stuffs
Print " Flag27 = " ; Flag27
Print " Flag28 = " ; Flag28
Print " FlagChk = " ; Flagchk
Print " Eight Amp Value = " ; Ea
Print " Ehv 29V Value = " ; Ehv
Print " Hv 28V Value = " ; Hv
Print " Mv 27V Value = " ; Mv
Print " Lv 25V Value = " ; Lv
Print " Ftd float time delay = " ; Ftd
Print " Dcount = " ; Dcount
Print " Fdt Mult. count (Fdcount) =
" ; Fdcount
Print " Fdmult = " ; Fdmult
Print " Startflag = " ; Startflag
Print " PortD.6 = " ; Pind.6
Print " Stod Start Relay Delay = " ; Stod
End If
If Rx = 33 Then '** 33 = chr !
Waitms 100 '** Must turn OFF Recv. ISR
Disable Urxc '** & interrupts if Input is used
Waitms 50 '** Need short delays
Disable Interrupts
Waitms 100
Input " Enter Tds value " , Tds
Waitms 100 '** Need short delays
Enable Urxc '** Must turn Recv. ISR ON to
Waitms 50 '** enable more Uart ISR's
Enable Interrupts
Waitms 100
End If
If Rx = 64 Then '** 64 = chr @
Vd = Stuffs / 5.0 '** Was 4.75
Amps = Stuff / 5.8 '** Was 3.26
Print " Volts = " ; Vd
Print " Amps. = " ; Amps
End If
If Rx = 35 Then '** 35 chr # - Hold Flags OFF
Flagchk = 1
Flag27 = 0
Flag28 = 0
End If
If Rx = 36 Then '** 36 chr $ - Set Flags to ON
Flagchk = 0
End If
If Rx = 37 Then '** 37 chr % - Set all volts &
Waitms 100 '** Amps Values
Disable Urxc
Waitms 50
Disable Interrupts
Waitms 100
Print : Print " Max. for
any Value is 255"
Input " Enter Tds max amps (110 = 40A)
" , Tds '** Tds max amps
(38A) value (110)
Input " Enter Lv min volts (130 = 25V)
" , Lv '** Lv 25V value
(130)
Input " Enter Mv med volts (138 = 27V)
" , Mv '** Mv 27V value
(138)
Input " Enter Hv high volts (141 = 28V)
" , Hv '** Hv 28V value
(141)
Input " Enter Ehv Extra high volts (143
= 29V) " , Ehv '** Ehv 29V value (143)
Input " Enter Ea 8A (145 max 250)
" , Ea '** Ea 8A value
(145)
Input " Enter Ftd float time delay (255
= 1 Sec.) " , Shit
'** Ftd float time delay value ( )
Input " Enter Fdt Mult. (Fdcount)
(240=4min.) " , Fdmult
Input " Stod Start Relay Delay 1 to 255
Sec's " , Stod
Waitms 50
Writeeeprom Ea , 2
Waitms 10
Writeeeprom Hv , 3
Waitms 10
Writeeeprom Mv , 4
Waitms 10
Writeeeprom Lv , 5
Waitms 10
Writeeeprom Shit , 6
Ftd = Shit * 100
Waitms 10
Writeeeprom Fdmult , 7
Waitms 10
Writeeeprom Stod , 8
Waitms 10
Writeeeprom Ehv , 9
Waitms 50
Enable Urxc '** Must turn Recv. ISR ON to
Waitms 50 '** enable more Uart ISR's
Enable Interrupts
Waitms 100
End If
If Rx = 94 Then '** 94 ^ Read Eeprom values
Waitms 100 '** Amps Values
Disable Urxc
Waitms 50
Disable Interrupts
Waitms 100
Readeeprom Ep , 2
Print : Print " Low amps
(8A=145) Ea = " ; Ep
Readeeprom Ehv , 9
Print " Extra high volts (29V = 143)
Ehv = " ; Ehv
Readeeprom Ep , 3
Print " High volts (28V = 141) Hv =
" ; Ep
Readeeprom Ep , 4
Print " Med. Volts (27V = 138) Mv =
" ; Ep
Readeeprom Ep , 5
Print " Low volts (25V = 130) Lv =
" ; Ep
Readeeprom Ep , 6
Print " Float delay (255 = 255) Shit =
" ; Ep
Readeeprom Ep , 7
Print " Float Mult. (240 = 240) Fdmult
= " ; Ep
Readeeprom Ep , 8
Print " Start delay (2sec = 2sec) Stod
= " ; Ep
Print
Print " Ea = " ; Ea
Print " Ehv = " ; Ehv
Print " Hv = " ; Hv
Print " Mv = " ; Mv
Print " Lv = " ; Lv
Print " Shit = " ; Shit
Print " Ftd = Shit * 100 Ftd = " ; Ftd
Print " Fdmult = " ; Fdmult
Print " Stod = " ; Stod
Waitms 50
Enable Urxc '** Must turn Recv. ISR ON to
Waitms 50 '** enable more Uart ISR's
Enable Interrupts
Waitms 100
End If
Rx = 0
Return '** Return to MAIN Program Loop
End '** End of program and code space
|