I went to the hardware hacker’s Mecca of Central Florida, Skycraft, and bought a hardware box to house my Solid State Relays in. In the end I ended up drilling too many holes, and didn’t like the way things were spaced.
It was also during this time I learned that the Solid State Relays I were planning to use would not be ideal for dimming. I was learning about Zero-Crossing, and found the opto-22′s I had wouldn’t be fast enough to be fired in as many places as I would like for precise, 8-bit dimming.
I was donated a surface mounted TRIAC, and a MOC3021 opto-isolator to drive them. I built a reference circuit from the opto-isolator’s datasheet that allowed for the drive of inductive loads, but found that the circuit was producing a high pitched hum; it worked though. I connected the isolator’s on pin via resistor to a 5v+ source, and was able to tap a string of christmas lights on and off by touching the drive pin to 5v+.
I decided it was time to start coding a PIC to phase control the TRIAC, and as I knew the ultimate goal was to drive the TRIACs serially, I started to look into PICs that supported UART. It just so happened that the spare PIC16F628s I had supported hardware UART, and were common chips.
I wrote VERY preliminary code that counted from 0-15, over and over at different speeds, and illuminated the count via LEDs. I coded the test routine to count 16 different intensity levels with, and display the count by binary on 4 LEDs. Other than that, it did not do much else besides set up a framework for future code. The video below showcases the hardware I was planning to use at the time.
As is shown, early on I planned on using a Mini-ITX motherboard I had to run a daemon to interpret network packets via programmable scripts, and use them to drive the PIC I was going to code. While I did not end up doing this, this idea ended up being used later on…
The next part of my code was of course a lot more complex. I had to find a way to detect the zero-crossing, and to turn on the Triac at the appropriate time. Of course, this was dependent on having zero crossing detection circuit. I scoured the internet, and came across this design by Michael Pearce:
His design called for a transformer that would step down the 120v AC to 6-8v. While undesirable, I went with an oversized, over-kill transformer I bought from Skycraft. Even with the size, I still had more than enough space for it my project box. I know I could have gone with other ways of detecting zero crossing without a transformer, but as my number one goal was safety, I liked the idea of using the transformer as a natural protection as it would step down voltage efficiently.
In the design, the output of the transformer becomes rectified, and is eventually fed into a Transistor. When the base is driven low, it causes a pull up resistor to drive an input pin high. I would use this to trigger a hardware interrupt on the PIC. The design also used the stepped down voltage coming from the rectifier to drive a 7805 5v Regulator. As I was using a PSU rail at the time, I wasn’t planning on using this, but ultimately ended up using it for power as the ITX computer was taken out of the design.
The circuit also has an adjustable 10k ohm pot used to fine tune the zero crossing detection. I connected the output of the circuit to an oscilloscope, with the AC Sine Wave on a second channel. I found that the Zero Crossing detection pin would rise before the actual crossing. On the scope, I measured these two events happened about 1.2ms apart. I knew I would have to account for this with an offset..
Sometime, around 4AM, last Thursday, I came up with this mess of a pseudo-code..
What I ended up planning was to set up a hardware interrupt to detect the zero-crossing, and then I’d copy whatever value I had for channel brightness (as was set by counter debug code) to a channel work register. After, I would set up a timer to account for the offset. When the offset finished, I started the actual routine.
The routine would then loop for how many levels of brightness I desired -1, at the time 16, and add one to the channel’s work register. I’d turn off that channel if the register did not overrun that pass, and turn it on if it did.
As an overrun would be any value that would exceed 255 (size of a byte) I used values 240-255 at the time to represent the 16 degrees of brightness, one of which being 0 of course. The routine would run for 15 loops, so if the value of 240 was used for a channel, by the end of the loop, the value would have become 255, and would have cut short before it overrun, hence never turn on. Likewise, if the maximum value of 255 was used, it would overrun the first loop, and hence be turned on. As 255 would overrun first loop every cycle, it would never turn off. These loops used a timer interrupt to space each half cycle 6.7% apart to have a linear scale of time for each value.
This would work great for this version of the code, (v0.4) but as I’d come to find I would run into problems once I increased to 256 levels of brightness.
Th early hardware I was testing with:
Youtube clip of early dimming code in action:
Next up, more permanent hardware, ICSP circuit, and optimization….







Hi.
Does the transformer induce some phase (delay) to the zero cross detection?
Juan, I’d imagine the Sine Wave looks the same after being stepped down, only with less power, so I don’t think a delay is being caused here, or the wave is being pushed out of phase.
The wave becomes rectified and drives a Transistor that in turn inverts the signal into a a square wave. i.e. when voltage is 0, the transistor passes no power, and a pull up drives the interrupt high. What I believe is happening is once the wave hits a low threshold, say 4v, for example, the transistor no longer functions, and the interrupt is triggered. I’d like to find a solution to this.
Hope that helps.
I know this has been idle for a few months but just to give a possible solution.
You have a processor, which allows you more flexibility that a transistor circuit monitoring a full wave rectifier.
If you use a single separate diode as a half wave rectifier,with some resistors you’ll get a square wave at the line frequency, that you could read with logic input.
Now if life were perfect,you’d be set, because all you would have to do is monitor that input for an edge. Rising or falling. That would be a zero crossing. It may even work just that simple. But possibly there is line noise on the AC that would give you several as the signal is near Vinputhigh. There is also a symmetry issue, where voltage crossing would be different on one phase from the other. Its the kind of thing you’d use a Schmidt trigger to read if you were using pure logic.
This is where the processor comes in. You can calculate how deep into the wave form the input crosses Vih, and when it will crass back again on the way down. From there you can calculate where the real zero crossing is.
With further elaboration you should be able to use that data make a phase locked loop in software that locks into the 60 Hz signal of the AC line. Using that as a time base, then you can determine your triac firing times.
On additional thought, you can really factor out the asymmetrical aspect of the half wave detector. Whatever Vih is, the peak of the AC powerline waveform is going to be half way between the rising edge and the falling edge. Likewise the nadir of the low part of the cycle will be half way between the falling edge and the next rising edge.
This PIC has a timer. So if (after deglitching) you take the times of the rising and falling edges, you should be able to calculate where the peaks are, and thereby the zero crossings.
I’d probably set it up so that a timer caused an interrupt when it rolled over, intending that to be a zero crossing. Reloading the timer count should take into account the error based on the the expected peak times. If the peak is not at 1/4 of a cycle, and the low at 3/4 of a cycle, calculate the error, and add that in when setting the timer count back 1/2 a cycle in the interrupt service routine.
You can even use an initialization process at the start of day to figure out how many timer ticks a cycle is, and not worry about an absolute scaled time base. just get an average for a few cycles.
Therefore with a bitof deglitching, you should be able to know
You can use another optocoupler on the transformer line in place of the transistor circuit instead. Look up the 4N26. The internal diode will half rectify the wave and the transistor will cause a more precise square wave you can base your timing from.
You must be Psychic. The last comment here was over a month ago, and I JUST had gotten done purchasing it’s sister chip, the H11AA1 when you commented. I was researching this earlier. The Renard PIC controller uses it, and I think I’ll adapt it also.