more accurately, you can switch DC on but you can’t turn
it off without removing power.
AC LAMP DIMMING
If a triac stays on until the gate is removed and voltage
passes through zero, how do we use it as an element in a
dimmer circuit? What we have to do is monitor the AC voltage for the zero-cross and then gate the triac sometime
after, and within the same half cycle. If we gate the triac
about half-way through one half of the AC cycle, a lamp
connected to this output will be at about 50% brightness.
Figure 3 illustrates an AC waveform showing the zero-cross points; there are two per cycle, so our dimmer control
circuit will actually fire the triac at a 120 Hz rate. The blue
area under the curve indicates the time when the triac is
conducting. Note the hold-off period; the shorter this
period, the brighter the lamp will light.
As you might expect, we’ll use another opto-isolator to
monitor the power line for zero-cross. Figure 4 shows a circuit that I’ve seen used in many home-brew lamp dimming
circuits and it works quite well. The output on the ZC line
has a high-going pulse every 8.333 milliseconds (120 Hz)
that occurs very near the zero-cross (it actually straddles the
zero-cross point as the LEDs in the H11AA1 have a 1.2V
forward voltage). Our program will use this pulse to start
the hold-off timer for each dimming channel.
In order to control eight dimmers and get their values
from an external device via serial input, we will construct an
ISR (interrupt service routine) that handles the receive
UART and the dimmers. I selected 38. 4 kBaud for the input
as this lets us refresh 128 channels in under 50 milliseconds
(good for zippy displays), and the math works out
pretty cleanly: With a 26.042 µs bit time, we need to run
the interrupt every 6. 51 µs in order to do 4x sampling of
serial bits. Fortunately for us, 6. 51 will divide cleanly into
32. 55 µs which is 1/256th of each 60 Hz half cycle. This
allows us to set channel brightness with a byte, and as it
takes a full byte, we can do a little code trickery to construct
the hold-off period.
Within the ISR, we’ll have a divider that runs the
dimmer processing every fifth cycle. It looks like this:
CJB dimmerTix, #5, Dimmer_Done
This is pretty easy — we increment dimmerTix and
when it hits five, we will process the dimmers (resetting
dimmerTix before we do). If you haven’t jumped in to
SX assembly, let me encourage you to give it a try.
Honestly, I’m a poster boy for the purpose of SX/B: to help
BASIC Stamp users migrate from Basic only to mixed and
assembly-only projects. Remember that SX/B compiles to
straight assembly, so you can always write something in
Basic and look at the compiled output to see how the
■ FIGURE 3. AC switching.
translation is made. Using this very process, I have been
adding a lot of assembly segments to my programs where
absolute efficiency is key; you can, too.
Okay, now that it’s time to process the dimmers, what
we need to do is check to see if we’re at the zero-cross
point. This is easy: the ZC input pin will be high if we are.
Let’s assume that’s the case and that we’re at the beginning
of a new half-cycle.
JNB ZCross, Update_Triacs
MOV acc1, chan1
MOV acc2, chan2
At the zero-cross point, the program clears all of the
triac gate control pins (on port RC). Then, the current
brightness level for each channel is reloaded into an
accumulator for that channel. Note that I’m only showing
two channels above, but the program actually has eight.
Okay, now for the fun stuff. The program uses a PWM
technique that is very clever and dirt simple to implement.
■ FIGURE 4.
November 2007 15