Arduino pwm frequency

Alright, bear with me…

As we all know, internal arduino pwm can be modified. After searching, I finally understand the code:

void setup()
{
 // configure hardware timer2 to generate a fast PWM on OC2B (Arduino digital pin 3)
 // set pin high on overflow, clear on compare match with OCR2B
 TCCR2A = 0x23;
 TCCR2B = 0x0C;  // select timer2 clock as 16 MHz I/O clock / 64 = 250 kHz
 OCR2A = 249;  // top/overflow value is 249 => produces a 1000 Hz PWM
 pinMode(3, OUTPUT);  // enable the PWM output (you now have a PWM signal on digital pin 3)
 OCR2B = 125;  // set the PWM to 50% duty cycle
}

from https://forum.arduino.cc/index.php?topic=18742.0
I implemented it in this:

/*
Eddy's temperature sensor and PWM fan speed controller.
This project was made to be placed inside the Riverbed x55 chasis.
See: https://makeitbreakitfixit.com/2016/06/20/hacking-a-riverbed-steelhead-cx755/
This code is protected under the GNU GENERAL PUBLIC LICENSE.
See https://github.com/Aristocles/TempController for more info.
www.makeitbreakitfixit.com
June 2016
This program reads the input from a thermistor (temperature sensor) and provides a PWM
signal to 3 fans to either switch them off or spin them at various speeds accordingly.
*/


//Modified in May 2019 by foxxyman: https://id.arduino.cc/foxxyman. Original info above^^
//The Original copy is under the GNU General Public License, and as such I convey the same GNU General Public License terms in this copy.
//Anyone having a problem with the above, please contact foxxyman: https://id.arduino.cc/foxxyman.



unsigned int serial_baud = 9600; // Serial baud speed. Must match the baud set in Linux script file
// There are three temperature thresholds with corresponding fan speeds. All temps in celsius.
// You can configure the temperature variables below, but the explanation below uses the default values.
// Between 0 and 34 degrees the fan is off.
// Once temp reaches 35 degrees, LOW_FAN speed begins
// If temp drops below 30, the fan switches off again. If the temp rises above 45 MID1_FAN speed begins
// If temp drops below , the fan drops back to LOW_FAN speed. If the temp rises above 55 MID2_FAN speed begins
//If the temp rises above 65 HI_FAN speed begins
// If temp drops below , the fan drops back to MID_FAN speed.
int low_min_temp = 35;
int low_max_temp = 45;
int mid1_min_temp = 45;
int mid1_max_temp = 55;
int mid2_min_temp = 55;
int mid2_max_temp = 65;
int hi_min_temp = 65;
int hi_max_temp = 100;
int warning_temp = 85; // temp that the warning led turns on at

// Fan power is a PWM signal between 0 and 255.
int slo_fan_speed = 60;
int mid1_fan_speed = 120;
int mid2_fan_speed = 185;
int max_fan_speed = 255;
//
int dly = 1000; // Delay in ms to wait between polling temp sensor
bool testing = false; // Setting to true sends cycling false temperatures. For testing only.



int fanSpeed = 0;
int temp = 1;
bool incrementing = true;
#define THERMISTOR A0 // Analog pin for temp sensor
#define FAN1 3 // All 3 fans are controlled the same
#define FAN2 6 // 
#define FAN3 9
#define LED 1  // the warning led

void setup() {
  Serial.begin(serial_baud); // Serial sync speed
  pinMode(FAN1, OUTPUT); // PWM output pins
  pinMode(FAN2, OUTPUT);
  pinMode(FAN3, OUTPUT);
  delay(500);
  pinMode(LED, OUTPUT);
  // configure hardware timer2 to generate a fast PWM on OC2B (Arduino digital pin 3)
 // set pin high on overflow, clear on compare match with OCR2B
 TCCR2A = 0x23;
 TCCR2B = 0x09;  // select timer2 clock as 16 MHz I/O clock / 64 = 250 kHz
 OCR2A = 79;  // top/overflow value is 249 => produces a 1000 Hz PWM
 pinMode(3, OUTPUT);  // enable the PWM output (you now have a PWM signal on digital pin 3)
 OCR2B = 125;  // set the PWM to 50% duty cycle
}

void loop() {
  double temp = Thermister(analogRead(THERMISTOR));  // Read temp sensor
     fanSpeed = actionCheck(temp, fanSpeed); // Checks temp and returns one of 4 actions for fans:
     Serial.print("["); Serial.print(temp); Serial.print("deg] ");      //0 = off, 1 = slow, 2 = mid, 3 = max
     executeAction(fanSpeed); // Sets the fans to appropriate action
     delay(dly);
   if(temp > warning_temp) {
     digitalWrite(LED, HIGH); //if the temp is higher than 85 degrees celsius,
   } else {                   //than led turns on
     digitalWrite(LED, LOW);  //if not, it’s off
   }
}

