Workbench Lighting Controller

Bling Up Your Bench!

Sophie Parker

Issue 24, July 2019

This article includes additional downloadable resources.
Please log in to access.

Log in

A multi-channel 12V PWM lighting controller for the workbench, with 4 simple channels and 2 RGB channels, that can be switched and dimmed together (master), or separately.


Thereʼs nothing more important to a maker than their making space. And in the case of an electronics hobbyist like myself, thatʼs the workbench. Good lighting is a vital part of a good workspace, reducing eye fatigue and making work with small components much easier.


This month I set up a brand new electronics workbench, and I wanted to take the opportunity to upgrade the lighting system. My previous lighting used two PWM dimmer modules with switches. It worked, but the parts were cheap and degrading after years of use.

The capabilities settled on were as follows: 6 channels, with individual on/off buttons, and one master encoder knob which fades all channels proportionally. By long-pressing a button, you can set the level of a channel individually using the encoder. This allows setting up relative levels for different lighting zones, and dimming the system as a whole.

This project assumes a fair amount of confidence in working with Arduinos and soldering PCBs. Itʼs designed to build on these skills to learn SMD soldering, and programming a bare embedded microcontroller through ICSP instead of an Arduino board. It was the first time I had worked with either, and I learned a lot. Hopefully, youʼll see itʼs less scary than it seems.

This project is quite complicated, but we step you through how it works, constructing the PCB, programming the software and constructing the enclosure.


Surface Mounted Devices (SMD) are everywhere in commercial products – theyʼre cheaper, smaller, and easier to automate in industrial processes than through-hole components. However, for the hobbyist, SMDs can be daunting for a number of reasons. Parts arenʼt held in place by pins in holes, and must instead be carefully positioned, and not knocked or tipped out of place. Parts and pads are often so tiny as to need a magnifying glass to distinguish them. Depending on the shape of the part, the pads may even be completely hidden, and impossible to reach with a soldering iron!

But despair not! SMD soldering is more accessible than it seems. For some parts, a fine soldering iron tip is all the equipment you need. However, a temperature-controlled heat gun and solder paste become a necessity for others. To complete this project as designed, youʼll need both of these, but you may be able to substitute parts to complete it with only a soldering iron. Using a heat gun is a very different skill to using a soldering iron, and itʼs fun and challenging to build some experience with it. I bought spares of the PCB and all the components, so I didnʼt have to worry about making some mistakes while developing my skills.

If you have any recovered PCBs from electronics lying around, itʼs a great idea to try removing and re-soldering a bunch of SMD components with your hot air gun to get familiar with the process. For me, a few hours of trial-and-error with an old PC motherboard like this taught me far more than the many tutorials I looked at.


This controller uses an ATmega328 (the same MCU as used on the Arduino Uno), and a 16-channel 12-bit IC PWM controller, the PCA9685 to switch 10 channels at up to 12V 3A each.

I decided I wanted the ability to use some RGB LED strip too (for bling factor), so there are 4 mono-output channels, and 2 channels with 3 adjustable 'sub-channels' each. This brings the total number of MOSFET-controlled outputs to 10 (4 + 3 + 3). Itʼs possible to use each output of the RGB channels separately, with the caveat that they share an on/off button.

Each on/off button is a right-angle tactile switch with a small SK6812 'side emit' addressable RGB LED (to keep IO pin count down) to show the status. The LEDs are mounted facing up to illuminate the buttons. These chips can be tricky to track down – AliExpress is the best bet. They are fragile, so order spares.

The main encoder is a right-angle 12 PPM encoder. The power switch can be any panel-mount switch rated to a high enough current for your application (15 or 20A is a good bet). I used a slim one found on Mouser. The slot in the PCB was designed to fit this switch – you may need to modify the PCB cutout or enclosure to fit a larger switch. All the connectors are 5.08mm-spaced pluggable terminal blocks. This avoids the need to solder on connectors, while allowing plugging and unplugging.


This IC is super flexible and easy to control. It has 16 outputs with 12-bit PWM (4096 brightness steps). Each output can be configured to source and/or sink current to drive high or low-side transistor switches, or small LEDs directly. The PWM frequency can be configured over I²C from 24 to 1526Hz. It has an internal oscillator and operates from 2.3 to 5V.

