Introduction: DIY PWM Control for PC Fans

About: GreenPAK™ is a broad family of cost-effective NVM programmable devices that enable innovators to integrate many system functions into a single custom circuit.

This Instructable describes building a fully-featured 12 V PC fan PWM controller. The design can control up to 16 3-pin computer fans. The design uses a pair of Dialog GreenPAK™ configurable mixed-signal ICs to control each fan’s duty cycle. It also includes two ways to change the speed of the fan:

a. with a quadrature/rotary encoder

b. with a Windows application built in C# that communicates with the GreenPAK through I2C.

Below we described steps needed understand how the GreenPAK chip has been programmed to create the PWM control for PC fans. However, if you just want to get the result of programming, download GreenPAK software to view the already completed GreenPAK Design File. Plug the GreenPAK Development Kit to your computer and hit program to create the custom IC for PWM control for PC fans.

Step 1: System Block Diagram

Step 2: SLG46108 Rotary Decoder Design

A rotary encoder is used to increase or decrease the duty cycle of the fans manually. This device outputs pulses on its Channel A and Channel B outputs that are 90 ° apart. See AN-1101: Unclocked Quadrature Decoder for more information about how a rotary encoder works.

A clocked rotary decoder can be created using a Dialog GreenPAK SLG46108 to process the Channel A and Channel B signals and output them as counterclockwise (CCW) and clockwise (CW) pulses.

When Channel A leads Channel B, the design outputs a short pulse on CW. When Channel B leads Channel A, it outputs a short pulse on CCW

Three DFFs synchronize the Channel A input with the clock. Similarly, the pipe delay with OUT0 set to two DFFs and OUT1 set to three DFFs create the same functionality for channel B.

To create CW and CCW outputs use a few LUTs, for more information about this standard rotary decoder design, visit this website.

The GreenPAK Rotary Decoder will receive input pulses A and B and output the CW and CCW pulses as shown in Figure 4.

The circuitry after the XOR gates ensures that there will never be a CW pulse and CCW pulse at the same time, allowing for any error with the rotary encoder. The 8 ms falling edge delay on the CW and CCW signals force them to stay high for 8 ms plus one clock cycle, which is necessary for the downstream SLG46826 GreenPAKs.

Step 3: SLG46826 Fan Controller Design

Step 4: PWM Generation With Offset Counters

A pair of offset counters with the same period are used to generate the PWM signal. The first counter sets a DFF, and the second resets it, creating a consistent duty cycle PWM signal as shown in Figure 6 and Figure 7.

CNT6 sets DFF10 and the inverted output of CNT1 resets DFF10. Pins 18 and 19 are used to output the PWM signal to external circuitry

Step 5: Duty Cycle Control With Clock Injection and Clock Skipping

The fan controller receives the CW and CCW signals as inputs from the rotary decoder and uses them to either increase or decrease the PWM signal that controls the fan speed. This is achieved with several digital logic components.

The duty cycle needs to increase when a CW pulse is received. This is done by injecting an extra clock pulse into the CNT6 block, causing it to output one clock cycle earlier than it otherwise would have. This process is shown in Figure 8.

CNT1 is still getting clocked at a constant rate, but CNT6 has a couple of extra clocks injected. Every time there is an extra clock to the counter, it shifts its output one clock period to the left.

Conversely, to decrease the duty cycle, skip a clock pulse for CNT6 as shown in Figure 9. CNT1 is still getting clocked at a constant rate, and there are skipped clock pulses for CNT6, where the counter did not get clocked when it was supposed to. This way the output of CNT6 is pushed to the right by one clock period at a time, shortening the output PWM duty cycle.

The clock injecting and clock skipping functionality is performed with use of some digital logic elements within the GreenPAK. A pair of multifunction blocks are used to create a pair of latch/edge detector combos. 4-bit LUT0 is used to mux between the general clock signal (CLK/8) and the clock injecting or clock skipping signals. This functionality is described in more detail in Step 7.

Step 6: BUTTON Input

The BUTTON input is debounced for 20 ms, then used to toggle a latch that determines whether this particular chip is selected. If it is selected, then the 4-bit LUT passes the clock skipping or injection signals. If the chip is not selected, then the 4-bit LUT simply passes the CLK/8 signal.

Step 7: Preventing Duty Cycle Rollover