//
// FUNCTIONS:
//
double Thermister(int RawADC) {
  if (testing) {
    if (temp >= (hi_max_temp + 9)) incrementing = false;
    if (temp <= 0) incrementing = true;
    if (incrementing) temp++;
    else temp--;
    return (temp % (hi_max_temp + 10)); // executed during testing
  }
  double temp = log(((10240000/RawADC) - 10000));
  // See http://en.wikipedia.org/wiki/Thermistor for explanation of formula
  temp = 1 / (0.001129148 + (0.000234125 * temp) + (0.0000000876741 * temp * temp * temp));
  temp = temp - 273.15;           // Convert Kelvin to Celcius
  return temp;
}

int actionCheck(int temp, int fanSpeed) {
  switch (fanSpeed) {
    case 1:
      if (temp < low_min_temp) return 0;
    case 2:
      if (temp < mid1_min_temp) return 1;
    case 3:
      if (temp < mid2_min_temp) return 2;
    case 4:
      if (temp < hi_min_temp) return 3;
  }
  if (temp > hi_max_temp) return 4;
  if ((temp > mid2_max_temp) && (fanSpeed == 1)) return 2; // the fanSpeed part ensures that the change only occurs when temp going up, not down
  if ((temp > low_max_temp) && (fanSpeed == 0)) return 1;
  return fanSpeed;
}

void executeAction(int fanSpeed) {
  Serial.print("Fan speed set to: "); Serial.println(fanSpeed);
  int rpm;
  switch (fanSpeed) {
    case 1:
      rpm = slo_fan_speed;
      break;
    case 2:
      rpm = mid1_fan_speed;
      break;
    case 3:
      rpm = mid2_fan_speed;
      break;
    case 4:
      rpm = max_fan_speed;
      break;
    default:
      rpm = 0;
  }
  analogWrite(FAN1, rpm);
  analogWrite(FAN2, rpm);
  analogWrite(FAN3, rpm); 
}

Obviously, I need the duty cycle to not be a constant. From what I understand, the duty cycle looks like it is constant in the code I have so far. Correct if I’m wrong. How do I make the duty cycle variable?

I have read: https://www.arduino.cc/en/Tutorial/SecretsOfArduinoPWM but if the explaination is in there, I don’t understand it.

-Thank you

Adjust OCR2B to change duty cycle.

DrAzzy:
Adjust OCR2B to change duty cycle.

Right

The thing is, I need the fan’s speed to change according to the resistance that the thermister gives to the arduino, and it looks like to me, that the duty cycle is constant through the whole time it’s running once the OCR2B is set. Maybe I got this all wrong?

Good job using code tags on your first posting.

I finally understand the code:

I'm not so certain that you do understand.

You took this Timer2 code for 50% duty cycle at 1KHz

TCCR2A = 0x23;
TCCR2B = 0x0C;  // select timer2 clock as 16 MHz I/O clock / 64 = 250 kHz
OCR2A = 249;  // top/overflow value is 249 => produces a 1000 Hz PWM
pinMode(3, OUTPUT);  // enable the PWM output (you now have a PWM signal on digital pin 3)
OCR2B = 125;  // set the PWM to 50% duty cycle

And tried to turn it into code to give 25Khz with duty cycle control

TCCR2A = 0x23;
TCCR2B = 0x09;  
OCR2A = 79;  
pinMode(3, OUTPUT); 
OCR2B = 125;

First, there is an error in the referenced thread, and TCCR2B = 0x09 (TCCR2B = B00001001) sets bits in WGM23 (which is part of the FastPWM to OCR2A mode selection) and CS20 which give a prescaler of 1.

With OCR2A = 79, what frequency do you think the timer is cycling at? Not 25KHz.

Second, OCR2B is set at 125. This is higher than the highest count the timer will reach(79). Do you think the compare match for the output pin activation will ever be met?

There is another thread on 25KHz computer fan control I would like to refer you to https://forum.arduino.cc/index.php?topic=415167.0

It helps address the issue that you have fans on three different timers

#define FAN1 3 // All 3 fans are controlled the same
#define FAN2 6 // 
#define FAN3 9

I think some more forum searching on multiple 4 pin fan control with 25KHz pwm will also be of benefit. You still have a ways to go.

@OP

1. Note that only the following lines of the sketch of your original post are in actions.