In this case, weʼre using low-side switches with N-channel MOSFETs. This means that each outputʼs positive side is connected directly to +12V. Itʼs the negative side that is switched by the MOSFET. (Take note of this when using with RGB LED strip – it must be common anode!) In addition, each channel is protected by a 3A polyfuse. This means if a channel is short circuited or pulls too much current, the fuse should go open circuit before the MOSFET can burn out.

The Build:

Workbench Lighting Controller

PARTS & Tools

The exact parts I used are listed in the subsequent tables. Substitute at your own risk. I ordered them all from Mouser Electronics. The quantities listed are the exact number on the board, though I recommend ordering enough to have spares for everything.

Refer to the Tools Required list to ensure you have the right tools and service aids to work with the SMD components.

An ICSP (In Circuit Serial Programmer) is also required. Supported by Arduino IDE (e.g. Usbtinyisp, Fabisp)

TOOLS Required:
Temperature-Controlled Soldering Iron
Temperature-Controlled Hot Air Gun
Tin-Lead Rosin-Core Solder
Tin-Lead Solder Paste in Syringe
'Tacky' Flux Paste in Syringe
ICSP Programmer Supported by Arduino IDE (E.g. Usbtinyisp, Fabisp)
Loupe/Magnifying Glass for Inspection
99%+ Isopropyl Alcohol
Acid Brush or Hard Toothbrush For Cleaning

TOOLS Required:

The PCB:

For this project, I decided to go straight to a PCB without constructing a full prototype beforehand.

Itʼs a risky decision, but sometimes pays off provided youʼre careful to read the documentation and double-check everything. Unfortunately, in my case, there were a few errors. The PCB files provided with the project have the following corrections compared to the one shown:

  • Power switch slot enlarged
  • Silkscreen values & outlines corrected

I designed the schematic and PCB in EAGLE (now owned by Autodesk). Itʼs a two-layer board with all components on the top side. There are some unconnected filled areas around the MOSFETs to provide better heat dissipation.

1 × Custom PCB - See website for Gerber files---
1 × Atmel ATmega328P-AU Chip^AtmelATMEGA328P-AU556-ATMEGA328P-AU
1 × PCA9685PW ChipNXP SemiconductorNPCA9685PW,118771-PCA9685PW,118
1 × SMD 22pF 16MHz Crystal (IQD LFXTAL027946)IQDLFXTAL027946449-LFXTAL027946REEL
1 × SMD 7805 5V 1A Voltage Regulator ChipON SemiMC7805CDTRKG863-MC7805CDTRKG
10 × SMD 3A PolyfuseBel Fuse0ZCF0300BF2C530-0ZCF0300BF2C
10 × SMD N-channel MOSFETsON SemiNTD3055L104T4G863-NTD3055L104T4G
1 × Right angle 12PPR EncoderTT ElectronicsEN12-VS11AF18858-EN12-VS11AF18
1 × SPST 20A Toggle SwitchCarling TechnologiesCA201-73691-CA201-73
6 × Right-angle Tactile SwitchTE ConnectivityFSMRA3JH506-FSMRA3JH
4 × 0.1μF 0805 SMD Ceramic CapacitorWurth885012207098710-885012207098
2 × 22pF 0805 SMD Ceramic CapacitorWurth885012007053710-885012007053
3 × 100μF SMD Electrolytic CapacitorPanasonicEEE-HC1C101XP667-EEE-HC1C101XP
3 × 10kΩ 0805 SMD ResistorVishayCRCW080510K0JNEAC71-CRCW080510K0JNEAC
5 × 2-pole Right Angle Terminal Block Base MSTBA*Phoenix Contact1757242651-1757242
2 × 4-pole Right Angle Terminal Block Base MSTBA*Phoenix Contact1757268651-1757268
5 × 2-pole Terminal Block Screw Terminal Plug MSTBT*Phoenix Contact1779987651-1779987
2 × 4-pole Terminal Block Screw Terminal Plug MSTBT*Phoenix Contact1780002651-1780002
1 × 2 × 3 2.54mm Male Pin Header for ICSP---
2 × 7cm Pieces of AWG16 Insulated Wire---
6 × SK6812 Side-emit Addressable LEDsFind on Ali ExpressSK6812 -

