Use an opto-isolator on an input pin and feed it the AC. This pin can serve as a reference for the 0V transitions on the AC line. A timer can be used to delay an output pin toggle based on % of time that passes between 0 crossing and AC peak. This should directly control a non zero crossed Triac or SCR. Like this..if the if the power is 60 hz, there are 120 zero crosses per second. Thats 8.3 milliseconds. If you use a byte size register you can divide that 8.3 ms by 255 and get that kind of resolution. I use only 128 as 255 is too much for such things as dimming lighting, etc. I did this in assembly on a PIC for my holiday light show. I don't think this kind of accuracy is possible without assembly and timers and interrupts. So in summary the program:
0) initialize a counter variable to count ac zero crosses
- set a timer to fire at 8.3ms / 128 and start it. Every time a zero cross occurs increase counter variable. If > 128 reset to zero and zero all outputs associated with loads.
- set an output value in another variable say 14
- in the timer loop after the increment, if your count variable has exceeded the set variable 14, togel the output pin.
- depending on the time you have and the speed of the ISR you can control quite a few channels all at different levels.
- either use a lookup table to play a predefined sequence or you will have to have another interface - I used a PC's parallel port to send channel info. This was checked in the ISR also to see if new data was available to load to the brightness registers.
- the output will be reversed since we are counting up. To get max brightness set the output variable to 0 to fire the output pin immediately after the zero cross. Set to 128 to have no output pin activity.
- I should have fixed this inversion thingy but never did.