unsigned int serial_baud = 9600; // Serial baud speed. 
int low_min_temp = 35;
int low_max_temp = 45;
int mid1_min_temp = 45;
int mid1_max_temp = 55;
int mid2_min_temp = 55;
int mid2_max_temp = 65;
int hi_min_temp = 65;
int hi_max_temp = 100;
int warning_temp = 85; // temp that the warning led turns on at

int slo_fan_speed = 60;
int mid1_fan_speed = 120;
int mid2_fan_speed = 185;
int max_fan_speed = 255;

int dly = 1000; // Delay in ms to wait between polling temp sensor
bool testing = false; // Setting to true sends cycling false temperatures. For testing only.

int fanSpeed = 0;
int temp = 1;
bool incrementing = true;

#define THERMISTOR A0 // Analog pin for temp sensor
#define FAN1 3 // All 3 fans are controlled the same
#define FAN2 6 // 
#define FAN3 9
#define LED 1  // the warning led

void setup() 
{
  Serial.begin(serial_baud); // Serial sync speed
  pinMode(FAN1, OUTPUT); // PWM output pins
  pinMode(FAN2, OUTPUT);
  pinMode(FAN3, OUTPUT);
  delay(500);
  pinMode(LED, OUTPUT);
}

void loop() 
{
     double temp = Thermister(analogRead(THERMISTOR));  // Read temp sensor
     fanSpeed = actionCheck(temp, fanSpeed); // Checks temp and returns one of 4 actions for fans:
     Serial.print("["); Serial.print(temp); Serial.print("deg] ");      //0 = off, 1 = slow, 2 = mid, 3 = max
     executeAction(fanSpeed); // Sets the fans to appropriate action
     delay(dly);
     
     if(temp > warning_temp) 
     {
        digitalWrite(LED, HIGH); //if the temp is higher than 85 degrees celsius,
     } 
     else 
     {                   //than led turns on
        digitalWrite(LED, LOW);  //if not, it's off
     }
}

double Thermister(int RawADC) 
{
  if (testing) 
{
    if (temp >= (hi_max_temp + 9)) incrementing = false;
    if (temp <= 0) incrementing = true;
    if (incrementing) temp++;
    else temp--;
    return (temp % (hi_max_temp + 10)); // executed during testing
  }
  double temp = log(((10240000/RawADC) - 10000));
  // See http://en.wikipedia.org/wiki/Thermistor for explanation of formula
  temp = 1 / (0.001129148 + (0.000234125 * temp) + (0.0000000876741 * temp * temp * temp));
  temp = temp - 273.15;           // Convert Kelvin to Celcius
  return temp;
}

int actionCheck(int temp, int fanSpeed) 
{
  switch (fanSpeed) 
  {
    case 1:
      if (temp < low_min_temp) return 0;
    case 2:
      if (temp < mid1_min_temp) return 1;
    case 3:
      if (temp < mid2_min_temp) return 2;
    case 4:
      if (temp < hi_min_temp) return 3;
  }
  
  if (temp > hi_max_temp) return 4;
  if ((temp > mid2_max_temp) && (fanSpeed == 1)) return 2; // 
  if ((temp > low_max_temp) && (fanSpeed == 0)) return 1;
  return fanSpeed;
}

void executeAction(int fanSpeed) 
{
  Serial.print("Fan speed set to: "); Serial.println(fanSpeed);
  int rpm;
  switch (fanSpeed) 
  {
    case 1:
      rpm = slo_fan_speed;
      break;
    case 2:
      rpm = mid1_fan_speed;
      break;
    case 3:
      rpm = mid2_fan_speed;
      break;
    case 4:
      rpm = max_fan_speed;
      break;
    default:
      rpm = 0;
  }
  
  analogWrite(FAN1, rpm);
  analogWrite(FAN2, rpm);
  analogWrite(FAN3, rpm); 
}

2. From the codes of Step-1, it is clear that you are regulating the speeds of your all 3 fans by the built-in PWM signals (Fig-1) of the Arduino UNO. (Your so called PWM signal generated by TC2 is not playing any role to regulate the speeds of the fans.)

Figure-1: Built-in PWM signals of UNO using analogWrite() functions.

(1) The speed of FAN1 is being regulated by 490 Hz PWM signal via DPin-3.
(1) The speed of FAN2 is being regulated by 980 Hz PWM signal via DPin-6.
(1) The speed of FAN3 is being regulated by 490 Hz PWM signal via DPin-9.

Obviously, I need the duty cycle to not be a constant. From what I understand, the duty cycle looks like it is constant in the code I have so far. Correct if I’m wrong. How do I make the duty cycle variable?

(1) The following 3 lines of codes regulates the speeds of your fans:

analogWrite(FAN1, rpm);
  analogWrite(FAN2, rpm);
  analogWrite(FAN3, rpm);

(2) The argument rpm control the duty cycle of the PWM signal and hence the speed of the fan.

(3) rpm changes as the parameter fanSpeed changes.

(3) fanSpeed changes as the temp changes.

So, the conclusion is this: the fan speeds are being regulated as the temperature changes.

Why are you saying that the fan speed remains constant?

Do you want to write codes for yourself to generate PWM signal using TC2 for the speed regulation of your fans? If so, what is the frequency of the expected PWM signal?

You may read the post of this link to see how PWM signal is being generated using TC1.

pwm328x.png

does this look good:

unsigned int serial_baud = 9600; // Serial baud speed. Must match the baud set in Linux script file
// There are three temperature thresholds with corresponding fan speeds. All temps in celsius.
// Between 0 and 34 degrees the fan is off.
// Once temp reaches 35 degrees, LOW_FAN speed begins
// If temp drops below 30, the fan switches off again. If the temp rises above 45 MID1_FAN speed begins
// If temp drops below , the fan drops back to LOW_FAN speed. If the temp rises above 55 MID2_FAN speed begins
//If the temp rises above 65 HI_FAN speed begins
// If temp drops below , the fan drops back to MID_FAN speed.
int low_min_temp = 35;
int low_max_temp = 45;
int mid1_min_temp = 45;
int mid1_max_temp = 55;
int mid2_min_temp = 55;
int mid2_max_temp = 65;
int hi_min_temp = 65;
int hi_max_temp = 100;
int warning_temp = 85; // temp that the warning led turns on at

// Fan power is a PWM signal between 0 and 255.
int slo_fan_speed = 60;
int mid1_fan_speed = 120;
int mid2_fan_speed = 185;
int max_fan_speed = 255;
//
int dly = 1000; // Delay in ms to wait between polling temp sensor
bool testing = false; // Setting to true sends cycling false temperatures. For testing only.



int fanSpeed = 0;
int temp = 1;
bool incrementing = true;
#define THERMISTOR A0 // Analog pin for temp sensor
#define FAN1 3 // All 3 fans are controlled the same
#define FAN2 11
#define LED 1  // the warning led

word pwmA = 160; // 50% duty (0-320 = 0-100% duty cycle)
word pwmB = 288; // 90% duty (0-320 = 0-100% duty cycle)

void setup() {
 { Serial.begin(serial_baud); // Serial sync speed
   pinMode(FAN1, OUTPUT); // PWM output pins
   pinMode(FAN2, OUTPUT);
   delay(500);
   pinMode(LED, OUTPUT);
 }
 { pinMode(9, OUTPUT);  //pwmA
  pinMode(10, OUTPUT); //pwmB

  TCCR1A = 0;            //clear timer registers
  TCCR1B = 0;
  TCNT1 = 0;

  TCCR1B |= _BV(CS10);   //no prescaler
  ICR1 = 320;            //PWM mode counts up 320 then down 320 counts (25kHz)

  OCR1A = pwmA;          //0-320 = 0-100% duty cycle
  TCCR1A |= _BV(COM1A1); //output A clear rising/set falling

  OCR1B = pwmB;          //0-320 = 0-100% duty cycle
  TCCR1A |= _BV(COM1B1); //output B clear rising/set falling

  TCCR1B |= _BV(WGM13);  //PWM mode with ICR1 Mode 10
  TCCR1A |= _BV(WGM11);  //WGM13:WGM10 set 1010
 }
}

void loop() {
  double temp = Thermister(analogRead(THERMISTOR));  // Read temp sensor
     fanSpeed = actionCheck(temp, fanSpeed); // Checks temp and returns one of 4 actions for fans:
     Serial.print("["); Serial.print(temp); Serial.print("deg] ");      //0 = off, 1 = slow, 2 = mid, 3 = max
     executeAction(fanSpeed); // Sets the fans to appropriate action
     delay(dly);
   if(temp > warning_temp) {
     digitalWrite(LED, HIGH); //if the temp is higher than 85 degrees celsius,
   } else {                   //than led turns on
     digitalWrite(LED, LOW);  //if not, it’s off
   }
}

//
// FUNCTIONS:
//
double Thermister(int RawADC) {
  if (testing) {
    if (temp >= (hi_max_temp + 9)) incrementing = false;
    if (temp <= 0) incrementing = true;
    if (incrementing) temp++;
    else temp--;
    return (temp % (hi_max_temp + 10)); // executed during testing
  }
  double temp = log(((10240000/RawADC) - 10000));
  // See http://en.wikipedia.org/wiki/Thermistor for explanation of formula
  temp = 1 / (0.001129148 + (0.000234125 * temp) + (0.0000000876741 * temp * temp * temp));
  temp = temp - 273.15;           // Convert Kelvin to Celcius
  return temp;
}