Parts Required:

OPTIONAL: ManufacturerPart No.Mouser Part No.
3D Printed Casing-Mean Well-
1 × 12V 6–30A Power Supply (Rating depends on your requirements)-GSM90A-12-P1M-
4 × M3 Brass Threaded Inserts-709-GSM90A-12-


+ Manufacturer or part used in the build. Substitute at own risk. ^ The P is required to program from the Arduino IDE, but a regular ATmega328 can work. * Cheaper generic alternatives available on eBay etc.



Start with the connectors and other through-hole components, except the tactile switches – these have to be installed after the addressable LEDs. The large 12V rail trace on the bottom layer means soldering the output connectors takes a fair bit of heat. A 70W or higher temperature-controlled iron is recommended.

Mount the PCB in a vice.

Solder the five 2-pole and two 4-pole connectors along the back of the board, making sure to be patient and check for cold joints due to the high thermal capacity of the copper busses.

Snap the encoder into its mounting holes and solder each pin. Also, insert and solder the ICSP 3x2 header.

To connect the power switch to the PCB, cut and strip two 7cm pieces of 15AWG (1mm2) wire, stripped, and tin one end. Tin each copper lug of the switch on the outside – the PCB will sit at a level between the lugs, so soldering the wires on the outside of each lug gives us the best clearance.

Solder the two short wires to the lugs. The order is not important as it is an SPST switch. My 'octopus' holder is a useful way to hold two items steady and together for soldering, especially when they get hot.

Solder the wire from the centre lug (black as pictured) in the hole closer to the edge, from the top side of the PCB.

Solder the wire from the side lug (red as pictured) in the other hole, from the bottom side of the PCB.

Cut off the wire close to the surface to minimise the chance of short circuits. Bend the centre lug of the switch upwards to increase the distance to the board when pushed into the slot. Ensure that the switch can be positioned so the front face is flush with the edge of the PCB without issues.

Use some heatshrink or wrap some electrical tape over each lug of the switch, so no conductive surfaces are left exposed.


Now itʼs time to start soldering SMD parts! There are a number of different techniques for this, and I tried several on different types of components.

I started with the polyfuses, as theyʼre large and fairly easy to position. Place the polyfuse on the board with tweezers. Itʼs a good idea to wipe down the pads on the board with isopropyl alcohol to remove grease and dirt before soldering.

First solder one pad of the component, using the stick of solder to push the part so itʼs centred on the pads while the soldering iron is keeping the opposite sideʼs solder melted, then solder the other pad only when youʼre sure itʼs positioned correctly (moving it around after soldering both sides is trickier).

I tested the pads with a multimeter to ensure they soldered well.

Sticking with passive components first, I moved on to the electrolytic capacitors. Here my decision to use only SMD components where possible came back to bite me – I hadnʼt fully understood that there are different kinds of SMD component designs, for different processes.

A NOTE ABOUT COMMERCIAL PCB SOLDERING: Automated PCB construction for commercial projects usually involves placing solder paste on pads with the use of a thin steel stencil, populating the components with a pick-n-place machine, then reflowing (melting) the solder paste into solder which then connects the components to the pads. A special temperature controlled oven is used for this process. The thing to note of this, is that actual access to the pads is not required for soldering! This allows BGAs (ball grid arrays, where pads are in a matrix underneath a flat chip for super-high pin density) and other components with ‘hiddenʼ pads you canʼt reach with a soldering iron.

The Panasonic capacitors I chose have two narrow pads along the underside, which are just visible from the sides. But they donʼt stick out, and the design footprints I used donʼt have much spare room either. This means that using a soldering iron one pin at a time like with the polyfuses was no longer an option.

So, on to SMD construction method two! Reflow soldering with solder paste. I also bought a tub of 'tacky' flux paste, and a syringe to dispense it, and found this greatly assisted in evening out the heat distribution and making the solder bond well.

