/*
Project to test staged pwm output to cooling fan, controlled by temperature sensor
Temperature range are divided into stages. When the temperature reading reached
a certain stage, the pwm output increase to that stage.
When the temperature dropped below that stage [minus a margin], for a defined peroid,
the pwm output decrease to that stage.
The goals are:
1. Increase fan PWM when the temperature gets hot
2. Decrease fan PWM when the temperature gets cold
3. The fan PWM response to hot condition quickly, but not changing
too often when getting cooler
4. Parameters are pre-defined
*/
//********** Tempareture Control **********
#define MIN_PWM_TEMPERATURE 40 //fan runs at MIN_PWM+1 stage at or above this temperature
#define MAX_PWM_TEMPERATURE 70 //fan runs at MAX_PWM at or above this temperature
#define WARNING_TEMPERATURE 90 //warning is given at or above this temperature
#define COOLDOWN_MARGIN 5
#define DOWNGRADE_DELAY 3000 //in millis
#define PWM_STAGES 4
#define MIN_PWM 20 //minimum fan PWM value
#define MAX_PWM 100 //maximum fan PWM
uint8_t fanPwm=0; //from 0 to 255, used for analogWrite
uint8_t fanPwmPercentage=0; //from 0 to 100, used for display
uint8_t upThreshold[PWM_STAGES+1];
uint8_t downThreshold[PWM_STAGES+1];
uint8_t stagePwm[PWM_STAGES+1];
uint8_t currentStage=0;
uint32_t downTimer=0; //timer used for the downgrade delay
bool downFlag=false; //flag used for the downgrade delay
uint32_t potTimer=0;
void setup()
{
Serial.begin(115200);
Serial.println("Program started.");
uint8_t temperatureRange=MAX_PWM_TEMPERATURE-MIN_PWM_TEMPERATURE;
uint8_t temperatureStep=temperatureRange/(PWM_STAGES-1);
uint8_t fanPwmRange = MAX_PWM-MIN_PWM;
uint8_t fanPwmStep = fanPwmRange/(PWM_STAGES);
upThreshold[0]=0;
downThreshold[0]=0;
stagePwm[0]=MIN_PWM;
for (uint8_t i=1;i<PWM_STAGES+1;i++)
{
upThreshold[i]= MIN_PWM_TEMPERATURE + temperatureStep*(i-1);
downThreshold[i]=upThreshold[i]-COOLDOWN_MARGIN;
stagePwm[i]=MIN_PWM+fanPwmStep*(i);
}
stagePwm[PWM_STAGES]=MAX_PWM;
for (uint8_t i=0;i<PWM_STAGES+1;i++)
{
Serial.print("upThreshold[");
Serial.print(i);
Serial.print("]=");
Serial.print(upThreshold[i]);
Serial.print(" downThreshold[");
Serial.print(i);
Serial.print("]=");
Serial.print(downThreshold[i]);
Serial.print(" stagePwm[");
Serial.print(i);
Serial.print("]=");
Serial.print(stagePwm[i]);
Serial.println();
}
pinMode(A0, INPUT);
potTimer=millis();
}
void loop()
{
checkPot();
}
void checkPot()
{
if (millis()-potTimer<1000)
return;
potTimer=millis();
uint16_t value=analogRead(A0);
uint8_t temperature = map(value,0,1023,MIN_PWM_TEMPERATURE-COOLDOWN_MARGIN*2,WARNING_TEMPERATURE+20);
uint8_t newStage=0;
bool upFlag=false;
//for stage downgrade
for (uint8_t i=PWM_STAGES;i>0;i--)
{
Serial.print(i);
if(temperature<=downThreshold[i])
{
newStage=i-1;
}
}
if(newStage<currentStage)
{
if(downFlag==false)
{
Serial.print("dn");
downFlag=true;
downTimer=millis();
}
}
//for stage upgrade
newStage=0;
for (uint8_t i=1;i<PWM_STAGES+1;i++)
{
Serial.print(i);
if(temperature>=upThreshold[i])
{
newStage=i;
}
}
if(newStage>currentStage)
{
Serial.print("up");
upFlag=true;
}
if (upFlag==true)
{
currentStage = newStage;
downFlag = false;
}
if (downFlag==true)
{
if (millis()-downTimer>DOWNGRADE_DELAY)
{
//initiate fan pwm stage downgrade
if (currentStage>0)
{
currentStage--;
}
downFlag = false;
}
}
Serial.print("T=");
Serial.print(temperature);
Serial.print(" newStage=");
Serial.print(newStage);
Serial.print(" currentStage=");
Serial.print(currentStage);
Serial.print(" upFlag=");
Serial.print(upFlag);
Serial.print(" downFlag=");
Serial.print(downFlag);
Serial.println();
}