Simple PWM Fan controller problem

Got a PWM fan connected to a nano, a variable 50k resistor so i can manually change the speed, a button (switch to gnd) as trigger.

PWM input of fan on Nano D10 pin
50k resistor on A10
Trigger on RX

const int analogInPin = A0;  // Analog input pin that the potentiometer is attached to

int sensorValue = 0;        // value read from the pot
int outputValue = 0;        // value output to the PWM (analog out)

void setup() {
   // Configure Timer 1 for PWM @ 25 kHz.
    TCCR1A = 0;           // undo the configuration done by...
    TCCR1B = 0;           // ...the Arduino core library
    TCNT1  = 0;           // reset timer
    TCCR1A = _BV(COM1A1)  // non-inverted PWM on ch. A
           | _BV(COM1B1)  // same on ch; B
           | _BV(WGM11);  // mode 10: ph. correct PWM, TOP = ICR1
    TCCR1B = _BV(WGM13)   // ditto
           | _BV(CS10);   // prescaler = 1
    ICR1   = 320;         // TOP = 320

    // Set the PWM pins as output.
    pinMode( 9, OUTPUT);
    pinMode(10, OUTPUT);
    pinMode(2, INPUT_PULLUP); 
}

// PWM output @ 25 kHz, only on pins 9 and 10.
// Output value should be between 0 and 320, inclusive.
void analogWrite25k(int pin, int value)
{
    switch (pin) {
        case 9:
            OCR1A = value;
            break;
        case 10:
            OCR1B = value;
            break;
        default:
            // no other pin will work
            break;
    }
}

void loop() {
   int sensorVal = digitalRead(2);

  //print out the value of the pushbutton

  Serial.println(sensorVal);

  // Keep in mind the pull-up means the pushbutton's logic is inverted. It goes

  // HIGH when it's open, and LOW when it's pressed. Turn on pin 13 when the

  // button's pressed, and off when it's not:

  if (sensorVal == LOW) {

       // read the analog in value:
    sensorValue = analogRead(analogInPin);

    // map it to the range of the analog out:
    outputValue = map(sensorValue, 0, 1023, 0, 320);

    analogWrite25k(10, outputValue);
 delay(3000);

  } else {

    analogWrite25k(10,0);
   }
}