I recommend testing your technique with the MCU crystal before moving on to the trickier electrolytic capacitors. This would have saved me frustration.

The crystal is easy to start with. Itʼs comparatively large, has only two pads, and the footprint is large too. Place a dab of solder paste and flux paste on the pads. Set the heat gun to low airflow, and around 250°C. I used a nozzle about 7mm in diameter, but itʼs not important.

Use tweezers to position the crystal over the pads, and gently push it down.

Point the hot air gun at it from 3-4cm away, using tweezers to keep the crystal positioned if it starts to blow away. Youʼll notice a sequence of things happen. First, the flux will spread out. Then the solder paste will begin to clump. Soon after, it will melt properly and wick onto the pad on the board and the component. When both pads have done the same, the component will 'suck' into position halfway between the pads, all on its own! This neat effect is because solder, like other molten metals, has very high surface tension. After the part has aligned itself, you can remove the heat.

If either of the pads have too little or too much solder, you can use a soldering iron and solder or desoldering braid to correct this. It is better to use less solder paste and add more, rather than removing it.

As SMD components can conceal solder bridges underneath them, itʼs a good idea to check components with a multimeter/continuity meter after soldering. If the pads are bridged due to too much solder, use the hot air gun to melt the solder, remove the part with tweezers, and use desoldering braid to remove all of the solder from the pads. Allow the board to cool before reapplying solder paste and trying again.

Next come the electrolytic capacitors. These are similar to the crystal in that they have a metal jacket and a plastic base form, but are trickier to solder due to the more concealed pads.

Place the solder paste, flux paste and components on the pads. Aim the hot air gun at the pads of one electrolytic capacitor (there are three on the board). Donʼt bring it too close, or the plastic will start melting. If this happens, keep applying hot air but keep the nozzle further away to reduce the temperature. After some time (be patient!) it should be wicked into place like the crystal was. Once again use a multimeter to check the connections.

Next, move on to the 0805 ceramic capacitors and resistors. These donʼt need much solder paste on their pads, and youʼll need to be careful with the hot air gun as theyʼre liable to blow away in the breeze! A dab of tacky flux helps keep these still until the solder paste melts and pulls them in place.

Repeat this for the crystal ceramics (being mindful of the different values), and the three 10k resistors.


Now all the passives are done, itʼs time for the active components.

Start by placing solder paste and flux on the three pads of the 7805 voltage regulator, then place it with tweezers and apply heat to solder.

Repeat for the ten MOSFETs, along the bottom of the board. You neednʼt do this one at a time – solder paste & flux all the pads, place all the MOSFETs, then progress along heating them one at a time with the hot air gun.

Solder the SK6812 LEDs. The original design was to have these on their side, but they actually work better flipped to shine upwards. Make sure to orient them as shown in images – pads facing the centre of the board, window facing up. The pads on these are quite fragile, and they donʼt stay in place unless you hold them with tweezers. Be careful not to use too much solder paste, it can be hard to see when the pads are bridged. Check the continuity between each set of adjacent pads is between 10 and 600kΩ after soldering them.

Itʼs chip time! Start with the PCA9685. Make sure to get it placed right on the mark to start with – itʼs all too easy to be one pin off.

Then the ATmega328P.

Now the only components absent are the tactile switches. However, itʼs a good idea to leave these off until youʼve tested the LEDs, to avoid having to desolder the switch to reach the LED underneath.


Now is also a good time to use Isopropyl alcohol and an acid-safe brush (or clean toothbrush) to clean up the flux residue on the board. Give the board a thorough visual inspection for bridged pins, cold solder joints, and other issues using a loupe or magnifying glass. Test for shorts/open circuits with a multimeter.

Testing & ICSP Programming

Unlike most projects, in this one it’s a good idea to program a test program to the board before completing construction, due to the placement of the tactile switches over the fragile LEDs. Also, due to the embedded microcontroller, we’ll be using In-Circuit Serial Programming (ICSP) instead of a USB Serial connection to program the test and final code.

