My Light Contraption


Disclaimer: I am not an expert in any of this. There is lots of information online regarding such designs. Although this setup worked for me, do not trust any of my calculations. Please work all this out for yourself and consult many other sources, or it may spontaneously burst into flames.

The contraption is a board containing two lights and a receptacle that are controlled by a computer communicating with the Arduino microcontroller. The project grew out of a desire to learn more about microcontroller programming and some circuit design, something I had never really done before.

Below is a video of the contraption in action. In the video, I control the two light bulbs, as well as a blender, from my computer. (Note: the video does not have sound)

Download Video:

Principle & Hardware

The hardware was laid out on a plain wood board as shown in the photos below.

Overall layout of the contraption
Close-up of the main circuits

Note that all power is actually flowing through the breadboard. This is probably not a very good idea, but as we are dealing with only an amp or two at most, I thought it might be satisfactory. I’ve included both an on/off switch, and a 5A circuit breaker for safety.

The schematic below shows the main circuit used in controlling the power to the lights and the receptacle. This circuit is nearly identical to that found in the MOC3022M datasheet

Triac circuit diagram

The main principle is as follows:

  1. The opto-isolating triac (MOC3022M) receives an input from an Arduino output pin.
  2. This allows bi-directional voltage on the triac side (pins 6 and 4). This voltage comes from the mains through 180Ω resistor R2 and to the gate pin on the triac T1.
  3. This voltage turns on the BTB08 triac (T1) through its gate pin. This allows conduction through the triac and through the load.

A few notes and equations: * The BTB08 triac chosen is ‘snubberless’. It therefore may not be necessary to include a snubber circuit for inductive loads. I didn’t include one, and as seen in the video, it seems to work ok for the blender motor. * The Arduino output (Vcc) is 5V. Therefore, the max current through the left side of the MOC3022M is 5V/390Ω = 12.8mA * The peak voltage of the AC Mains is approximately 170V. Therefore, current through the right side of the MOC3022M is limited to 170V/180Ω = 0.94A. This is just under the maximum of 1A listed in the data sheet * The triac T1 is always operating in quadrants I or III.

Zero-Crossing Detector

If no voltage is applied to the left side of the MOC3022M, the mains current flow through the T1 triac will stop when the mains voltage reaches the zero-point crossing. The solution is to leave the Arduino output on, which works only if you want the mains circuit completely on. However, for dimming, you must know when the zero cross occurs.

Zero-cross detection circuit diagram

This circuit allows an Arduino input pin to register when the AC mains voltage is in the positive half-wave.

  1. The negative half-wave is removed by the diode. Therefore, the RMS voltage is 60V
  2. The four resistors have an equivalent resistance of 10kΩ. Therefore, the RMS current is 60V/10kΩ = 6mA. The reason for several resistors is to reduce the power at each resistor. The voltage across each resistor is 30V, therefore the power dissipation is (30V)(30V)/10kΩ = 90mW

Note that detection by the Arduino of the start of the positive half of the sine wave is delayed, and the detection of the end is too early. Below is an exaggerated diagram.

Zero-cross detection sketch

The counter in the diagram refers to the AVR timer counter that counts ticks between the rising and falling edges. The average of the rising and falling edge counters gives 60Hz. In order to dim, the triac must turn on at a specified point during the sine wave. That point is calculated in the code. Therefore, the timer for turning on the triac must be kept in sync with the timer for the zero-cross detection. This is done by modifying the phase-shifting-timer’s counter register when the microcontroller detects a rising edge. A more-accurate value for the phase-shifting counter can be approximated, assuming the symmetry present in the diagram (see the code). This could also be done for the falling edge as well, although would require more code in an interrupt routine, which is generally a bad thing.

Due to the zero-cross behavior, even if the Arduino output is left completely on, there is some delay in turning on the triac due the gate current and voltage required to trigger the triac. This delay can be calculated:

  • Gate current for the triac is 50mA (from the data sheet)
  • The gate voltage is 1.3V
  • The opto-isolator detector on-state voltage is 3V max
  • Therefore, the AC mains voltage must reach (180Ω)(0.05A)+3V+1.3V=13.3V
  • Taking the inverse sine of 13.3V/170V results in a phase-shift of 4.5° or 0.0785 radians.


Dimming is accomplished by providing a pulse at the appropriate time, allowing conduction through the triac.

After implementing the dimming, I recorded the following data with an oscilloscope. These plots represent, from top to bottom, reduction of the power output by 75%, 50%, and 25%.

Phase-shifting demonstration as read by an oscilloscope


Despite using an Arduino microcontroller, the code is written in straight C using the AVR library. The GUI is written in C++ and uses Qt.

The code can be downloaded or viewed on GitHub.

The documentation is generated from doxygen and available online here.

See Also

Data Sheets

Application Notes