int actionCheck(int temp, int fanSpeed) {
  switch (fanSpeed) {
    case 1:
      if (temp < low_min_temp) return 0;
    case 2:
      if (temp < mid1_min_temp) return 1;
    case 3:
      if (temp < mid2_min_temp) return 2;
    case 4:
      if (temp < hi_min_temp) return 3;
  }
  if (temp > hi_max_temp) return 4;
  if ((temp > mid2_max_temp) && (fanSpeed == 1)) return 2; // the fanSpeed part ensures that the change only occurs when temp going up, not down
  if ((temp > low_max_temp) && (fanSpeed == 0)) return 1;
  return fanSpeed;
}

void executeAction(int fanSpeed) {
  Serial.print("Fan speed set to: "); Serial.println(fanSpeed);
  int rpm;
  switch (fanSpeed) {
    case 1:
      rpm = slo_fan_speed;
      break;
    case 2:
      rpm = mid1_fan_speed;
      break;
    case 3:
      rpm = mid2_fan_speed;
      break;
    case 4:
      rpm = max_fan_speed;
      break;
    default:
      rpm = 0;
  }
  analogWrite(FAN1, rpm);
  analogWrite(FAN2, rpm);
}

?

thanks for looking it over

@OP

1. Let us assume that your objectives are:
(1) You have 2 fans (FAN1 and FAN2) connected at DPin-9 and DPin-10 of the Arduino UNO.

(2) You want to regulate the speeds of the fans of Step-1 by 25 kHz PWM signals to be generated using TC1 Module in its Mode-10 operation.

(3) The PWM timing diagram of Mode-10 operation of TC1 is given below in Fig-1.

Figure-1: PWM timing diagram of Mode-10 of TC1

(4) The formula for the frequency of the PWM signal of Fig-1 is:
fPCPWM = clkSYS/N (1/(2ICR1))
Where:
clkSYS = 16000000; N = prescale divider = 1; ICR1 (TOP) determines the frequency.
==> 25103 = 16000000/1 * (1/(2ICR1))
==> ICR1 = 320 = 0x0140.

(5) The Codes: (untested; give a try and report result)

unsigned int serial_baud = 9600; 
int low_min_temp = 35;
int low_max_temp = 45;
int mid1_min_temp = 45;
int mid1_max_temp = 55;
int mid2_min_temp = 55;
int mid2_max_temp = 65;
int hi_min_temp = 65;
int hi_max_temp = 100;
int warning_temp = 85; // temp that the warning led turns on at

// Fan power is a PWM signal between 0 and 255.
int slo_fan_speed = 60;
int mid1_fan_speed = 120;
int mid2_fan_speed = 185;
int max_fan_speed = 255;
int rpm;

int dly = 1000;         // Delay in ms to wait between polling temp sensor
bool testing = false; // Setting to true sends cycling false temperatures. For testing only.

int fanSpeed = 0;
int temp = 1;
bool incrementing = true;
#define THERMISTOR A0 // Analog pin for temp sensor
#define FAN1 9 // All 3 fans are controlled the same
#define FAN2 10
#define LED 1  // the warning led

//word pwmA = 160; // 50% duty (0-320 = 0-100% duty cycle)
//word pwmB = 288; // 90% duty (0-320 = 0-100% duty cycle)

void setup() 
{
 { 
   Serial.begin(serial_baud); // Serial sync speed
   pinMode(FAN1, OUTPUT); // PWM output pins
   pinMode(FAN2, OUTPUT);
   delay(500);
   pinMode(LED, OUTPUT);

   bitSet(TIMSK1, 5); // = _BV(ICIE);     //Match at TOP (ICR1) interrupt is enabled
   sei();       //SREG = _BV(I);                 //global interrupt bit is mad active
 }
 
{ 
   pinMode(9, OUTPUT);  //pwmA
   pinMode(10, OUTPUT); //pwmB
 
  TCCR1A = 0x00;
  TCCR1A |= _BV(COM1A1); //output A (OC1A PWM) clears at match of TCNT1 with ICR1 (TOP)
  TCCR1A |= _BV(WGM11);  // for PWM Mode-10

  TCCR1B = 0x00;
  TCCR1B |= _BV(COM1B1); //output B (OC1B PWM) clears at match of TCNT1 with ICR1 (TOP)
  TCCR1B |= _BV(CS10);      //prescale divider is 1
  TCCR1B |= _BV(WGM13);  //for PWM Mode 10

  TCNT1 = 0;              //
  ICR1 = 320;            //TOP value for 25 kHz PWM at DPin-9 (OC1A) and DPin-10 (OC1B)

  OCR1A = 160;          // just initial value for 75% duty cycle (0-320 = 50%-100% duty cycle)
  OCR1B = 160;          // just initial value for 75% duty cycle (0-320 = 50%-100% duty cycle)
 }
}