Open the LED Test program (available from the DIYODE website) in the Arduino IDE. It's just example code from the FastLED library adapted to use the correct configuration for the SK6812s. You’ll need to install the FastLED library through the Manage Libraries interface if you haven’t already.

Under Tools, select “Arduino/Genuino Uno” from the Boards menu. Plug in your USB ICSP programmer, and select it from the Programmer menu. Mine was a generic version of the USBtinyISP.

Connect your ICSP programmer to the ICSP header on the board. Pin 1 is marked with a white silkscreen dot on the PCB.

Upload the LED Test program, using the Sketch › Upload Using Programmer option. If all goes well, the IDE should detect and use your USB ICSP programmer to flash the Atmega328P directly. Note that it’s not necessary to burn an Arduino bootloader as we don’t need serial programming capability.

If all the LEDs work correctly, solder in the tactile switches the normal (throughhole) way. If they don't, inspect the LEDs with a loupe or magnifying glass for shorts & cold joints. To correct, use the heat gun to desolder them, clean the pads, and resolder them (and/or replace the chip with a spare).

Your board should be complete! Now lets move on to the real code.


The main code for the lighting controller can be downloaded below. But first, install the required libraries using the Arduino IDE Library Manager (Sketch menu › Include Library › Manage Libraries).

You can try installing other versions, but there’s a chance the code won’t work the same, so I recommend using the same version.

A full explanation of the code is beyond this article, but it’s worth discussing the quirks of controlling the PCA9685 chip.

Here is the function which sends stored brightness values to the PCA9685’s registers.

void updateGroupOutput(uint8_t group) {
  for (uint8_t channel = groupStartChannel[group]; channel <groupStartChannel[group + 1]; channel++) {
    uint16_t val = (uint16_t)(channelValue[channel] * masterValue *4095.0);
    if (val == 0 || groupEnabled[group] == false) { // Special case for off / disabled
Pca9685Outputs[channel], 0, 4095);
    } else if (val == 4095) { 
// Special case for full
Pca9685Outputs[channel], 4096, 0);
    } else {
Pca9685Outputs[channel], 4095 - val, 4095);

The for loop setup is converting the ‘group’ (this refers to the 6 user-facing channels) to the electrical (sub-)channel, of which there are 10, and iterating through however many channels there are in the group.

A 12-bit unsigned value for the PWM setting is created by multiplying the floating point values of the channel’s individual brightness with the master brightness setting, then by 4095.0 to change from 0.0-1.0 range to 0-4095 range.

There are special cases for both full brightness and zero brightness, due to the PCA9685’s control pattern. The registers for the PCA9685 don’t just take a single ‘duty cycle’ value. They actually store an ‘on time’, and ‘off time’ value, both 16 bits (with 13 bits usable). This allows manipulation of PWM phase as well as duty.

To set a channel fully off, we set the on time to 0. Zero isn’t properly counted in the timer cycle of the chip, resulting in it never being turned on at all. The second value of 4095 is unimportant.

To set a channel fully on, we use a special value of 4096. This uses a detail hidden in the datasheet, that setting the 13th bit means the channel will be turned on and then left on.


When you’ve opened the .ino file, click the Verify button to check the code compiles correctly.

Follow the same steps as the LED test program to upload using the USB ICSP programmer.

Next, disconnect the programmer, and attach 12V power. Then turn the power switch on.

By default, you should see a faint white glow on all six LEDs. This is just to illuminate the buttons, and show that it's turned on. Attach a 12V load like a segment of LED strip to one of the channels (being sure to check the polarity). Press the corresponding channel button on the other side (note that the order is mirrored -- button 1 is on the top right, viewing from above).

The LED strip should light up at full!


The case for the controller has a top and bottom half, 6 buttons, and a knob for the encoder.

M3 brass threaded inserts and screws are used to hold the two halves together. If you haven't used these before, they provide a stronger and hardier hold than threading screws directly into 3D printed parts. It is possible to thread directly into the part with some modification of the OpenSCAD file. If you are using threaded inserts, check that yours match the dimensions in the OpenSCAD parametric file. Make any other modifications such as mounting holes/brackets, then render and export to STL. Alternatively, use the provided STL files if you're happy with the form or would rather edit in a different CAD application.