What i /want/ to happen is that i push the trigger than fan starts running (at whatever preset speed i've turned the dial to) for 3 seconds, then shut down. But thats not what happens, when powered up it just runs the fan at a slow speed and changing the dial doesn't change anything.

If i strip out all my attempts at putting in the timer element then the original sketch works (turning the dial changes the speed of the fan) so clearly i've completely failed at creating the trigger/read/timer code and i've spent all week tinkering with it and not managing to make any difference. Can anyone help me with an example sketch of how i should be doing this that i can then reverse the fan speed stuff into?

Yep I think the problem is in the corner. Post an annotated schematic of how you have wired it including links to technical information on the hardware items.

25 kHz PWM, D10 is the PWM-pin, A0-pin for speed control, DPin-2 to start the Fan -- correct?

At power up, the Fan is OFF; you press Button at DPin-2 to start the Fan; Fan runs for 3-sec and then stops.

The Fan stops after 3-sec of running; after that, what will happen to the Fan -- will it remain at stopped condition or will you press the Button again to statr the Fan?

What is the opertaing voltage of the Fan? Do you have seperate power supply for the Fan? Have you connected together the Fan's power supply GND and NANO's GND?

What does that mean -- do you want to turn the Fan in the opposite direction or you want to decrease the speed of the Fan?

the problem isn't physical - when i use /just/ the fan speed control stuff it all works. The problem is when i try to add the "press a button and run this just for 3 seconds then stop" code

yes pin in/out = correct
yes - all stopped, press the button and the fan runs for 3 seconds (after checking what speed i have set via A0) then the fan stops. If the button is pressed again then it checks the speed and runs the fan for 3 seconds... etc

its a 12v fan - the physical design of all this is fine; my only problem is getting the code right for the "push button & run for 3 seconds" coding

So simply, any time i want i push the button and the fan runs for 3 seconds (at the speed set via the potentiometer dial) then stops. Can repeat

1 Like

Looks like you could use some bore serial debug prints. And a Serial.begin of course.

Well explained!

Uplaod the following sketch (tested on UNO), operate your Fan, and report result:

const int analogInPin = A0;  // Analog input pin that the potentiometer is attached to
unsigned long presentMillis;

void setup()
{
  Serial.begin(115200);
  pinMode(9, OUTPUT);  //PWM Ch-A
  pinMode(2, INPUT_PULLUP);
  // Configure Timer 1 for PWM @ 25 kHz.
  //f = 16 MHz / 2xNxICR1
  TCCR1A = 0;           // undo the configuration done by...
  TCCR1B = 0;           // ...the Arduino core library
  TCNT1  = 0;           // reset timer
  TCCR1A |= _BV(COM1A1);  // non-inverted PWM on ch. A
  TCCR1A |= _BV(WGM11); // mode 10: ph. correct PWM, TOP = ICR1
  TCCR1B |= _BV(WGM13);   // ditto

  ICR1   = 320;//TOP = 320
  OCR1A = 160;//intial duty cycle 50%
  // TCCR1B |= (1 << CS12); do not statrt Fan
}

void loop()
{
  if (digitalRead(2) == LOW)
  {
    presentMillis = millis();
    TCCR1B |= (1 << CS10); //start PWM signal for fan
    while (millis() - presentMillis < 3000)//3-sec run
    {
      unsigned int y = analogRead(analogInPin);
      OCR1A = map(y, 0, 1023, 0, 320);//duty cycle: 0% to 100%
    }
    OCR1A = 0;  //3-sec elapsed; stop Fan
    presentMillis = millis();
  }
}

wow my attempt was way off then...

uploaded that and the fan just runs constantly, pushing the button doesn't stop/start it (though it does trigger the onboard LED suggesting the input is being read)
adjusting the potentiometer doesn't change the speed; the fan just runs constantly

Just to double check it's not me making a silly mistake, the PWM Pin 9 = D6 on the nano right? Arduino Nano Board Guide (Pinout, Specifications, Comparison)

Are you using Arduino NANO or Nano ESP32?
image
Arduino NANO

image
Nano ESP32

If you are using Arduino NANO, then it is D9.

For testing:
Disconnect the Fan; connect a LED with a 2.2k series resistor with D9.
Upload the sketch.
Just press the Button; check that LED is ON; check that LED goes OFF after 3-sec; press the Button; chcek that LED is ON.

Change the OFF time to 10-sec. Upload the sketch.
Turn on the LED by pressing the Button.
When the LED is ON, slowly change the Potentiometer at A0-pin and check that the brightness of the LED changes.

Regular Arduino Nano

wired in the LED, pressed the button (connecting RX0 to gnd) and the wired in LED doesn't light at all.

Just in case I've messed up the pins again i tried it connecting pin labelled D2 to gnd and still the LED doesn't light.

So i don't think it's outputting any PWM info which would be the main problem.
I also think the Fan needs to be actively sent a "0" speed the rest of the time to tell it to stop, i think the reason the fan is just running regardless is because it's not receiving any speed data so just doing its own thing?

1. Make the following setup of Fig-1:


Figure-1:

2. Upload the following sketch:

const int analogInPin = A0;  // Analog input pin that the potentiometer is attached to
unsigned long presentMillis;

void setup()
{
  Serial.begin(115200);
  pinMode(9, OUTPUT);  //PWM Ch-A
  pinMode(2, INPUT_PULLUP);
  // Configure Timer 1 for PWM @ 25 kHz.
  //f = 16 MHz / 2xNxICR1
  TCCR1A = 0;           // undo the configuration done by...
  TCCR1B = 0;           // ...the Arduino core library
  TCNT1  = 0;           // reset timer
  TCCR1A |= _BV(COM1A1);  // non-inverted PWM on ch. A
  TCCR1A |= _BV(WGM11); // mode 10: ph. correct PWM, TOP = ICR1
  TCCR1B |= _BV(WGM13);   // ditto

  ICR1   = 320;//TOP = 320
  OCR1A = 160;//intial duty cycle 50%
  // TCCR1B |= (1 << CS12); do not statrt Fan
}

void loop()
{
  if (digitalRead(2) == LOW)
  {
    presentMillis = millis();
    TCCR1B |= (1 << CS10); //start PWM signal for fan
    while (millis() - presentMillis < 10000)//10-sec test run
    {
      unsigned int y = analogRead(analogInPin);
      OCR1A = map(y, 0, 1023, 0, 320);//duty cycle: 0% to 100%
    }
    OCR1A = 0;  //3-sec elapsed; stop Fan
    presentMillis = millis();
  }
}

3. Ceck that LED1 is OFF. LED1 is simulating the Fan.
4. Gently, press K1 Button.
5. Check that LED1 is ON.
6. Wait for 10-sec.
7. Check that LED1 is OFF.
8. Press K1.
9. Check that LED1 is ON.
10. Rotate Pot and observe that the brightness of LED1 changes.
11. Check that LED1 goes OFF after 10-sec.
12. And so on....

Yep, nothing, pressing the button and the LED doesn't light. I've got another nano arriving tomorrow so i can double check its not a board fault Dropbox - 2023-10-09 16.31.39.jpg - Simplify your life

I have given you a tutorial in post #12. You should give answer like below to allow me knowing your exact problem. If you can't proceed logically or you can't follow the tutorial of post #12, second NANO is not going to help you much. You must be sure that the present NANO is probably bad!

1. OK or NOT OK.
2. OK or NOT Ok.
3. And son on....

RX is pin 1.

ok.....

  1. yes removed all and then built that circuit as shown
  2. yes uploaded that sketch, uploaded with no error codes
  3. yes, LED is off
  4. pressed the K1 button
  5. no, it's not on
  6. waited for 10 seconds
  7. well yes it's off because it never came on
  8. pressed k1 button
  9. nope, led still not turning on
  10. rotated, LED still off so no brightness changed
  11. wasn't turned on so nothing to turn off

so disassembled and repeated the entire build / upload process, still absolutely nothing happening.
tried with alternative power supply and repeated, no change
checked the LED was working and in correct orientation, it was
Left the entire setup for half an hour and tried again just in case.

So 3 possibilities
Wiring fault - unlikely since i've made and remade it 3 times
Sketch Fault - possible; as i've learned here i'm really not a good sketchwriter
Arduino Fault - will know either way by replacing the arduino tomorrow.

1 Like

yes i clearly got my pins mixed up in earlier passes at this.

1. Upload the following sketch. Check that the onboard LED (L) is blinking. If the LED blinks, we may assume that your Arduino UNO is functional. Works well for my NANO.
image

void setup() 
{
  pinMode(13, OUTPUT);
}

void loop() 
{
  digitalWrite(13, HIGH);
  delay(1000);
  digitalWrite(13, LOW);
  delay(1000);
}

2. Upload the following sketch and check that LED1 of Fig-1 of post #12 blinks at 1-sec interval. Works well for my NANO.

void setup() 
{
  pinMode(9, OUTPUT);
}

void loop() 
{
  digitalWrite(9, HIGH);
  delay(1000);
  digitalWrite(9, LOW);
  delay(1000);
}

3. Upload the following sketch. Slowly turn Pot of Fig-1 of post #12 and observe that the brightness of LED1 changes. Works well for my NANO.

void setup()
{
   Serial.begin(9600);
}

void loop()
{
     analogWrite(9, map(analogRead(A0), 0,1023,0,255));
     delay(1000);
}

4. Upload the following sketch and check that the LED1 of Fig-1 of post #12 blinks at 1-sec interval. Works well for my NANO.

void setup()
{
  Serial.begin(9600);
  oneHz();  //1 Hz signal at DPin-9
}

void loop() {}

void oneHz()
{
  pinMode(9, OUTPUT); //Ch-A

  TCCR1A = 0x00;   //reset
  TCCR1B = 0x00;   //TC1 reset and OFF
  //fOC1A/B = clckSys/(N*(1+ICR1); Mode-14 FPWM; OCR1A controls duty cycle
  // 1 Hz = 16000000/(256*(1+ICR1) N=(1,8,64),256,(1024) ==> ICR1 = 25000
  TCCR1A |= (1 << WGM11); //Mode-14 Fast PWM
  TCCR1B |= (1 << WGM13) | (1 << WGM12);  //Mode-14 Fast PWM

  TCCR1A |= (1 << COM1A1) | (0 << COM1A0); //Non-invert: HIGH-LOW

  ICR1 = 62499;   // TOP for 1Hz frequnecy
  OCR1A = 31250;  //= 50% duty cycle
  TCNT1 = 0;
  TCCR1B |= (1 << CS12);//TC1 statrt with N = 256;
}

5. Perform Tutorial of post #12. Works well for my NANO.

    • yes uploaded and works as described though flashes approx every 4 seconds, not 1 second
    • yes uploaded and works as described though flashes approx every 4 seconds, not 1 second
    • yes uploaded and works as described though there is a delay between adjusting the value and the brightness changing of approx 4 seconds
    • yes uploaded and works as described though the cycle is approx 2 seconds, not 1 second. This flashing is (roughly) double the speed of the flashing in previous tests.

Congratulations! Enjoy!!

Is your previous Arduino NNAO bad and you are are using a new NANO?

It is the same on both the old and new Nano's

I don't understand your comment as the test sketches are running, but at the wrong speed. Also the main sketch (fan control) still doesn't work