I've been fortunate enough to have good experience with phase control using microcontrollers.
Although I don't use AVR micro controllers in projects, the same general rules apply, so here are a couple of pointers for the uninitiated:
Hardware Component Selection (aimed at most hobbyist projects):
H11AA1's are a great choice for the zero cross detection. The emitter is bidirectional, which reduces the board component count.
MOC302x - series opto's are a great for the output. They are opto-triacs very well suited to triggering the gate of a larger triac.
I've found BTA20 and BTA40 series triacs to be hard-wearing, good for general use and difficult to damage. From memory they're also snubberless, which is great for inductive loads.
Hardware Safety Considerations:
MAKE SURE YOUR PCB TRACKS CAN HANDLE THE CURRENT YOU INTEND TO CONTROL. The current carrying capacity of a PCB track can be increased by leaving the solder mask off and bulking the track up with solder during assembly.
Place a fuse (resettable if possible) in series with the triac to protect against overcurrent.
Keep 5v and 240VAC areas on your board well separated. There's little risk of flash-over at 240VAC, but there's high risk of touching live areas when doing debugging and testing.
Place a "DANGER HIGH VOLTAGE" marking in a prominent position on the silk.
Mark high voltage connectors CLEARLY to reduce the risk of incorrect connections.
Make sure the resistors on the AC side are properly rated for the wattage they'll need to drive.
Make sure you stay within current limit specs of both optocouplers.
Pull down your firing optocoupler's emitter to ground to ensure the AC load is forced OFF if the microcontroller is malfunctioning, non operational, unprogrammed or otherwise not in control of the load. You don't want a motor spinning up while you program the microcontroller etc. etc. etc.
Hardware Design Considerations:
Make sure the output optocoupler delivers sufficient gate current for the triac to turn on.
Keep the capacitance of the zero-cross detection line and the output to the firing optocoupler as low as you possibly can - this will ensure that there's no detection and command delays that could spill over a zero-cross event.
Triac's have a holding current - keep this in mind when choosing a triac for your load impedance. Don't specify your triac holding current at the threshold. Factor in some operational margin to accommodate worst-case components in a batch - not all triacs in a series are the same. Manufacturing tolerances will cause them to differ slightly in their specifications.
Also keep in mind that the manufacturer's specs are at a given temperature. If your application's temperature differs significantly, things like current thresholds may be substantially lower or higher.
Firmware Design Considerations:
Do as little as possible in an interrupt handler. Keep them simple and to the point.
Remember: Triacs can be turned on anywhere during the AC cycle (except at the zero cross point exactly) but will only turn off when BOTH the following are true:
1.) The AC sine wive is at the zero cross.
2.) There is no gate current.
Unless BOTH the above conditions are fulfilled, the triac will stay on.
Don't turn the triac off too quickly after you've turned it on. Allow some time for the load current to reach the holding current threshold. For inductive loads, the current lag may require you to increase the the duration of the firing pulse to allow the current through the triac to ramp up beyond the holding threshold. This also implies that your minimum on-time (think minimum "dim" level or minimum motor speed) will be greater than the triac turn on time. Don't expect your phase control firmware to be able to "dim" down to 0%. Aim for 5% and simply turn off the triac completely beyond that. The same applies to low leading edge delays. Aim for 95% and simply turn the triac on manually at values higher than 95%. This will prevent zero-cross mismatch flickering.
If your leading edge delay plus your pulse duration exceeds half the period of the AC frequency, you will have gate current flowing in the triac across the zero cross and the triac will be fully on for at least the next half-cycle. This is the major cause of flashing, flickering and motor jittering. Falling edge detection works better than rising edge detection in mitigating this issue.
Make sure you understand your chosen timer well. Some microcontrollers have timer peripherals that only allow adjustment of counter, reload, overflow and prescalers when the timer is inactive. Others, like ARM Cortex based microcontrollers, can be updated on-the-fly. Make sure that timer updates are done atomically, otherwise your reload or counter updates may be interrupted by other parts of the system.
If you have more than one output to control, make sure your functions are re-entrant, as timer interrupts may cause a function to exit and resume later.
All the best