There are serial controlled dimmers such as these for various load wattages. There are also some wireless controlled dimmers (WiFi, BlueTooth etc) listed on the same page.
For ballasted fluorescent lights, a different type of dimmer is needed: a Ballast Control Module.
Similar, lower cost products are available on various auction sites, but caution is good when buying mains electrical equipment from overseas. Also, it might be worth verifying certification of these products for use in your country.
If you want to build your own dimmer, please note that playing with live mains can be somewhat fatal, so to speak. Unless you are qualified to work with electrical mains, this is best avoided.
I'd start to debug by attempting to switch the load on and off a few times in the setup to ensure the TRIAC is firing, for example:
void setup()
{
pinMode(AC_LOAD, OUTPUT); // Set the AC Load as output
for (int i=0; i < 10; i++)
{
digitalWrite(AC_LOAD, HIGH); // triac firing
delay(1000);
digitalWrite(AC_LOAD, LOW); // triac Off
delay(1000);
}
}
The MOC3021SM Datasheet shows that 15mA may be required to drive the LED. At 3.3V as shown in the schematic R5 the 470R resistor would limit the current to 7mA and at 5V it would still only be 10mA and that's ignoring the forward voltage drop.
You can use a normal LED resistor calculation to determine the resistance, it looks like about 1.15V forward voltage drop for that part at room temperature so 120 ohms at 3.3V would be more appropriate to give a bit above 15mA. The following are the recommendations regarding LED current from the datasheet:
All devices are guaranteed to trigger at an IF value less than or equal
to max IFT. Therefore, recommended operating IF lies between max IFT
(30mA for MOC3020M, 15mA for MOC3010M and MOC3021M, 10mA for MOC3011M
andMOC3022M, 5mA for MOC3012M and MOC3023M) and absolute max IF(60mA)
If that works OK next step may be to test the zero-crossing detection works at least once, maybe using the following and seeing if it turns on after 10 seconds:
void setup()
{
pinMode(AC_LOAD, OUTPUT); // Set the AC Load as output
digitalWrite(AC_LOAD, LOW); // triac Off
delay(10000);
attachInterrupt(0, zero_crosss_int, RISING); // Choose the zero cross interrupt # from the table above
}
void zero_crosss_int() // function to be fired at the zero crossing to dim the light
{
digitalWrite(AC_LOAD, HIGH); // triac firing
}
If that doesn't work maybe remove U1 the optocoupler (if in a socket?) and see if the above works if you short the output between the emitter and collector (carefully!) on U1 together to pull the input down to ground. It may be you have a general interrupt configuration problem depending on which pin it's connected to, which you should add to the question, but that will help isolate a software versus hardware problem.
Best Answer
You can dim a light bulb two ways - decrease the current or decrease the duty cycle of the source waveform.
If you put a resistor (or potentiometer) in series with the bulb, the current will be decreased accordingly. The bulb filament will not heat up as much, and will dim. This is a huge waist of energy, because the resistor will use a lot of power in the form of heat as a result of reducing the current.
If you decrease the duty cycle of the source waveform, the average current will drop and cause the same reaction. How much power is saved depends on the circuit used to control the duty cycle. Look up triac.