3D print the top case and bottom case. They take 3-4 hours each.

Next, you can print the 6 button inserts and the encoder knob together in one go. I recommend changing to a transparent filament for the buttons, so the light can shine through.

After they have printed, use a black permanent marker to colour in the top surface of the buttons, leaving the inset number clearly visible to light up.


It's time to install the threaded inserts. Place each insert over the hole it will fit in. Use your soldering iron to gently push down on the insert (while heating it up) until it embeds itself in the plastic, being careful to keep it centred and level. You should use a clean iron tip to avoid accidentally tinning the fasteners with solder.

Because the front panel is printed vertically and hot filament will droop with gravity, the front mounting holes may not be perfectly circular. I used a rounded needle file to gently round them out to fit the printed buttons, power switch, and encoder shaft. You could also use a hand turned twist drill to spin out any debris.

Mount the six buttons from the inside of the top case. Fit the tab into the slot in the case, then push gently until the round button fits into the hole in the panel. If it’s too tight a fit, try gently filing the inside of the hole to fit. The buttons should be able to move around enough to be pressed about one millimetre, but shouldn’t fall out by themselves.

Remove the hex nut from the power switch. Take the PCB and top case, both upside down, and slide together, fitting the encoder and power switch through their mounting holes. Take the bottom case and fit over the top until the screw holes in the top line up through the PCB holes, with the threaded inserts in the bottom half.

Use four M3 × 8mm machine screws in the recesses in the top case to attach the case together. Note the recesses are countersunk inside, but flat screws will still work.

Place the power switch nut on the front panel and tighten it slightly. Fit the encoder knob onto the encoder shaft. For a more permanent hold than just friction, place a dab of contact adhesive inside the knob first.

And there you go, the workbench lighting controller is complete! Hook up a 12V power supply to the power input terminal block, and switch it on.

Next, use the mounting tabs to attach the controller to the underside of a shelf or bench in a convenient location.


In normal mode, turning the encoder on the front changes the Master level in 2.5% increments. Pressing each of the buttons toggles whether the channel is enabled.

To change the level of a channel independently of the others, long press the channel button. The channel LED will turn magenta, for a single channel, or red, for an RGB channel. Turning the encoder will now affect only the selected single channel or sub-channel (in channels 5 & 6). Short pressing the button again will advance through the blue and green sub-channels if available, and then return to normal mode.

If a channel is off when long-pressed, it is temporarily enabled to have its level set, and then disabled again when returned to normal mode.

If no changes are made for five seconds, the current settings are written to EEPROM. This means that when turned off and on again, the controller will remember the previous state, despite cutting power to the microcontroller with no warning.


I think it's important to talk about things that went wrong, and what was learned in the process, because no project goes perfectly, especially one exploring new areas.

The PCB design I received was missing many silk screen labels, which taught me to pay closer attention to the step of generating the Gerber files from the PCB editor.

I destroyed several SMD components while teaching myself the soldering process. Also, I started reflowing with the plastic-based electrolytic capacitors, not realising they were actually one of the trickier components to solder properly.

Were I to redesign this project, I'd probably use regular WS2812 LED chips, instead of the hard-to-find but smaller side-emit SK6812s. I'd also use different tactile switches that didn't get in the way of the LEDs. I would perhaps replace the MOSFETs and electrolytic caps with through-hole ones because they’re cheaper and easier to use. But in general, I'm quite happy with the final product, and I anticipate it will serve me for years to come. I'm already planning to make another one for my local makerspace.

This controller could be used to control other 12V devices than lights. The current design is only safe for purely resistive loads, but it could be modified to add flyback diodes and then be used to control an array of DC motors, for example.

A touchscreen could display replace the front panel buttons and LEDs.

The addition of a light sensor would allow automatic adaptive dimming. A battery-backed Real-Time Clock could allow changing values according to the time of day, or a PIR movement sensor used to automatically turn on when people are present.

The EAGLE board files are available along with the Gerbers at the DIYODE website to make modifying the PCB for your own requirements easy.