The RS latches 3-bit LUT5 and 3-bit LUT3 are used to make sure that you cannot inject or skip so many clocks that the offset counters roll over. This is to avoid the system reaching 100 % duty cycle and then rolling over to a 1 % duty cycle if it receives another injected clock.

The RS latches prevent this from happening by latching the inputs to the multifunction blocks when the system is one clock cycle away from rolling over. A pair of DFFs delay the PWM_SET and PWM_nRST signals by one clock period as shown in Figure 11.

A pair of LUTs are used to create the necessary logic. If the duty cycle is so low that the delayed PWM_SET signal occurs at the same time as the PWM_nRST signal, a further decrease in the duty cycle will cause a rollover.

Similarly, if approaching maximum duty cycle, such that the delayed PWM_nRST signal occurs at the same time as the PWM_SET signal, it is necessary to avoid any further increase to the duty cycle. In this instance, delay the nRST signal by two clock cycles to ensure that the system does not roll over from 99 % to 1 %.

Step 8: Duty Cycle Control With I2C

This design incorporates another way to control the duty cycle other than clock skipping/clock injecting. An external microcontroller can be used to write I2C commands to the GreenPAK to set the duty cycle.

Controlling the duty cycle over I2C requires the controller to perform a specific command sequence. These commands are shown in order in Table 1. An "x" indicates a bit that should not change, "[" indicates a START bit, and "]" indicates a STOP bit

The PDLY block generates a short active high pulse on the falling edge of the CLK/8 signal, which is called !CLK/8. That signal is used to clock DFF14 at a steady frequency. When I2C_SET goes high asynchronously, the next rising edge of !CLK/8 causes DFF14 to output HIGH, which triggers the CNT5 OneShot. The OneShot runs for the number of clock cycles that the user wrote as specified in the "Write to CNT5" I2C command in Table 1. In this case, it is 10 clock cycles. The OneShot allows the 25 MHz oscillator to run for exactly its duration and no longer, so that 3-bit LUT0 receives the number of clock cycles that were written to CNT5.

Figure 15 shows these signals, where the red clocks are the ones that are sent to 3-bit LUT0, which passes them into CNT6 (the PWM_SET counter), thus creating the offset for the duty cycle generation.

Step 9: Tachometer Reading

If desired, the user can read the tachometer value over I2C to track how quickly the fan is turning by reading the CNT2 value. CNT2 is incremented every time ACMP0H has a rising edge, and can be asynchronously reset with an I2C command. Note that this is an optional feature, and the threshold of ACMP0H will need to be tweaked according to the specifications of the particular fan being used.

Step 10: External Circuit Design

The external circuit is fairly simple. There is a pushbutton connected to Pin6 of the GreenPAK to toggle whether this particular device is selected for rotary control, and an LED connected to Pin12 and Pin13 to indicate when the device is selected.

Since the fan runs off 12 V, a pair of FETs to control its switching is required. The GreenPAK's Pin18 and Pin19 drive an nFET. When the nFET is turned on, it pulls the gate of the pFET LOW, which connects the fan to +12 V. When the nFET is turned off, the gate of the PFET is pulled up by the 1 kΩ resistor, which disconnects the fan from +12 V.

Step 11: PCB Design

To prototype the design a couple of PCBs were assembled. The PCB on the left is the "Fan Controller," which houses the rotary encoder, 12 V jack, SLG46108 GreenPAK, and connectors for the FT232H USB to I2C breakout board. The two PCBs on the right are "Fan Boards," which contain the SLG46826 GreenPAKs, pushbuttons, switches, LEDs, and fan headers.

Each Fan Board has a shrouded male header on the left side and a female header on the right side so that they can be daisy-chained together. Each Fan Board can be populated with resources to independently control two fans.

Step 12: C# Application

A C# application was written to interface with the Fan Boards through the FT232H USB-I2C bridge. This application can be used to adjust the frequency of each fan with I2C commands that are generated by the application.

The application pings all 16 I2C addresses once per second and populates the GUI with the slave addresses that are present. In this example Fan 1 (slave address 0001) and Fan 3 (slave address 0011) connected to the board. Adjustments to the duty cycle of each fan individually can be made by moving the slider bar or by typing a value from 0-256 in the textbox underneath the slider bar.


Using this design it is possible to independently control up to 16 fans (since there are 16 possible I2C slave addresses) either with a rotary encoder or with a C# application. It has been demonstrated how to generate a PWM signal with a pair of offset counters, and how to increase and decrease the duty cycle of that signal without rollover.