void loop() 
{
     double temp = Thermister(analogRead(THERMISTOR));  // Read temp sensor
     fanSpeed = actionCheck(temp, fanSpeed); // Checks temp and returns one of 4 actions for fans:
     Serial.print("["); Serial.print(temp); Serial.print("deg] ");      //0 = off, 1 = slow, 2 = mid, 3 = max
     executeAction(fanSpeed); // Sets the fans to appropriate action
     delay(dly);
     
   if(temp > warning_temp) 
   {
      digitalWrite(LED, HIGH); //if the temp is higher than 85 degrees celsius,
   } 
   else 
   {                   //than led turns on
     digitalWrite(LED, LOW);  //if not, it's off
   }
}

double Thermister(int RawADC) 
{
  if (testing) 
  {
    if (temp >= (hi_max_temp + 9)) incrementing = false;
    if (temp <= 0) incrementing = true;
    if (incrementing) temp++;
    else temp--;
    return (temp % (hi_max_temp + 10)); // executed during testing
  }
  double temp = log(((10240000/RawADC) - 10000));
  // See http://en.wikipedia.org/wiki/Thermistor for explanation of formula
  temp = 1 / (0.001129148 + (0.000234125 * temp) + (0.0000000876741 * temp * temp * temp));
  temp = temp - 273.15;           // Convert Kelvin to Celcius
  return temp;
}

int actionCheck(int temp, int fanSpeed) 
{
  switch (fanSpeed) 
  {
    case 1:
      if (temp < low_min_temp) return 0;
    case 2:
      if (temp < mid1_min_temp) return 1;
    case 3:
      if (temp < mid2_min_temp) return 2;
    case 4:
      if (temp < hi_min_temp) return 3;
  }
  
  if (temp > hi_max_temp) return 4;
  if ((temp > mid2_max_temp) && (fanSpeed == 1)) return 2; 
  if ((temp > low_max_temp) && (fanSpeed == 0)) return 1;
  return fanSpeed;
}

void executeAction(int fanSpeed) 
{
  Serial.print("Fan speed set to: "); Serial.println(fanSpeed);
 // int rpm;
  switch (fanSpeed) 
  {
    case 1:
      rpm = slo_fan_speed;
      break;
    case 2:
      rpm = mid1_fan_speed;
      break;
    case 3:
      rpm = mid2_fan_speed;
      break;
    case 4:
      rpm = max_fan_speed;
      break;
    default:
      rpm = 0;
  }
  
  //analogWrite(FAN1, rpm);    //rpm regulates duty cycle
  //analogWrite(FAN2, rpm);
}

ISR(TIMER1_CAPT_vect)   //update OCR1A to regulate duty cycle
{
    OCR1A = map(rpm, 60, 255, 0, 320);  //OCR1A must be within: 0 - 320
    OCR1B = map(rpm, 60, 255, 0, 320);  //OCR1B must be within: 0 - 320

}

pwmMode10x.png

Alright, I've been busy. I flashed the code, and connected everything together. I used an old computer PSU. It didn't work. The PSU works, because we used it while we were waiting for a replacement PSU. I think I may have connected the thermister wrong. I followed the instructions for the original code here: http://makeitbreakitfixit.com/2016/07/02/thermistor-and-pwm-speed-controller/; but, I looked at other projects, and others use theremister in series with a resistor create a voltage divider. I'm not sure how I'm supposed to go about that part of it. Here is the circuit: (the fan part got messed up, but you get the point): https://drive.google.com/file/d/14qze5N4NDJSe_IQZvIuei-MoAK324xcZ/view?usp=sharing

I used the code from poet 6.

I followed the instructions for the original code here: http://makeitbreakitfixit.com/2016/07/02/thermistor-and-pwm-speed-controller/; but, I looked at other projects, and others use thermistor in series with a resistor create a voltage divider.

That is correct. This diagram from the circuit you referenced shows that

I used the code from poet 6.

??

cattledog:
That is correct. This diagram from the circuit you referenced shows that

??

I didn’t realize that :smiley:
I also meant “post 6”.

There are still problems. I put the thermister in series with a 10Kohm resister. I then turn the PSU on. The Arduino doesn’t turn on. I remove the capacitors, and the 5V and 12V connect directly to their respective power strips on the breadboard. The Arduino then lights up. the fan does nothing. I press the reset button. The fan spins for a second, and slows to a stop. Does the resistor have too high a value?

Here is the circuit: (the fan part got messed up, but you get the point): drive.google.com/file/d/14qze5N4NDJSe_IQZvIuei-MoAK324xcZ/view

Please attach a hand drawn circuit diagram. What you have is not very helpful.

How is the Arduino pwm output controlling the 24v going to the fans? I don't see a relay, transistor, or mosfet in the circuit.

EDIT: I just remembered that they were computer fans which take a 5v control pwm signal.

Do not have any part of the circuit connected to D0 or D1 as they are the serial connections.

I drew up this diagram, hopefully you can read it. The components are all connected together through a breadboard. To save time and space, I drew it without a breadboard. There is also a picture of everything connected to the breadboard in that album. My phone's camera is not modern, neither is phone (from 2016); that would explain the quality.

|500x374

There are some things I don't understand about your circuit. You show a 5v GND and a 12v GND. Are they common, i.e. tied together and at the same level?

The capacitors in series with the 5v and 12v look wrong. They are blocking the output current flow, and current is needed to operate the voltage divider and the fans. If they were between the voltage supply and ground they would stabilize the voltage, but I doubt they are needed.

If you use digitalWrite(9,HIGH), can you get the fan to be full on?

cattledog: |500x374

There are some things I don't understand about your circuit. You show a 5v GND and a 12v GND. Are they common, i.e. tied together and at the same level?

The capacitors in series with the 5v and 12v look wrong. They are blocking the output current flow, and current is needed to operate the voltage divider and the fans. If they were between the voltage supply and ground they would stabilize the voltage, but I doubt they are needed.

If you use digitalWrite(9,HIGH), can you get the fan to be full on?

All the grounds are common, the way I designed it was just easier for me.

The only time fan will spin, is right as I turn everything on; though it'll also spin when I disconnect the pwm signal, so I'm not sure the fan is the problem. It runs great with digitalWrite(9,High).

You will need to use the Serial output to debug your program, and possibly simplify the code to isolate problems. Explain exactly what the code is doing properly and not doing properly?

Is the temperature section working properly? Is the temperature to fan speed to rpm working correctly? What values are you seeing for OCR1A?

Here's an idea to simplify the code and see if the pwm is driving the fans. Change the loop code from post 6

Change #1

double temp = Thermister(analogRead(THERMISTOR));  // Read temp sensor
    fanSpeed = 3;
// fanSpeed = actionCheck(temp, fanSpeed); // Checks temp and returns one of 4 actions for fans:
     Serial.print("["); Serial.print(temp); Serial.print("deg] ");      //0 = off, 1 = slow, 2 = mid, 3 = max
     executeAction(fanSpeed); // Sets the fans to appropriate action
     delay(dly);

If the fan does not spin, try with executeAction(fanSpeed) commented out. The code should default to 50% duty cycle.

Change #2

double temp = Thermister(analogRead(THERMISTOR));  // Read temp sensor
    fanSpeed = 3;
// fanSpeed = actionCheck(temp, fanSpeed); // Checks temp and returns one of 4 actions for fans:
     Serial.print("["); Serial.print(temp); Serial.print("deg] ");      //0 = off, 1 = slow, 2 = mid, 3 = max
     //executeAction(fanSpeed); // Sets the fans to appropriate action
     delay(dly);

cattledog: You will need to use the Serial output to debug your program, and possibly simplify the code to isolate problems. Explain exactly what the code is doing properly and not doing properly?

Is the temperature section working properly? Is the temperature to fan speed to rpm working correctly? What values are you seeing for OCR1A?

Here's an idea to simplify the code and see if the pwm is driving the fans. Change the loop code from post 6

Change #1

double temp = Thermister(analogRead(THERMISTOR));  // Read temp sensor
    fanSpeed = 3;
// fanSpeed = actionCheck(temp, fanSpeed); // Checks temp and returns one of 4 actions for fans:
     Serial.print("["); Serial.print(temp); Serial.print("deg] ");      //0 = off, 1 = slow, 2 = mid, 3 = max
     executeAction(fanSpeed); // Sets the fans to appropriate action
     delay(dly);

If the fan does not spin, try with executeAction(fanSpeed) commented out. The code should default to 50% duty cycle.

Change #2

double temp = Thermister(analogRead(THERMISTOR));  // Read temp sensor
    fanSpeed = 3;
// fanSpeed = actionCheck(temp, fanSpeed); // Checks temp and returns one of 4 actions for fans:
     Serial.print("["); Serial.print(temp); Serial.print("deg] ");      //0 = off, 1 = slow, 2 = mid, 3 = max
     //executeAction(fanSpeed); // Sets the fans to appropriate action
     delay(dly);

Thanks, I will try that. It'll be a few days before I try those things and respond, probably late Sunday or sometime Monday (Mountain Standard Time).

Here’s another debug idea which will help localize the problem, and will point to hardware or software. I would certainly remove the in line capacitor from the 12v fan supply when you run this.

Install the TimerOne library using the library manager. There is a library example for a 25KHz pwm fan. Change the pin numbers to what you are using, and see if the fan responds.

#include <TimerOne.h>

// This example creates a PWM signal with 25 kHz carrier.
//
// Arduino's analogWrite() gives you PWM output, but no control over the
// carrier frequency.  The default frequency is low, typically 490 or
// 3920 Hz.  Sometimes you may need a faster carrier frequency.
//
// The specification for 4-wire PWM fans recommends a 25 kHz frequency
// and allows 21 to 28 kHz.  The default from analogWrite() might work
// with some fans, but to follow the specification we need 25 kHz.
//
// http://www.formfactors.org/developer/specs/REV1_2_Public.pdf
//
// Connect the PWM pin to the fan's control wire (usually blue).  The
// board's ground must be connected to the fan's ground, and the fan
// needs +12 volt power from the computer or a separate power supply.

const int fanPin = 4;

void setup(void)
{
  Timer1.initialize(40);  // 40 us = 25 kHz
  Serial.begin(9600);
}

void loop(void)
{
  // slowly increase the PWM fan speed
  //
  for (float dutyCycle = 30.0; dutyCycle < 100.0; dutyCycle++) {
    Serial.print("PWM Fan, Duty Cycle = ");
    Serial.println(dutyCycle);
    Timer1.pwm(fanPin, (dutyCycle / 100) * 1023);
    delay(500);
  }
}

cattledog:
You will need to use the Serial output to debug your program, and possibly simplify the code to isolate problems. Explain exactly what the code is doing properly and not doing properly?

Is the temperature section working properly?
Is the temperature to fan speed to rpm working correctly?
What values are you seeing for OCR1A?

Here’s an idea to simplify the code and see if the pwm is driving the fans. Change the loop code from post 6

Change #1

double temp = Thermister(analogRead(THERMISTOR));  // Read temp sensor

fanSpeed = 3;
// fanSpeed = actionCheck(temp, fanSpeed); // Checks temp and returns one of 4 actions for fans:
    Serial.print("["); Serial.print(temp); Serial.print("deg] ");      //0 = off, 1 = slow, 2 = mid, 3 = max
    executeAction(fanSpeed); // Sets the fans to appropriate action
    delay(dly);

change it to what?

cattledog:
Here’s another debug idea which will help localize the problem, and will point to hardware or software. I would certainly remove the in line capacitor from the 12v fan supply when you run this.

Install the TimerOne library using the library manager. There is a library example for a 25KHz pwm fan. Change the pin numbers to what you are using, and see if the fan responds.

#include <TimerOne.h>

// This example creates a PWM signal with 25 kHz carrier.
//
// Arduino’s analogWrite() gives you PWM output, but no control over the
// carrier frequency.  The default frequency is low, typically 490 or
// 3920 Hz.  Sometimes you may need a faster carrier frequency.
//
// The specification for 4-wire PWM fans recommends a 25 kHz frequency
// and allows 21 to 28 kHz.  The default from analogWrite() might work
// with some fans, but to follow the specification we need 25 kHz.
//
// http://www.formfactors.org/developer/specs/REV1_2_Public.pdf
//
// Connect the PWM pin to the fan’s control wire (usually blue).  The
// board’s ground must be connected to the fan’s ground, and the fan
// needs +12 volt power from the computer or a separate power supply.

const int fanPin = 4;

void setup(void)
{
  Timer1.initialize(40);  // 40 us = 25 kHz
  Serial.begin(9600);
}

void loop(void)
{
  // slowly increase the PWM fan speed
  //
  for (float dutyCycle = 30.0; dutyCycle < 100.0; dutyCycle++) {
    Serial.print("PWM Fan, Duty Cycle = ");
    Serial.println(dutyCycle);
    Timer1.pwm(fanPin, (dutyCycle / 100) * 1023);
    delay(500);
  }
}

this code works just fine

this code works just fine

Good news. That means the fan wiring is correct. You now need to debug your program to find out why the fan is not running.

change it to what?

Do you not see commented out lines and added lines? There is a fixed fan speed and then seeing if the problem lies in either of the two functions actionCheck() and executeAction().