Problem: My new office was unfathomably warm. Solution: Completely over-engineer custom PCB to control the fan. Actual Solution: Test first…
Recently I’ve moved house, and with moving comes my beautiful new office, with a slight issue.
It’s hot.
Like really hot.
I bought and have used an Air-Conditioner, previously having temperatures of up to 35C… This worked great until it was too hot for nothing, but not hot enough to run the $0.25/hr AC. Let me be a bit clearer. I’m too cheap to spend $0.25/hr on being mildly hot, but I’m still hot
The solution? A custom STM32F1 PCB to control a 12V Noctua PWM fan :)
So armed with a burning desire (literally) to cool myself down, I decided to build a board using the STM32F103C8T6.
The “solution” was to use this to control a Noctua fan via PWM with maybe a little twisty knob thing to adjust the fan-speed.
Below is an attached image of the Schematic, with:
- 5 decoupling caps for VBAT&VDDx3 with a ferrite-bead on VDDA and some more caps.
- Switch to pull boot0 high/low
- usb-c because why on earth would I use anything else.. I need to justify my manic purchasing of usb-c cables…
- An external crystal, because obviously I need to run PWM at … 48Mhz
- AMS1117-3.3 LDO for voltage regulation.
- Lots of breakout sockets
The process went something like this:
Schematic
Design a beautiful schematic and triple, quadruple, quintuple check then check again.

Route
This is a two-step process where both are extremely pivotal to a working end product.
- Route route route, very carefully, thinking alot about each decision.
- Get annoyed and tired and half-ass the last 10%, which as we all know is actually the last 50%

It may be ugly, but it’s my ugly. After staring at my screen for too long, I finally hit order and waited whatever the opposite of patiently waiting is.
Once it had arrived and I gently ripped open the packaging I booted up my laptop and got to coding.
IOC
Create a .ioc file in STM32CubeMX that generated the initial boilerplate for me.

Coding
This part was the easiest of all due to my familiarity, it took maybe 30 minutes to get this basic example working
#include "main.h"
TIM_HandleTypeDef htim2;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_TIM2_Init(void);
void SetFanSpeed(uint8_t speed_percent) {
if (speed_percent > 100) {
speed_percent = 100;
}
uint32_t pulse = (htim2.Init.Period + 1) * speed_percent / 100;
__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_2, pulse);
}
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_TIM2_Init();
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_2);
while (1)
{
SetFanSpeed(25);
HAL_Delay(2000);
SetFanSpeed(75);
HAL_Delay(2000);
SetFanSpeed(100);
HAL_Delay(2000);
for (uint8_t speed = 0; speed <= 100; speed++) {
SetFanSpeed(speed);
HAL_Delay(20);
}
for (uint8_t speed = 100; speed > 0; speed--) {
SetFanSpeed(speed);
HAL_Delay(20);
}
}
}I should’ve checked this first…
** IT WORKS **
Oh and it does so everso beautifully. I believe I can compare this experience to parenthood, it’s my thing that I created that is working! Same thing right? Now you might notice that all this code does is ramp up and ramp down the fan? Why on earth would I create a custom PCB for a fan that just randomly spins up and down?
It didn’t work. The noctua fan was moving almost no air, and was too puny and small to create any measurable temperature difference.
Meaning to cool down my office it was practically useless.
Armed with this newfound knowledge I also discovered that with no PWM control, the fan ran at 100%, which was barely enough for me regardless.
The fan now sits on my desk, powered by a USB cable and buck-boost converter, gently blowing air on my houseplants. They seem to appreciate it. My office temperature remains unchanged - well until I got hot again and bought an industrial exhaust fan… but that’s a different story.
A silver lining?
Was it worth it? Well yes as a learning experience.
I learnt:
- STM32 HAL framework
- Alot about decoupling capacitors
- Crystal oscillators
- USB-C and the 5.1k resistors on CC
- The importance of practicality and not rushing to get to the end.
Isn’t that the point of hobbiest projects anyway? The friends we made along the way and such.
My next PCB is currently being made by JLCPCB which uses the beautiful CH32v003F4P6, a $0.1 microcontroller, for reading CO2 levels with an SCD40.
Here’s a sneak preview:
