Created
December 10, 2025 09:01
-
-
Save LenweSaralonde/7baae7044d0e66c083d5045d0f162324 to your computer and use it in GitHub Desktop.
Simple PWM fan controller for Arduino Nano
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <EEPROM.h> | |
| // 25 kHz PWM Fan Controller with Button Speed Steps | |
| // Arduino Nano (ATmega328P) | |
| // PWM on D9 (OC1A), Button on D2 | |
| // Onboard LED (D13) pulses reflect fan duty | |
| // Last setting is stored in EEPROM | |
| const byte PIN_BUTTON = 2; | |
| const byte PIN_LED = 13; // Onboard LED | |
| const byte PIN_FAN_PWM = 9; | |
| const int LED_PULSE_PERIOD = 500; // Period for the pulsing LED indicator | |
| const int EEPROM_ADDR_STEP = 0; // EEPROM address to store last step | |
| float SPEED_STEPS[] = { 0.0, 0.2, 0.4, 0.6, 0.8, 1.0 }; | |
| unsigned long lastLedPeriod = 0; | |
| const int numSteps = sizeof(SPEED_STEPS) / sizeof(SPEED_STEPS[0]); | |
| int currentStep = 0; | |
| bool lastButtonState = HIGH; | |
| unsigned long lastDebounce = 0; | |
| void setup() { | |
| pinMode(PIN_FAN_PWM, OUTPUT); // PWM output | |
| pinMode(PIN_BUTTON, INPUT_PULLUP); // Button input | |
| pinMode(PIN_LED, OUTPUT); // Onboard LED | |
| // Timer1 → 25 kHz PWM on D9 | |
| TCCR1A = 0; | |
| TCCR1B = 0; | |
| ICR1 = 639; // TOP → 25 kHz | |
| TCCR1B |= (1 << WGM13) | (1 << WGM12); | |
| TCCR1A |= (1 << WGM11); | |
| TCCR1A |= (1 << COM1A1); // non-inverting mode | |
| TCCR1B |= (1 << CS10); // prescaler = 1 | |
| // Load last step from EEPROM | |
| int storedStep = EEPROM.read(EEPROM_ADDR_STEP); | |
| if (storedStep >= 0 && storedStep < numSteps) { | |
| currentStep = storedStep; | |
| } else { | |
| currentStep = 0; | |
| } | |
| } | |
| void loop() { | |
| // ------------------- Button Handling ------------------- | |
| bool reading = digitalRead(PIN_BUTTON); | |
| if (reading != lastButtonState) { | |
| if (reading == LOW && lastButtonState == HIGH && millis() - lastDebounce > 50) { | |
| currentStep++; | |
| if (currentStep >= numSteps) { | |
| currentStep = 0; | |
| } | |
| EEPROM.update(EEPROM_ADDR_STEP, currentStep); | |
| } | |
| lastDebounce = millis(); | |
| lastButtonState = reading; | |
| } | |
| // ------------------- Apply Fan PWM ------------------- | |
| float duty = SPEED_STEPS[currentStep]; | |
| OCR1A = (uint16_t)(duty * ICR1); | |
| // ------------------- LED Pulse ------------------- | |
| // Scale duty 0.0–1.0 to pulse length of onboard LED | |
| if (millis() - lastLedPeriod >= LED_PULSE_PERIOD * duty) { | |
| digitalWrite(PIN_LED, LOW); | |
| } | |
| if (millis() - lastLedPeriod >= LED_PULSE_PERIOD) { | |
| if (duty > 0) { | |
| digitalWrite(PIN_LED, HIGH); | |
| } | |
| lastLedPeriod = millis(); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment